diff --git a/.gitignore b/.gitignore index d3f9aff55..0ddf3aba2 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,11 @@ local.properties *.suo *.user *.sln.docstates +*.sln +*.vcxproj +*.vcxproj.filters +*.vcproj + # Build results [Dd]ebug/ @@ -62,6 +67,11 @@ local.properties *.vspscc .builds *.dotCover +*.dll +*.lib +*.exp +*.exe + ## TODO: If you have NuGet Package Restore enabled, uncomment this #packages/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..6ea0659d3 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required (VERSION 2.8.12) + +set(TORQUE_APP_NAME "" CACHE STRING "the app name") + +if("${TORQUE_APP_NAME}" STREQUAL "") + message(FATAL_ERROR "Please set TORQUE_APP_NAME first") +endif() + +project(${TORQUE_APP_NAME}) + +add_subdirectory(Tools/CMake) diff --git a/Engine/lib/collada/include/dae/daeTypes.h b/Engine/lib/collada/include/dae/daeTypes.h index 27e560cdd..41e116a4a 100644 --- a/Engine/lib/collada/include/dae/daeTypes.h +++ b/Engine/lib/collada/include/dae/daeTypes.h @@ -21,6 +21,7 @@ #include #include #include +#include #include diff --git a/Engine/lib/convexDecomp/NvThreadConfig.cpp b/Engine/lib/convexDecomp/NvThreadConfig.cpp index af6f2bdda..5756bafa8 100644 --- a/Engine/lib/convexDecomp/NvThreadConfig.cpp +++ b/Engine/lib/convexDecomp/NvThreadConfig.cpp @@ -133,6 +133,8 @@ void tc_spinloop() asm ( "pause" ); #elif defined( _XBOX ) // Pause would do nothing on the Xbox. Threads are not scheduled. + #elif defined( _WIN64 ) + YieldProcessor( ); #else __asm { pause }; #endif @@ -144,7 +146,7 @@ void tc_interlockedExchange(void *dest, const int64_t exchange) // not working assert(false); //__sync_lock_test_and_set((int64_t*)dest, exchange); - #elif defined( _XBOX ) +#elif defined( _XBOX ) || defined( _WIN64 ) InterlockedExchange((volatile LONG *)dest, exchange); #else __asm @@ -172,7 +174,7 @@ NxI32 tc_interlockedCompareExchange(void *dest, NxI32 exchange, NxI32 compare) return 0; //return __sync_val_compare_and_swap((uintptr_t*)dest, exchange, compare); //return __sync_bool_compare_and_swap((uintptr_t*)dest, exchange, compare); - #elif defined( _XBOX ) + #elif defined( _XBOX ) || defined( _WIN64 ) return InterlockedCompareExchange((volatile LONG *)dest, exchange, compare); #else char _ret; @@ -202,7 +204,7 @@ NxI32 tc_interlockedCompareExchange(void *dest, const NxI32 exchange1, const NxI //uint64_t exchange = ((uint64_t)exchange1 << 32) | (uint64_t)exchange2; //uint64_t compare = ((uint64_t)compare1 << 32) | (uint64_t)compare2; //return __sync_bool_compare_and_swap((int64_t*)dest, exchange, compare); - #elif defined( _XBOX ) + #elif defined( _XBOX ) || defined( _WIN64 ) assert(false); return 0; #else diff --git a/Engine/lib/gtest/CONTRIBUTORS b/Engine/lib/gtest/CONTRIBUTORS new file mode 100644 index 000000000..feae2fc04 --- /dev/null +++ b/Engine/lib/gtest/CONTRIBUTORS @@ -0,0 +1,37 @@ +# This file contains a list of people who've made non-trivial +# contribution to the Google C++ Testing Framework project. People +# who commit code to the project are encouraged to add their names +# here. Please keep the list sorted by first names. + +Ajay Joshi +Balázs Dán +Bharat Mediratta +Chandler Carruth +Chris Prince +Chris Taylor +Dan Egnor +Eric Roman +Hady Zalek +Jeffrey Yasskin +Jói Sigurðsson +Keir Mierle +Keith Ray +Kenton Varda +Manuel Klimek +Markus Heule +Mika Raento +Miklós Fazekas +Pasi Valminen +Patrick Hanna +Patrick Riley +Peter Kaminski +Preston Jackson +Rainer Klaffenboeck +Russ Cox +Russ Rufer +Sean Mcafee +Sigurður Ásgeirsson +Tracy Bialik +Vadim Berman +Vlad Losev +Zhanyong Wan diff --git a/Engine/lib/gtest/LICENSE b/Engine/lib/gtest/LICENSE new file mode 100644 index 000000000..1941a11f8 --- /dev/null +++ b/Engine/lib/gtest/LICENSE @@ -0,0 +1,28 @@ +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Engine/lib/gtest/README b/Engine/lib/gtest/README new file mode 100644 index 000000000..26f35a847 --- /dev/null +++ b/Engine/lib/gtest/README @@ -0,0 +1,435 @@ +Google C++ Testing Framework +============================ + +http://code.google.com/p/googletest/ + +Overview +-------- + +Google's framework for writing C++ tests on a variety of platforms +(Linux, Mac OS X, Windows, Windows CE, Symbian, etc). Based on the +xUnit architecture. Supports automatic test discovery, a rich set of +assertions, user-defined assertions, death tests, fatal and non-fatal +failures, various options for running the tests, and XML test report +generation. + +Please see the project page above for more information as well as the +mailing list for questions, discussions, and development. There is +also an IRC channel on OFTC (irc.oftc.net) #gtest available. Please +join us! + +Requirements for End Users +-------------------------- + +Google Test is designed to have fairly minimal requirements to build +and use with your projects, but there are some. Currently, we support +Linux, Windows, Mac OS X, and Cygwin. We will also make our best +effort to support other platforms (e.g. Solaris, AIX, and z/OS). +However, since core members of the Google Test project have no access +to these platforms, Google Test may have outstanding issues there. If +you notice any problems on your platform, please notify +googletestframework@googlegroups.com. Patches for fixing them are +even more welcome! + +### Linux Requirements ### + +These are the base requirements to build and use Google Test from a source +package (as described below): + * GNU-compatible Make or gmake + * POSIX-standard shell + * POSIX(-2) Regular Expressions (regex.h) + * A C++98-standard-compliant compiler + +### Windows Requirements ### + + * Microsoft Visual C++ 7.1 or newer + +### Cygwin Requirements ### + + * Cygwin 1.5.25-14 or newer + +### Mac OS X Requirements ### + + * Mac OS X 10.4 Tiger or newer + * Developer Tools Installed + +Also, you'll need CMake 2.6.4 or higher if you want to build the +samples using the provided CMake script, regardless of the platform. + +Requirements for Contributors +----------------------------- + +We welcome patches. If you plan to contribute a patch, you need to +build Google Test and its own tests from an SVN checkout (described +below), which has further requirements: + + * Python version 2.3 or newer (for running some of the tests and + re-generating certain source files from templates) + * CMake 2.6.4 or newer + +Getting the Source +------------------ + +There are two primary ways of getting Google Test's source code: you +can download a stable source release in your preferred archive format, +or directly check out the source from our Subversion (SVN) repositary. +The SVN checkout requires a few extra steps and some extra software +packages on your system, but lets you track the latest development and +make patches much more easily, so we highly encourage it. + +### Source Package ### + +Google Test is released in versioned source packages which can be +downloaded from the download page [1]. Several different archive +formats are provided, but the only difference is the tools used to +manipulate them, and the size of the resulting file. Download +whichever you are most comfortable with. + + [1] http://code.google.com/p/googletest/downloads/list + +Once the package is downloaded, expand it using whichever tools you +prefer for that type. This will result in a new directory with the +name "gtest-X.Y.Z" which contains all of the source code. Here are +some examples on Linux: + + tar -xvzf gtest-X.Y.Z.tar.gz + tar -xvjf gtest-X.Y.Z.tar.bz2 + unzip gtest-X.Y.Z.zip + +### SVN Checkout ### + +To check out the main branch (also known as the "trunk") of Google +Test, run the following Subversion command: + + svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn + +Setting up the Build +-------------------- + +To build Google Test and your tests that use it, you need to tell your +build system where to find its headers and source files. The exact +way to do it depends on which build system you use, and is usually +straightforward. + +### Generic Build Instructions ### + +Suppose you put Google Test in directory ${GTEST_DIR}. To build it, +create a library build target (or a project as called by Visual Studio +and Xcode) to compile + + ${GTEST_DIR}/src/gtest-all.cc + +with ${GTEST_DIR}/include in the system header search path and ${GTEST_DIR} +in the normal header search path. Assuming a Linux-like system and gcc, +something like the following will do: + + g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} \ + -pthread -c ${GTEST_DIR}/src/gtest-all.cc + ar -rv libgtest.a gtest-all.o + +(We need -pthread as Google Test uses threads.) + +Next, you should compile your test source file with +${GTEST_DIR}/include in the system header search path, and link it +with gtest and any other necessary libraries: + + g++ -isystem ${GTEST_DIR}/include -pthread path/to/your_test.cc libgtest.a \ + -o your_test + +As an example, the make/ directory contains a Makefile that you can +use to build Google Test on systems where GNU make is available +(e.g. Linux, Mac OS X, and Cygwin). It doesn't try to build Google +Test's own tests. Instead, it just builds the Google Test library and +a sample test. You can use it as a starting point for your own build +script. + +If the default settings are correct for your environment, the +following commands should succeed: + + cd ${GTEST_DIR}/make + make + ./sample1_unittest + +If you see errors, try to tweak the contents of make/Makefile to make +them go away. There are instructions in make/Makefile on how to do +it. + +### Using CMake ### + +Google Test comes with a CMake build script (CMakeLists.txt) that can +be used on a wide range of platforms ("C" stands for cross-platofrm.). +If you don't have CMake installed already, you can download it for +free from http://www.cmake.org/. + +CMake works by generating native makefiles or build projects that can +be used in the compiler environment of your choice. The typical +workflow starts with: + + mkdir mybuild # Create a directory to hold the build output. + cd mybuild + cmake ${GTEST_DIR} # Generate native build scripts. + +If you want to build Google Test's samples, you should replace the +last command with + + cmake -Dgtest_build_samples=ON ${GTEST_DIR} + +If you are on a *nix system, you should now see a Makefile in the +current directory. Just type 'make' to build gtest. + +If you use Windows and have Vistual Studio installed, a gtest.sln file +and several .vcproj files will be created. You can then build them +using Visual Studio. + +On Mac OS X with Xcode installed, a .xcodeproj file will be generated. + +### Legacy Build Scripts ### + +Before settling on CMake, we have been providing hand-maintained build +projects/scripts for Visual Studio, Xcode, and Autotools. While we +continue to provide them for convenience, they are not actively +maintained any more. We highly recommend that you follow the +instructions in the previous two sections to integrate Google Test +with your existing build system. + +If you still need to use the legacy build scripts, here's how: + +The msvc\ folder contains two solutions with Visual C++ projects. +Open the gtest.sln or gtest-md.sln file using Visual Studio, and you +are ready to build Google Test the same way you build any Visual +Studio project. Files that have names ending with -md use DLL +versions of Microsoft runtime libraries (the /MD or the /MDd compiler +option). Files without that suffix use static versions of the runtime +libraries (the /MT or the /MTd option). Please note that one must use +the same option to compile both gtest and the test code. If you use +Visual Studio 2005 or above, we recommend the -md version as /MD is +the default for new projects in these versions of Visual Studio. + +On Mac OS X, open the gtest.xcodeproj in the xcode/ folder using +Xcode. Build the "gtest" target. The universal binary framework will +end up in your selected build directory (selected in the Xcode +"Preferences..." -> "Building" pane and defaults to xcode/build). +Alternatively, at the command line, enter: + + xcodebuild + +This will build the "Release" configuration of gtest.framework in your +default build location. See the "xcodebuild" man page for more +information about building different configurations and building in +different locations. + +If you wish to use the Google Test Xcode project with Xcode 4.x and +above, you need to either: + * update the SDK configuration options in xcode/Config/General.xconfig. + Comment options SDKROOT, MACOS_DEPLOYMENT_TARGET, and GCC_VERSION. If + you choose this route you lose the ability to target earlier versions + of MacOS X. + * Install an SDK for an earlier version. This doesn't appear to be + supported by Apple, but has been reported to work + (http://stackoverflow.com/questions/5378518). + +Tweaking Google Test +-------------------- + +Google Test can be used in diverse environments. The default +configuration may not work (or may not work well) out of the box in +some environments. However, you can easily tweak Google Test by +defining control macros on the compiler command line. Generally, +these macros are named like GTEST_XYZ and you define them to either 1 +or 0 to enable or disable a certain feature. + +We list the most frequently used macros below. For a complete list, +see file include/gtest/internal/gtest-port.h. + +### Choosing a TR1 Tuple Library ### + +Some Google Test features require the C++ Technical Report 1 (TR1) +tuple library, which is not yet available with all compilers. The +good news is that Google Test implements a subset of TR1 tuple that's +enough for its own need, and will automatically use this when the +compiler doesn't provide TR1 tuple. + +Usually you don't need to care about which tuple library Google Test +uses. However, if your project already uses TR1 tuple, you need to +tell Google Test to use the same TR1 tuple library the rest of your +project uses, or the two tuple implementations will clash. To do +that, add + + -DGTEST_USE_OWN_TR1_TUPLE=0 + +to the compiler flags while compiling Google Test and your tests. If +you want to force Google Test to use its own tuple library, just add + + -DGTEST_USE_OWN_TR1_TUPLE=1 + +to the compiler flags instead. + +If you don't want Google Test to use tuple at all, add + + -DGTEST_HAS_TR1_TUPLE=0 + +and all features using tuple will be disabled. + +### Multi-threaded Tests ### + +Google Test is thread-safe where the pthread library is available. +After #include "gtest/gtest.h", you can check the GTEST_IS_THREADSAFE +macro to see whether this is the case (yes if the macro is #defined to +1, no if it's undefined.). + +If Google Test doesn't correctly detect whether pthread is available +in your environment, you can force it with + + -DGTEST_HAS_PTHREAD=1 + +or + + -DGTEST_HAS_PTHREAD=0 + +When Google Test uses pthread, you may need to add flags to your +compiler and/or linker to select the pthread library, or you'll get +link errors. If you use the CMake script or the deprecated Autotools +script, this is taken care of for you. If you use your own build +script, you'll need to read your compiler and linker's manual to +figure out what flags to add. + +### As a Shared Library (DLL) ### + +Google Test is compact, so most users can build and link it as a +static library for the simplicity. You can choose to use Google Test +as a shared library (known as a DLL on Windows) if you prefer. + +To compile *gtest* as a shared library, add + + -DGTEST_CREATE_SHARED_LIBRARY=1 + +to the compiler flags. You'll also need to tell the linker to produce +a shared library instead - consult your linker's manual for how to do +it. + +To compile your *tests* that use the gtest shared library, add + + -DGTEST_LINKED_AS_SHARED_LIBRARY=1 + +to the compiler flags. + +Note: while the above steps aren't technically necessary today when +using some compilers (e.g. GCC), they may become necessary in the +future, if we decide to improve the speed of loading the library (see +http://gcc.gnu.org/wiki/Visibility for details). Therefore you are +recommended to always add the above flags when using Google Test as a +shared library. Otherwise a future release of Google Test may break +your build script. + +### Avoiding Macro Name Clashes ### + +In C++, macros don't obey namespaces. Therefore two libraries that +both define a macro of the same name will clash if you #include both +definitions. In case a Google Test macro clashes with another +library, you can force Google Test to rename its macro to avoid the +conflict. + +Specifically, if both Google Test and some other code define macro +FOO, you can add + + -DGTEST_DONT_DEFINE_FOO=1 + +to the compiler flags to tell Google Test to change the macro's name +from FOO to GTEST_FOO. Currently FOO can be FAIL, SUCCEED, or TEST. +For example, with -DGTEST_DONT_DEFINE_TEST=1, you'll need to write + + GTEST_TEST(SomeTest, DoesThis) { ... } + +instead of + + TEST(SomeTest, DoesThis) { ... } + +in order to define a test. + +Upgrating from an Earlier Version +--------------------------------- + +We strive to keep Google Test releases backward compatible. +Sometimes, though, we have to make some breaking changes for the +users' long-term benefits. This section describes what you'll need to +do if you are upgrading from an earlier version of Google Test. + +### Upgrading from 1.3.0 or Earlier ### + +You may need to explicitly enable or disable Google Test's own TR1 +tuple library. See the instructions in section "Choosing a TR1 Tuple +Library". + +### Upgrading from 1.4.0 or Earlier ### + +The Autotools build script (configure + make) is no longer officially +supportted. You are encouraged to migrate to your own build system or +use CMake. If you still need to use Autotools, you can find +instructions in the README file from Google Test 1.4.0. + +On platforms where the pthread library is available, Google Test uses +it in order to be thread-safe. See the "Multi-threaded Tests" section +for what this means to your build script. + +If you use Microsoft Visual C++ 7.1 with exceptions disabled, Google +Test will no longer compile. This should affect very few people, as a +large portion of STL (including ) doesn't compile in this mode +anyway. We decided to stop supporting it in order to greatly simplify +Google Test's implementation. + +Developing Google Test +---------------------- + +This section discusses how to make your own changes to Google Test. + +### Testing Google Test Itself ### + +To make sure your changes work as intended and don't break existing +functionality, you'll want to compile and run Google Test's own tests. +For that you can use CMake: + + mkdir mybuild + cd mybuild + cmake -Dgtest_build_tests=ON ${GTEST_DIR} + +Make sure you have Python installed, as some of Google Test's tests +are written in Python. If the cmake command complains about not being +able to find Python ("Could NOT find PythonInterp (missing: +PYTHON_EXECUTABLE)"), try telling it explicitly where your Python +executable can be found: + + cmake -DPYTHON_EXECUTABLE=path/to/python -Dgtest_build_tests=ON ${GTEST_DIR} + +Next, you can build Google Test and all of its own tests. On *nix, +this is usually done by 'make'. To run the tests, do + + make test + +All tests should pass. + +### Regenerating Source Files ### + +Some of Google Test's source files are generated from templates (not +in the C++ sense) using a script. A template file is named FOO.pump, +where FOO is the name of the file it will generate. For example, the +file include/gtest/internal/gtest-type-util.h.pump is used to generate +gtest-type-util.h in the same directory. + +Normally you don't need to worry about regenerating the source files, +unless you need to modify them. In that case, you should modify the +corresponding .pump files instead and run the pump.py Python script to +regenerate them. You can find pump.py in the scripts/ directory. +Read the Pump manual [2] for how to use it. + + [2] http://code.google.com/p/googletest/wiki/PumpManual + +### Contributing a Patch ### + +We welcome patches. Please read the Google Test developer's guide [3] +for how you can contribute. In particular, make sure you have signed +the Contributor License Agreement, or we won't be able to accept the +patch. + + [3] http://code.google.com/p/googletest/wiki/GoogleTestDevGuide + +Happy testing! diff --git a/Engine/lib/gtest/fused-src/gtest/gtest-all.cc b/Engine/lib/gtest/fused-src/gtest/gtest-all.cc new file mode 100644 index 000000000..a9a03b2e3 --- /dev/null +++ b/Engine/lib/gtest/fused-src/gtest/gtest-all.cc @@ -0,0 +1,9592 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: mheule@google.com (Markus Heule) +// +// Google C++ Testing Framework (Google Test) +// +// Sometimes it's desirable to build Google Test by compiling a single file. +// This file serves this purpose. + +// This line ensures that gtest.h can be compiled on its own, even +// when it's fused. +#include "gtest/gtest.h" + +// The following lines pull in the real gtest *.cc files. +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// The Google C++ Testing Framework (Google Test) + +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// Utilities for testing Google Test itself and code that uses Google Test +// (e.g. frameworks built on top of Google Test). + +#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ +#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ + + +namespace testing { + +// This helper class can be used to mock out Google Test failure reporting +// so that we can test Google Test or code that builds on Google Test. +// +// An object of this class appends a TestPartResult object to the +// TestPartResultArray object given in the constructor whenever a Google Test +// failure is reported. It can either intercept only failures that are +// generated in the same thread that created this object or it can intercept +// all generated failures. The scope of this mock object can be controlled with +// the second argument to the two arguments constructor. +class GTEST_API_ ScopedFakeTestPartResultReporter + : public TestPartResultReporterInterface { + public: + // The two possible mocking modes of this object. + enum InterceptMode { + INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures. + INTERCEPT_ALL_THREADS // Intercepts all failures. + }; + + // The c'tor sets this object as the test part result reporter used + // by Google Test. The 'result' parameter specifies where to report the + // results. This reporter will only catch failures generated in the current + // thread. DEPRECATED + explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result); + + // Same as above, but you can choose the interception scope of this object. + ScopedFakeTestPartResultReporter(InterceptMode intercept_mode, + TestPartResultArray* result); + + // The d'tor restores the previous test part result reporter. + virtual ~ScopedFakeTestPartResultReporter(); + + // Appends the TestPartResult object to the TestPartResultArray + // received in the constructor. + // + // This method is from the TestPartResultReporterInterface + // interface. + virtual void ReportTestPartResult(const TestPartResult& result); + private: + void Init(); + + const InterceptMode intercept_mode_; + TestPartResultReporterInterface* old_reporter_; + TestPartResultArray* const result_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter); +}; + +namespace internal { + +// A helper class for implementing EXPECT_FATAL_FAILURE() and +// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given +// TestPartResultArray contains exactly one failure that has the given +// type and contains the given substring. If that's not the case, a +// non-fatal failure will be generated. +class GTEST_API_ SingleFailureChecker { + public: + // The constructor remembers the arguments. + SingleFailureChecker(const TestPartResultArray* results, + TestPartResult::Type type, + const string& substr); + ~SingleFailureChecker(); + private: + const TestPartResultArray* const results_; + const TestPartResult::Type type_; + const string substr_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker); +}; + +} // namespace internal + +} // namespace testing + +// A set of macros for testing Google Test assertions or code that's expected +// to generate Google Test fatal failures. It verifies that the given +// statement will cause exactly one fatal Google Test failure with 'substr' +// being part of the failure message. +// +// There are two different versions of this macro. EXPECT_FATAL_FAILURE only +// affects and considers failures generated in the current thread and +// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. +// +// The verification of the assertion is done correctly even when the statement +// throws an exception or aborts the current function. +// +// Known restrictions: +// - 'statement' cannot reference local non-static variables or +// non-static members of the current object. +// - 'statement' cannot return a value. +// - You cannot stream a failure message to this macro. +// +// Note that even though the implementations of the following two +// macros are much alike, we cannot refactor them to use a common +// helper macro, due to some peculiarity in how the preprocessor +// works. The AcceptsMacroThatExpandsToUnprotectedComma test in +// gtest_unittest.cc will fail to compile if we do that. +#define EXPECT_FATAL_FAILURE(statement, substr) \ + do { \ + class GTestExpectFatalFailureHelper {\ + public:\ + static void Execute() { statement; }\ + };\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ + GTestExpectFatalFailureHelper::Execute();\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ + do { \ + class GTestExpectFatalFailureHelper {\ + public:\ + static void Execute() { statement; }\ + };\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ALL_THREADS, >est_failures);\ + GTestExpectFatalFailureHelper::Execute();\ + }\ + } while (::testing::internal::AlwaysFalse()) + +// A macro for testing Google Test assertions or code that's expected to +// generate Google Test non-fatal failures. It asserts that the given +// statement will cause exactly one non-fatal Google Test failure with 'substr' +// being part of the failure message. +// +// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only +// affects and considers failures generated in the current thread and +// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. +// +// 'statement' is allowed to reference local variables and members of +// the current object. +// +// The verification of the assertion is done correctly even when the statement +// throws an exception or aborts the current function. +// +// Known restrictions: +// - You cannot stream a failure message to this macro. +// +// Note that even though the implementations of the following two +// macros are much alike, we cannot refactor them to use a common +// helper macro, due to some peculiarity in how the preprocessor +// works. If we do that, the code won't compile when the user gives +// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that +// expands to code containing an unprotected comma. The +// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc +// catches that. +// +// For the same reason, we have to write +// if (::testing::internal::AlwaysTrue()) { statement; } +// instead of +// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) +// to avoid an MSVC warning on unreachable code. +#define EXPECT_NONFATAL_FAILURE(statement, substr) \ + do {\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ + if (::testing::internal::AlwaysTrue()) { statement; }\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ + do {\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \ + >est_failures);\ + if (::testing::internal::AlwaysTrue()) { statement; }\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include // NOLINT +#include +#include + +#if GTEST_OS_LINUX + +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +# define GTEST_HAS_GETTIMEOFDAY_ 1 + +# include // NOLINT +# include // NOLINT +# include // NOLINT +// Declares vsnprintf(). This header is not available on Windows. +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include + +#elif GTEST_OS_SYMBIAN +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT + +#elif GTEST_OS_ZOS +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT + +// On z/OS we additionally need strings.h for strcasecmp. +# include // NOLINT + +#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE. + +# include // NOLINT + +#elif GTEST_OS_WINDOWS // We are on Windows proper. + +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include // NOLINT + +# if GTEST_OS_WINDOWS_MINGW +// MinGW has gettimeofday() but not _ftime64(). +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +// TODO(kenton@google.com): There are other ways to get the time on +// Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW +// supports these. consider using them instead. +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT +# endif // GTEST_OS_WINDOWS_MINGW + +// cpplint thinks that the header is already included, so we want to +// silence it. +# include // NOLINT + +#else + +// Assume other platforms have gettimeofday(). +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +# define GTEST_HAS_GETTIMEOFDAY_ 1 + +// cpplint thinks that the header is already included, so we want to +// silence it. +# include // NOLINT +# include // NOLINT + +#endif // GTEST_OS_LINUX + +#if GTEST_HAS_EXCEPTIONS +# include +#endif + +#if GTEST_CAN_STREAM_RESULTS_ +# include // NOLINT +# include // NOLINT +#endif + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Utility functions and classes used by the Google C++ testing framework. +// +// Author: wan@google.com (Zhanyong Wan) +// +// This file contains purely Google Test's internal implementation. Please +// DO NOT #INCLUDE IT IN A USER PROGRAM. + +#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_ +#define GTEST_SRC_GTEST_INTERNAL_INL_H_ + +// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is +// part of Google Test's implementation; otherwise it's undefined. +#if !GTEST_IMPLEMENTATION_ +// A user is trying to include this from his code - just say no. +# error "gtest-internal-inl.h is part of Google Test's internal implementation." +# error "It must not be included except by Google Test itself." +#endif // GTEST_IMPLEMENTATION_ + +#ifndef _WIN32_WCE +# include +#endif // !_WIN32_WCE +#include +#include // For strtoll/_strtoul64/malloc/free. +#include // For memmove. + +#include +#include +#include + + +#if GTEST_CAN_STREAM_RESULTS_ +# include // NOLINT +# include // NOLINT +#endif + +#if GTEST_OS_WINDOWS +# include // NOLINT +#endif // GTEST_OS_WINDOWS + + +namespace testing { + +// Declares the flags. +// +// We don't want the users to modify this flag in the code, but want +// Google Test's own unit tests to be able to access it. Therefore we +// declare it here as opposed to in gtest.h. +GTEST_DECLARE_bool_(death_test_use_fork); + +namespace internal { + +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest; + +// Names of the flags (needed for parsing Google Test flags). +const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests"; +const char kBreakOnFailureFlag[] = "break_on_failure"; +const char kCatchExceptionsFlag[] = "catch_exceptions"; +const char kColorFlag[] = "color"; +const char kFilterFlag[] = "filter"; +const char kListTestsFlag[] = "list_tests"; +const char kOutputFlag[] = "output"; +const char kPrintTimeFlag[] = "print_time"; +const char kRandomSeedFlag[] = "random_seed"; +const char kRepeatFlag[] = "repeat"; +const char kShuffleFlag[] = "shuffle"; +const char kStackTraceDepthFlag[] = "stack_trace_depth"; +const char kStreamResultToFlag[] = "stream_result_to"; +const char kThrowOnFailureFlag[] = "throw_on_failure"; + +// A valid random seed must be in [1, kMaxRandomSeed]. +const int kMaxRandomSeed = 99999; + +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +GTEST_API_ extern bool g_help_flag; + +// Returns the current time in milliseconds. +GTEST_API_ TimeInMillis GetTimeInMillis(); + +// Returns true iff Google Test should use colors in the output. +GTEST_API_ bool ShouldUseColor(bool stdout_is_tty); + +// Formats the given time in milliseconds as seconds. +GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms); + +// Converts the given time in milliseconds to a date string in the ISO 8601 +// format, without the timezone information. N.B.: due to the use the +// non-reentrant localtime() function, this function is not thread safe. Do +// not use it in any code that can be called from multiple threads. +GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms); + +// Parses a string for an Int32 flag, in the form of "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +GTEST_API_ bool ParseInt32Flag( + const char* str, const char* flag, Int32* value); + +// Returns a random seed in range [1, kMaxRandomSeed] based on the +// given --gtest_random_seed flag value. +inline int GetRandomSeedFromFlag(Int32 random_seed_flag) { + const unsigned int raw_seed = (random_seed_flag == 0) ? + static_cast(GetTimeInMillis()) : + static_cast(random_seed_flag); + + // Normalizes the actual seed to range [1, kMaxRandomSeed] such that + // it's easy to type. + const int normalized_seed = + static_cast((raw_seed - 1U) % + static_cast(kMaxRandomSeed)) + 1; + return normalized_seed; +} + +// Returns the first valid random seed after 'seed'. The behavior is +// undefined if 'seed' is invalid. The seed after kMaxRandomSeed is +// considered to be 1. +inline int GetNextRandomSeed(int seed) { + GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed) + << "Invalid random seed " << seed << " - must be in [1, " + << kMaxRandomSeed << "]."; + const int next_seed = seed + 1; + return (next_seed > kMaxRandomSeed) ? 1 : next_seed; +} + +// This class saves the values of all Google Test flags in its c'tor, and +// restores them in its d'tor. +class GTestFlagSaver { + public: + // The c'tor. + GTestFlagSaver() { + also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests); + break_on_failure_ = GTEST_FLAG(break_on_failure); + catch_exceptions_ = GTEST_FLAG(catch_exceptions); + color_ = GTEST_FLAG(color); + death_test_style_ = GTEST_FLAG(death_test_style); + death_test_use_fork_ = GTEST_FLAG(death_test_use_fork); + filter_ = GTEST_FLAG(filter); + internal_run_death_test_ = GTEST_FLAG(internal_run_death_test); + list_tests_ = GTEST_FLAG(list_tests); + output_ = GTEST_FLAG(output); + print_time_ = GTEST_FLAG(print_time); + random_seed_ = GTEST_FLAG(random_seed); + repeat_ = GTEST_FLAG(repeat); + shuffle_ = GTEST_FLAG(shuffle); + stack_trace_depth_ = GTEST_FLAG(stack_trace_depth); + stream_result_to_ = GTEST_FLAG(stream_result_to); + throw_on_failure_ = GTEST_FLAG(throw_on_failure); + } + + // The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS. + ~GTestFlagSaver() { + GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_; + GTEST_FLAG(break_on_failure) = break_on_failure_; + GTEST_FLAG(catch_exceptions) = catch_exceptions_; + GTEST_FLAG(color) = color_; + GTEST_FLAG(death_test_style) = death_test_style_; + GTEST_FLAG(death_test_use_fork) = death_test_use_fork_; + GTEST_FLAG(filter) = filter_; + GTEST_FLAG(internal_run_death_test) = internal_run_death_test_; + GTEST_FLAG(list_tests) = list_tests_; + GTEST_FLAG(output) = output_; + GTEST_FLAG(print_time) = print_time_; + GTEST_FLAG(random_seed) = random_seed_; + GTEST_FLAG(repeat) = repeat_; + GTEST_FLAG(shuffle) = shuffle_; + GTEST_FLAG(stack_trace_depth) = stack_trace_depth_; + GTEST_FLAG(stream_result_to) = stream_result_to_; + GTEST_FLAG(throw_on_failure) = throw_on_failure_; + } + + private: + // Fields for saving the original values of flags. + bool also_run_disabled_tests_; + bool break_on_failure_; + bool catch_exceptions_; + std::string color_; + std::string death_test_style_; + bool death_test_use_fork_; + std::string filter_; + std::string internal_run_death_test_; + bool list_tests_; + std::string output_; + bool print_time_; + internal::Int32 random_seed_; + internal::Int32 repeat_; + bool shuffle_; + internal::Int32 stack_trace_depth_; + std::string stream_result_to_; + bool throw_on_failure_; +} GTEST_ATTRIBUTE_UNUSED_; + +// Converts a Unicode code point to a narrow string in UTF-8 encoding. +// code_point parameter is of type UInt32 because wchar_t may not be +// wide enough to contain a code point. +// If the code_point is not a valid Unicode code point +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted +// to "(Invalid Unicode 0xXXXXXXXX)". +GTEST_API_ std::string CodePointToUtf8(UInt32 code_point); + +// Converts a wide string to a narrow string in UTF-8 encoding. +// The wide string is assumed to have the following encoding: +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-32 if sizeof(wchar_t) == 4 (on Linux) +// Parameter str points to a null-terminated wide string. +// Parameter num_chars may additionally limit the number +// of wchar_t characters processed. -1 is used when the entire string +// should be processed. +// If the string contains code points that are not valid Unicode code points +// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding +// and contains invalid UTF-16 surrogate pairs, values in those pairs +// will be encoded as individual Unicode characters from Basic Normal Plane. +GTEST_API_ std::string WideStringToUtf8(const wchar_t* str, int num_chars); + +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded(); + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (e.g., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +GTEST_API_ bool ShouldShard(const char* total_shards_str, + const char* shard_index_str, + bool in_subprocess_for_death_test); + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error and +// and aborts. +GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val); + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +GTEST_API_ bool ShouldRunTestOnShard( + int total_shards, int shard_index, int test_id); + +// STL container utilities. + +// Returns the number of elements in the given container that satisfy +// the given predicate. +template +inline int CountIf(const Container& c, Predicate predicate) { + // Implemented as an explicit loop since std::count_if() in libCstd on + // Solaris has a non-standard signature. + int count = 0; + for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) { + if (predicate(*it)) + ++count; + } + return count; +} + +// Applies a function/functor to each element in the container. +template +void ForEach(const Container& c, Functor functor) { + std::for_each(c.begin(), c.end(), functor); +} + +// Returns the i-th element of the vector, or default_value if i is not +// in range [0, v.size()). +template +inline E GetElementOr(const std::vector& v, int i, E default_value) { + return (i < 0 || i >= static_cast(v.size())) ? default_value : v[i]; +} + +// Performs an in-place shuffle of a range of the vector's elements. +// 'begin' and 'end' are element indices as an STL-style range; +// i.e. [begin, end) are shuffled, where 'end' == size() means to +// shuffle to the end of the vector. +template +void ShuffleRange(internal::Random* random, int begin, int end, + std::vector* v) { + const int size = static_cast(v->size()); + GTEST_CHECK_(0 <= begin && begin <= size) + << "Invalid shuffle range start " << begin << ": must be in range [0, " + << size << "]."; + GTEST_CHECK_(begin <= end && end <= size) + << "Invalid shuffle range finish " << end << ": must be in range [" + << begin << ", " << size << "]."; + + // Fisher-Yates shuffle, from + // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle + for (int range_width = end - begin; range_width >= 2; range_width--) { + const int last_in_range = begin + range_width - 1; + const int selected = begin + random->Generate(range_width); + std::swap((*v)[selected], (*v)[last_in_range]); + } +} + +// Performs an in-place shuffle of the vector's elements. +template +inline void Shuffle(internal::Random* random, std::vector* v) { + ShuffleRange(random, 0, static_cast(v->size()), v); +} + +// A function for deleting an object. Handy for being used as a +// functor. +template +static void Delete(T* x) { + delete x; +} + +// A predicate that checks the key of a TestProperty against a known key. +// +// TestPropertyKeyIs is copyable. +class TestPropertyKeyIs { + public: + // Constructor. + // + // TestPropertyKeyIs has NO default constructor. + explicit TestPropertyKeyIs(const std::string& key) : key_(key) {} + + // Returns true iff the test name of test property matches on key_. + bool operator()(const TestProperty& test_property) const { + return test_property.key() == key_; + } + + private: + std::string key_; +}; + +// Class UnitTestOptions. +// +// This class contains functions for processing options the user +// specifies when running the tests. It has only static members. +// +// In most cases, the user can specify an option using either an +// environment variable or a command line flag. E.g. you can set the +// test filter using either GTEST_FILTER or --gtest_filter. If both +// the variable and the flag are present, the latter overrides the +// former. +class GTEST_API_ UnitTestOptions { + public: + // Functions for processing the gtest_output flag. + + // Returns the output format, or "" for normal printed output. + static std::string GetOutputFormat(); + + // Returns the absolute path of the requested output file, or the + // default (test_detail.xml in the original working directory) if + // none was explicitly specified. + static std::string GetAbsolutePathToOutputFile(); + + // Functions for processing the gtest_filter flag. + + // Returns true iff the wildcard pattern matches the string. The + // first ':' or '\0' character in pattern marks the end of it. + // + // This recursive algorithm isn't very efficient, but is clear and + // works well enough for matching test names, which are short. + static bool PatternMatchesString(const char *pattern, const char *str); + + // Returns true iff the user-specified filter matches the test case + // name and the test name. + static bool FilterMatchesTest(const std::string &test_case_name, + const std::string &test_name); + +#if GTEST_OS_WINDOWS + // Function for supporting the gtest_catch_exception flag. + + // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the + // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. + // This function is useful as an __except condition. + static int GTestShouldProcessSEH(DWORD exception_code); +#endif // GTEST_OS_WINDOWS + + // Returns true if "name" matches the ':' separated list of glob-style + // filters in "filter". + static bool MatchesFilter(const std::string& name, const char* filter); +}; + +// Returns the current application's name, removing directory path if that +// is present. Used by UnitTestOptions::GetOutputFile. +GTEST_API_ FilePath GetCurrentExecutableName(); + +// The role interface for getting the OS stack trace as a string. +class OsStackTraceGetterInterface { + public: + OsStackTraceGetterInterface() {} + virtual ~OsStackTraceGetterInterface() {} + + // Returns the current OS stack trace as an std::string. Parameters: + // + // max_depth - the maximum number of stack frames to be included + // in the trace. + // skip_count - the number of top frames to be skipped; doesn't count + // against max_depth. + virtual string CurrentStackTrace(int max_depth, int skip_count) = 0; + + // UponLeavingGTest() should be called immediately before Google Test calls + // user code. It saves some information about the current stack that + // CurrentStackTrace() will use to find and hide Google Test stack frames. + virtual void UponLeavingGTest() = 0; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface); +}; + +// A working implementation of the OsStackTraceGetterInterface interface. +class OsStackTraceGetter : public OsStackTraceGetterInterface { + public: + OsStackTraceGetter() : caller_frame_(NULL) {} + + virtual string CurrentStackTrace(int max_depth, int skip_count) + GTEST_LOCK_EXCLUDED_(mutex_); + + virtual void UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_); + + // This string is inserted in place of stack frames that are part of + // Google Test's implementation. + static const char* const kElidedFramesMarker; + + private: + Mutex mutex_; // protects all internal state + + // We save the stack frame below the frame that calls user code. + // We do this because the address of the frame immediately below + // the user code changes between the call to UponLeavingGTest() + // and any calls to CurrentStackTrace() from within the user code. + void* caller_frame_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter); +}; + +// Information about a Google Test trace point. +struct TraceInfo { + const char* file; + int line; + std::string message; +}; + +// This is the default global test part result reporter used in UnitTestImpl. +// This class should only be used by UnitTestImpl. +class DefaultGlobalTestPartResultReporter + : public TestPartResultReporterInterface { + public: + explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test); + // Implements the TestPartResultReporterInterface. Reports the test part + // result in the current test. + virtual void ReportTestPartResult(const TestPartResult& result); + + private: + UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter); +}; + +// This is the default per thread test part result reporter used in +// UnitTestImpl. This class should only be used by UnitTestImpl. +class DefaultPerThreadTestPartResultReporter + : public TestPartResultReporterInterface { + public: + explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test); + // Implements the TestPartResultReporterInterface. The implementation just + // delegates to the current global test part result reporter of *unit_test_. + virtual void ReportTestPartResult(const TestPartResult& result); + + private: + UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter); +}; + +// The private implementation of the UnitTest class. We don't protect +// the methods under a mutex, as this class is not accessible by a +// user and the UnitTest class that delegates work to this class does +// proper locking. +class GTEST_API_ UnitTestImpl { + public: + explicit UnitTestImpl(UnitTest* parent); + virtual ~UnitTestImpl(); + + // There are two different ways to register your own TestPartResultReporter. + // You can register your own repoter to listen either only for test results + // from the current thread or for results from all threads. + // By default, each per-thread test result repoter just passes a new + // TestPartResult to the global test result reporter, which registers the + // test part result for the currently running test. + + // Returns the global test part result reporter. + TestPartResultReporterInterface* GetGlobalTestPartResultReporter(); + + // Sets the global test part result reporter. + void SetGlobalTestPartResultReporter( + TestPartResultReporterInterface* reporter); + + // Returns the test part result reporter for the current thread. + TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread(); + + // Sets the test part result reporter for the current thread. + void SetTestPartResultReporterForCurrentThread( + TestPartResultReporterInterface* reporter); + + // Gets the number of successful test cases. + int successful_test_case_count() const; + + // Gets the number of failed test cases. + int failed_test_case_count() const; + + // Gets the number of all test cases. + int total_test_case_count() const; + + // Gets the number of all test cases that contain at least one test + // that should run. + int test_case_to_run_count() const; + + // Gets the number of successful tests. + int successful_test_count() const; + + // Gets the number of failed tests. + int failed_test_count() const; + + // Gets the number of disabled tests that will be reported in the XML report. + int reportable_disabled_test_count() const; + + // Gets the number of disabled tests. + int disabled_test_count() const; + + // Gets the number of tests to be printed in the XML report. + int reportable_test_count() const; + + // Gets the number of all tests. + int total_test_count() const; + + // Gets the number of tests that should run. + int test_to_run_count() const; + + // Gets the time of the test program start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp() const { return start_timestamp_; } + + // Gets the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns true iff the unit test passed (i.e. all test cases passed). + bool Passed() const { return !Failed(); } + + // Returns true iff the unit test failed (i.e. some test case failed + // or something outside of all tests failed). + bool Failed() const { + return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed(); + } + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[i]; + } + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i) { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[index]; + } + + // Provides access to the event listener list. + TestEventListeners* listeners() { return &listeners_; } + + // Returns the TestResult for the test that's currently running, or + // the TestResult for the ad hoc test if no test is running. + TestResult* current_test_result(); + + // Returns the TestResult for the ad hoc test. + const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; } + + // Sets the OS stack trace getter. + // + // Does nothing if the input and the current OS stack trace getter + // are the same; otherwise, deletes the old getter and makes the + // input the current getter. + void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter); + + // Returns the current OS stack trace getter if it is not NULL; + // otherwise, creates an OsStackTraceGetter, makes it the current + // getter, and returns it. + OsStackTraceGetterInterface* os_stack_trace_getter(); + + // Returns the current OS stack trace as an std::string. + // + // The maximum number of stack frames to be included is specified by + // the gtest_stack_trace_depth flag. The skip_count parameter + // specifies the number of top frames to be skipped, which doesn't + // count against the number of frames to be included. + // + // For example, if Foo() calls Bar(), which in turn calls + // CurrentOsStackTraceExceptTop(1), Foo() will be included in the + // trace but Bar() and CurrentOsStackTraceExceptTop() won't. + std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_; + + // Finds and returns a TestCase with the given name. If one doesn't + // exist, creates one and returns it. + // + // Arguments: + // + // test_case_name: name of the test case + // type_param: the name of the test's type parameter, or NULL if + // this is not a typed or a type-parameterized test. + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + TestCase* GetTestCase(const char* test_case_name, + const char* type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc); + + // Adds a TestInfo to the unit test. + // + // Arguments: + // + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + // test_info: the TestInfo object + void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc, + TestInfo* test_info) { + // In order to support thread-safe death tests, we need to + // remember the original working directory when the test program + // was first invoked. We cannot do this in RUN_ALL_TESTS(), as + // the user may have changed the current directory before calling + // RUN_ALL_TESTS(). Therefore we capture the current directory in + // AddTestInfo(), which is called to register a TEST or TEST_F + // before main() is reached. + if (original_working_dir_.IsEmpty()) { + original_working_dir_.Set(FilePath::GetCurrentDir()); + GTEST_CHECK_(!original_working_dir_.IsEmpty()) + << "Failed to get the current working directory."; + } + + GetTestCase(test_info->test_case_name(), + test_info->type_param(), + set_up_tc, + tear_down_tc)->AddTestInfo(test_info); + } + +#if GTEST_HAS_PARAM_TEST + // Returns ParameterizedTestCaseRegistry object used to keep track of + // value-parameterized tests and instantiate and register them. + internal::ParameterizedTestCaseRegistry& parameterized_test_registry() { + return parameterized_test_registry_; + } +#endif // GTEST_HAS_PARAM_TEST + + // Sets the TestCase object for the test that's currently running. + void set_current_test_case(TestCase* a_current_test_case) { + current_test_case_ = a_current_test_case; + } + + // Sets the TestInfo object for the test that's currently running. If + // current_test_info is NULL, the assertion results will be stored in + // ad_hoc_test_result_. + void set_current_test_info(TestInfo* a_current_test_info) { + current_test_info_ = a_current_test_info; + } + + // Registers all parameterized tests defined using TEST_P and + // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter + // combination. This method can be called more then once; it has guards + // protecting from registering the tests more then once. If + // value-parameterized tests are disabled, RegisterParameterizedTests is + // present but does nothing. + void RegisterParameterizedTests(); + + // Runs all tests in this UnitTest object, prints the result, and + // returns true if all tests are successful. If any exception is + // thrown during a test, this test is considered to be failed, but + // the rest of the tests will still be run. + bool RunAllTests(); + + // Clears the results of all tests, except the ad hoc tests. + void ClearNonAdHocTestResult() { + ForEach(test_cases_, TestCase::ClearTestCaseResult); + } + + // Clears the results of ad-hoc test assertions. + void ClearAdHocTestResult() { + ad_hoc_test_result_.Clear(); + } + + // Adds a TestProperty to the current TestResult object when invoked in a + // context of a test or a test case, or to the global property set. If the + // result already contains a property with the same key, the value will be + // updated. + void RecordProperty(const TestProperty& test_property); + + enum ReactionToSharding { + HONOR_SHARDING_PROTOCOL, + IGNORE_SHARDING_PROTOCOL + }; + + // Matches the full name of each test against the user-specified + // filter to decide whether the test should run, then records the + // result in each TestCase and TestInfo object. + // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests + // based on sharding variables in the environment. + // Returns the number of tests that should run. + int FilterTests(ReactionToSharding shard_tests); + + // Prints the names of the tests matching the user-specified filter flag. + void ListTestsMatchingFilter(); + + const TestCase* current_test_case() const { return current_test_case_; } + TestInfo* current_test_info() { return current_test_info_; } + const TestInfo* current_test_info() const { return current_test_info_; } + + // Returns the vector of environments that need to be set-up/torn-down + // before/after the tests are run. + std::vector& environments() { return environments_; } + + // Getters for the per-thread Google Test trace stack. + std::vector& gtest_trace_stack() { + return *(gtest_trace_stack_.pointer()); + } + const std::vector& gtest_trace_stack() const { + return gtest_trace_stack_.get(); + } + +#if GTEST_HAS_DEATH_TEST + void InitDeathTestSubprocessControlInfo() { + internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag()); + } + // Returns a pointer to the parsed --gtest_internal_run_death_test + // flag, or NULL if that flag was not specified. + // This information is useful only in a death test child process. + // Must not be called before a call to InitGoogleTest. + const InternalRunDeathTestFlag* internal_run_death_test_flag() const { + return internal_run_death_test_flag_.get(); + } + + // Returns a pointer to the current death test factory. + internal::DeathTestFactory* death_test_factory() { + return death_test_factory_.get(); + } + + void SuppressTestEventsIfInSubprocess(); + + friend class ReplaceDeathTestFactory; +#endif // GTEST_HAS_DEATH_TEST + + // Initializes the event listener performing XML output as specified by + // UnitTestOptions. Must not be called before InitGoogleTest. + void ConfigureXmlOutput(); + +#if GTEST_CAN_STREAM_RESULTS_ + // Initializes the event listener for streaming test results to a socket. + // Must not be called before InitGoogleTest. + void ConfigureStreamingOutput(); +#endif + + // Performs initialization dependent upon flag values obtained in + // ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to + // ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest + // this function is also called from RunAllTests. Since this function can be + // called more than once, it has to be idempotent. + void PostFlagParsingInit(); + + // Gets the random seed used at the start of the current test iteration. + int random_seed() const { return random_seed_; } + + // Gets the random number generator. + internal::Random* random() { return &random_; } + + // Shuffles all test cases, and the tests within each test case, + // making sure that death tests are still run first. + void ShuffleTests(); + + // Restores the test cases and tests to their order before the first shuffle. + void UnshuffleTests(); + + // Returns the value of GTEST_FLAG(catch_exceptions) at the moment + // UnitTest::Run() starts. + bool catch_exceptions() const { return catch_exceptions_; } + + private: + friend class ::testing::UnitTest; + + // Used by UnitTest::Run() to capture the state of + // GTEST_FLAG(catch_exceptions) at the moment it starts. + void set_catch_exceptions(bool value) { catch_exceptions_ = value; } + + // The UnitTest object that owns this implementation object. + UnitTest* const parent_; + + // The working directory when the first TEST() or TEST_F() was + // executed. + internal::FilePath original_working_dir_; + + // The default test part result reporters. + DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_; + DefaultPerThreadTestPartResultReporter + default_per_thread_test_part_result_reporter_; + + // Points to (but doesn't own) the global test part result reporter. + TestPartResultReporterInterface* global_test_part_result_repoter_; + + // Protects read and write access to global_test_part_result_reporter_. + internal::Mutex global_test_part_result_reporter_mutex_; + + // Points to (but doesn't own) the per-thread test part result reporter. + internal::ThreadLocal + per_thread_test_part_result_reporter_; + + // The vector of environments that need to be set-up/torn-down + // before/after the tests are run. + std::vector environments_; + + // The vector of TestCases in their original order. It owns the + // elements in the vector. + std::vector test_cases_; + + // Provides a level of indirection for the test case list to allow + // easy shuffling and restoring the test case order. The i-th + // element of this vector is the index of the i-th test case in the + // shuffled order. + std::vector test_case_indices_; + +#if GTEST_HAS_PARAM_TEST + // ParameterizedTestRegistry object used to register value-parameterized + // tests. + internal::ParameterizedTestCaseRegistry parameterized_test_registry_; + + // Indicates whether RegisterParameterizedTests() has been called already. + bool parameterized_tests_registered_; +#endif // GTEST_HAS_PARAM_TEST + + // Index of the last death test case registered. Initially -1. + int last_death_test_case_; + + // This points to the TestCase for the currently running test. It + // changes as Google Test goes through one test case after another. + // When no test is running, this is set to NULL and Google Test + // stores assertion results in ad_hoc_test_result_. Initially NULL. + TestCase* current_test_case_; + + // This points to the TestInfo for the currently running test. It + // changes as Google Test goes through one test after another. When + // no test is running, this is set to NULL and Google Test stores + // assertion results in ad_hoc_test_result_. Initially NULL. + TestInfo* current_test_info_; + + // Normally, a user only writes assertions inside a TEST or TEST_F, + // or inside a function called by a TEST or TEST_F. Since Google + // Test keeps track of which test is current running, it can + // associate such an assertion with the test it belongs to. + // + // If an assertion is encountered when no TEST or TEST_F is running, + // Google Test attributes the assertion result to an imaginary "ad hoc" + // test, and records the result in ad_hoc_test_result_. + TestResult ad_hoc_test_result_; + + // The list of event listeners that can be used to track events inside + // Google Test. + TestEventListeners listeners_; + + // The OS stack trace getter. Will be deleted when the UnitTest + // object is destructed. By default, an OsStackTraceGetter is used, + // but the user can set this field to use a custom getter if that is + // desired. + OsStackTraceGetterInterface* os_stack_trace_getter_; + + // True iff PostFlagParsingInit() has been called. + bool post_flag_parse_init_performed_; + + // The random number seed used at the beginning of the test run. + int random_seed_; + + // Our random number generator. + internal::Random random_; + + // The time of the test program start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp_; + + // How long the test took to run, in milliseconds. + TimeInMillis elapsed_time_; + +#if GTEST_HAS_DEATH_TEST + // The decomposed components of the gtest_internal_run_death_test flag, + // parsed when RUN_ALL_TESTS is called. + internal::scoped_ptr internal_run_death_test_flag_; + internal::scoped_ptr death_test_factory_; +#endif // GTEST_HAS_DEATH_TEST + + // A per-thread stack of traces created by the SCOPED_TRACE() macro. + internal::ThreadLocal > gtest_trace_stack_; + + // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests() + // starts. + bool catch_exceptions_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl); +}; // class UnitTestImpl + +// Convenience function for accessing the global UnitTest +// implementation object. +inline UnitTestImpl* GetUnitTestImpl() { + return UnitTest::GetInstance()->impl(); +} + +#if GTEST_USES_SIMPLE_RE + +// Internal helper functions for implementing the simple regular +// expression matcher. +GTEST_API_ bool IsInSet(char ch, const char* str); +GTEST_API_ bool IsAsciiDigit(char ch); +GTEST_API_ bool IsAsciiPunct(char ch); +GTEST_API_ bool IsRepeat(char ch); +GTEST_API_ bool IsAsciiWhiteSpace(char ch); +GTEST_API_ bool IsAsciiWordChar(char ch); +GTEST_API_ bool IsValidEscape(char ch); +GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch); +GTEST_API_ bool ValidateRegex(const char* regex); +GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str); +GTEST_API_ bool MatchRepetitionAndRegexAtHead( + bool escaped, char ch, char repeat, const char* regex, const char* str); +GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str); + +#endif // GTEST_USES_SIMPLE_RE + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv); +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv); + +#if GTEST_HAS_DEATH_TEST + +// Returns the message describing the last system error, regardless of the +// platform. +GTEST_API_ std::string GetLastErrnoDescription(); + +# if GTEST_OS_WINDOWS +// Provides leak-safe Windows kernel handle ownership. +class AutoHandle { + public: + AutoHandle() : handle_(INVALID_HANDLE_VALUE) {} + explicit AutoHandle(HANDLE handle) : handle_(handle) {} + + ~AutoHandle() { Reset(); } + + HANDLE Get() const { return handle_; } + void Reset() { Reset(INVALID_HANDLE_VALUE); } + void Reset(HANDLE handle) { + if (handle != handle_) { + if (handle_ != INVALID_HANDLE_VALUE) + ::CloseHandle(handle_); + handle_ = handle; + } + } + + private: + HANDLE handle_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle); +}; +# endif // GTEST_OS_WINDOWS + +// Attempts to parse a string into a positive integer pointed to by the +// number parameter. Returns true if that is possible. +// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use +// it here. +template +bool ParseNaturalNumber(const ::std::string& str, Integer* number) { + // Fail fast if the given string does not begin with a digit; + // this bypasses strtoXXX's "optional leading whitespace and plus + // or minus sign" semantics, which are undesirable here. + if (str.empty() || !IsDigit(str[0])) { + return false; + } + errno = 0; + + char* end; + // BiggestConvertible is the largest integer type that system-provided + // string-to-number conversion routines can return. + +# if GTEST_OS_WINDOWS && !defined(__GNUC__) + + // MSVC and C++ Builder define __int64 instead of the standard long long. + typedef unsigned __int64 BiggestConvertible; + const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10); + +# else + + typedef unsigned long long BiggestConvertible; // NOLINT + const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10); + +# endif // GTEST_OS_WINDOWS && !defined(__GNUC__) + + const bool parse_success = *end == '\0' && errno == 0; + + // TODO(vladl@google.com): Convert this to compile time assertion when it is + // available. + GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed)); + + const Integer result = static_cast(parsed); + if (parse_success && static_cast(result) == parsed) { + *number = result; + return true; + } + return false; +} +#endif // GTEST_HAS_DEATH_TEST + +// TestResult contains some private methods that should be hidden from +// Google Test user but are required for testing. This class allow our tests +// to access them. +// +// This class is supplied only for the purpose of testing Google Test's own +// constructs. Do not use it in user tests, either directly or indirectly. +class TestResultAccessor { + public: + static void RecordProperty(TestResult* test_result, + const std::string& xml_element, + const TestProperty& property) { + test_result->RecordProperty(xml_element, property); + } + + static void ClearTestPartResults(TestResult* test_result) { + test_result->ClearTestPartResults(); + } + + static const std::vector& test_part_results( + const TestResult& test_result) { + return test_result.test_part_results(); + } +}; + +#if GTEST_CAN_STREAM_RESULTS_ + +// Streams test results to the given port on the given host machine. +class StreamingListener : public EmptyTestEventListener { + public: + // Abstract base class for writing strings to a socket. + class AbstractSocketWriter { + public: + virtual ~AbstractSocketWriter() {} + + // Sends a string to the socket. + virtual void Send(const string& message) = 0; + + // Closes the socket. + virtual void CloseConnection() {} + + // Sends a string and a newline to the socket. + void SendLn(const string& message) { + Send(message + "\n"); + } + }; + + // Concrete class for actually writing strings to a socket. + class SocketWriter : public AbstractSocketWriter { + public: + SocketWriter(const string& host, const string& port) + : sockfd_(-1), host_name_(host), port_num_(port) { + MakeConnection(); + } + + virtual ~SocketWriter() { + if (sockfd_ != -1) + CloseConnection(); + } + + // Sends a string to the socket. + virtual void Send(const string& message) { + GTEST_CHECK_(sockfd_ != -1) + << "Send() can be called only when there is a connection."; + + const int len = static_cast(message.length()); + if (write(sockfd_, message.c_str(), len) != len) { + GTEST_LOG_(WARNING) + << "stream_result_to: failed to stream to " + << host_name_ << ":" << port_num_; + } + } + + private: + // Creates a client socket and connects to the server. + void MakeConnection(); + + // Closes the socket. + void CloseConnection() { + GTEST_CHECK_(sockfd_ != -1) + << "CloseConnection() can be called only when there is a connection."; + + close(sockfd_); + sockfd_ = -1; + } + + int sockfd_; // socket file descriptor + const string host_name_; + const string port_num_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter); + }; // class SocketWriter + + // Escapes '=', '&', '%', and '\n' characters in str as "%xx". + static string UrlEncode(const char* str); + + StreamingListener(const string& host, const string& port) + : socket_writer_(new SocketWriter(host, port)) { Start(); } + + explicit StreamingListener(AbstractSocketWriter* socket_writer) + : socket_writer_(socket_writer) { Start(); } + + void OnTestProgramStart(const UnitTest& /* unit_test */) { + SendLn("event=TestProgramStart"); + } + + void OnTestProgramEnd(const UnitTest& unit_test) { + // Note that Google Test current only report elapsed time for each + // test iteration, not for the entire test program. + SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed())); + + // Notify the streaming server to stop. + socket_writer_->CloseConnection(); + } + + void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) { + SendLn("event=TestIterationStart&iteration=" + + StreamableToString(iteration)); + } + + void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) { + SendLn("event=TestIterationEnd&passed=" + + FormatBool(unit_test.Passed()) + "&elapsed_time=" + + StreamableToString(unit_test.elapsed_time()) + "ms"); + } + + void OnTestCaseStart(const TestCase& test_case) { + SendLn(std::string("event=TestCaseStart&name=") + test_case.name()); + } + + void OnTestCaseEnd(const TestCase& test_case) { + SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) + + "&elapsed_time=" + StreamableToString(test_case.elapsed_time()) + + "ms"); + } + + void OnTestStart(const TestInfo& test_info) { + SendLn(std::string("event=TestStart&name=") + test_info.name()); + } + + void OnTestEnd(const TestInfo& test_info) { + SendLn("event=TestEnd&passed=" + + FormatBool((test_info.result())->Passed()) + + "&elapsed_time=" + + StreamableToString((test_info.result())->elapsed_time()) + "ms"); + } + + void OnTestPartResult(const TestPartResult& test_part_result) { + const char* file_name = test_part_result.file_name(); + if (file_name == NULL) + file_name = ""; + SendLn("event=TestPartResult&file=" + UrlEncode(file_name) + + "&line=" + StreamableToString(test_part_result.line_number()) + + "&message=" + UrlEncode(test_part_result.message())); + } + + private: + // Sends the given message and a newline to the socket. + void SendLn(const string& message) { socket_writer_->SendLn(message); } + + // Called at the start of streaming to notify the receiver what + // protocol we are using. + void Start() { SendLn("gtest_streaming_protocol_version=1.0"); } + + string FormatBool(bool value) { return value ? "1" : "0"; } + + const scoped_ptr socket_writer_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener); +}; // class StreamingListener + +#endif // GTEST_CAN_STREAM_RESULTS_ + +} // namespace internal +} // namespace testing + +#endif // GTEST_SRC_GTEST_INTERNAL_INL_H_ +#undef GTEST_IMPLEMENTATION_ + +#if GTEST_OS_WINDOWS +# define vsnprintf _vsnprintf +#endif // GTEST_OS_WINDOWS + +namespace testing { + +using internal::CountIf; +using internal::ForEach; +using internal::GetElementOr; +using internal::Shuffle; + +// Constants. + +// A test whose test case name or test name matches this filter is +// disabled and not run. +static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*"; + +// A test case whose name matches this filter is considered a death +// test case and will be run before test cases whose name doesn't +// match this filter. +static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*"; + +// A test filter that matches everything. +static const char kUniversalFilter[] = "*"; + +// The default output file for XML output. +static const char kDefaultOutputFile[] = "test_detail.xml"; + +// The environment variable name for the test shard index. +static const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; +// The environment variable name for the total number of test shards. +static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; +// The environment variable name for the test shard status file. +static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE"; + +namespace internal { + +// The text used in failure messages to indicate the start of the +// stack trace. +const char kStackTraceMarker[] = "\nStack trace:\n"; + +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +bool g_help_flag = false; + +} // namespace internal + +static const char* GetDefaultFilter() { + return kUniversalFilter; +} + +GTEST_DEFINE_bool_( + also_run_disabled_tests, + internal::BoolFromGTestEnv("also_run_disabled_tests", false), + "Run disabled tests too, in addition to the tests normally being run."); + +GTEST_DEFINE_bool_( + break_on_failure, + internal::BoolFromGTestEnv("break_on_failure", false), + "True iff a failed assertion should be a debugger break-point."); + +GTEST_DEFINE_bool_( + catch_exceptions, + internal::BoolFromGTestEnv("catch_exceptions", true), + "True iff " GTEST_NAME_ + " should catch exceptions and treat them as test failures."); + +GTEST_DEFINE_string_( + color, + internal::StringFromGTestEnv("color", "auto"), + "Whether to use colors in the output. Valid values: yes, no, " + "and auto. 'auto' means to use colors if the output is " + "being sent to a terminal and the TERM environment variable " + "is set to a terminal type that supports colors."); + +GTEST_DEFINE_string_( + filter, + internal::StringFromGTestEnv("filter", GetDefaultFilter()), + "A colon-separated list of glob (not regex) patterns " + "for filtering the tests to run, optionally followed by a " + "'-' and a : separated list of negative patterns (tests to " + "exclude). A test is run if it matches one of the positive " + "patterns and does not match any of the negative patterns."); + +GTEST_DEFINE_bool_(list_tests, false, + "List all tests without running them."); + +GTEST_DEFINE_string_( + output, + internal::StringFromGTestEnv("output", ""), + "A format (currently must be \"xml\"), optionally followed " + "by a colon and an output file name or directory. A directory " + "is indicated by a trailing pathname separator. " + "Examples: \"xml:filename.xml\", \"xml::directoryname/\". " + "If a directory is specified, output files will be created " + "within that directory, with file-names based on the test " + "executable's name and, if necessary, made unique by adding " + "digits."); + +GTEST_DEFINE_bool_( + print_time, + internal::BoolFromGTestEnv("print_time", true), + "True iff " GTEST_NAME_ + " should display elapsed time in text output."); + +GTEST_DEFINE_int32_( + random_seed, + internal::Int32FromGTestEnv("random_seed", 0), + "Random number seed to use when shuffling test orders. Must be in range " + "[1, 99999], or 0 to use a seed based on the current time."); + +GTEST_DEFINE_int32_( + repeat, + internal::Int32FromGTestEnv("repeat", 1), + "How many times to repeat each test. Specify a negative number " + "for repeating forever. Useful for shaking out flaky tests."); + +GTEST_DEFINE_bool_( + show_internal_stack_frames, false, + "True iff " GTEST_NAME_ " should include internal stack frames when " + "printing test failure stack traces."); + +GTEST_DEFINE_bool_( + shuffle, + internal::BoolFromGTestEnv("shuffle", false), + "True iff " GTEST_NAME_ + " should randomize tests' order on every run."); + +GTEST_DEFINE_int32_( + stack_trace_depth, + internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth), + "The maximum number of stack frames to print when an " + "assertion fails. The valid range is 0 through 100, inclusive."); + +GTEST_DEFINE_string_( + stream_result_to, + internal::StringFromGTestEnv("stream_result_to", ""), + "This flag specifies the host name and the port number on which to stream " + "test results. Example: \"localhost:555\". The flag is effective only on " + "Linux."); + +GTEST_DEFINE_bool_( + throw_on_failure, + internal::BoolFromGTestEnv("throw_on_failure", false), + "When this flag is specified, a failed assertion will throw an exception " + "if exceptions are enabled or exit the program with a non-zero code " + "otherwise."); + +namespace internal { + +// Generates a random number from [0, range), using a Linear +// Congruential Generator (LCG). Crashes if 'range' is 0 or greater +// than kMaxRange. +UInt32 Random::Generate(UInt32 range) { + // These constants are the same as are used in glibc's rand(3). + state_ = (1103515245U*state_ + 12345U) % kMaxRange; + + GTEST_CHECK_(range > 0) + << "Cannot generate a number in the range [0, 0)."; + GTEST_CHECK_(range <= kMaxRange) + << "Generation of a number in [0, " << range << ") was requested, " + << "but this can only generate numbers in [0, " << kMaxRange << ")."; + + // Converting via modulus introduces a bit of downward bias, but + // it's simple, and a linear congruential generator isn't too good + // to begin with. + return state_ % range; +} + +// GTestIsInitialized() returns true iff the user has initialized +// Google Test. Useful for catching the user mistake of not initializing +// Google Test before calling RUN_ALL_TESTS(). +// +// A user must call testing::InitGoogleTest() to initialize Google +// Test. g_init_gtest_count is set to the number of times +// InitGoogleTest() has been called. We don't protect this variable +// under a mutex as it is only accessed in the main thread. +GTEST_API_ int g_init_gtest_count = 0; +static bool GTestIsInitialized() { return g_init_gtest_count != 0; } + +// Iterates over a vector of TestCases, keeping a running sum of the +// results of calling a given int-returning method on each. +// Returns the sum. +static int SumOverTestCaseList(const std::vector& case_list, + int (TestCase::*method)() const) { + int sum = 0; + for (size_t i = 0; i < case_list.size(); i++) { + sum += (case_list[i]->*method)(); + } + return sum; +} + +// Returns true iff the test case passed. +static bool TestCasePassed(const TestCase* test_case) { + return test_case->should_run() && test_case->Passed(); +} + +// Returns true iff the test case failed. +static bool TestCaseFailed(const TestCase* test_case) { + return test_case->should_run() && test_case->Failed(); +} + +// Returns true iff test_case contains at least one test that should +// run. +static bool ShouldRunTestCase(const TestCase* test_case) { + return test_case->should_run(); +} + +// AssertHelper constructor. +AssertHelper::AssertHelper(TestPartResult::Type type, + const char* file, + int line, + const char* message) + : data_(new AssertHelperData(type, file, line, message)) { +} + +AssertHelper::~AssertHelper() { + delete data_; +} + +// Message assignment, for assertion streaming support. +void AssertHelper::operator=(const Message& message) const { + UnitTest::GetInstance()-> + AddTestPartResult(data_->type, data_->file, data_->line, + AppendUserMessage(data_->message, message), + UnitTest::GetInstance()->impl() + ->CurrentOsStackTraceExceptTop(1) + // Skips the stack frame for this function itself. + ); // NOLINT +} + +// Mutex for linked pointers. +GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex); + +// Application pathname gotten in InitGoogleTest. +std::string g_executable_path; + +// Returns the current application's name, removing directory path if that +// is present. +FilePath GetCurrentExecutableName() { + FilePath result; + +#if GTEST_OS_WINDOWS + result.Set(FilePath(g_executable_path).RemoveExtension("exe")); +#else + result.Set(FilePath(g_executable_path)); +#endif // GTEST_OS_WINDOWS + + return result.RemoveDirectoryName(); +} + +// Functions for processing the gtest_output flag. + +// Returns the output format, or "" for normal printed output. +std::string UnitTestOptions::GetOutputFormat() { + const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); + if (gtest_output_flag == NULL) return std::string(""); + + const char* const colon = strchr(gtest_output_flag, ':'); + return (colon == NULL) ? + std::string(gtest_output_flag) : + std::string(gtest_output_flag, colon - gtest_output_flag); +} + +// Returns the name of the requested output file, or the default if none +// was explicitly specified. +std::string UnitTestOptions::GetAbsolutePathToOutputFile() { + const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); + if (gtest_output_flag == NULL) + return ""; + + const char* const colon = strchr(gtest_output_flag, ':'); + if (colon == NULL) + return internal::FilePath::ConcatPaths( + internal::FilePath( + UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(kDefaultOutputFile)).string(); + + internal::FilePath output_name(colon + 1); + if (!output_name.IsAbsolutePath()) + // TODO(wan@google.com): on Windows \some\path is not an absolute + // path (as its meaning depends on the current drive), yet the + // following logic for turning it into an absolute path is wrong. + // Fix it. + output_name = internal::FilePath::ConcatPaths( + internal::FilePath(UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(colon + 1)); + + if (!output_name.IsDirectory()) + return output_name.string(); + + internal::FilePath result(internal::FilePath::GenerateUniqueFileName( + output_name, internal::GetCurrentExecutableName(), + GetOutputFormat().c_str())); + return result.string(); +} + +// Returns true iff the wildcard pattern matches the string. The +// first ':' or '\0' character in pattern marks the end of it. +// +// This recursive algorithm isn't very efficient, but is clear and +// works well enough for matching test names, which are short. +bool UnitTestOptions::PatternMatchesString(const char *pattern, + const char *str) { + switch (*pattern) { + case '\0': + case ':': // Either ':' or '\0' marks the end of the pattern. + return *str == '\0'; + case '?': // Matches any single character. + return *str != '\0' && PatternMatchesString(pattern + 1, str + 1); + case '*': // Matches any string (possibly empty) of characters. + return (*str != '\0' && PatternMatchesString(pattern, str + 1)) || + PatternMatchesString(pattern + 1, str); + default: // Non-special character. Matches itself. + return *pattern == *str && + PatternMatchesString(pattern + 1, str + 1); + } +} + +bool UnitTestOptions::MatchesFilter( + const std::string& name, const char* filter) { + const char *cur_pattern = filter; + for (;;) { + if (PatternMatchesString(cur_pattern, name.c_str())) { + return true; + } + + // Finds the next pattern in the filter. + cur_pattern = strchr(cur_pattern, ':'); + + // Returns if no more pattern can be found. + if (cur_pattern == NULL) { + return false; + } + + // Skips the pattern separater (the ':' character). + cur_pattern++; + } +} + +// Returns true iff the user-specified filter matches the test case +// name and the test name. +bool UnitTestOptions::FilterMatchesTest(const std::string &test_case_name, + const std::string &test_name) { + const std::string& full_name = test_case_name + "." + test_name.c_str(); + + // Split --gtest_filter at '-', if there is one, to separate into + // positive filter and negative filter portions + const char* const p = GTEST_FLAG(filter).c_str(); + const char* const dash = strchr(p, '-'); + std::string positive; + std::string negative; + if (dash == NULL) { + positive = GTEST_FLAG(filter).c_str(); // Whole string is a positive filter + negative = ""; + } else { + positive = std::string(p, dash); // Everything up to the dash + negative = std::string(dash + 1); // Everything after the dash + if (positive.empty()) { + // Treat '-test1' as the same as '*-test1' + positive = kUniversalFilter; + } + } + + // A filter is a colon-separated list of patterns. It matches a + // test if any pattern in it matches the test. + return (MatchesFilter(full_name, positive.c_str()) && + !MatchesFilter(full_name, negative.c_str())); +} + +#if GTEST_HAS_SEH +// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the +// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. +// This function is useful as an __except condition. +int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) { + // Google Test should handle a SEH exception if: + // 1. the user wants it to, AND + // 2. this is not a breakpoint exception, AND + // 3. this is not a C++ exception (VC++ implements them via SEH, + // apparently). + // + // SEH exception code for C++ exceptions. + // (see http://support.microsoft.com/kb/185294 for more information). + const DWORD kCxxExceptionCode = 0xe06d7363; + + bool should_handle = true; + + if (!GTEST_FLAG(catch_exceptions)) + should_handle = false; + else if (exception_code == EXCEPTION_BREAKPOINT) + should_handle = false; + else if (exception_code == kCxxExceptionCode) + should_handle = false; + + return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH; +} +#endif // GTEST_HAS_SEH + +} // namespace internal + +// The c'tor sets this object as the test part result reporter used by +// Google Test. The 'result' parameter specifies where to report the +// results. Intercepts only failures from the current thread. +ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( + TestPartResultArray* result) + : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD), + result_(result) { + Init(); +} + +// The c'tor sets this object as the test part result reporter used by +// Google Test. The 'result' parameter specifies where to report the +// results. +ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( + InterceptMode intercept_mode, TestPartResultArray* result) + : intercept_mode_(intercept_mode), + result_(result) { + Init(); +} + +void ScopedFakeTestPartResultReporter::Init() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + if (intercept_mode_ == INTERCEPT_ALL_THREADS) { + old_reporter_ = impl->GetGlobalTestPartResultReporter(); + impl->SetGlobalTestPartResultReporter(this); + } else { + old_reporter_ = impl->GetTestPartResultReporterForCurrentThread(); + impl->SetTestPartResultReporterForCurrentThread(this); + } +} + +// The d'tor restores the test part result reporter used by Google Test +// before. +ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + if (intercept_mode_ == INTERCEPT_ALL_THREADS) { + impl->SetGlobalTestPartResultReporter(old_reporter_); + } else { + impl->SetTestPartResultReporterForCurrentThread(old_reporter_); + } +} + +// Increments the test part result count and remembers the result. +// This method is from the TestPartResultReporterInterface interface. +void ScopedFakeTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + result_->Append(result); +} + +namespace internal { + +// Returns the type ID of ::testing::Test. We should always call this +// instead of GetTypeId< ::testing::Test>() to get the type ID of +// testing::Test. This is to work around a suspected linker bug when +// using Google Test as a framework on Mac OS X. The bug causes +// GetTypeId< ::testing::Test>() to return different values depending +// on whether the call is from the Google Test framework itself or +// from user test code. GetTestTypeId() is guaranteed to always +// return the same value, as it always calls GetTypeId<>() from the +// gtest.cc, which is within the Google Test framework. +TypeId GetTestTypeId() { + return GetTypeId(); +} + +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId(); + +// This predicate-formatter checks that 'results' contains a test part +// failure of the given type and that the failure message contains the +// given substring. +AssertionResult HasOneFailure(const char* /* results_expr */, + const char* /* type_expr */, + const char* /* substr_expr */, + const TestPartResultArray& results, + TestPartResult::Type type, + const string& substr) { + const std::string expected(type == TestPartResult::kFatalFailure ? + "1 fatal failure" : + "1 non-fatal failure"); + Message msg; + if (results.size() != 1) { + msg << "Expected: " << expected << "\n" + << " Actual: " << results.size() << " failures"; + for (int i = 0; i < results.size(); i++) { + msg << "\n" << results.GetTestPartResult(i); + } + return AssertionFailure() << msg; + } + + const TestPartResult& r = results.GetTestPartResult(0); + if (r.type() != type) { + return AssertionFailure() << "Expected: " << expected << "\n" + << " Actual:\n" + << r; + } + + if (strstr(r.message(), substr.c_str()) == NULL) { + return AssertionFailure() << "Expected: " << expected << " containing \"" + << substr << "\"\n" + << " Actual:\n" + << r; + } + + return AssertionSuccess(); +} + +// The constructor of SingleFailureChecker remembers where to look up +// test part results, what type of failure we expect, and what +// substring the failure message should contain. +SingleFailureChecker:: SingleFailureChecker( + const TestPartResultArray* results, + TestPartResult::Type type, + const string& substr) + : results_(results), + type_(type), + substr_(substr) {} + +// The destructor of SingleFailureChecker verifies that the given +// TestPartResultArray contains exactly one failure that has the given +// type and contains the given substring. If that's not the case, a +// non-fatal failure will be generated. +SingleFailureChecker::~SingleFailureChecker() { + EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_); +} + +DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter( + UnitTestImpl* unit_test) : unit_test_(unit_test) {} + +void DefaultGlobalTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + unit_test_->current_test_result()->AddTestPartResult(result); + unit_test_->listeners()->repeater()->OnTestPartResult(result); +} + +DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter( + UnitTestImpl* unit_test) : unit_test_(unit_test) {} + +void DefaultPerThreadTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result); +} + +// Returns the global test part result reporter. +TestPartResultReporterInterface* +UnitTestImpl::GetGlobalTestPartResultReporter() { + internal::MutexLock lock(&global_test_part_result_reporter_mutex_); + return global_test_part_result_repoter_; +} + +// Sets the global test part result reporter. +void UnitTestImpl::SetGlobalTestPartResultReporter( + TestPartResultReporterInterface* reporter) { + internal::MutexLock lock(&global_test_part_result_reporter_mutex_); + global_test_part_result_repoter_ = reporter; +} + +// Returns the test part result reporter for the current thread. +TestPartResultReporterInterface* +UnitTestImpl::GetTestPartResultReporterForCurrentThread() { + return per_thread_test_part_result_reporter_.get(); +} + +// Sets the test part result reporter for the current thread. +void UnitTestImpl::SetTestPartResultReporterForCurrentThread( + TestPartResultReporterInterface* reporter) { + per_thread_test_part_result_reporter_.set(reporter); +} + +// Gets the number of successful test cases. +int UnitTestImpl::successful_test_case_count() const { + return CountIf(test_cases_, TestCasePassed); +} + +// Gets the number of failed test cases. +int UnitTestImpl::failed_test_case_count() const { + return CountIf(test_cases_, TestCaseFailed); +} + +// Gets the number of all test cases. +int UnitTestImpl::total_test_case_count() const { + return static_cast(test_cases_.size()); +} + +// Gets the number of all test cases that contain at least one test +// that should run. +int UnitTestImpl::test_case_to_run_count() const { + return CountIf(test_cases_, ShouldRunTestCase); +} + +// Gets the number of successful tests. +int UnitTestImpl::successful_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count); +} + +// Gets the number of failed tests. +int UnitTestImpl::failed_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count); +} + +// Gets the number of disabled tests that will be reported in the XML report. +int UnitTestImpl::reportable_disabled_test_count() const { + return SumOverTestCaseList(test_cases_, + &TestCase::reportable_disabled_test_count); +} + +// Gets the number of disabled tests. +int UnitTestImpl::disabled_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count); +} + +// Gets the number of tests to be printed in the XML report. +int UnitTestImpl::reportable_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::reportable_test_count); +} + +// Gets the number of all tests. +int UnitTestImpl::total_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::total_test_count); +} + +// Gets the number of tests that should run. +int UnitTestImpl::test_to_run_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count); +} + +// Returns the current OS stack trace as an std::string. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// CurrentOsStackTraceExceptTop(1), Foo() will be included in the +// trace but Bar() and CurrentOsStackTraceExceptTop() won't. +std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) { + (void)skip_count; + return ""; +} + +// Returns the current time in milliseconds. +TimeInMillis GetTimeInMillis() { +#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__) + // Difference between 1970-01-01 and 1601-01-01 in milliseconds. + // http://analogous.blogspot.com/2005/04/epoch.html + const TimeInMillis kJavaEpochToWinFileTimeDelta = + static_cast(116444736UL) * 100000UL; + const DWORD kTenthMicrosInMilliSecond = 10000; + + SYSTEMTIME now_systime; + FILETIME now_filetime; + ULARGE_INTEGER now_int64; + // TODO(kenton@google.com): Shouldn't this just use + // GetSystemTimeAsFileTime()? + GetSystemTime(&now_systime); + if (SystemTimeToFileTime(&now_systime, &now_filetime)) { + now_int64.LowPart = now_filetime.dwLowDateTime; + now_int64.HighPart = now_filetime.dwHighDateTime; + now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) - + kJavaEpochToWinFileTimeDelta; + return now_int64.QuadPart; + } + return 0; +#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_ + __timeb64 now; + +# ifdef _MSC_VER + + // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996 + // (deprecated function) there. + // TODO(kenton@google.com): Use GetTickCount()? Or use + // SystemTimeToFileTime() +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4996) // Temporarily disables warning 4996. + _ftime64(&now); +# pragma warning(pop) // Restores the warning state. +# else + + _ftime64(&now); + +# endif // _MSC_VER + + return static_cast(now.time) * 1000 + now.millitm; +#elif GTEST_HAS_GETTIMEOFDAY_ + struct timeval now; + gettimeofday(&now, NULL); + return static_cast(now.tv_sec) * 1000 + now.tv_usec / 1000; +#else +# error "Don't know how to get the current time on your system." +#endif +} + +// Utilities + +// class String. + +#if GTEST_OS_WINDOWS_MOBILE +// Creates a UTF-16 wide string from the given ANSI string, allocating +// memory using new. The caller is responsible for deleting the return +// value using delete[]. Returns the wide string, or NULL if the +// input is NULL. +LPCWSTR String::AnsiToUtf16(const char* ansi) { + if (!ansi) return NULL; + const int length = strlen(ansi); + const int unicode_length = + MultiByteToWideChar(CP_ACP, 0, ansi, length, + NULL, 0); + WCHAR* unicode = new WCHAR[unicode_length + 1]; + MultiByteToWideChar(CP_ACP, 0, ansi, length, + unicode, unicode_length); + unicode[unicode_length] = 0; + return unicode; +} + +// Creates an ANSI string from the given wide string, allocating +// memory using new. The caller is responsible for deleting the return +// value using delete[]. Returns the ANSI string, or NULL if the +// input is NULL. +const char* String::Utf16ToAnsi(LPCWSTR utf16_str) { + if (!utf16_str) return NULL; + const int ansi_length = + WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, + NULL, 0, NULL, NULL); + char* ansi = new char[ansi_length + 1]; + WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, + ansi, ansi_length, NULL, NULL); + ansi[ansi_length] = 0; + return ansi; +} + +#endif // GTEST_OS_WINDOWS_MOBILE + +// Compares two C strings. Returns true iff they have the same content. +// +// Unlike strcmp(), this function can handle NULL argument(s). A NULL +// C string is considered different to any non-NULL C string, +// including the empty string. +bool String::CStringEquals(const char * lhs, const char * rhs) { + if ( lhs == NULL ) return rhs == NULL; + + if ( rhs == NULL ) return false; + + return strcmp(lhs, rhs) == 0; +} + +#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING + +// Converts an array of wide chars to a narrow string using the UTF-8 +// encoding, and streams the result to the given Message object. +static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length, + Message* msg) { + for (size_t i = 0; i != length; ) { // NOLINT + if (wstr[i] != L'\0') { + *msg << WideStringToUtf8(wstr + i, static_cast(length - i)); + while (i != length && wstr[i] != L'\0') + i++; + } else { + *msg << '\0'; + i++; + } + } +} + +#endif // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING + +} // namespace internal + +// Constructs an empty Message. +// We allocate the stringstream separately because otherwise each use of +// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's +// stack frame leading to huge stack frames in some cases; gcc does not reuse +// the stack space. +Message::Message() : ss_(new ::std::stringstream) { + // By default, we want there to be enough precision when printing + // a double to a Message. + *ss_ << std::setprecision(std::numeric_limits::digits10 + 2); +} + +// These two overloads allow streaming a wide C string to a Message +// using the UTF-8 encoding. +Message& Message::operator <<(const wchar_t* wide_c_str) { + return *this << internal::String::ShowWideCString(wide_c_str); +} +Message& Message::operator <<(wchar_t* wide_c_str) { + return *this << internal::String::ShowWideCString(wide_c_str); +} + +#if GTEST_HAS_STD_WSTRING +// Converts the given wide string to a narrow string using the UTF-8 +// encoding, and streams the result to this Message object. +Message& Message::operator <<(const ::std::wstring& wstr) { + internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); + return *this; +} +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_WSTRING +// Converts the given wide string to a narrow string using the UTF-8 +// encoding, and streams the result to this Message object. +Message& Message::operator <<(const ::wstring& wstr) { + internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); + return *this; +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +// Gets the text streamed to this object so far as an std::string. +// Each '\0' character in the buffer is replaced with "\\0". +std::string Message::GetString() const { + return internal::StringStreamToString(ss_.get()); +} + +// AssertionResult constructors. +// Used in EXPECT_TRUE/FALSE(assertion_result). +AssertionResult::AssertionResult(const AssertionResult& other) + : success_(other.success_), + message_(other.message_.get() != NULL ? + new ::std::string(*other.message_) : + static_cast< ::std::string*>(NULL)) { +} + +// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. +AssertionResult AssertionResult::operator!() const { + AssertionResult negation(!success_); + if (message_.get() != NULL) + negation << *message_; + return negation; +} + +// Makes a successful assertion result. +AssertionResult AssertionSuccess() { + return AssertionResult(true); +} + +// Makes a failed assertion result. +AssertionResult AssertionFailure() { + return AssertionResult(false); +} + +// Makes a failed assertion result with the given failure message. +// Deprecated; use AssertionFailure() << message. +AssertionResult AssertionFailure(const Message& message) { + return AssertionFailure() << message; +} + +namespace internal { + +// Constructs and returns the message for an equality assertion +// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. +// +// The first four parameters are the expressions used in the assertion +// and their values, as strings. For example, for ASSERT_EQ(foo, bar) +// where foo is 5 and bar is 6, we have: +// +// expected_expression: "foo" +// actual_expression: "bar" +// expected_value: "5" +// actual_value: "6" +// +// The ignoring_case parameter is true iff the assertion is a +// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will +// be inserted into the message. +AssertionResult EqFailure(const char* expected_expression, + const char* actual_expression, + const std::string& expected_value, + const std::string& actual_value, + bool ignoring_case) { + Message msg; + msg << "Value of: " << actual_expression; + if (actual_value != actual_expression) { + msg << "\n Actual: " << actual_value; + } + + msg << "\nExpected: " << expected_expression; + if (ignoring_case) { + msg << " (ignoring case)"; + } + if (expected_value != expected_expression) { + msg << "\nWhich is: " << expected_value; + } + + return AssertionFailure() << msg; +} + +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +std::string GetBoolAssertionFailureMessage( + const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value) { + const char* actual_message = assertion_result.message(); + Message msg; + msg << "Value of: " << expression_text + << "\n Actual: " << actual_predicate_value; + if (actual_message[0] != '\0') + msg << " (" << actual_message << ")"; + msg << "\nExpected: " << expected_predicate_value; + return msg.GetString(); +} + +// Helper function for implementing ASSERT_NEAR. +AssertionResult DoubleNearPredFormat(const char* expr1, + const char* expr2, + const char* abs_error_expr, + double val1, + double val2, + double abs_error) { + const double diff = fabs(val1 - val2); + if (diff <= abs_error) return AssertionSuccess(); + + // TODO(wan): do not print the value of an expression if it's + // already a literal. + return AssertionFailure() + << "The difference between " << expr1 << " and " << expr2 + << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n" + << expr1 << " evaluates to " << val1 << ",\n" + << expr2 << " evaluates to " << val2 << ", and\n" + << abs_error_expr << " evaluates to " << abs_error << "."; +} + + +// Helper template for implementing FloatLE() and DoubleLE(). +template +AssertionResult FloatingPointLE(const char* expr1, + const char* expr2, + RawType val1, + RawType val2) { + // Returns success if val1 is less than val2, + if (val1 < val2) { + return AssertionSuccess(); + } + + // or if val1 is almost equal to val2. + const FloatingPoint lhs(val1), rhs(val2); + if (lhs.AlmostEquals(rhs)) { + return AssertionSuccess(); + } + + // Note that the above two checks will both fail if either val1 or + // val2 is NaN, as the IEEE floating-point standard requires that + // any predicate involving a NaN must return false. + + ::std::stringstream val1_ss; + val1_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << val1; + + ::std::stringstream val2_ss; + val2_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << val2; + + return AssertionFailure() + << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n" + << " Actual: " << StringStreamToString(&val1_ss) << " vs " + << StringStreamToString(&val2_ss); +} + +} // namespace internal + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +AssertionResult FloatLE(const char* expr1, const char* expr2, + float val1, float val2) { + return internal::FloatingPointLE(expr1, expr2, val1, val2); +} + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +AssertionResult DoubleLE(const char* expr1, const char* expr2, + double val1, double val2) { + return internal::FloatingPointLE(expr1, expr2, val1, val2); +} + +namespace internal { + +// The helper function for {ASSERT|EXPECT}_EQ with int or enum +// arguments. +AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual) { + if (expected == actual) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + FormatForComparisonFailureMessage(expected, actual), + FormatForComparisonFailureMessage(actual, expected), + false); +} + +// A macro for implementing the helper functions needed to implement +// ASSERT_?? and EXPECT_?? with integer or enum arguments. It is here +// just to avoid copy-and-paste of similar code. +#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ +AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ + BiggestInt val1, BiggestInt val2) {\ + if (val1 op val2) {\ + return AssertionSuccess();\ + } else {\ + return AssertionFailure() \ + << "Expected: (" << expr1 << ") " #op " (" << expr2\ + << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ + << " vs " << FormatForComparisonFailureMessage(val2, val1);\ + }\ +} + +// Implements the helper function for {ASSERT|EXPECT}_NE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(NE, !=) +// Implements the helper function for {ASSERT|EXPECT}_LE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(LE, <=) +// Implements the helper function for {ASSERT|EXPECT}_LT with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(LT, < ) +// Implements the helper function for {ASSERT|EXPECT}_GE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(GE, >=) +// Implements the helper function for {ASSERT|EXPECT}_GT with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(GT, > ) + +#undef GTEST_IMPL_CMP_HELPER_ + +// The helper function for {ASSERT|EXPECT}_STREQ. +AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual) { + if (String::CStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + PrintToString(expected), + PrintToString(actual), + false); +} + +// The helper function for {ASSERT|EXPECT}_STRCASEEQ. +AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual) { + if (String::CaseInsensitiveCStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + PrintToString(expected), + PrintToString(actual), + true); +} + +// The helper function for {ASSERT|EXPECT}_STRNE. +AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2) { + if (!String::CStringEquals(s1, s2)) { + return AssertionSuccess(); + } else { + return AssertionFailure() << "Expected: (" << s1_expression << ") != (" + << s2_expression << "), actual: \"" + << s1 << "\" vs \"" << s2 << "\""; + } +} + +// The helper function for {ASSERT|EXPECT}_STRCASENE. +AssertionResult CmpHelperSTRCASENE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2) { + if (!String::CaseInsensitiveCStringEquals(s1, s2)) { + return AssertionSuccess(); + } else { + return AssertionFailure() + << "Expected: (" << s1_expression << ") != (" + << s2_expression << ") (ignoring case), actual: \"" + << s1 << "\" vs \"" << s2 << "\""; + } +} + +} // namespace internal + +namespace { + +// Helper functions for implementing IsSubString() and IsNotSubstring(). + +// This group of overloaded functions return true iff needle is a +// substring of haystack. NULL is considered a substring of itself +// only. + +bool IsSubstringPred(const char* needle, const char* haystack) { + if (needle == NULL || haystack == NULL) + return needle == haystack; + + return strstr(haystack, needle) != NULL; +} + +bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) { + if (needle == NULL || haystack == NULL) + return needle == haystack; + + return wcsstr(haystack, needle) != NULL; +} + +// StringType here can be either ::std::string or ::std::wstring. +template +bool IsSubstringPred(const StringType& needle, + const StringType& haystack) { + return haystack.find(needle) != StringType::npos; +} + +// This function implements either IsSubstring() or IsNotSubstring(), +// depending on the value of the expected_to_be_substring parameter. +// StringType here can be const char*, const wchar_t*, ::std::string, +// or ::std::wstring. +template +AssertionResult IsSubstringImpl( + bool expected_to_be_substring, + const char* needle_expr, const char* haystack_expr, + const StringType& needle, const StringType& haystack) { + if (IsSubstringPred(needle, haystack) == expected_to_be_substring) + return AssertionSuccess(); + + const bool is_wide_string = sizeof(needle[0]) > 1; + const char* const begin_string_quote = is_wide_string ? "L\"" : "\""; + return AssertionFailure() + << "Value of: " << needle_expr << "\n" + << " Actual: " << begin_string_quote << needle << "\"\n" + << "Expected: " << (expected_to_be_substring ? "" : "not ") + << "a substring of " << haystack_expr << "\n" + << "Which is: " << begin_string_quote << haystack << "\""; +} + +} // namespace + +// IsSubstring() and IsNotSubstring() check whether needle is a +// substring of haystack (NULL is considered a substring of itself +// only), and return an appropriate error message when they fail. + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +#if GTEST_HAS_STD_WSTRING +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} +#endif // GTEST_HAS_STD_WSTRING + +namespace internal { + +#if GTEST_OS_WINDOWS + +namespace { + +// Helper function for IsHRESULT{SuccessFailure} predicates +AssertionResult HRESULTFailureHelper(const char* expr, + const char* expected, + long hr) { // NOLINT +# if GTEST_OS_WINDOWS_MOBILE + + // Windows CE doesn't support FormatMessage. + const char error_text[] = ""; + +# else + + // Looks up the human-readable system message for the HRESULT code + // and since we're not passing any params to FormatMessage, we don't + // want inserts expanded. + const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS; + const DWORD kBufSize = 4096; + // Gets the system's human readable message string for this HRESULT. + char error_text[kBufSize] = { '\0' }; + DWORD message_length = ::FormatMessageA(kFlags, + 0, // no source, we're asking system + hr, // the error + 0, // no line width restrictions + error_text, // output buffer + kBufSize, // buf size + NULL); // no arguments for inserts + // Trims tailing white space (FormatMessage leaves a trailing CR-LF) + for (; message_length && IsSpace(error_text[message_length - 1]); + --message_length) { + error_text[message_length - 1] = '\0'; + } + +# endif // GTEST_OS_WINDOWS_MOBILE + + const std::string error_hex("0x" + String::FormatHexInt(hr)); + return ::testing::AssertionFailure() + << "Expected: " << expr << " " << expected << ".\n" + << " Actual: " << error_hex << " " << error_text << "\n"; +} + +} // namespace + +AssertionResult IsHRESULTSuccess(const char* expr, long hr) { // NOLINT + if (SUCCEEDED(hr)) { + return AssertionSuccess(); + } + return HRESULTFailureHelper(expr, "succeeds", hr); +} + +AssertionResult IsHRESULTFailure(const char* expr, long hr) { // NOLINT + if (FAILED(hr)) { + return AssertionSuccess(); + } + return HRESULTFailureHelper(expr, "fails", hr); +} + +#endif // GTEST_OS_WINDOWS + +// Utility functions for encoding Unicode text (wide strings) in +// UTF-8. + +// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8 +// like this: +// +// Code-point length Encoding +// 0 - 7 bits 0xxxxxxx +// 8 - 11 bits 110xxxxx 10xxxxxx +// 12 - 16 bits 1110xxxx 10xxxxxx 10xxxxxx +// 17 - 21 bits 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + +// The maximum code-point a one-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint1 = (static_cast(1) << 7) - 1; + +// The maximum code-point a two-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint2 = (static_cast(1) << (5 + 6)) - 1; + +// The maximum code-point a three-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint3 = (static_cast(1) << (4 + 2*6)) - 1; + +// The maximum code-point a four-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint4 = (static_cast(1) << (3 + 3*6)) - 1; + +// Chops off the n lowest bits from a bit pattern. Returns the n +// lowest bits. As a side effect, the original bit pattern will be +// shifted to the right by n bits. +inline UInt32 ChopLowBits(UInt32* bits, int n) { + const UInt32 low_bits = *bits & ((static_cast(1) << n) - 1); + *bits >>= n; + return low_bits; +} + +// Converts a Unicode code point to a narrow string in UTF-8 encoding. +// code_point parameter is of type UInt32 because wchar_t may not be +// wide enough to contain a code point. +// If the code_point is not a valid Unicode code point +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted +// to "(Invalid Unicode 0xXXXXXXXX)". +std::string CodePointToUtf8(UInt32 code_point) { + if (code_point > kMaxCodePoint4) { + return "(Invalid Unicode 0x" + String::FormatHexInt(code_point) + ")"; + } + + char str[5]; // Big enough for the largest valid code point. + if (code_point <= kMaxCodePoint1) { + str[1] = '\0'; + str[0] = static_cast(code_point); // 0xxxxxxx + } else if (code_point <= kMaxCodePoint2) { + str[2] = '\0'; + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xC0 | code_point); // 110xxxxx + } else if (code_point <= kMaxCodePoint3) { + str[3] = '\0'; + str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xE0 | code_point); // 1110xxxx + } else { // code_point <= kMaxCodePoint4 + str[4] = '\0'; + str[3] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xF0 | code_point); // 11110xxx + } + return str; +} + +// The following two functions only make sense if the the system +// uses UTF-16 for wide string encoding. All supported systems +// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16. + +// Determines if the arguments constitute UTF-16 surrogate pair +// and thus should be combined into a single Unicode code point +// using CreateCodePointFromUtf16SurrogatePair. +inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) { + return sizeof(wchar_t) == 2 && + (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00; +} + +// Creates a Unicode code point from UTF16 surrogate pair. +inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first, + wchar_t second) { + const UInt32 mask = (1 << 10) - 1; + return (sizeof(wchar_t) == 2) ? + (((first & mask) << 10) | (second & mask)) + 0x10000 : + // This function should not be called when the condition is + // false, but we provide a sensible default in case it is. + static_cast(first); +} + +// Converts a wide string to a narrow string in UTF-8 encoding. +// The wide string is assumed to have the following encoding: +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-32 if sizeof(wchar_t) == 4 (on Linux) +// Parameter str points to a null-terminated wide string. +// Parameter num_chars may additionally limit the number +// of wchar_t characters processed. -1 is used when the entire string +// should be processed. +// If the string contains code points that are not valid Unicode code points +// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding +// and contains invalid UTF-16 surrogate pairs, values in those pairs +// will be encoded as individual Unicode characters from Basic Normal Plane. +std::string WideStringToUtf8(const wchar_t* str, int num_chars) { + if (num_chars == -1) + num_chars = static_cast(wcslen(str)); + + ::std::stringstream stream; + for (int i = 0; i < num_chars; ++i) { + UInt32 unicode_code_point; + + if (str[i] == L'\0') { + break; + } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) { + unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i], + str[i + 1]); + i++; + } else { + unicode_code_point = static_cast(str[i]); + } + + stream << CodePointToUtf8(unicode_code_point); + } + return StringStreamToString(&stream); +} + +// Converts a wide C string to an std::string using the UTF-8 encoding. +// NULL will be converted to "(null)". +std::string String::ShowWideCString(const wchar_t * wide_c_str) { + if (wide_c_str == NULL) return "(null)"; + + return internal::WideStringToUtf8(wide_c_str, -1); +} + +// Compares two wide C strings. Returns true iff they have the same +// content. +// +// Unlike wcscmp(), this function can handle NULL argument(s). A NULL +// C string is considered different to any non-NULL C string, +// including the empty string. +bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) { + if (lhs == NULL) return rhs == NULL; + + if (rhs == NULL) return false; + + return wcscmp(lhs, rhs) == 0; +} + +// Helper function for *_STREQ on wide strings. +AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const wchar_t* expected, + const wchar_t* actual) { + if (String::WideCStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + PrintToString(expected), + PrintToString(actual), + false); +} + +// Helper function for *_STRNE on wide strings. +AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const wchar_t* s1, + const wchar_t* s2) { + if (!String::WideCStringEquals(s1, s2)) { + return AssertionSuccess(); + } + + return AssertionFailure() << "Expected: (" << s1_expression << ") != (" + << s2_expression << "), actual: " + << PrintToString(s1) + << " vs " << PrintToString(s2); +} + +// Compares two C strings, ignoring case. Returns true iff they have +// the same content. +// +// Unlike strcasecmp(), this function can handle NULL argument(s). A +// NULL C string is considered different to any non-NULL C string, +// including the empty string. +bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) { + if (lhs == NULL) + return rhs == NULL; + if (rhs == NULL) + return false; + return posix::StrCaseCmp(lhs, rhs) == 0; +} + + // Compares two wide C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike wcscasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL wide C string, + // including the empty string. + // NB: The implementations on different platforms slightly differ. + // On windows, this method uses _wcsicmp which compares according to LC_CTYPE + // environment variable. On GNU platform this method uses wcscasecmp + // which compares according to LC_CTYPE category of the current locale. + // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the + // current locale. +bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs, + const wchar_t* rhs) { + if (lhs == NULL) return rhs == NULL; + + if (rhs == NULL) return false; + +#if GTEST_OS_WINDOWS + return _wcsicmp(lhs, rhs) == 0; +#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID + return wcscasecmp(lhs, rhs) == 0; +#else + // Android, Mac OS X and Cygwin don't define wcscasecmp. + // Other unknown OSes may not define it either. + wint_t left, right; + do { + left = towlower(*lhs++); + right = towlower(*rhs++); + } while (left && left == right); + return left == right; +#endif // OS selector +} + +// Returns true iff str ends with the given suffix, ignoring case. +// Any string is considered to end with an empty suffix. +bool String::EndsWithCaseInsensitive( + const std::string& str, const std::string& suffix) { + const size_t str_len = str.length(); + const size_t suffix_len = suffix.length(); + return (str_len >= suffix_len) && + CaseInsensitiveCStringEquals(str.c_str() + str_len - suffix_len, + suffix.c_str()); +} + +// Formats an int value as "%02d". +std::string String::FormatIntWidth2(int value) { + std::stringstream ss; + ss << std::setfill('0') << std::setw(2) << value; + return ss.str(); +} + +// Formats an int value as "%X". +std::string String::FormatHexInt(int value) { + std::stringstream ss; + ss << std::hex << std::uppercase << value; + return ss.str(); +} + +// Formats a byte as "%02X". +std::string String::FormatByte(unsigned char value) { + std::stringstream ss; + ss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase + << static_cast(value); + return ss.str(); +} + +// Converts the buffer in a stringstream to an std::string, converting NUL +// bytes to "\\0" along the way. +std::string StringStreamToString(::std::stringstream* ss) { + const ::std::string& str = ss->str(); + const char* const start = str.c_str(); + const char* const end = start + str.length(); + + std::string result; + result.reserve(2 * (end - start)); + for (const char* ch = start; ch != end; ++ch) { + if (*ch == '\0') { + result += "\\0"; // Replaces NUL with "\\0"; + } else { + result += *ch; + } + } + + return result; +} + +// Appends the user-supplied message to the Google-Test-generated message. +std::string AppendUserMessage(const std::string& gtest_msg, + const Message& user_msg) { + // Appends the user message if it's non-empty. + const std::string user_msg_string = user_msg.GetString(); + if (user_msg_string.empty()) { + return gtest_msg; + } + + return gtest_msg + "\n" + user_msg_string; +} + +} // namespace internal + +// class TestResult + +// Creates an empty TestResult. +TestResult::TestResult() + : death_test_count_(0), + elapsed_time_(0) { +} + +// D'tor. +TestResult::~TestResult() { +} + +// Returns the i-th test part result among all the results. i can +// range from 0 to total_part_count() - 1. If i is not in that range, +// aborts the program. +const TestPartResult& TestResult::GetTestPartResult(int i) const { + if (i < 0 || i >= total_part_count()) + internal::posix::Abort(); + return test_part_results_.at(i); +} + +// Returns the i-th test property. i can range from 0 to +// test_property_count() - 1. If i is not in that range, aborts the +// program. +const TestProperty& TestResult::GetTestProperty(int i) const { + if (i < 0 || i >= test_property_count()) + internal::posix::Abort(); + return test_properties_.at(i); +} + +// Clears the test part results. +void TestResult::ClearTestPartResults() { + test_part_results_.clear(); +} + +// Adds a test part result to the list. +void TestResult::AddTestPartResult(const TestPartResult& test_part_result) { + test_part_results_.push_back(test_part_result); +} + +// Adds a test property to the list. If a property with the same key as the +// supplied property is already represented, the value of this test_property +// replaces the old value for that key. +void TestResult::RecordProperty(const std::string& xml_element, + const TestProperty& test_property) { + if (!ValidateTestProperty(xml_element, test_property)) { + return; + } + internal::MutexLock lock(&test_properites_mutex_); + const std::vector::iterator property_with_matching_key = + std::find_if(test_properties_.begin(), test_properties_.end(), + internal::TestPropertyKeyIs(test_property.key())); + if (property_with_matching_key == test_properties_.end()) { + test_properties_.push_back(test_property); + return; + } + property_with_matching_key->SetValue(test_property.value()); +} + +// The list of reserved attributes used in the element of XML +// output. +static const char* const kReservedTestSuitesAttributes[] = { + "disabled", + "errors", + "failures", + "name", + "random_seed", + "tests", + "time", + "timestamp" +}; + +// The list of reserved attributes used in the element of XML +// output. +static const char* const kReservedTestSuiteAttributes[] = { + "disabled", + "errors", + "failures", + "name", + "tests", + "time" +}; + +// The list of reserved attributes used in the element of XML output. +static const char* const kReservedTestCaseAttributes[] = { + "classname", + "name", + "status", + "time", + "type_param", + "value_param" +}; + +template +std::vector ArrayAsVector(const char* const (&array)[kSize]) { + return std::vector(array, array + kSize); +} + +static std::vector GetReservedAttributesForElement( + const std::string& xml_element) { + if (xml_element == "testsuites") { + return ArrayAsVector(kReservedTestSuitesAttributes); + } else if (xml_element == "testsuite") { + return ArrayAsVector(kReservedTestSuiteAttributes); + } else if (xml_element == "testcase") { + return ArrayAsVector(kReservedTestCaseAttributes); + } else { + GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element; + } + // This code is unreachable but some compilers may not realizes that. + return std::vector(); +} + +static std::string FormatWordList(const std::vector& words) { + Message word_list; + for (size_t i = 0; i < words.size(); ++i) { + if (i > 0 && words.size() > 2) { + word_list << ", "; + } + if (i == words.size() - 1) { + word_list << "and "; + } + word_list << "'" << words[i] << "'"; + } + return word_list.GetString(); +} + +bool ValidateTestPropertyName(const std::string& property_name, + const std::vector& reserved_names) { + if (std::find(reserved_names.begin(), reserved_names.end(), property_name) != + reserved_names.end()) { + ADD_FAILURE() << "Reserved key used in RecordProperty(): " << property_name + << " (" << FormatWordList(reserved_names) + << " are reserved by " << GTEST_NAME_ << ")"; + return false; + } + return true; +} + +// Adds a failure if the key is a reserved attribute of the element named +// xml_element. Returns true if the property is valid. +bool TestResult::ValidateTestProperty(const std::string& xml_element, + const TestProperty& test_property) { + return ValidateTestPropertyName(test_property.key(), + GetReservedAttributesForElement(xml_element)); +} + +// Clears the object. +void TestResult::Clear() { + test_part_results_.clear(); + test_properties_.clear(); + death_test_count_ = 0; + elapsed_time_ = 0; +} + +// Returns true iff the test failed. +bool TestResult::Failed() const { + for (int i = 0; i < total_part_count(); ++i) { + if (GetTestPartResult(i).failed()) + return true; + } + return false; +} + +// Returns true iff the test part fatally failed. +static bool TestPartFatallyFailed(const TestPartResult& result) { + return result.fatally_failed(); +} + +// Returns true iff the test fatally failed. +bool TestResult::HasFatalFailure() const { + return CountIf(test_part_results_, TestPartFatallyFailed) > 0; +} + +// Returns true iff the test part non-fatally failed. +static bool TestPartNonfatallyFailed(const TestPartResult& result) { + return result.nonfatally_failed(); +} + +// Returns true iff the test has a non-fatal failure. +bool TestResult::HasNonfatalFailure() const { + return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0; +} + +// Gets the number of all test parts. This is the sum of the number +// of successful test parts and the number of failed test parts. +int TestResult::total_part_count() const { + return static_cast(test_part_results_.size()); +} + +// Returns the number of the test properties. +int TestResult::test_property_count() const { + return static_cast(test_properties_.size()); +} + +// class Test + +// Creates a Test object. + +// The c'tor saves the values of all Google Test flags. +Test::Test() + : gtest_flag_saver_(new internal::GTestFlagSaver) { +} + +// The d'tor restores the values of all Google Test flags. +Test::~Test() { + delete gtest_flag_saver_; +} + +// Sets up the test fixture. +// +// A sub-class may override this. +void Test::SetUp() { +} + +// Tears down the test fixture. +// +// A sub-class may override this. +void Test::TearDown() { +} + +// Allows user supplied key value pairs to be recorded for later output. +void Test::RecordProperty(const std::string& key, const std::string& value) { + UnitTest::GetInstance()->RecordProperty(key, value); +} + +// Allows user supplied key value pairs to be recorded for later output. +void Test::RecordProperty(const std::string& key, int value) { + Message value_message; + value_message << value; + RecordProperty(key, value_message.GetString().c_str()); +} + +namespace internal { + +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const std::string& message) { + // This function is a friend of UnitTest and as such has access to + // AddTestPartResult. + UnitTest::GetInstance()->AddTestPartResult( + result_type, + NULL, // No info about the source file where the exception occurred. + -1, // We have no info on which line caused the exception. + message, + ""); // No stack trace, either. +} + +} // namespace internal + +// Google Test requires all tests in the same test case to use the same test +// fixture class. This function checks if the current test has the +// same fixture class as the first test in the current test case. If +// yes, it returns true; otherwise it generates a Google Test failure and +// returns false. +bool Test::HasSameFixtureClass() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + const TestCase* const test_case = impl->current_test_case(); + + // Info about the first test in the current test case. + const TestInfo* const first_test_info = test_case->test_info_list()[0]; + const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_; + const char* const first_test_name = first_test_info->name(); + + // Info about the current test. + const TestInfo* const this_test_info = impl->current_test_info(); + const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_; + const char* const this_test_name = this_test_info->name(); + + if (this_fixture_id != first_fixture_id) { + // Is the first test defined using TEST? + const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId(); + // Is this test defined using TEST? + const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId(); + + if (first_is_TEST || this_is_TEST) { + // The user mixed TEST and TEST_F in this test case - we'll tell + // him/her how to fix it. + + // Gets the name of the TEST and the name of the TEST_F. Note + // that first_is_TEST and this_is_TEST cannot both be true, as + // the fixture IDs are different for the two tests. + const char* const TEST_name = + first_is_TEST ? first_test_name : this_test_name; + const char* const TEST_F_name = + first_is_TEST ? this_test_name : first_test_name; + + ADD_FAILURE() + << "All tests in the same test case must use the same test fixture\n" + << "class, so mixing TEST_F and TEST in the same test case is\n" + << "illegal. In test case " << this_test_info->test_case_name() + << ",\n" + << "test " << TEST_F_name << " is defined using TEST_F but\n" + << "test " << TEST_name << " is defined using TEST. You probably\n" + << "want to change the TEST to TEST_F or move it to another test\n" + << "case."; + } else { + // The user defined two fixture classes with the same name in + // two namespaces - we'll tell him/her how to fix it. + ADD_FAILURE() + << "All tests in the same test case must use the same test fixture\n" + << "class. However, in test case " + << this_test_info->test_case_name() << ",\n" + << "you defined test " << first_test_name + << " and test " << this_test_name << "\n" + << "using two different test fixture classes. This can happen if\n" + << "the two classes are from different namespaces or translation\n" + << "units and have the same name. You should probably rename one\n" + << "of the classes to put the tests into different test cases."; + } + return false; + } + + return true; +} + +#if GTEST_HAS_SEH + +// Adds an "exception thrown" fatal failure to the current test. This +// function returns its result via an output parameter pointer because VC++ +// prohibits creation of objects with destructors on stack in functions +// using __try (see error C2712). +static std::string* FormatSehExceptionMessage(DWORD exception_code, + const char* location) { + Message message; + message << "SEH exception with code 0x" << std::setbase(16) << + exception_code << std::setbase(10) << " thrown in " << location << "."; + + return new std::string(message.GetString()); +} + +#endif // GTEST_HAS_SEH + +namespace internal { + +#if GTEST_HAS_EXCEPTIONS + +// Adds an "exception thrown" fatal failure to the current test. +static std::string FormatCxxExceptionMessage(const char* description, + const char* location) { + Message message; + if (description != NULL) { + message << "C++ exception with description \"" << description << "\""; + } else { + message << "Unknown C++ exception"; + } + message << " thrown in " << location << "."; + + return message.GetString(); +} + +static std::string PrintTestPartResultToString( + const TestPartResult& test_part_result); + +GoogleTestFailureException::GoogleTestFailureException( + const TestPartResult& failure) + : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {} + +#endif // GTEST_HAS_EXCEPTIONS + +// We put these helper functions in the internal namespace as IBM's xlC +// compiler rejects the code if they were declared static. + +// Runs the given method and handles SEH exceptions it throws, when +// SEH is supported; returns the 0-value for type Result in case of an +// SEH exception. (Microsoft compilers cannot handle SEH and C++ +// exceptions in the same function. Therefore, we provide a separate +// wrapper function for handling SEH exceptions.) +template +Result HandleSehExceptionsInMethodIfSupported( + T* object, Result (T::*method)(), const char* location) { +#if GTEST_HAS_SEH + __try { + return (object->*method)(); + } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT + GetExceptionCode())) { + // We create the exception message on the heap because VC++ prohibits + // creation of objects with destructors on stack in functions using __try + // (see error C2712). + std::string* exception_message = FormatSehExceptionMessage( + GetExceptionCode(), location); + internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure, + *exception_message); + delete exception_message; + return static_cast(0); + } +#else + (void)location; + return (object->*method)(); +#endif // GTEST_HAS_SEH +} + +// Runs the given method and catches and reports C++ and/or SEH-style +// exceptions, if they are supported; returns the 0-value for type +// Result in case of an SEH exception. +template +Result HandleExceptionsInMethodIfSupported( + T* object, Result (T::*method)(), const char* location) { + // NOTE: The user code can affect the way in which Google Test handles + // exceptions by setting GTEST_FLAG(catch_exceptions), but only before + // RUN_ALL_TESTS() starts. It is technically possible to check the flag + // after the exception is caught and either report or re-throw the + // exception based on the flag's value: + // + // try { + // // Perform the test method. + // } catch (...) { + // if (GTEST_FLAG(catch_exceptions)) + // // Report the exception as failure. + // else + // throw; // Re-throws the original exception. + // } + // + // However, the purpose of this flag is to allow the program to drop into + // the debugger when the exception is thrown. On most platforms, once the + // control enters the catch block, the exception origin information is + // lost and the debugger will stop the program at the point of the + // re-throw in this function -- instead of at the point of the original + // throw statement in the code under test. For this reason, we perform + // the check early, sacrificing the ability to affect Google Test's + // exception handling in the method where the exception is thrown. + if (internal::GetUnitTestImpl()->catch_exceptions()) { +#if GTEST_HAS_EXCEPTIONS + try { + return HandleSehExceptionsInMethodIfSupported(object, method, location); + } catch (const internal::GoogleTestFailureException&) { // NOLINT + // This exception type can only be thrown by a failed Google + // Test assertion with the intention of letting another testing + // framework catch it. Therefore we just re-throw it. + throw; + } catch (const std::exception& e) { // NOLINT + internal::ReportFailureInUnknownLocation( + TestPartResult::kFatalFailure, + FormatCxxExceptionMessage(e.what(), location)); + } catch (...) { // NOLINT + internal::ReportFailureInUnknownLocation( + TestPartResult::kFatalFailure, + FormatCxxExceptionMessage(NULL, location)); + } + return static_cast(0); +#else + return HandleSehExceptionsInMethodIfSupported(object, method, location); +#endif // GTEST_HAS_EXCEPTIONS + } else { + return (object->*method)(); + } +} + +} // namespace internal + +// Runs the test and updates the test result. +void Test::Run() { + if (!HasSameFixtureClass()) return; + + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()"); + // We will run the test only if SetUp() was successful. + if (!HasFatalFailure()) { + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &Test::TestBody, "the test body"); + } + + // However, we want to clean up as much as possible. Hence we will + // always call TearDown(), even if SetUp() or the test body has + // failed. + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &Test::TearDown, "TearDown()"); +} + +// Returns true iff the current test has a fatal failure. +bool Test::HasFatalFailure() { + return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure(); +} + +// Returns true iff the current test has a non-fatal failure. +bool Test::HasNonfatalFailure() { + return internal::GetUnitTestImpl()->current_test_result()-> + HasNonfatalFailure(); +} + +// class TestInfo + +// Constructs a TestInfo object. It assumes ownership of the test factory +// object. +TestInfo::TestInfo(const std::string& a_test_case_name, + const std::string& a_name, + const char* a_type_param, + const char* a_value_param, + internal::TypeId fixture_class_id, + internal::TestFactoryBase* factory) + : test_case_name_(a_test_case_name), + name_(a_name), + type_param_(a_type_param ? new std::string(a_type_param) : NULL), + value_param_(a_value_param ? new std::string(a_value_param) : NULL), + fixture_class_id_(fixture_class_id), + should_run_(false), + is_disabled_(false), + matches_filter_(false), + factory_(factory), + result_() {} + +// Destructs a TestInfo object. +TestInfo::~TestInfo() { delete factory_; } + +namespace internal { + +// Creates a new TestInfo object and registers it with Google Test; +// returns the created object. +// +// Arguments: +// +// test_case_name: name of the test case +// name: name of the test +// type_param: the name of the test's type parameter, or NULL if +// this is not a typed or a type-parameterized test. +// value_param: text representation of the test's value parameter, +// or NULL if this is not a value-parameterized test. +// fixture_class_id: ID of the test fixture class +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +// factory: pointer to the factory that creates a test object. +// The newly created TestInfo instance will assume +// ownership of the factory object. +TestInfo* MakeAndRegisterTestInfo( + const char* test_case_name, + const char* name, + const char* type_param, + const char* value_param, + TypeId fixture_class_id, + SetUpTestCaseFunc set_up_tc, + TearDownTestCaseFunc tear_down_tc, + TestFactoryBase* factory) { + TestInfo* const test_info = + new TestInfo(test_case_name, name, type_param, value_param, + fixture_class_id, factory); + GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); + return test_info; +} + +#if GTEST_HAS_PARAM_TEST +void ReportInvalidTestCaseType(const char* test_case_name, + const char* file, int line) { + Message errors; + errors + << "Attempted redefinition of test case " << test_case_name << ".\n" + << "All tests in the same test case must use the same test fixture\n" + << "class. However, in test case " << test_case_name << ", you tried\n" + << "to define a test using a fixture class different from the one\n" + << "used earlier. This can happen if the two fixture classes are\n" + << "from different namespaces and have the same name. You should\n" + << "probably rename one of the classes to put the tests into different\n" + << "test cases."; + + fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), + errors.GetString().c_str()); +} +#endif // GTEST_HAS_PARAM_TEST + +} // namespace internal + +namespace { + +// A predicate that checks the test name of a TestInfo against a known +// value. +// +// This is used for implementation of the TestCase class only. We put +// it in the anonymous namespace to prevent polluting the outer +// namespace. +// +// TestNameIs is copyable. +class TestNameIs { + public: + // Constructor. + // + // TestNameIs has NO default constructor. + explicit TestNameIs(const char* name) + : name_(name) {} + + // Returns true iff the test name of test_info matches name_. + bool operator()(const TestInfo * test_info) const { + return test_info && test_info->name() == name_; + } + + private: + std::string name_; +}; + +} // namespace + +namespace internal { + +// This method expands all parameterized tests registered with macros TEST_P +// and INSTANTIATE_TEST_CASE_P into regular tests and registers those. +// This will be done just once during the program runtime. +void UnitTestImpl::RegisterParameterizedTests() { +#if GTEST_HAS_PARAM_TEST + if (!parameterized_tests_registered_) { + parameterized_test_registry_.RegisterTests(); + parameterized_tests_registered_ = true; + } +#endif +} + +} // namespace internal + +// Creates the test object, runs it, records its result, and then +// deletes it. +void TestInfo::Run() { + if (!should_run_) return; + + // Tells UnitTest where to store test result. + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->set_current_test_info(this); + + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + + // Notifies the unit test event listeners that a test is about to start. + repeater->OnTestStart(*this); + + const TimeInMillis start = internal::GetTimeInMillis(); + + impl->os_stack_trace_getter()->UponLeavingGTest(); + + // Creates the test object. + Test* const test = internal::HandleExceptionsInMethodIfSupported( + factory_, &internal::TestFactoryBase::CreateTest, + "the test fixture's constructor"); + + // Runs the test only if the test object was created and its + // constructor didn't generate a fatal failure. + if ((test != NULL) && !Test::HasFatalFailure()) { + // This doesn't throw as all user code that can throw are wrapped into + // exception handling code. + test->Run(); + } + + // Deletes the test object. + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + test, &Test::DeleteSelf_, "the test fixture's destructor"); + + result_.set_elapsed_time(internal::GetTimeInMillis() - start); + + // Notifies the unit test event listener that a test has just finished. + repeater->OnTestEnd(*this); + + // Tells UnitTest to stop associating assertion results to this + // test. + impl->set_current_test_info(NULL); +} + +// class TestCase + +// Gets the number of successful tests in this test case. +int TestCase::successful_test_count() const { + return CountIf(test_info_list_, TestPassed); +} + +// Gets the number of failed tests in this test case. +int TestCase::failed_test_count() const { + return CountIf(test_info_list_, TestFailed); +} + +// Gets the number of disabled tests that will be reported in the XML report. +int TestCase::reportable_disabled_test_count() const { + return CountIf(test_info_list_, TestReportableDisabled); +} + +// Gets the number of disabled tests in this test case. +int TestCase::disabled_test_count() const { + return CountIf(test_info_list_, TestDisabled); +} + +// Gets the number of tests to be printed in the XML report. +int TestCase::reportable_test_count() const { + return CountIf(test_info_list_, TestReportable); +} + +// Get the number of tests in this test case that should run. +int TestCase::test_to_run_count() const { + return CountIf(test_info_list_, ShouldRunTest); +} + +// Gets the number of all tests. +int TestCase::total_test_count() const { + return static_cast(test_info_list_.size()); +} + +// Creates a TestCase with the given name. +// +// Arguments: +// +// name: name of the test case +// a_type_param: the name of the test case's type parameter, or NULL if +// this is not a typed or a type-parameterized test case. +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +TestCase::TestCase(const char* a_name, const char* a_type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc) + : name_(a_name), + type_param_(a_type_param ? new std::string(a_type_param) : NULL), + set_up_tc_(set_up_tc), + tear_down_tc_(tear_down_tc), + should_run_(false), + elapsed_time_(0) { +} + +// Destructor of TestCase. +TestCase::~TestCase() { + // Deletes every Test in the collection. + ForEach(test_info_list_, internal::Delete); +} + +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +const TestInfo* TestCase::GetTestInfo(int i) const { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; +} + +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +TestInfo* TestCase::GetMutableTestInfo(int i) { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; +} + +// Adds a test to this test case. Will delete the test upon +// destruction of the TestCase object. +void TestCase::AddTestInfo(TestInfo * test_info) { + test_info_list_.push_back(test_info); + test_indices_.push_back(static_cast(test_indices_.size())); +} + +// Runs every test in this TestCase. +void TestCase::Run() { + if (!should_run_) return; + + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->set_current_test_case(this); + + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + + repeater->OnTestCaseStart(*this); + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &TestCase::RunSetUpTestCase, "SetUpTestCase()"); + + const internal::TimeInMillis start = internal::GetTimeInMillis(); + for (int i = 0; i < total_test_count(); i++) { + GetMutableTestInfo(i)->Run(); + } + elapsed_time_ = internal::GetTimeInMillis() - start; + + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &TestCase::RunTearDownTestCase, "TearDownTestCase()"); + + repeater->OnTestCaseEnd(*this); + impl->set_current_test_case(NULL); +} + +// Clears the results of all tests in this test case. +void TestCase::ClearResult() { + ad_hoc_test_result_.Clear(); + ForEach(test_info_list_, TestInfo::ClearTestResult); +} + +// Shuffles the tests in this test case. +void TestCase::ShuffleTests(internal::Random* random) { + Shuffle(random, &test_indices_); +} + +// Restores the test order to before the first shuffle. +void TestCase::UnshuffleTests() { + for (size_t i = 0; i < test_indices_.size(); i++) { + test_indices_[i] = static_cast(i); + } +} + +// Formats a countable noun. Depending on its quantity, either the +// singular form or the plural form is used. e.g. +// +// FormatCountableNoun(1, "formula", "formuli") returns "1 formula". +// FormatCountableNoun(5, "book", "books") returns "5 books". +static std::string FormatCountableNoun(int count, + const char * singular_form, + const char * plural_form) { + return internal::StreamableToString(count) + " " + + (count == 1 ? singular_form : plural_form); +} + +// Formats the count of tests. +static std::string FormatTestCount(int test_count) { + return FormatCountableNoun(test_count, "test", "tests"); +} + +// Formats the count of test cases. +static std::string FormatTestCaseCount(int test_case_count) { + return FormatCountableNoun(test_case_count, "test case", "test cases"); +} + +// Converts a TestPartResult::Type enum to human-friendly string +// representation. Both kNonFatalFailure and kFatalFailure are translated +// to "Failure", as the user usually doesn't care about the difference +// between the two when viewing the test result. +static const char * TestPartResultTypeToString(TestPartResult::Type type) { + switch (type) { + case TestPartResult::kSuccess: + return "Success"; + + case TestPartResult::kNonFatalFailure: + case TestPartResult::kFatalFailure: +#ifdef _MSC_VER + return "error: "; +#else + return "Failure\n"; +#endif + default: + return "Unknown result type"; + } +} + +namespace internal { + +// Prints a TestPartResult to an std::string. +static std::string PrintTestPartResultToString( + const TestPartResult& test_part_result) { + return (Message() + << internal::FormatFileLocation(test_part_result.file_name(), + test_part_result.line_number()) + << " " << TestPartResultTypeToString(test_part_result.type()) + << test_part_result.message()).GetString(); +} + +// Prints a TestPartResult. +static void PrintTestPartResult(const TestPartResult& test_part_result) { + const std::string& result = + PrintTestPartResultToString(test_part_result); + printf("%s\n", result.c_str()); + fflush(stdout); + // If the test program runs in Visual Studio or a debugger, the + // following statements add the test part result message to the Output + // window such that the user can double-click on it to jump to the + // corresponding source code location; otherwise they do nothing. +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + // We don't call OutputDebugString*() on Windows Mobile, as printing + // to stdout is done by OutputDebugString() there already - we don't + // want the same message printed twice. + ::OutputDebugStringA(result.c_str()); + ::OutputDebugStringA("\n"); +#endif +} + +// class PrettyUnitTestResultPrinter + +enum GTestColor { + COLOR_DEFAULT, + COLOR_RED, + COLOR_GREEN, + COLOR_YELLOW +}; + +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + +// Returns the character attribute for the given color. +WORD GetColorAttribute(GTestColor color) { + switch (color) { + case COLOR_RED: return FOREGROUND_RED; + case COLOR_GREEN: return FOREGROUND_GREEN; + case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN; + default: return 0; + } +} + +#else + +// Returns the ANSI color code for the given color. COLOR_DEFAULT is +// an invalid input. +const char* GetAnsiColorCode(GTestColor color) { + switch (color) { + case COLOR_RED: return "1"; + case COLOR_GREEN: return "2"; + case COLOR_YELLOW: return "3"; + default: return NULL; + }; +} + +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + +// Returns true iff Google Test should use colors in the output. +bool ShouldUseColor(bool stdout_is_tty) { + const char* const gtest_color = GTEST_FLAG(color).c_str(); + + if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) { +#if GTEST_OS_WINDOWS + // On Windows the TERM variable is usually not set, but the + // console there does support colors. + return stdout_is_tty; +#else + // On non-Windows platforms, we rely on the TERM variable. + const char* const term = posix::GetEnv("TERM"); + const bool term_supports_color = + String::CStringEquals(term, "xterm") || + String::CStringEquals(term, "xterm-color") || + String::CStringEquals(term, "xterm-256color") || + String::CStringEquals(term, "screen") || + String::CStringEquals(term, "screen-256color") || + String::CStringEquals(term, "linux") || + String::CStringEquals(term, "cygwin"); + return stdout_is_tty && term_supports_color; +#endif // GTEST_OS_WINDOWS + } + + return String::CaseInsensitiveCStringEquals(gtest_color, "yes") || + String::CaseInsensitiveCStringEquals(gtest_color, "true") || + String::CaseInsensitiveCStringEquals(gtest_color, "t") || + String::CStringEquals(gtest_color, "1"); + // We take "yes", "true", "t", and "1" as meaning "yes". If the + // value is neither one of these nor "auto", we treat it as "no" to + // be conservative. +} + +// Helpers for printing colored strings to stdout. Note that on Windows, we +// cannot simply emit special characters and have the terminal change colors. +// This routine must actually emit the characters rather than return a string +// that would be colored when printed, as can be done on Linux. +void ColoredPrintf(GTestColor color, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || GTEST_OS_IOS + const bool use_color = false; +#else + static const bool in_color_mode = + ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0); + const bool use_color = in_color_mode && (color != COLOR_DEFAULT); +#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS + // The '!= 0' comparison is necessary to satisfy MSVC 7.1. + + if (!use_color) { + vprintf(fmt, args); + va_end(args); + return; + } + +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); + + // Gets the current text color. + CONSOLE_SCREEN_BUFFER_INFO buffer_info; + GetConsoleScreenBufferInfo(stdout_handle, &buffer_info); + const WORD old_color_attrs = buffer_info.wAttributes; + + // We need to flush the stream buffers into the console before each + // SetConsoleTextAttribute call lest it affect the text that is already + // printed but has not yet reached the console. + fflush(stdout); + SetConsoleTextAttribute(stdout_handle, + GetColorAttribute(color) | FOREGROUND_INTENSITY); + vprintf(fmt, args); + + fflush(stdout); + // Restores the text color. + SetConsoleTextAttribute(stdout_handle, old_color_attrs); +#else + printf("\033[0;3%sm", GetAnsiColorCode(color)); + vprintf(fmt, args); + printf("\033[m"); // Resets the terminal to default. +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + va_end(args); +} + +// Text printed in Google Test's text output and --gunit_list_tests +// output to label the type parameter and value parameter for a test. +static const char kTypeParamLabel[] = "TypeParam"; +static const char kValueParamLabel[] = "GetParam()"; + +void PrintFullTestCommentIfPresent(const TestInfo& test_info) { + const char* const type_param = test_info.type_param(); + const char* const value_param = test_info.value_param(); + + if (type_param != NULL || value_param != NULL) { + printf(", where "); + if (type_param != NULL) { + printf("%s = %s", kTypeParamLabel, type_param); + if (value_param != NULL) + printf(" and "); + } + if (value_param != NULL) { + printf("%s = %s", kValueParamLabel, value_param); + } + } +} + +// This class implements the TestEventListener interface. +// +// Class PrettyUnitTestResultPrinter is copyable. +class PrettyUnitTestResultPrinter : public TestEventListener { + public: + PrettyUnitTestResultPrinter() {} + static void PrintTestName(const char * test_case, const char * test) { + printf("%s.%s", test_case, test); + } + + // The following methods override what's in the TestEventListener class. + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} + + private: + static void PrintFailedTests(const UnitTest& unit_test); +}; + + // Fired before each iteration of tests starts. +void PrettyUnitTestResultPrinter::OnTestIterationStart( + const UnitTest& unit_test, int iteration) { + if (GTEST_FLAG(repeat) != 1) + printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1); + + const char* const filter = GTEST_FLAG(filter).c_str(); + + // Prints the filter if it's not *. This reminds the user that some + // tests may be skipped. + if (!String::CStringEquals(filter, kUniversalFilter)) { + ColoredPrintf(COLOR_YELLOW, + "Note: %s filter = %s\n", GTEST_NAME_, filter); + } + + if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) { + const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1); + ColoredPrintf(COLOR_YELLOW, + "Note: This is test shard %d of %s.\n", + static_cast(shard_index) + 1, + internal::posix::GetEnv(kTestTotalShards)); + } + + if (GTEST_FLAG(shuffle)) { + ColoredPrintf(COLOR_YELLOW, + "Note: Randomizing tests' orders with a seed of %d .\n", + unit_test.random_seed()); + } + + ColoredPrintf(COLOR_GREEN, "[==========] "); + printf("Running %s from %s.\n", + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart( + const UnitTest& /*unit_test*/) { + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("Global test environment set-up.\n"); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) { + const std::string counts = + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s", counts.c_str(), test_case.name()); + if (test_case.type_param() == NULL) { + printf("\n"); + } else { + printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param()); + } + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) { + ColoredPrintf(COLOR_GREEN, "[ RUN ] "); + PrintTestName(test_info.test_case_name(), test_info.name()); + printf("\n"); + fflush(stdout); +} + +// Called after an assertion failure. +void PrettyUnitTestResultPrinter::OnTestPartResult( + const TestPartResult& result) { + // If the test part succeeded, we don't need to do anything. + if (result.type() == TestPartResult::kSuccess) + return; + + // Print failure message from the assertion (e.g. expected this and got that). + PrintTestPartResult(result); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) { + if (test_info.result()->Passed()) { + ColoredPrintf(COLOR_GREEN, "[ OK ] "); + } else { + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + } + PrintTestName(test_info.test_case_name(), test_info.name()); + if (test_info.result()->Failed()) + PrintFullTestCommentIfPresent(test_info); + + if (GTEST_FLAG(print_time)) { + printf(" (%s ms)\n", internal::StreamableToString( + test_info.result()->elapsed_time()).c_str()); + } else { + printf("\n"); + } + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) { + if (!GTEST_FLAG(print_time)) return; + + const std::string counts = + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s (%s ms total)\n\n", + counts.c_str(), test_case.name(), + internal::StreamableToString(test_case.elapsed_time()).c_str()); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart( + const UnitTest& /*unit_test*/) { + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("Global test environment tear-down\n"); + fflush(stdout); +} + +// Internal helper for printing the list of failed tests. +void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) { + const int failed_test_count = unit_test.failed_test_count(); + if (failed_test_count == 0) { + return; + } + + for (int i = 0; i < unit_test.total_test_case_count(); ++i) { + const TestCase& test_case = *unit_test.GetTestCase(i); + if (!test_case.should_run() || (test_case.failed_test_count() == 0)) { + continue; + } + for (int j = 0; j < test_case.total_test_count(); ++j) { + const TestInfo& test_info = *test_case.GetTestInfo(j); + if (!test_info.should_run() || test_info.result()->Passed()) { + continue; + } + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + printf("%s.%s", test_case.name(), test_info.name()); + PrintFullTestCommentIfPresent(test_info); + printf("\n"); + } + } +} + +void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + ColoredPrintf(COLOR_GREEN, "[==========] "); + printf("%s from %s ran.", + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + if (GTEST_FLAG(print_time)) { + printf(" (%s ms total)", + internal::StreamableToString(unit_test.elapsed_time()).c_str()); + } + printf("\n"); + ColoredPrintf(COLOR_GREEN, "[ PASSED ] "); + printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str()); + + int num_failures = unit_test.failed_test_count(); + if (!unit_test.Passed()) { + const int failed_test_count = unit_test.failed_test_count(); + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str()); + PrintFailedTests(unit_test); + printf("\n%2d FAILED %s\n", num_failures, + num_failures == 1 ? "TEST" : "TESTS"); + } + + int num_disabled = unit_test.reportable_disabled_test_count(); + if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) { + if (!num_failures) { + printf("\n"); // Add a spacer if no FAILURE banner is displayed. + } + ColoredPrintf(COLOR_YELLOW, + " YOU HAVE %d DISABLED %s\n\n", + num_disabled, + num_disabled == 1 ? "TEST" : "TESTS"); + } + // Ensure that Google Test output is printed before, e.g., heapchecker output. + fflush(stdout); +} + +// End PrettyUnitTestResultPrinter + +// class TestEventRepeater +// +// This class forwards events to other event listeners. +class TestEventRepeater : public TestEventListener { + public: + TestEventRepeater() : forwarding_enabled_(true) {} + virtual ~TestEventRepeater(); + void Append(TestEventListener *listener); + TestEventListener* Release(TestEventListener* listener); + + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled() const { return forwarding_enabled_; } + void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; } + + virtual void OnTestProgramStart(const UnitTest& unit_test); + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test); + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test); + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& unit_test); + + private: + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled_; + // The list of listeners that receive events. + std::vector listeners_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater); +}; + +TestEventRepeater::~TestEventRepeater() { + ForEach(listeners_, Delete); +} + +void TestEventRepeater::Append(TestEventListener *listener) { + listeners_.push_back(listener); +} + +// TODO(vladl@google.com): Factor the search functionality into Vector::Find. +TestEventListener* TestEventRepeater::Release(TestEventListener *listener) { + for (size_t i = 0; i < listeners_.size(); ++i) { + if (listeners_[i] == listener) { + listeners_.erase(listeners_.begin() + i); + return listener; + } + } + + return NULL; +} + +// Since most methods are very similar, use macros to reduce boilerplate. +// This defines a member that forwards the call to all listeners. +#define GTEST_REPEATER_METHOD_(Name, Type) \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (size_t i = 0; i < listeners_.size(); i++) { \ + listeners_[i]->Name(parameter); \ + } \ + } \ +} +// This defines a member that forwards the call to all listeners in reverse +// order. +#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { \ + listeners_[i]->Name(parameter); \ + } \ + } \ +} + +GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest) +GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest) +GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase) +GTEST_REPEATER_METHOD_(OnTestStart, TestInfo) +GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult) +GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo) +GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase) +GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest) + +#undef GTEST_REPEATER_METHOD_ +#undef GTEST_REVERSE_REPEATER_METHOD_ + +void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (size_t i = 0; i < listeners_.size(); i++) { + listeners_[i]->OnTestIterationStart(unit_test, iteration); + } + } +} + +void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { + listeners_[i]->OnTestIterationEnd(unit_test, iteration); + } + } +} + +// End TestEventRepeater + +// This class generates an XML output file. +class XmlUnitTestResultPrinter : public EmptyTestEventListener { + public: + explicit XmlUnitTestResultPrinter(const char* output_file); + + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + + private: + // Is c a whitespace character that is normalized to a space character + // when it appears in an XML attribute value? + static bool IsNormalizableWhitespace(char c) { + return c == 0x9 || c == 0xA || c == 0xD; + } + + // May c appear in a well-formed XML document? + static bool IsValidXmlCharacter(char c) { + return IsNormalizableWhitespace(c) || c >= 0x20; + } + + // Returns an XML-escaped copy of the input string str. If + // is_attribute is true, the text is meant to appear as an attribute + // value, and normalizable whitespace is preserved by replacing it + // with character references. + static std::string EscapeXml(const std::string& str, bool is_attribute); + + // Returns the given string with all characters invalid in XML removed. + static std::string RemoveInvalidXmlCharacters(const std::string& str); + + // Convenience wrapper around EscapeXml when str is an attribute value. + static std::string EscapeXmlAttribute(const std::string& str) { + return EscapeXml(str, true); + } + + // Convenience wrapper around EscapeXml when str is not an attribute value. + static std::string EscapeXmlText(const char* str) { + return EscapeXml(str, false); + } + + // Verifies that the given attribute belongs to the given element and + // streams the attribute as XML. + static void OutputXmlAttribute(std::ostream* stream, + const std::string& element_name, + const std::string& name, + const std::string& value); + + // Streams an XML CDATA section, escaping invalid CDATA sequences as needed. + static void OutputXmlCDataSection(::std::ostream* stream, const char* data); + + // Streams an XML representation of a TestInfo object. + static void OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info); + + // Prints an XML representation of a TestCase object + static void PrintXmlTestCase(::std::ostream* stream, + const TestCase& test_case); + + // Prints an XML summary of unit_test to output stream out. + static void PrintXmlUnitTest(::std::ostream* stream, + const UnitTest& unit_test); + + // Produces a string representing the test properties in a result as space + // delimited XML attributes based on the property key="value" pairs. + // When the std::string is not empty, it includes a space at the beginning, + // to delimit this attribute from prior attributes. + static std::string TestPropertiesAsXmlAttributes(const TestResult& result); + + // The output file. + const std::string output_file_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter); +}; + +// Creates a new XmlUnitTestResultPrinter. +XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file) + : output_file_(output_file) { + if (output_file_.c_str() == NULL || output_file_.empty()) { + fprintf(stderr, "XML output file may not be null\n"); + fflush(stderr); + exit(EXIT_FAILURE); + } +} + +// Called after the unit test ends. +void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + FILE* xmlout = NULL; + FilePath output_file(output_file_); + FilePath output_dir(output_file.RemoveFileName()); + + if (output_dir.CreateDirectoriesRecursively()) { + xmlout = posix::FOpen(output_file_.c_str(), "w"); + } + if (xmlout == NULL) { + // TODO(wan): report the reason of the failure. + // + // We don't do it for now as: + // + // 1. There is no urgent need for it. + // 2. It's a bit involved to make the errno variable thread-safe on + // all three operating systems (Linux, Windows, and Mac OS). + // 3. To interpret the meaning of errno in a thread-safe way, + // we need the strerror_r() function, which is not available on + // Windows. + fprintf(stderr, + "Unable to open file \"%s\"\n", + output_file_.c_str()); + fflush(stderr); + exit(EXIT_FAILURE); + } + std::stringstream stream; + PrintXmlUnitTest(&stream, unit_test); + fprintf(xmlout, "%s", StringStreamToString(&stream).c_str()); + fclose(xmlout); +} + +// Returns an XML-escaped copy of the input string str. If is_attribute +// is true, the text is meant to appear as an attribute value, and +// normalizable whitespace is preserved by replacing it with character +// references. +// +// Invalid XML characters in str, if any, are stripped from the output. +// It is expected that most, if not all, of the text processed by this +// module will consist of ordinary English text. +// If this module is ever modified to produce version 1.1 XML output, +// most invalid characters can be retained using character references. +// TODO(wan): It might be nice to have a minimally invasive, human-readable +// escaping scheme for invalid characters, rather than dropping them. +std::string XmlUnitTestResultPrinter::EscapeXml( + const std::string& str, bool is_attribute) { + Message m; + + for (size_t i = 0; i < str.size(); ++i) { + const char ch = str[i]; + switch (ch) { + case '<': + m << "<"; + break; + case '>': + m << ">"; + break; + case '&': + m << "&"; + break; + case '\'': + if (is_attribute) + m << "'"; + else + m << '\''; + break; + case '"': + if (is_attribute) + m << """; + else + m << '"'; + break; + default: + if (IsValidXmlCharacter(ch)) { + if (is_attribute && IsNormalizableWhitespace(ch)) + m << "&#x" << String::FormatByte(static_cast(ch)) + << ";"; + else + m << ch; + } + break; + } + } + + return m.GetString(); +} + +// Returns the given string with all characters invalid in XML removed. +// Currently invalid characters are dropped from the string. An +// alternative is to replace them with certain characters such as . or ?. +std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters( + const std::string& str) { + std::string output; + output.reserve(str.size()); + for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) + if (IsValidXmlCharacter(*it)) + output.push_back(*it); + + return output; +} + +// The following routines generate an XML representation of a UnitTest +// object. +// +// This is how Google Test concepts map to the DTD: +// +// <-- corresponds to a UnitTest object +// <-- corresponds to a TestCase object +// <-- corresponds to a TestInfo object +// ... +// ... +// ... +// <-- individual assertion failures +// +// +// + +// Formats the given time in milliseconds as seconds. +std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) { + ::std::stringstream ss; + ss << ms/1000.0; + return ss.str(); +} + +// Converts the given epoch time in milliseconds to a date string in the ISO +// 8601 format, without the timezone information. +std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) { + // Using non-reentrant version as localtime_r is not portable. + time_t seconds = static_cast(ms / 1000); +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4996) // Temporarily disables warning 4996 + // (function or variable may be unsafe). + const struct tm* const time_struct = localtime(&seconds); // NOLINT +# pragma warning(pop) // Restores the warning state again. +#else + const struct tm* const time_struct = localtime(&seconds); // NOLINT +#endif + if (time_struct == NULL) + return ""; // Invalid ms value + + // YYYY-MM-DDThh:mm:ss + return StreamableToString(time_struct->tm_year + 1900) + "-" + + String::FormatIntWidth2(time_struct->tm_mon + 1) + "-" + + String::FormatIntWidth2(time_struct->tm_mday) + "T" + + String::FormatIntWidth2(time_struct->tm_hour) + ":" + + String::FormatIntWidth2(time_struct->tm_min) + ":" + + String::FormatIntWidth2(time_struct->tm_sec); +} + +// Streams an XML CDATA section, escaping invalid CDATA sequences as needed. +void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream, + const char* data) { + const char* segment = data; + *stream << ""); + if (next_segment != NULL) { + stream->write( + segment, static_cast(next_segment - segment)); + *stream << "]]>]]>"); + } else { + *stream << segment; + break; + } + } + *stream << "]]>"; +} + +void XmlUnitTestResultPrinter::OutputXmlAttribute( + std::ostream* stream, + const std::string& element_name, + const std::string& name, + const std::string& value) { + const std::vector& allowed_names = + GetReservedAttributesForElement(element_name); + + GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) != + allowed_names.end()) + << "Attribute " << name << " is not allowed for element <" << element_name + << ">."; + + *stream << " " << name << "=\"" << EscapeXmlAttribute(value) << "\""; +} + +// Prints an XML representation of a TestInfo object. +// TODO(wan): There is also value in printing properties with the plain printer. +void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info) { + const TestResult& result = *test_info.result(); + const std::string kTestcase = "testcase"; + + *stream << " \n"; + } + const string location = internal::FormatCompilerIndependentFileLocation( + part.file_name(), part.line_number()); + const string summary = location + "\n" + part.summary(); + *stream << " "; + const string detail = location + "\n" + part.message(); + OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str()); + *stream << "\n"; + } + } + + if (failures == 0) + *stream << " />\n"; + else + *stream << " \n"; +} + +// Prints an XML representation of a TestCase object +void XmlUnitTestResultPrinter::PrintXmlTestCase(std::ostream* stream, + const TestCase& test_case) { + const std::string kTestsuite = "testsuite"; + *stream << " <" << kTestsuite; + OutputXmlAttribute(stream, kTestsuite, "name", test_case.name()); + OutputXmlAttribute(stream, kTestsuite, "tests", + StreamableToString(test_case.reportable_test_count())); + OutputXmlAttribute(stream, kTestsuite, "failures", + StreamableToString(test_case.failed_test_count())); + OutputXmlAttribute( + stream, kTestsuite, "disabled", + StreamableToString(test_case.reportable_disabled_test_count())); + OutputXmlAttribute(stream, kTestsuite, "errors", "0"); + OutputXmlAttribute(stream, kTestsuite, "time", + FormatTimeInMillisAsSeconds(test_case.elapsed_time())); + *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result()) + << ">\n"; + + for (int i = 0; i < test_case.total_test_count(); ++i) { + if (test_case.GetTestInfo(i)->is_reportable()) + OutputXmlTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i)); + } + *stream << " \n"; +} + +// Prints an XML summary of unit_test to output stream out. +void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream, + const UnitTest& unit_test) { + const std::string kTestsuites = "testsuites"; + + *stream << "\n"; + *stream << "<" << kTestsuites; + + OutputXmlAttribute(stream, kTestsuites, "tests", + StreamableToString(unit_test.reportable_test_count())); + OutputXmlAttribute(stream, kTestsuites, "failures", + StreamableToString(unit_test.failed_test_count())); + OutputXmlAttribute( + stream, kTestsuites, "disabled", + StreamableToString(unit_test.reportable_disabled_test_count())); + OutputXmlAttribute(stream, kTestsuites, "errors", "0"); + OutputXmlAttribute( + stream, kTestsuites, "timestamp", + FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp())); + OutputXmlAttribute(stream, kTestsuites, "time", + FormatTimeInMillisAsSeconds(unit_test.elapsed_time())); + + if (GTEST_FLAG(shuffle)) { + OutputXmlAttribute(stream, kTestsuites, "random_seed", + StreamableToString(unit_test.random_seed())); + } + + *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result()); + + OutputXmlAttribute(stream, kTestsuites, "name", "AllTests"); + *stream << ">\n"; + + for (int i = 0; i < unit_test.total_test_case_count(); ++i) { + if (unit_test.GetTestCase(i)->reportable_test_count() > 0) + PrintXmlTestCase(stream, *unit_test.GetTestCase(i)); + } + *stream << "\n"; +} + +// Produces a string representing the test properties in a result as space +// delimited XML attributes based on the property key="value" pairs. +std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( + const TestResult& result) { + Message attributes; + for (int i = 0; i < result.test_property_count(); ++i) { + const TestProperty& property = result.GetTestProperty(i); + attributes << " " << property.key() << "=" + << "\"" << EscapeXmlAttribute(property.value()) << "\""; + } + return attributes.GetString(); +} + +// End XmlUnitTestResultPrinter + +#if GTEST_CAN_STREAM_RESULTS_ + +// Checks if str contains '=', '&', '%' or '\n' characters. If yes, +// replaces them by "%xx" where xx is their hexadecimal value. For +// example, replaces "=" with "%3D". This algorithm is O(strlen(str)) +// in both time and space -- important as the input str may contain an +// arbitrarily long test failure message and stack trace. +string StreamingListener::UrlEncode(const char* str) { + string result; + result.reserve(strlen(str) + 1); + for (char ch = *str; ch != '\0'; ch = *++str) { + switch (ch) { + case '%': + case '=': + case '&': + case '\n': + result.append("%" + String::FormatByte(static_cast(ch))); + break; + default: + result.push_back(ch); + break; + } + } + return result; +} + +void StreamingListener::SocketWriter::MakeConnection() { + GTEST_CHECK_(sockfd_ == -1) + << "MakeConnection() can't be called when there is already a connection."; + + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses. + hints.ai_socktype = SOCK_STREAM; + addrinfo* servinfo = NULL; + + // Use the getaddrinfo() to get a linked list of IP addresses for + // the given host name. + const int error_num = getaddrinfo( + host_name_.c_str(), port_num_.c_str(), &hints, &servinfo); + if (error_num != 0) { + GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: " + << gai_strerror(error_num); + } + + // Loop through all the results and connect to the first we can. + for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL; + cur_addr = cur_addr->ai_next) { + sockfd_ = socket( + cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol); + if (sockfd_ != -1) { + // Connect the client socket to the server socket. + if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) { + close(sockfd_); + sockfd_ = -1; + } + } + } + + freeaddrinfo(servinfo); // all done with this structure + + if (sockfd_ == -1) { + GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to " + << host_name_ << ":" << port_num_; + } +} + +// End of class Streaming Listener +#endif // GTEST_CAN_STREAM_RESULTS__ + +// Class ScopedTrace + +// Pushes the given source file location and message onto a per-thread +// trace stack maintained by Google Test. +ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) + GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { + TraceInfo trace; + trace.file = file; + trace.line = line; + trace.message = message.GetString(); + + UnitTest::GetInstance()->PushGTestTrace(trace); +} + +// Pops the info pushed by the c'tor. +ScopedTrace::~ScopedTrace() + GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { + UnitTest::GetInstance()->PopGTestTrace(); +} + + +// class OsStackTraceGetter + +// Returns the current OS stack trace as an std::string. Parameters: +// +// max_depth - the maximum number of stack frames to be included +// in the trace. +// skip_count - the number of top frames to be skipped; doesn't count +// against max_depth. +// +string OsStackTraceGetter::CurrentStackTrace(int /* max_depth */, + int /* skip_count */) + GTEST_LOCK_EXCLUDED_(mutex_) { + return ""; +} + +void OsStackTraceGetter::UponLeavingGTest() + GTEST_LOCK_EXCLUDED_(mutex_) { +} + +const char* const +OsStackTraceGetter::kElidedFramesMarker = + "... " GTEST_NAME_ " internal frames ..."; + +// A helper class that creates the premature-exit file in its +// constructor and deletes the file in its destructor. +class ScopedPrematureExitFile { + public: + explicit ScopedPrematureExitFile(const char* premature_exit_filepath) + : premature_exit_filepath_(premature_exit_filepath) { + // If a path to the premature-exit file is specified... + if (premature_exit_filepath != NULL && *premature_exit_filepath != '\0') { + // create the file with a single "0" character in it. I/O + // errors are ignored as there's nothing better we can do and we + // don't want to fail the test because of this. + FILE* pfile = posix::FOpen(premature_exit_filepath, "w"); + fwrite("0", 1, 1, pfile); + fclose(pfile); + } + } + + ~ScopedPrematureExitFile() { + if (premature_exit_filepath_ != NULL && *premature_exit_filepath_ != '\0') { + remove(premature_exit_filepath_); + } + } + + private: + const char* const premature_exit_filepath_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile); +}; + +} // namespace internal + +// class TestEventListeners + +TestEventListeners::TestEventListeners() + : repeater_(new internal::TestEventRepeater()), + default_result_printer_(NULL), + default_xml_generator_(NULL) { +} + +TestEventListeners::~TestEventListeners() { delete repeater_; } + +// Returns the standard listener responsible for the default console +// output. Can be removed from the listeners list to shut down default +// console output. Note that removing this object from the listener list +// with Release transfers its ownership to the user. +void TestEventListeners::Append(TestEventListener* listener) { + repeater_->Append(listener); +} + +// Removes the given event listener from the list and returns it. It then +// becomes the caller's responsibility to delete the listener. Returns +// NULL if the listener is not found in the list. +TestEventListener* TestEventListeners::Release(TestEventListener* listener) { + if (listener == default_result_printer_) + default_result_printer_ = NULL; + else if (listener == default_xml_generator_) + default_xml_generator_ = NULL; + return repeater_->Release(listener); +} + +// Returns repeater that broadcasts the TestEventListener events to all +// subscribers. +TestEventListener* TestEventListeners::repeater() { return repeater_; } + +// Sets the default_result_printer attribute to the provided listener. +// The listener is also added to the listener list and previous +// default_result_printer is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) { + if (default_result_printer_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_result_printer_); + default_result_printer_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Sets the default_xml_generator attribute to the provided listener. The +// listener is also added to the listener list and previous +// default_xml_generator is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) { + if (default_xml_generator_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_xml_generator_); + default_xml_generator_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Controls whether events will be forwarded by the repeater to the +// listeners in the list. +bool TestEventListeners::EventForwardingEnabled() const { + return repeater_->forwarding_enabled(); +} + +void TestEventListeners::SuppressEventForwarding() { + repeater_->set_forwarding_enabled(false); +} + +// class UnitTest + +// Gets the singleton UnitTest object. The first time this method is +// called, a UnitTest object is constructed and returned. Consecutive +// calls will return the same object. +// +// We don't protect this under mutex_ as a user is not supposed to +// call this before main() starts, from which point on the return +// value will never change. +UnitTest* UnitTest::GetInstance() { + // When compiled with MSVC 7.1 in optimized mode, destroying the + // UnitTest object upon exiting the program messes up the exit code, + // causing successful tests to appear failed. We have to use a + // different implementation in this case to bypass the compiler bug. + // This implementation makes the compiler happy, at the cost of + // leaking the UnitTest object. + + // CodeGear C++Builder insists on a public destructor for the + // default implementation. Use this implementation to keep good OO + // design with private destructor. + +#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) + static UnitTest* const instance = new UnitTest; + return instance; +#else + static UnitTest instance; + return &instance; +#endif // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) +} + +// Gets the number of successful test cases. +int UnitTest::successful_test_case_count() const { + return impl()->successful_test_case_count(); +} + +// Gets the number of failed test cases. +int UnitTest::failed_test_case_count() const { + return impl()->failed_test_case_count(); +} + +// Gets the number of all test cases. +int UnitTest::total_test_case_count() const { + return impl()->total_test_case_count(); +} + +// Gets the number of all test cases that contain at least one test +// that should run. +int UnitTest::test_case_to_run_count() const { + return impl()->test_case_to_run_count(); +} + +// Gets the number of successful tests. +int UnitTest::successful_test_count() const { + return impl()->successful_test_count(); +} + +// Gets the number of failed tests. +int UnitTest::failed_test_count() const { return impl()->failed_test_count(); } + +// Gets the number of disabled tests that will be reported in the XML report. +int UnitTest::reportable_disabled_test_count() const { + return impl()->reportable_disabled_test_count(); +} + +// Gets the number of disabled tests. +int UnitTest::disabled_test_count() const { + return impl()->disabled_test_count(); +} + +// Gets the number of tests to be printed in the XML report. +int UnitTest::reportable_test_count() const { + return impl()->reportable_test_count(); +} + +// Gets the number of all tests. +int UnitTest::total_test_count() const { return impl()->total_test_count(); } + +// Gets the number of tests that should run. +int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); } + +// Gets the time of the test program start, in ms from the start of the +// UNIX epoch. +internal::TimeInMillis UnitTest::start_timestamp() const { + return impl()->start_timestamp(); +} + +// Gets the elapsed time, in milliseconds. +internal::TimeInMillis UnitTest::elapsed_time() const { + return impl()->elapsed_time(); +} + +// Returns true iff the unit test passed (i.e. all test cases passed). +bool UnitTest::Passed() const { return impl()->Passed(); } + +// Returns true iff the unit test failed (i.e. some test case failed +// or something outside of all tests failed). +bool UnitTest::Failed() const { return impl()->Failed(); } + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +const TestCase* UnitTest::GetTestCase(int i) const { + return impl()->GetTestCase(i); +} + +// Returns the TestResult containing information on test failures and +// properties logged outside of individual test cases. +const TestResult& UnitTest::ad_hoc_test_result() const { + return *impl()->ad_hoc_test_result(); +} + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +TestCase* UnitTest::GetMutableTestCase(int i) { + return impl()->GetMutableTestCase(i); +} + +// Returns the list of event listeners that can be used to track events +// inside Google Test. +TestEventListeners& UnitTest::listeners() { + return *impl()->listeners(); +} + +// Registers and returns a global test environment. When a test +// program is run, all global test environments will be set-up in the +// order they were registered. After all tests in the program have +// finished, all global test environments will be torn-down in the +// *reverse* order they were registered. +// +// The UnitTest object takes ownership of the given environment. +// +// We don't protect this under mutex_, as we only support calling it +// from the main thread. +Environment* UnitTest::AddEnvironment(Environment* env) { + if (env == NULL) { + return NULL; + } + + impl_->environments().push_back(env); + return env; +} + +// Adds a TestPartResult to the current TestResult object. All Google Test +// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call +// this to report their results. The user code should use the +// assertion macros instead of calling this directly. +void UnitTest::AddTestPartResult( + TestPartResult::Type result_type, + const char* file_name, + int line_number, + const std::string& message, + const std::string& os_stack_trace) GTEST_LOCK_EXCLUDED_(mutex_) { + Message msg; + msg << message; + + internal::MutexLock lock(&mutex_); + if (impl_->gtest_trace_stack().size() > 0) { + msg << "\n" << GTEST_NAME_ << " trace:"; + + for (int i = static_cast(impl_->gtest_trace_stack().size()); + i > 0; --i) { + const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1]; + msg << "\n" << internal::FormatFileLocation(trace.file, trace.line) + << " " << trace.message; + } + } + + if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) { + msg << internal::kStackTraceMarker << os_stack_trace; + } + + const TestPartResult result = + TestPartResult(result_type, file_name, line_number, + msg.GetString().c_str()); + impl_->GetTestPartResultReporterForCurrentThread()-> + ReportTestPartResult(result); + + if (result_type != TestPartResult::kSuccess) { + // gtest_break_on_failure takes precedence over + // gtest_throw_on_failure. This allows a user to set the latter + // in the code (perhaps in order to use Google Test assertions + // with another testing framework) and specify the former on the + // command line for debugging. + if (GTEST_FLAG(break_on_failure)) { +#if GTEST_OS_WINDOWS + // Using DebugBreak on Windows allows gtest to still break into a debugger + // when a failure happens and both the --gtest_break_on_failure and + // the --gtest_catch_exceptions flags are specified. + DebugBreak(); +#else + // Dereference NULL through a volatile pointer to prevent the compiler + // from removing. We use this rather than abort() or __builtin_trap() for + // portability: Symbian doesn't implement abort() well, and some debuggers + // don't correctly trap abort(). + *static_cast(NULL) = 1; +#endif // GTEST_OS_WINDOWS + } else if (GTEST_FLAG(throw_on_failure)) { +#if GTEST_HAS_EXCEPTIONS + throw internal::GoogleTestFailureException(result); +#else + // We cannot call abort() as it generates a pop-up in debug mode + // that cannot be suppressed in VC 7.1 or below. + exit(1); +#endif + } + } +} + +// Adds a TestProperty to the current TestResult object when invoked from +// inside a test, to current TestCase's ad_hoc_test_result_ when invoked +// from SetUpTestCase or TearDownTestCase, or to the global property set +// when invoked elsewhere. If the result already contains a property with +// the same key, the value will be updated. +void UnitTest::RecordProperty(const std::string& key, + const std::string& value) { + impl_->RecordProperty(TestProperty(key, value)); +} + +// Runs all tests in this UnitTest object and prints the result. +// Returns 0 if successful, or 1 otherwise. +// +// We don't protect this under mutex_, as we only support calling it +// from the main thread. +int UnitTest::Run() { + const bool in_death_test_child_process = + internal::GTEST_FLAG(internal_run_death_test).length() > 0; + + // Google Test implements this protocol for catching that a test + // program exits before returning control to Google Test: + // + // 1. Upon start, Google Test creates a file whose absolute path + // is specified by the environment variable + // TEST_PREMATURE_EXIT_FILE. + // 2. When Google Test has finished its work, it deletes the file. + // + // This allows a test runner to set TEST_PREMATURE_EXIT_FILE before + // running a Google-Test-based test program and check the existence + // of the file at the end of the test execution to see if it has + // exited prematurely. + + // If we are in the child process of a death test, don't + // create/delete the premature exit file, as doing so is unnecessary + // and will confuse the parent process. Otherwise, create/delete + // the file upon entering/leaving this function. If the program + // somehow exits before this function has a chance to return, the + // premature-exit file will be left undeleted, causing a test runner + // that understands the premature-exit-file protocol to report the + // test as having failed. + const internal::ScopedPrematureExitFile premature_exit_file( + in_death_test_child_process ? + NULL : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE")); + + // Captures the value of GTEST_FLAG(catch_exceptions). This value will be + // used for the duration of the program. + impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions)); + +#if GTEST_HAS_SEH + // Either the user wants Google Test to catch exceptions thrown by the + // tests or this is executing in the context of death test child + // process. In either case the user does not want to see pop-up dialogs + // about crashes - they are expected. + if (impl()->catch_exceptions() || in_death_test_child_process) { +# if !GTEST_OS_WINDOWS_MOBILE + // SetErrorMode doesn't exist on CE. + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | + SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); +# endif // !GTEST_OS_WINDOWS_MOBILE + +# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE + // Death test children can be terminated with _abort(). On Windows, + // _abort() can show a dialog with a warning message. This forces the + // abort message to go to stderr instead. + _set_error_mode(_OUT_TO_STDERR); +# endif + +# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program. We need to suppress + // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement + // executed. Google Test will notify the user of any unexpected + // failure via stderr. + // + // VC++ doesn't define _set_abort_behavior() prior to the version 8.0. + // Users of prior VC versions shall suffer the agony and pain of + // clicking through the countless debug dialogs. + // TODO(vladl@google.com): find a way to suppress the abort dialog() in the + // debug mode when compiled with VC 7.1 or lower. + if (!GTEST_FLAG(break_on_failure)) + _set_abort_behavior( + 0x0, // Clear the following flags: + _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump. +# endif + } +#endif // GTEST_HAS_SEH + + return internal::HandleExceptionsInMethodIfSupported( + impl(), + &internal::UnitTestImpl::RunAllTests, + "auxiliary test code (environments or event listeners)") ? 0 : 1; +} + +// Returns the working directory when the first TEST() or TEST_F() was +// executed. +const char* UnitTest::original_working_dir() const { + return impl_->original_working_dir_.c_str(); +} + +// Returns the TestCase object for the test that's currently running, +// or NULL if no test is running. +const TestCase* UnitTest::current_test_case() const + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + return impl_->current_test_case(); +} + +// Returns the TestInfo object for the test that's currently running, +// or NULL if no test is running. +const TestInfo* UnitTest::current_test_info() const + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + return impl_->current_test_info(); +} + +// Returns the random seed used at the start of the current test run. +int UnitTest::random_seed() const { return impl_->random_seed(); } + +#if GTEST_HAS_PARAM_TEST +// Returns ParameterizedTestCaseRegistry object used to keep track of +// value-parameterized tests and instantiate and register them. +internal::ParameterizedTestCaseRegistry& + UnitTest::parameterized_test_registry() + GTEST_LOCK_EXCLUDED_(mutex_) { + return impl_->parameterized_test_registry(); +} +#endif // GTEST_HAS_PARAM_TEST + +// Creates an empty UnitTest. +UnitTest::UnitTest() { + impl_ = new internal::UnitTestImpl(this); +} + +// Destructor of UnitTest. +UnitTest::~UnitTest() { + delete impl_; +} + +// Pushes a trace defined by SCOPED_TRACE() on to the per-thread +// Google Test trace stack. +void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + impl_->gtest_trace_stack().push_back(trace); +} + +// Pops a trace from the per-thread Google Test trace stack. +void UnitTest::PopGTestTrace() + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + impl_->gtest_trace_stack().pop_back(); +} + +namespace internal { + +UnitTestImpl::UnitTestImpl(UnitTest* parent) + : parent_(parent), +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4355) // Temporarily disables warning 4355 + // (using this in initializer). + default_global_test_part_result_reporter_(this), + default_per_thread_test_part_result_reporter_(this), +# pragma warning(pop) // Restores the warning state again. +#else + default_global_test_part_result_reporter_(this), + default_per_thread_test_part_result_reporter_(this), +#endif // _MSC_VER + global_test_part_result_repoter_( + &default_global_test_part_result_reporter_), + per_thread_test_part_result_reporter_( + &default_per_thread_test_part_result_reporter_), +#if GTEST_HAS_PARAM_TEST + parameterized_test_registry_(), + parameterized_tests_registered_(false), +#endif // GTEST_HAS_PARAM_TEST + last_death_test_case_(-1), + current_test_case_(NULL), + current_test_info_(NULL), + ad_hoc_test_result_(), + os_stack_trace_getter_(NULL), + post_flag_parse_init_performed_(false), + random_seed_(0), // Will be overridden by the flag before first use. + random_(0), // Will be reseeded before first use. + start_timestamp_(0), + elapsed_time_(0), +#if GTEST_HAS_DEATH_TEST + death_test_factory_(new DefaultDeathTestFactory), +#endif + // Will be overridden by the flag before first use. + catch_exceptions_(false) { + listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter); +} + +UnitTestImpl::~UnitTestImpl() { + // Deletes every TestCase. + ForEach(test_cases_, internal::Delete); + + // Deletes every Environment. + ForEach(environments_, internal::Delete); + + delete os_stack_trace_getter_; +} + +// Adds a TestProperty to the current TestResult object when invoked in a +// context of a test, to current test case's ad_hoc_test_result when invoke +// from SetUpTestCase/TearDownTestCase, or to the global property set +// otherwise. If the result already contains a property with the same key, +// the value will be updated. +void UnitTestImpl::RecordProperty(const TestProperty& test_property) { + std::string xml_element; + TestResult* test_result; // TestResult appropriate for property recording. + + if (current_test_info_ != NULL) { + xml_element = "testcase"; + test_result = &(current_test_info_->result_); + } else if (current_test_case_ != NULL) { + xml_element = "testsuite"; + test_result = &(current_test_case_->ad_hoc_test_result_); + } else { + xml_element = "testsuites"; + test_result = &ad_hoc_test_result_; + } + test_result->RecordProperty(xml_element, test_property); +} + +#if GTEST_HAS_DEATH_TEST +// Disables event forwarding if the control is currently in a death test +// subprocess. Must not be called before InitGoogleTest. +void UnitTestImpl::SuppressTestEventsIfInSubprocess() { + if (internal_run_death_test_flag_.get() != NULL) + listeners()->SuppressEventForwarding(); +} +#endif // GTEST_HAS_DEATH_TEST + +// Initializes event listeners performing XML output as specified by +// UnitTestOptions. Must not be called before InitGoogleTest. +void UnitTestImpl::ConfigureXmlOutput() { + const std::string& output_format = UnitTestOptions::GetOutputFormat(); + if (output_format == "xml") { + listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter( + UnitTestOptions::GetAbsolutePathToOutputFile().c_str())); + } else if (output_format != "") { + printf("WARNING: unrecognized output format \"%s\" ignored.\n", + output_format.c_str()); + fflush(stdout); + } +} + +#if GTEST_CAN_STREAM_RESULTS_ +// Initializes event listeners for streaming test results in string form. +// Must not be called before InitGoogleTest. +void UnitTestImpl::ConfigureStreamingOutput() { + const std::string& target = GTEST_FLAG(stream_result_to); + if (!target.empty()) { + const size_t pos = target.find(':'); + if (pos != std::string::npos) { + listeners()->Append(new StreamingListener(target.substr(0, pos), + target.substr(pos+1))); + } else { + printf("WARNING: unrecognized streaming target \"%s\" ignored.\n", + target.c_str()); + fflush(stdout); + } + } +} +#endif // GTEST_CAN_STREAM_RESULTS_ + +// Performs initialization dependent upon flag values obtained in +// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to +// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest +// this function is also called from RunAllTests. Since this function can be +// called more than once, it has to be idempotent. +void UnitTestImpl::PostFlagParsingInit() { + // Ensures that this function does not execute more than once. + if (!post_flag_parse_init_performed_) { + post_flag_parse_init_performed_ = true; + +#if GTEST_HAS_DEATH_TEST + InitDeathTestSubprocessControlInfo(); + SuppressTestEventsIfInSubprocess(); +#endif // GTEST_HAS_DEATH_TEST + + // Registers parameterized tests. This makes parameterized tests + // available to the UnitTest reflection API without running + // RUN_ALL_TESTS. + RegisterParameterizedTests(); + + // Configures listeners for XML output. This makes it possible for users + // to shut down the default XML output before invoking RUN_ALL_TESTS. + ConfigureXmlOutput(); + +#if GTEST_CAN_STREAM_RESULTS_ + // Configures listeners for streaming test results to the specified server. + ConfigureStreamingOutput(); +#endif // GTEST_CAN_STREAM_RESULTS_ + } +} + +// A predicate that checks the name of a TestCase against a known +// value. +// +// This is used for implementation of the UnitTest class only. We put +// it in the anonymous namespace to prevent polluting the outer +// namespace. +// +// TestCaseNameIs is copyable. +class TestCaseNameIs { + public: + // Constructor. + explicit TestCaseNameIs(const std::string& name) + : name_(name) {} + + // Returns true iff the name of test_case matches name_. + bool operator()(const TestCase* test_case) const { + return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0; + } + + private: + std::string name_; +}; + +// Finds and returns a TestCase with the given name. If one doesn't +// exist, creates one and returns it. It's the CALLER'S +// RESPONSIBILITY to ensure that this function is only called WHEN THE +// TESTS ARE NOT SHUFFLED. +// +// Arguments: +// +// test_case_name: name of the test case +// type_param: the name of the test case's type parameter, or NULL if +// this is not a typed or a type-parameterized test case. +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +TestCase* UnitTestImpl::GetTestCase(const char* test_case_name, + const char* type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc) { + // Can we find a TestCase with the given name? + const std::vector::const_iterator test_case = + std::find_if(test_cases_.begin(), test_cases_.end(), + TestCaseNameIs(test_case_name)); + + if (test_case != test_cases_.end()) + return *test_case; + + // No. Let's create one. + TestCase* const new_test_case = + new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc); + + // Is this a death test case? + if (internal::UnitTestOptions::MatchesFilter(test_case_name, + kDeathTestCaseFilter)) { + // Yes. Inserts the test case after the last death test case + // defined so far. This only works when the test cases haven't + // been shuffled. Otherwise we may end up running a death test + // after a non-death test. + ++last_death_test_case_; + test_cases_.insert(test_cases_.begin() + last_death_test_case_, + new_test_case); + } else { + // No. Appends to the end of the list. + test_cases_.push_back(new_test_case); + } + + test_case_indices_.push_back(static_cast(test_case_indices_.size())); + return new_test_case; +} + +// Helpers for setting up / tearing down the given environment. They +// are for use in the ForEach() function. +static void SetUpEnvironment(Environment* env) { env->SetUp(); } +static void TearDownEnvironment(Environment* env) { env->TearDown(); } + +// Runs all tests in this UnitTest object, prints the result, and +// returns true if all tests are successful. If any exception is +// thrown during a test, the test is considered to be failed, but the +// rest of the tests will still be run. +// +// When parameterized tests are enabled, it expands and registers +// parameterized tests first in RegisterParameterizedTests(). +// All other functions called from RunAllTests() may safely assume that +// parameterized tests are ready to be counted and run. +bool UnitTestImpl::RunAllTests() { + // Makes sure InitGoogleTest() was called. + if (!GTestIsInitialized()) { + printf("%s", + "\nThis test program did NOT call ::testing::InitGoogleTest " + "before calling RUN_ALL_TESTS(). Please fix it.\n"); + return false; + } + + // Do not run any test if the --help flag was specified. + if (g_help_flag) + return true; + + // Repeats the call to the post-flag parsing initialization in case the + // user didn't call InitGoogleTest. + PostFlagParsingInit(); + + // Even if sharding is not on, test runners may want to use the + // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding + // protocol. + internal::WriteToShardStatusFileIfNeeded(); + + // True iff we are in a subprocess for running a thread-safe-style + // death test. + bool in_subprocess_for_death_test = false; + +#if GTEST_HAS_DEATH_TEST + in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL); +#endif // GTEST_HAS_DEATH_TEST + + const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex, + in_subprocess_for_death_test); + + // Compares the full test names with the filter to decide which + // tests to run. + const bool has_tests_to_run = FilterTests(should_shard + ? HONOR_SHARDING_PROTOCOL + : IGNORE_SHARDING_PROTOCOL) > 0; + + // Lists the tests and exits if the --gtest_list_tests flag was specified. + if (GTEST_FLAG(list_tests)) { + // This must be called *after* FilterTests() has been called. + ListTestsMatchingFilter(); + return true; + } + + random_seed_ = GTEST_FLAG(shuffle) ? + GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0; + + // True iff at least one test has failed. + bool failed = false; + + TestEventListener* repeater = listeners()->repeater(); + + start_timestamp_ = GetTimeInMillis(); + repeater->OnTestProgramStart(*parent_); + + // How many times to repeat the tests? We don't want to repeat them + // when we are inside the subprocess of a death test. + const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat); + // Repeats forever if the repeat count is negative. + const bool forever = repeat < 0; + for (int i = 0; forever || i != repeat; i++) { + // We want to preserve failures generated by ad-hoc test + // assertions executed before RUN_ALL_TESTS(). + ClearNonAdHocTestResult(); + + const TimeInMillis start = GetTimeInMillis(); + + // Shuffles test cases and tests if requested. + if (has_tests_to_run && GTEST_FLAG(shuffle)) { + random()->Reseed(random_seed_); + // This should be done before calling OnTestIterationStart(), + // such that a test event listener can see the actual test order + // in the event. + ShuffleTests(); + } + + // Tells the unit test event listeners that the tests are about to start. + repeater->OnTestIterationStart(*parent_, i); + + // Runs each test case if there is at least one test to run. + if (has_tests_to_run) { + // Sets up all environments beforehand. + repeater->OnEnvironmentsSetUpStart(*parent_); + ForEach(environments_, SetUpEnvironment); + repeater->OnEnvironmentsSetUpEnd(*parent_); + + // Runs the tests only if there was no fatal failure during global + // set-up. + if (!Test::HasFatalFailure()) { + for (int test_index = 0; test_index < total_test_case_count(); + test_index++) { + GetMutableTestCase(test_index)->Run(); + } + } + + // Tears down all environments in reverse order afterwards. + repeater->OnEnvironmentsTearDownStart(*parent_); + std::for_each(environments_.rbegin(), environments_.rend(), + TearDownEnvironment); + repeater->OnEnvironmentsTearDownEnd(*parent_); + } + + elapsed_time_ = GetTimeInMillis() - start; + + // Tells the unit test event listener that the tests have just finished. + repeater->OnTestIterationEnd(*parent_, i); + + // Gets the result and clears it. + if (!Passed()) { + failed = true; + } + + // Restores the original test order after the iteration. This + // allows the user to quickly repro a failure that happens in the + // N-th iteration without repeating the first (N - 1) iterations. + // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in + // case the user somehow changes the value of the flag somewhere + // (it's always safe to unshuffle the tests). + UnshuffleTests(); + + if (GTEST_FLAG(shuffle)) { + // Picks a new random seed for each iteration. + random_seed_ = GetNextRandomSeed(random_seed_); + } + } + + repeater->OnTestProgramEnd(*parent_); + + return !failed; +} + +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded() { + const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile); + if (test_shard_file != NULL) { + FILE* const file = posix::FOpen(test_shard_file, "w"); + if (file == NULL) { + ColoredPrintf(COLOR_RED, + "Could not write to the test shard status file \"%s\" " + "specified by the %s environment variable.\n", + test_shard_file, kTestShardStatusFile); + fflush(stdout); + exit(EXIT_FAILURE); + } + fclose(file); + } +} + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (i.e., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +bool ShouldShard(const char* total_shards_env, + const char* shard_index_env, + bool in_subprocess_for_death_test) { + if (in_subprocess_for_death_test) { + return false; + } + + const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1); + const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1); + + if (total_shards == -1 && shard_index == -1) { + return false; + } else if (total_shards == -1 && shard_index != -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestShardIndex << " = " << shard_index + << ", but have left " << kTestTotalShards << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (total_shards != -1 && shard_index == -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestTotalShards << " = " << total_shards + << ", but have left " << kTestShardIndex << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (shard_index < 0 || shard_index >= total_shards) { + const Message msg = Message() + << "Invalid environment variables: we require 0 <= " + << kTestShardIndex << " < " << kTestTotalShards + << ", but you have " << kTestShardIndex << "=" << shard_index + << ", " << kTestTotalShards << "=" << total_shards << ".\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } + + return total_shards > 1; +} + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error +// and aborts. +Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) { + const char* str_val = posix::GetEnv(var); + if (str_val == NULL) { + return default_val; + } + + Int32 result; + if (!ParseInt32(Message() << "The value of environment variable " << var, + str_val, &result)) { + exit(EXIT_FAILURE); + } + return result; +} + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) { + return (test_id % total_shards) == shard_index; +} + +// Compares the name of each test with the user-specified filter to +// decide whether the test should be run, then records the result in +// each TestCase and TestInfo object. +// If shard_tests == true, further filters tests based on sharding +// variables in the environment - see +// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide. +// Returns the number of tests that should run. +int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) { + const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestTotalShards, -1) : -1; + const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestShardIndex, -1) : -1; + + // num_runnable_tests are the number of tests that will + // run across all shards (i.e., match filter and are not disabled). + // num_selected_tests are the number of tests to be run on + // this shard. + int num_runnable_tests = 0; + int num_selected_tests = 0; + for (size_t i = 0; i < test_cases_.size(); i++) { + TestCase* const test_case = test_cases_[i]; + const std::string &test_case_name = test_case->name(); + test_case->set_should_run(false); + + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + TestInfo* const test_info = test_case->test_info_list()[j]; + const std::string test_name(test_info->name()); + // A test is disabled if test case name or test name matches + // kDisableTestFilter. + const bool is_disabled = + internal::UnitTestOptions::MatchesFilter(test_case_name, + kDisableTestFilter) || + internal::UnitTestOptions::MatchesFilter(test_name, + kDisableTestFilter); + test_info->is_disabled_ = is_disabled; + + const bool matches_filter = + internal::UnitTestOptions::FilterMatchesTest(test_case_name, + test_name); + test_info->matches_filter_ = matches_filter; + + const bool is_runnable = + (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) && + matches_filter; + + const bool is_selected = is_runnable && + (shard_tests == IGNORE_SHARDING_PROTOCOL || + ShouldRunTestOnShard(total_shards, shard_index, + num_runnable_tests)); + + num_runnable_tests += is_runnable; + num_selected_tests += is_selected; + + test_info->should_run_ = is_selected; + test_case->set_should_run(test_case->should_run() || is_selected); + } + } + return num_selected_tests; +} + +// Prints the given C-string on a single line by replacing all '\n' +// characters with string "\\n". If the output takes more than +// max_length characters, only prints the first max_length characters +// and "...". +static void PrintOnOneLine(const char* str, int max_length) { + if (str != NULL) { + for (int i = 0; *str != '\0'; ++str) { + if (i >= max_length) { + printf("..."); + break; + } + if (*str == '\n') { + printf("\\n"); + i += 2; + } else { + printf("%c", *str); + ++i; + } + } + } +} + +// Prints the names of the tests matching the user-specified filter flag. +void UnitTestImpl::ListTestsMatchingFilter() { + // Print at most this many characters for each type/value parameter. + const int kMaxParamLength = 250; + + for (size_t i = 0; i < test_cases_.size(); i++) { + const TestCase* const test_case = test_cases_[i]; + bool printed_test_case_name = false; + + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + const TestInfo* const test_info = + test_case->test_info_list()[j]; + if (test_info->matches_filter_) { + if (!printed_test_case_name) { + printed_test_case_name = true; + printf("%s.", test_case->name()); + if (test_case->type_param() != NULL) { + printf(" # %s = ", kTypeParamLabel); + // We print the type parameter on a single line to make + // the output easy to parse by a program. + PrintOnOneLine(test_case->type_param(), kMaxParamLength); + } + printf("\n"); + } + printf(" %s", test_info->name()); + if (test_info->value_param() != NULL) { + printf(" # %s = ", kValueParamLabel); + // We print the value parameter on a single line to make the + // output easy to parse by a program. + PrintOnOneLine(test_info->value_param(), kMaxParamLength); + } + printf("\n"); + } + } + } + fflush(stdout); +} + +// Sets the OS stack trace getter. +// +// Does nothing if the input and the current OS stack trace getter are +// the same; otherwise, deletes the old getter and makes the input the +// current getter. +void UnitTestImpl::set_os_stack_trace_getter( + OsStackTraceGetterInterface* getter) { + if (os_stack_trace_getter_ != getter) { + delete os_stack_trace_getter_; + os_stack_trace_getter_ = getter; + } +} + +// Returns the current OS stack trace getter if it is not NULL; +// otherwise, creates an OsStackTraceGetter, makes it the current +// getter, and returns it. +OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() { + if (os_stack_trace_getter_ == NULL) { + os_stack_trace_getter_ = new OsStackTraceGetter; + } + + return os_stack_trace_getter_; +} + +// Returns the TestResult for the test that's currently running, or +// the TestResult for the ad hoc test if no test is running. +TestResult* UnitTestImpl::current_test_result() { + return current_test_info_ ? + &(current_test_info_->result_) : &ad_hoc_test_result_; +} + +// Shuffles all test cases, and the tests within each test case, +// making sure that death tests are still run first. +void UnitTestImpl::ShuffleTests() { + // Shuffles the death test cases. + ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_); + + // Shuffles the non-death test cases. + ShuffleRange(random(), last_death_test_case_ + 1, + static_cast(test_cases_.size()), &test_case_indices_); + + // Shuffles the tests inside each test case. + for (size_t i = 0; i < test_cases_.size(); i++) { + test_cases_[i]->ShuffleTests(random()); + } +} + +// Restores the test cases and tests to their order before the first shuffle. +void UnitTestImpl::UnshuffleTests() { + for (size_t i = 0; i < test_cases_.size(); i++) { + // Unshuffles the tests in each test case. + test_cases_[i]->UnshuffleTests(); + // Resets the index of each test case. + test_case_indices_[i] = static_cast(i); + } +} + +// Returns the current OS stack trace as an std::string. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in +// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. +std::string GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/, + int skip_count) { + // We pass skip_count + 1 to skip this wrapper function in addition + // to what the user really wants to skip. + return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1); +} + +// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to +// suppress unreachable code warnings. +namespace { +class ClassUniqueToAlwaysTrue {}; +} + +bool IsTrue(bool condition) { return condition; } + +bool AlwaysTrue() { +#if GTEST_HAS_EXCEPTIONS + // This condition is always false so AlwaysTrue() never actually throws, + // but it makes the compiler think that it may throw. + if (IsTrue(false)) + throw ClassUniqueToAlwaysTrue(); +#endif // GTEST_HAS_EXCEPTIONS + return true; +} + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +bool SkipPrefix(const char* prefix, const char** pstr) { + const size_t prefix_len = strlen(prefix); + if (strncmp(*pstr, prefix, prefix_len) == 0) { + *pstr += prefix_len; + return true; + } + return false; +} + +// Parses a string as a command line flag. The string should have +// the format "--flag=value". When def_optional is true, the "=value" +// part can be omitted. +// +// Returns the value of the flag, or NULL if the parsing failed. +const char* ParseFlagValue(const char* str, + const char* flag, + bool def_optional) { + // str and flag must not be NULL. + if (str == NULL || flag == NULL) return NULL; + + // The flag must start with "--" followed by GTEST_FLAG_PREFIX_. + const std::string flag_str = std::string("--") + GTEST_FLAG_PREFIX_ + flag; + const size_t flag_len = flag_str.length(); + if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL; + + // Skips the flag name. + const char* flag_end = str + flag_len; + + // When def_optional is true, it's OK to not have a "=value" part. + if (def_optional && (flag_end[0] == '\0')) { + return flag_end; + } + + // If def_optional is true and there are more characters after the + // flag name, or if def_optional is false, there must be a '=' after + // the flag name. + if (flag_end[0] != '=') return NULL; + + // Returns the string after "=". + return flag_end + 1; +} + +// Parses a string for a bool flag, in the form of either +// "--flag=value" or "--flag". +// +// In the former case, the value is taken as true as long as it does +// not start with '0', 'f', or 'F'. +// +// In the latter case, the value is taken as true. +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseBoolFlag(const char* str, const char* flag, bool* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, true); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Converts the string value to a bool. + *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F'); + return true; +} + +// Parses a string for an Int32 flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseInt32Flag(const char* str, const char* flag, Int32* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Sets *value to the value of the flag. + return ParseInt32(Message() << "The value of flag --" << flag, + value_str, value); +} + +// Parses a string for a string flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseStringFlag(const char* str, const char* flag, std::string* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Sets *value to the value of the flag. + *value = value_str; + return true; +} + +// Determines whether a string has a prefix that Google Test uses for its +// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_. +// If Google Test detects that a command line flag has its prefix but is not +// recognized, it will print its help message. Flags starting with +// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test +// internal flags and do not trigger the help message. +static bool HasGoogleTestFlagPrefix(const char* str) { + return (SkipPrefix("--", &str) || + SkipPrefix("-", &str) || + SkipPrefix("/", &str)) && + !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) && + (SkipPrefix(GTEST_FLAG_PREFIX_, &str) || + SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str)); +} + +// Prints a string containing code-encoded text. The following escape +// sequences can be used in the string to control the text color: +// +// @@ prints a single '@' character. +// @R changes the color to red. +// @G changes the color to green. +// @Y changes the color to yellow. +// @D changes to the default terminal text color. +// +// TODO(wan@google.com): Write tests for this once we add stdout +// capturing to Google Test. +static void PrintColorEncoded(const char* str) { + GTestColor color = COLOR_DEFAULT; // The current color. + + // Conceptually, we split the string into segments divided by escape + // sequences. Then we print one segment at a time. At the end of + // each iteration, the str pointer advances to the beginning of the + // next segment. + for (;;) { + const char* p = strchr(str, '@'); + if (p == NULL) { + ColoredPrintf(color, "%s", str); + return; + } + + ColoredPrintf(color, "%s", std::string(str, p).c_str()); + + const char ch = p[1]; + str = p + 2; + if (ch == '@') { + ColoredPrintf(color, "@"); + } else if (ch == 'D') { + color = COLOR_DEFAULT; + } else if (ch == 'R') { + color = COLOR_RED; + } else if (ch == 'G') { + color = COLOR_GREEN; + } else if (ch == 'Y') { + color = COLOR_YELLOW; + } else { + --str; + } + } +} + +static const char kColorEncodedHelpMessage[] = +"This program contains tests written using " GTEST_NAME_ ". You can use the\n" +"following command line flags to control its behavior:\n" +"\n" +"Test Selection:\n" +" @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n" +" List the names of all tests instead of running them. The name of\n" +" TEST(Foo, Bar) is \"Foo.Bar\".\n" +" @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS" + "[@G-@YNEGATIVE_PATTERNS]@D\n" +" Run only the tests whose name matches one of the positive patterns but\n" +" none of the negative patterns. '?' matches any single character; '*'\n" +" matches any substring; ':' separates two patterns.\n" +" @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n" +" Run all disabled tests too.\n" +"\n" +"Test Execution:\n" +" @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n" +" Run the tests repeatedly; use a negative count to repeat forever.\n" +" @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n" +" Randomize tests' orders on every iteration.\n" +" @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n" +" Random number seed to use for shuffling test orders (between 1 and\n" +" 99999, or 0 to use a seed based on the current time).\n" +"\n" +"Test Output:\n" +" @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n" +" Enable/disable colored output. The default is @Gauto@D.\n" +" -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n" +" Don't print the elapsed time of each test.\n" +" @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G" + GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n" +" Generate an XML report in the given directory or with the given file\n" +" name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n" +#if GTEST_CAN_STREAM_RESULTS_ +" @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n" +" Stream test results to the given server.\n" +#endif // GTEST_CAN_STREAM_RESULTS_ +"\n" +"Assertion Behavior:\n" +#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n" +" Set the default death test style.\n" +#endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n" +" Turn assertion failures into debugger break-points.\n" +" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n" +" Turn assertion failures into C++ exceptions.\n" +" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n" +" Do not report exceptions as test failures. Instead, allow them\n" +" to crash the program or throw a pop-up (on Windows).\n" +"\n" +"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set " + "the corresponding\n" +"environment variable of a flag (all letters in upper-case). For example, to\n" +"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_ + "color=no@D or set\n" +"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n" +"\n" +"For more information, please read the " GTEST_NAME_ " documentation at\n" +"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n" +"(not one in your own code or tests), please report it to\n" +"@G<" GTEST_DEV_EMAIL_ ">@D.\n"; + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. The type parameter CharType can be +// instantiated to either char or wchar_t. +template +void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) { + for (int i = 1; i < *argc; i++) { + const std::string arg_string = StreamableToString(argv[i]); + const char* const arg = arg_string.c_str(); + + using internal::ParseBoolFlag; + using internal::ParseInt32Flag; + using internal::ParseStringFlag; + + // Do we see a Google Test flag? + if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag, + >EST_FLAG(also_run_disabled_tests)) || + ParseBoolFlag(arg, kBreakOnFailureFlag, + >EST_FLAG(break_on_failure)) || + ParseBoolFlag(arg, kCatchExceptionsFlag, + >EST_FLAG(catch_exceptions)) || + ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) || + ParseStringFlag(arg, kDeathTestStyleFlag, + >EST_FLAG(death_test_style)) || + ParseBoolFlag(arg, kDeathTestUseFork, + >EST_FLAG(death_test_use_fork)) || + ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) || + ParseStringFlag(arg, kInternalRunDeathTestFlag, + >EST_FLAG(internal_run_death_test)) || + ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) || + ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) || + ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) || + ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) || + ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) || + ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) || + ParseInt32Flag(arg, kStackTraceDepthFlag, + >EST_FLAG(stack_trace_depth)) || + ParseStringFlag(arg, kStreamResultToFlag, + >EST_FLAG(stream_result_to)) || + ParseBoolFlag(arg, kThrowOnFailureFlag, + >EST_FLAG(throw_on_failure)) + ) { + // Yes. Shift the remainder of the argv list left by one. Note + // that argv has (*argc + 1) elements, the last one always being + // NULL. The following loop moves the trailing NULL element as + // well. + for (int j = i; j != *argc; j++) { + argv[j] = argv[j + 1]; + } + + // Decrements the argument count. + (*argc)--; + + // We also need to decrement the iterator as we just removed + // an element. + i--; + } else if (arg_string == "--help" || arg_string == "-h" || + arg_string == "-?" || arg_string == "/?" || + HasGoogleTestFlagPrefix(arg)) { + // Both help flag and unrecognized Google Test flags (excluding + // internal ones) trigger help display. + g_help_flag = true; + } + } + + if (g_help_flag) { + // We print the help here instead of in RUN_ALL_TESTS(), as the + // latter may not be called at all if the user is using Google + // Test with another testing framework. + PrintColorEncoded(kColorEncodedHelpMessage); + } +} + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. +void ParseGoogleTestFlagsOnly(int* argc, char** argv) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} +void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} + +// The internal implementation of InitGoogleTest(). +// +// The type parameter CharType can be instantiated to either char or +// wchar_t. +template +void InitGoogleTestImpl(int* argc, CharType** argv) { + g_init_gtest_count++; + + // We don't want to run the initialization code twice. + if (g_init_gtest_count != 1) return; + + if (*argc <= 0) return; + + internal::g_executable_path = internal::StreamableToString(argv[0]); + +#if GTEST_HAS_DEATH_TEST + + g_argvs.clear(); + for (int i = 0; i != *argc; i++) { + g_argvs.push_back(StreamableToString(argv[i])); + } + +#endif // GTEST_HAS_DEATH_TEST + + ParseGoogleTestFlagsOnly(argc, argv); + GetUnitTestImpl()->PostFlagParsingInit(); +} + +} // namespace internal + +// Initializes Google Test. This must be called before calling +// RUN_ALL_TESTS(). In particular, it parses a command line for the +// flags that Google Test recognizes. Whenever a Google Test flag is +// seen, it is removed from argv, and *argc is decremented. +// +// No value is returned. Instead, the Google Test flag variables are +// updated. +// +// Calling the function for the second time has no user-visible effect. +void InitGoogleTest(int* argc, char** argv) { + internal::InitGoogleTestImpl(argc, argv); +} + +// This overloaded version can be used in Windows programs compiled in +// UNICODE mode. +void InitGoogleTest(int* argc, wchar_t** argv) { + internal::InitGoogleTestImpl(argc, argv); +} + +} // namespace testing +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev) +// +// This file implements death tests. + + +#if GTEST_HAS_DEATH_TEST + +# if GTEST_OS_MAC +# include +# endif // GTEST_OS_MAC + +# include +# include +# include + +# if GTEST_OS_LINUX +# include +# endif // GTEST_OS_LINUX + +# include + +# if GTEST_OS_WINDOWS +# include +# else +# include +# include +# endif // GTEST_OS_WINDOWS + +# if GTEST_OS_QNX +# include +# endif // GTEST_OS_QNX + +#endif // GTEST_HAS_DEATH_TEST + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { + +// Constants. + +// The default death test style. +static const char kDefaultDeathTestStyle[] = "fast"; + +GTEST_DEFINE_string_( + death_test_style, + internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle), + "Indicates how to run a death test in a forked child process: " + "\"threadsafe\" (child process re-executes the test binary " + "from the beginning, running only the specific death test) or " + "\"fast\" (child process runs the death test immediately " + "after forking)."); + +GTEST_DEFINE_bool_( + death_test_use_fork, + internal::BoolFromGTestEnv("death_test_use_fork", false), + "Instructs to use fork()/_exit() instead of clone() in death tests. " + "Ignored and always uses fork() on POSIX systems where clone() is not " + "implemented. Useful when running under valgrind or similar tools if " + "those do not support clone(). Valgrind 3.3.1 will just fail if " + "it sees an unsupported combination of clone() flags. " + "It is not recommended to use this flag w/o valgrind though it will " + "work in 99% of the cases. Once valgrind is fixed, this flag will " + "most likely be removed."); + +namespace internal { +GTEST_DEFINE_string_( + internal_run_death_test, "", + "Indicates the file, line number, temporal index of " + "the single death test to run, and a file descriptor to " + "which a success code may be sent, all separated by " + "the '|' characters. This flag is specified if and only if the current " + "process is a sub-process launched for running a thread-safe " + "death test. FOR INTERNAL USE ONLY."); +} // namespace internal + +#if GTEST_HAS_DEATH_TEST + +namespace internal { + +// Valid only for fast death tests. Indicates the code is running in the +// child process of a fast style death test. +static bool g_in_fast_death_test_child = false; + +// Returns a Boolean value indicating whether the caller is currently +// executing in the context of the death test child process. Tools such as +// Valgrind heap checkers may need this to modify their behavior in death +// tests. IMPORTANT: This is an internal utility. Using it may break the +// implementation of death tests. User code MUST NOT use it. +bool InDeathTestChild() { +# if GTEST_OS_WINDOWS + + // On Windows, death tests are thread-safe regardless of the value of the + // death_test_style flag. + return !GTEST_FLAG(internal_run_death_test).empty(); + +# else + + if (GTEST_FLAG(death_test_style) == "threadsafe") + return !GTEST_FLAG(internal_run_death_test).empty(); + else + return g_in_fast_death_test_child; +#endif +} + +} // namespace internal + +// ExitedWithCode constructor. +ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { +} + +// ExitedWithCode function-call operator. +bool ExitedWithCode::operator()(int exit_status) const { +# if GTEST_OS_WINDOWS + + return exit_status == exit_code_; + +# else + + return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_; + +# endif // GTEST_OS_WINDOWS +} + +# if !GTEST_OS_WINDOWS +// KilledBySignal constructor. +KilledBySignal::KilledBySignal(int signum) : signum_(signum) { +} + +// KilledBySignal function-call operator. +bool KilledBySignal::operator()(int exit_status) const { + return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_; +} +# endif // !GTEST_OS_WINDOWS + +namespace internal { + +// Utilities needed for death tests. + +// Generates a textual description of a given exit code, in the format +// specified by wait(2). +static std::string ExitSummary(int exit_code) { + Message m; + +# if GTEST_OS_WINDOWS + + m << "Exited with exit status " << exit_code; + +# else + + if (WIFEXITED(exit_code)) { + m << "Exited with exit status " << WEXITSTATUS(exit_code); + } else if (WIFSIGNALED(exit_code)) { + m << "Terminated by signal " << WTERMSIG(exit_code); + } +# ifdef WCOREDUMP + if (WCOREDUMP(exit_code)) { + m << " (core dumped)"; + } +# endif +# endif // GTEST_OS_WINDOWS + + return m.GetString(); +} + +// Returns true if exit_status describes a process that was terminated +// by a signal, or exited normally with a nonzero exit code. +bool ExitedUnsuccessfully(int exit_status) { + return !ExitedWithCode(0)(exit_status); +} + +# if !GTEST_OS_WINDOWS +// Generates a textual failure message when a death test finds more than +// one thread running, or cannot determine the number of threads, prior +// to executing the given statement. It is the responsibility of the +// caller not to pass a thread_count of 1. +static std::string DeathTestThreadWarning(size_t thread_count) { + Message msg; + msg << "Death tests use fork(), which is unsafe particularly" + << " in a threaded context. For this test, " << GTEST_NAME_ << " "; + if (thread_count == 0) + msg << "couldn't detect the number of threads."; + else + msg << "detected " << thread_count << " threads."; + return msg.GetString(); +} +# endif // !GTEST_OS_WINDOWS + +// Flag characters for reporting a death test that did not die. +static const char kDeathTestLived = 'L'; +static const char kDeathTestReturned = 'R'; +static const char kDeathTestThrew = 'T'; +static const char kDeathTestInternalError = 'I'; + +// An enumeration describing all of the possible ways that a death test can +// conclude. DIED means that the process died while executing the test +// code; LIVED means that process lived beyond the end of the test code; +// RETURNED means that the test statement attempted to execute a return +// statement, which is not allowed; THREW means that the test statement +// returned control by throwing an exception. IN_PROGRESS means the test +// has not yet concluded. +// TODO(vladl@google.com): Unify names and possibly values for +// AbortReason, DeathTestOutcome, and flag characters above. +enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW }; + +// Routine for aborting the program which is safe to call from an +// exec-style death test child process, in which case the error +// message is propagated back to the parent process. Otherwise, the +// message is simply printed to stderr. In either case, the program +// then exits with status 1. +void DeathTestAbort(const std::string& message) { + // On a POSIX system, this function may be called from a threadsafe-style + // death test child process, which operates on a very small stack. Use + // the heap for any additional non-minuscule memory requirements. + const InternalRunDeathTestFlag* const flag = + GetUnitTestImpl()->internal_run_death_test_flag(); + if (flag != NULL) { + FILE* parent = posix::FDOpen(flag->write_fd(), "w"); + fputc(kDeathTestInternalError, parent); + fprintf(parent, "%s", message.c_str()); + fflush(parent); + _exit(1); + } else { + fprintf(stderr, "%s", message.c_str()); + fflush(stderr); + posix::Abort(); + } +} + +// A replacement for CHECK that calls DeathTestAbort if the assertion +// fails. +# define GTEST_DEATH_TEST_CHECK_(expression) \ + do { \ + if (!::testing::internal::IsTrue(expression)) { \ + DeathTestAbort( \ + ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ + + ::testing::internal::StreamableToString(__LINE__) + ": " \ + + #expression); \ + } \ + } while (::testing::internal::AlwaysFalse()) + +// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for +// evaluating any system call that fulfills two conditions: it must return +// -1 on failure, and set errno to EINTR when it is interrupted and +// should be tried again. The macro expands to a loop that repeatedly +// evaluates the expression as long as it evaluates to -1 and sets +// errno to EINTR. If the expression evaluates to -1 but errno is +// something other than EINTR, DeathTestAbort is called. +# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \ + do { \ + int gtest_retval; \ + do { \ + gtest_retval = (expression); \ + } while (gtest_retval == -1 && errno == EINTR); \ + if (gtest_retval == -1) { \ + DeathTestAbort( \ + ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ + + ::testing::internal::StreamableToString(__LINE__) + ": " \ + + #expression + " != -1"); \ + } \ + } while (::testing::internal::AlwaysFalse()) + +// Returns the message describing the last system error in errno. +std::string GetLastErrnoDescription() { + return errno == 0 ? "" : posix::StrError(errno); +} + +// This is called from a death test parent process to read a failure +// message from the death test child process and log it with the FATAL +// severity. On Windows, the message is read from a pipe handle. On other +// platforms, it is read from a file descriptor. +static void FailFromInternalError(int fd) { + Message error; + char buffer[256]; + int num_read; + + do { + while ((num_read = posix::Read(fd, buffer, 255)) > 0) { + buffer[num_read] = '\0'; + error << buffer; + } + } while (num_read == -1 && errno == EINTR); + + if (num_read == 0) { + GTEST_LOG_(FATAL) << error.GetString(); + } else { + const int last_error = errno; + GTEST_LOG_(FATAL) << "Error while reading death test internal: " + << GetLastErrnoDescription() << " [" << last_error << "]"; + } +} + +// Death test constructor. Increments the running death test count +// for the current test. +DeathTest::DeathTest() { + TestInfo* const info = GetUnitTestImpl()->current_test_info(); + if (info == NULL) { + DeathTestAbort("Cannot run a death test outside of a TEST or " + "TEST_F construct"); + } +} + +// Creates and returns a death test by dispatching to the current +// death test factory. +bool DeathTest::Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test) { + return GetUnitTestImpl()->death_test_factory()->Create( + statement, regex, file, line, test); +} + +const char* DeathTest::LastMessage() { + return last_death_test_message_.c_str(); +} + +void DeathTest::set_last_death_test_message(const std::string& message) { + last_death_test_message_ = message; +} + +std::string DeathTest::last_death_test_message_; + +// Provides cross platform implementation for some death functionality. +class DeathTestImpl : public DeathTest { + protected: + DeathTestImpl(const char* a_statement, const RE* a_regex) + : statement_(a_statement), + regex_(a_regex), + spawned_(false), + status_(-1), + outcome_(IN_PROGRESS), + read_fd_(-1), + write_fd_(-1) {} + + // read_fd_ is expected to be closed and cleared by a derived class. + ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); } + + void Abort(AbortReason reason); + virtual bool Passed(bool status_ok); + + const char* statement() const { return statement_; } + const RE* regex() const { return regex_; } + bool spawned() const { return spawned_; } + void set_spawned(bool is_spawned) { spawned_ = is_spawned; } + int status() const { return status_; } + void set_status(int a_status) { status_ = a_status; } + DeathTestOutcome outcome() const { return outcome_; } + void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; } + int read_fd() const { return read_fd_; } + void set_read_fd(int fd) { read_fd_ = fd; } + int write_fd() const { return write_fd_; } + void set_write_fd(int fd) { write_fd_ = fd; } + + // Called in the parent process only. Reads the result code of the death + // test child process via a pipe, interprets it to set the outcome_ + // member, and closes read_fd_. Outputs diagnostics and terminates in + // case of unexpected codes. + void ReadAndInterpretStatusByte(); + + private: + // The textual content of the code this object is testing. This class + // doesn't own this string and should not attempt to delete it. + const char* const statement_; + // The regular expression which test output must match. DeathTestImpl + // doesn't own this object and should not attempt to delete it. + const RE* const regex_; + // True if the death test child process has been successfully spawned. + bool spawned_; + // The exit status of the child process. + int status_; + // How the death test concluded. + DeathTestOutcome outcome_; + // Descriptor to the read end of the pipe to the child process. It is + // always -1 in the child process. The child keeps its write end of the + // pipe in write_fd_. + int read_fd_; + // Descriptor to the child's write end of the pipe to the parent process. + // It is always -1 in the parent process. The parent keeps its end of the + // pipe in read_fd_. + int write_fd_; +}; + +// Called in the parent process only. Reads the result code of the death +// test child process via a pipe, interprets it to set the outcome_ +// member, and closes read_fd_. Outputs diagnostics and terminates in +// case of unexpected codes. +void DeathTestImpl::ReadAndInterpretStatusByte() { + char flag; + int bytes_read; + + // The read() here blocks until data is available (signifying the + // failure of the death test) or until the pipe is closed (signifying + // its success), so it's okay to call this in the parent before + // the child process has exited. + do { + bytes_read = posix::Read(read_fd(), &flag, 1); + } while (bytes_read == -1 && errno == EINTR); + + if (bytes_read == 0) { + set_outcome(DIED); + } else if (bytes_read == 1) { + switch (flag) { + case kDeathTestReturned: + set_outcome(RETURNED); + break; + case kDeathTestThrew: + set_outcome(THREW); + break; + case kDeathTestLived: + set_outcome(LIVED); + break; + case kDeathTestInternalError: + FailFromInternalError(read_fd()); // Does not return. + break; + default: + GTEST_LOG_(FATAL) << "Death test child process reported " + << "unexpected status byte (" + << static_cast(flag) << ")"; + } + } else { + GTEST_LOG_(FATAL) << "Read from death test child process failed: " + << GetLastErrnoDescription(); + } + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd())); + set_read_fd(-1); +} + +// Signals that the death test code which should have exited, didn't. +// Should be called only in a death test child process. +// Writes a status byte to the child's status file descriptor, then +// calls _exit(1). +void DeathTestImpl::Abort(AbortReason reason) { + // The parent process considers the death test to be a failure if + // it finds any data in our pipe. So, here we write a single flag byte + // to the pipe, then exit. + const char status_ch = + reason == TEST_DID_NOT_DIE ? kDeathTestLived : + reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned; + + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1)); + // We are leaking the descriptor here because on some platforms (i.e., + // when built as Windows DLL), destructors of global objects will still + // run after calling _exit(). On such systems, write_fd_ will be + // indirectly closed from the destructor of UnitTestImpl, causing double + // close if it is also closed here. On debug configurations, double close + // may assert. As there are no in-process buffers to flush here, we are + // relying on the OS to close the descriptor after the process terminates + // when the destructors are not run. + _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) +} + +// Returns an indented copy of stderr output for a death test. +// This makes distinguishing death test output lines from regular log lines +// much easier. +static ::std::string FormatDeathTestOutput(const ::std::string& output) { + ::std::string ret; + for (size_t at = 0; ; ) { + const size_t line_end = output.find('\n', at); + ret += "[ DEATH ] "; + if (line_end == ::std::string::npos) { + ret += output.substr(at); + break; + } + ret += output.substr(at, line_end + 1 - at); + at = line_end + 1; + } + return ret; +} + +// Assesses the success or failure of a death test, using both private +// members which have previously been set, and one argument: +// +// Private data members: +// outcome: An enumeration describing how the death test +// concluded: DIED, LIVED, THREW, or RETURNED. The death test +// fails in the latter three cases. +// status: The exit status of the child process. On *nix, it is in the +// in the format specified by wait(2). On Windows, this is the +// value supplied to the ExitProcess() API or a numeric code +// of the exception that terminated the program. +// regex: A regular expression object to be applied to +// the test's captured standard error output; the death test +// fails if it does not match. +// +// Argument: +// status_ok: true if exit_status is acceptable in the context of +// this particular death test, which fails if it is false +// +// Returns true iff all of the above conditions are met. Otherwise, the +// first failing condition, in the order given above, is the one that is +// reported. Also sets the last death test message string. +bool DeathTestImpl::Passed(bool status_ok) { + if (!spawned()) + return false; + + const std::string error_message = GetCapturedStderr(); + + bool success = false; + Message buffer; + + buffer << "Death test: " << statement() << "\n"; + switch (outcome()) { + case LIVED: + buffer << " Result: failed to die.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case THREW: + buffer << " Result: threw an exception.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case RETURNED: + buffer << " Result: illegal return in test statement.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case DIED: + if (status_ok) { + const bool matched = RE::PartialMatch(error_message.c_str(), *regex()); + if (matched) { + success = true; + } else { + buffer << " Result: died but not with expected error.\n" + << " Expected: " << regex()->pattern() << "\n" + << "Actual msg:\n" << FormatDeathTestOutput(error_message); + } + } else { + buffer << " Result: died but not with expected exit code:\n" + << " " << ExitSummary(status()) << "\n" + << "Actual msg:\n" << FormatDeathTestOutput(error_message); + } + break; + case IN_PROGRESS: + default: + GTEST_LOG_(FATAL) + << "DeathTest::Passed somehow called before conclusion of test"; + } + + DeathTest::set_last_death_test_message(buffer.GetString()); + return success; +} + +# if GTEST_OS_WINDOWS +// WindowsDeathTest implements death tests on Windows. Due to the +// specifics of starting new processes on Windows, death tests there are +// always threadsafe, and Google Test considers the +// --gtest_death_test_style=fast setting to be equivalent to +// --gtest_death_test_style=threadsafe there. +// +// A few implementation notes: Like the Linux version, the Windows +// implementation uses pipes for child-to-parent communication. But due to +// the specifics of pipes on Windows, some extra steps are required: +// +// 1. The parent creates a communication pipe and stores handles to both +// ends of it. +// 2. The parent starts the child and provides it with the information +// necessary to acquire the handle to the write end of the pipe. +// 3. The child acquires the write end of the pipe and signals the parent +// using a Windows event. +// 4. Now the parent can release the write end of the pipe on its side. If +// this is done before step 3, the object's reference count goes down to +// 0 and it is destroyed, preventing the child from acquiring it. The +// parent now has to release it, or read operations on the read end of +// the pipe will not return when the child terminates. +// 5. The parent reads child's output through the pipe (outcome code and +// any possible error messages) from the pipe, and its stderr and then +// determines whether to fail the test. +// +// Note: to distinguish Win32 API calls from the local method and function +// calls, the former are explicitly resolved in the global namespace. +// +class WindowsDeathTest : public DeathTestImpl { + public: + WindowsDeathTest(const char* a_statement, + const RE* a_regex, + const char* file, + int line) + : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {} + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + virtual TestRole AssumeRole(); + + private: + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; + // Handle to the write end of the pipe to the child process. + AutoHandle write_handle_; + // Child process handle. + AutoHandle child_handle_; + // Event the child process uses to signal the parent that it has + // acquired the handle to the write end of the pipe. After seeing this + // event the parent can release its own handles to make sure its + // ReadFile() calls return when the child terminates. + AutoHandle event_handle_; +}; + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int WindowsDeathTest::Wait() { + if (!spawned()) + return 0; + + // Wait until the child either signals that it has acquired the write end + // of the pipe or it dies. + const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() }; + switch (::WaitForMultipleObjects(2, + wait_handles, + FALSE, // Waits for any of the handles. + INFINITE)) { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + break; + default: + GTEST_DEATH_TEST_CHECK_(false); // Should not get here. + } + + // The child has acquired the write end of the pipe or exited. + // We release the handle on our side and continue. + write_handle_.Reset(); + event_handle_.Reset(); + + ReadAndInterpretStatusByte(); + + // Waits for the child process to exit if it haven't already. This + // returns immediately if the child has already exited, regardless of + // whether previous calls to WaitForMultipleObjects synchronized on this + // handle or not. + GTEST_DEATH_TEST_CHECK_( + WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(), + INFINITE)); + DWORD status_code; + GTEST_DEATH_TEST_CHECK_( + ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE); + child_handle_.Reset(); + set_status(static_cast(status_code)); + return status(); +} + +// The AssumeRole process for a Windows death test. It creates a child +// process with the same executable as the current process to run the +// death test. The child process is given the --gtest_filter and +// --gtest_internal_run_death_test flags such that it knows to run the +// current death test only. +DeathTest::TestRole WindowsDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + // ParseInternalRunDeathTestFlag() has performed all the necessary + // processing. + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + // WindowsDeathTest uses an anonymous pipe to communicate results of + // a death test. + SECURITY_ATTRIBUTES handles_are_inheritable = { + sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; + HANDLE read_handle, write_handle; + GTEST_DEATH_TEST_CHECK_( + ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable, + 0) // Default buffer size. + != FALSE); + set_read_fd(::_open_osfhandle(reinterpret_cast(read_handle), + O_RDONLY)); + write_handle_.Reset(write_handle); + event_handle_.Reset(::CreateEvent( + &handles_are_inheritable, + TRUE, // The event will automatically reset to non-signaled state. + FALSE, // The initial state is non-signalled. + NULL)); // The even is unnamed. + GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL); + const std::string filter_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + + info->test_case_name() + "." + info->name(); + const std::string internal_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + + "=" + file_ + "|" + StreamableToString(line_) + "|" + + StreamableToString(death_test_index) + "|" + + StreamableToString(static_cast(::GetCurrentProcessId())) + + // size_t has the same width as pointers on both 32-bit and 64-bit + // Windows platforms. + // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx. + "|" + StreamableToString(reinterpret_cast(write_handle)) + + "|" + StreamableToString(reinterpret_cast(event_handle_.Get())); + + char executable_path[_MAX_PATH + 1]; // NOLINT + GTEST_DEATH_TEST_CHECK_( + _MAX_PATH + 1 != ::GetModuleFileNameA(NULL, + executable_path, + _MAX_PATH)); + + std::string command_line = + std::string(::GetCommandLineA()) + " " + filter_flag + " \"" + + internal_flag + "\""; + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // Flush the log buffers since the log streams are shared with the child. + FlushInfoLog(); + + // The child process will share the standard handles with the parent. + STARTUPINFOA startup_info; + memset(&startup_info, 0, sizeof(STARTUPINFO)); + startup_info.dwFlags = STARTF_USESTDHANDLES; + startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE); + startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); + startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); + + PROCESS_INFORMATION process_info; + GTEST_DEATH_TEST_CHECK_(::CreateProcessA( + executable_path, + const_cast(command_line.c_str()), + NULL, // Retuned process handle is not inheritable. + NULL, // Retuned thread handle is not inheritable. + TRUE, // Child inherits all inheritable handles (for write_handle_). + 0x0, // Default creation flags. + NULL, // Inherit the parent's environment. + UnitTest::GetInstance()->original_working_dir(), + &startup_info, + &process_info) != FALSE); + child_handle_.Reset(process_info.hProcess); + ::CloseHandle(process_info.hThread); + set_spawned(true); + return OVERSEE_TEST; +} +# else // We are not on Windows. + +// ForkingDeathTest provides implementations for most of the abstract +// methods of the DeathTest interface. Only the AssumeRole method is +// left undefined. +class ForkingDeathTest : public DeathTestImpl { + public: + ForkingDeathTest(const char* statement, const RE* regex); + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + + protected: + void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } + + private: + // PID of child process during death test; 0 in the child process itself. + pid_t child_pid_; +}; + +// Constructs a ForkingDeathTest. +ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex) + : DeathTestImpl(a_statement, a_regex), + child_pid_(-1) {} + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int ForkingDeathTest::Wait() { + if (!spawned()) + return 0; + + ReadAndInterpretStatusByte(); + + int status_value; + GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0)); + set_status(status_value); + return status_value; +} + +// A concrete death test class that forks, then immediately runs the test +// in the child process. +class NoExecDeathTest : public ForkingDeathTest { + public: + NoExecDeathTest(const char* a_statement, const RE* a_regex) : + ForkingDeathTest(a_statement, a_regex) { } + virtual TestRole AssumeRole(); +}; + +// The AssumeRole process for a fork-and-run death test. It implements a +// straightforward fork, with a simple pipe to transmit the status byte. +DeathTest::TestRole NoExecDeathTest::AssumeRole() { + const size_t thread_count = GetThreadCount(); + if (thread_count != 1) { + GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count); + } + + int pipe_fd[2]; + GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); + + DeathTest::set_last_death_test_message(""); + CaptureStderr(); + // When we fork the process below, the log file buffers are copied, but the + // file descriptors are shared. We flush all log files here so that closing + // the file descriptors in the child process doesn't throw off the + // synchronization between descriptors and buffers in the parent process. + // This is as close to the fork as possible to avoid a race condition in case + // there are multiple threads running before the death test, and another + // thread writes to the log file. + FlushInfoLog(); + + const pid_t child_pid = fork(); + GTEST_DEATH_TEST_CHECK_(child_pid != -1); + set_child_pid(child_pid); + if (child_pid == 0) { + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0])); + set_write_fd(pipe_fd[1]); + // Redirects all logging to stderr in the child process to prevent + // concurrent writes to the log files. We capture stderr in the parent + // process and append the child process' output to a log. + LogToStderr(); + // Event forwarding to the listeners of event listener API mush be shut + // down in death test subprocesses. + GetUnitTestImpl()->listeners()->SuppressEventForwarding(); + g_in_fast_death_test_child = true; + return EXECUTE_TEST; + } else { + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); + set_read_fd(pipe_fd[0]); + set_spawned(true); + return OVERSEE_TEST; + } +} + +// A concrete death test class that forks and re-executes the main +// program from the beginning, with command-line flags set that cause +// only this specific death test to be run. +class ExecDeathTest : public ForkingDeathTest { + public: + ExecDeathTest(const char* a_statement, const RE* a_regex, + const char* file, int line) : + ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { } + virtual TestRole AssumeRole(); + private: + static ::std::vector + GetArgvsForDeathTestChildProcess() { + ::std::vector args = GetInjectableArgvs(); + return args; + } + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; +}; + +// Utility class for accumulating command-line arguments. +class Arguments { + public: + Arguments() { + args_.push_back(NULL); + } + + ~Arguments() { + for (std::vector::iterator i = args_.begin(); i != args_.end(); + ++i) { + free(*i); + } + } + void AddArgument(const char* argument) { + args_.insert(args_.end() - 1, posix::StrDup(argument)); + } + + template + void AddArguments(const ::std::vector& arguments) { + for (typename ::std::vector::const_iterator i = arguments.begin(); + i != arguments.end(); + ++i) { + args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); + } + } + char* const* Argv() { + return &args_[0]; + } + + private: + std::vector args_; +}; + +// A struct that encompasses the arguments to the child process of a +// threadsafe-style death test process. +struct ExecDeathTestArgs { + char* const* argv; // Command-line arguments for the child's call to exec + int close_fd; // File descriptor to close; the read end of a pipe +}; + +# if GTEST_OS_MAC +inline char** GetEnviron() { + // When Google Test is built as a framework on MacOS X, the environ variable + // is unavailable. Apple's documentation (man environ) recommends using + // _NSGetEnviron() instead. + return *_NSGetEnviron(); +} +# else +// Some POSIX platforms expect you to declare environ. extern "C" makes +// it reside in the global namespace. +extern "C" char** environ; +inline char** GetEnviron() { return environ; } +# endif // GTEST_OS_MAC + +# if !GTEST_OS_QNX +// The main function for a threadsafe-style death test child process. +// This function is called in a clone()-ed process and thus must avoid +// any potentially unsafe operations like malloc or libc functions. +static int ExecDeathTestChildMain(void* child_arg) { + ExecDeathTestArgs* const args = static_cast(child_arg); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd)); + + // We need to execute the test program in the same environment where + // it was originally invoked. Therefore we change to the original + // working directory first. + const char* const original_dir = + UnitTest::GetInstance()->original_working_dir(); + // We can safely call chdir() as it's a direct system call. + if (chdir(original_dir) != 0) { + DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + + GetLastErrnoDescription()); + return EXIT_FAILURE; + } + + // We can safely call execve() as it's a direct system call. We + // cannot use execvp() as it's a libc function and thus potentially + // unsafe. Since execve() doesn't search the PATH, the user must + // invoke the test program via a valid path that contains at least + // one path separator. + execve(args->argv[0], args->argv, GetEnviron()); + DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " + + original_dir + " failed: " + + GetLastErrnoDescription()); + return EXIT_FAILURE; +} +# endif // !GTEST_OS_QNX + +// Two utility routines that together determine the direction the stack +// grows. +// This could be accomplished more elegantly by a single recursive +// function, but we want to guard against the unlikely possibility of +// a smart compiler optimizing the recursion away. +// +// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining +// StackLowerThanAddress into StackGrowsDown, which then doesn't give +// correct answer. +void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_; +void StackLowerThanAddress(const void* ptr, bool* result) { + int dummy; + *result = (&dummy < ptr); +} + +bool StackGrowsDown() { + int dummy; + bool result; + StackLowerThanAddress(&dummy, &result); + return result; +} + +// Spawns a child process with the same executable as the current process in +// a thread-safe manner and instructs it to run the death test. The +// implementation uses fork(2) + exec. On systems where clone(2) is +// available, it is used instead, being slightly more thread-safe. On QNX, +// fork supports only single-threaded environments, so this function uses +// spawn(2) there instead. The function dies with an error message if +// anything goes wrong. +static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { + ExecDeathTestArgs args = { argv, close_fd }; + pid_t child_pid = -1; + +# if GTEST_OS_QNX + // Obtains the current directory and sets it to be closed in the child + // process. + const int cwd_fd = open(".", O_RDONLY); + GTEST_DEATH_TEST_CHECK_(cwd_fd != -1); + GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC)); + // We need to execute the test program in the same environment where + // it was originally invoked. Therefore we change to the original + // working directory first. + const char* const original_dir = + UnitTest::GetInstance()->original_working_dir(); + // We can safely call chdir() as it's a direct system call. + if (chdir(original_dir) != 0) { + DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + + GetLastErrnoDescription()); + return EXIT_FAILURE; + } + + int fd_flags; + // Set close_fd to be closed after spawn. + GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD)); + GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD, + fd_flags | FD_CLOEXEC)); + struct inheritance inherit = {0}; + // spawn is a system call. + child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron()); + // Restores the current working directory. + GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd)); + +# else // GTEST_OS_QNX +# if GTEST_OS_LINUX + // When a SIGPROF signal is received while fork() or clone() are executing, + // the process may hang. To avoid this, we ignore SIGPROF here and re-enable + // it after the call to fork()/clone() is complete. + struct sigaction saved_sigprof_action; + struct sigaction ignore_sigprof_action; + memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action)); + sigemptyset(&ignore_sigprof_action.sa_mask); + ignore_sigprof_action.sa_handler = SIG_IGN; + GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction( + SIGPROF, &ignore_sigprof_action, &saved_sigprof_action)); +# endif // GTEST_OS_LINUX + +# if GTEST_HAS_CLONE + const bool use_fork = GTEST_FLAG(death_test_use_fork); + + if (!use_fork) { + static const bool stack_grows_down = StackGrowsDown(); + const size_t stack_size = getpagesize(); + // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. + void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); + + // Maximum stack alignment in bytes: For a downward-growing stack, this + // amount is subtracted from size of the stack space to get an address + // that is within the stack space and is aligned on all systems we care + // about. As far as I know there is no ABI with stack alignment greater + // than 64. We assume stack and stack_size already have alignment of + // kMaxStackAlignment. + const size_t kMaxStackAlignment = 64; + void* const stack_top = + static_cast(stack) + + (stack_grows_down ? stack_size - kMaxStackAlignment : 0); + GTEST_DEATH_TEST_CHECK_(stack_size > kMaxStackAlignment && + reinterpret_cast(stack_top) % kMaxStackAlignment == 0); + + child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args); + + GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1); + } +# else + const bool use_fork = true; +# endif // GTEST_HAS_CLONE + + if (use_fork && (child_pid = fork()) == 0) { + ExecDeathTestChildMain(&args); + _exit(0); + } +# endif // GTEST_OS_QNX +# if GTEST_OS_LINUX + GTEST_DEATH_TEST_CHECK_SYSCALL_( + sigaction(SIGPROF, &saved_sigprof_action, NULL)); +# endif // GTEST_OS_LINUX + + GTEST_DEATH_TEST_CHECK_(child_pid != -1); + return child_pid; +} + +// The AssumeRole process for a fork-and-exec death test. It re-executes the +// main program from the beginning, setting the --gtest_filter +// and --gtest_internal_run_death_test flags to cause only the current +// death test to be re-run. +DeathTest::TestRole ExecDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + int pipe_fd[2]; + GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); + // Clear the close-on-exec flag on the write end of the pipe, lest + // it be closed when the child process does an exec: + GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1); + + const std::string filter_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + + info->test_case_name() + "." + info->name(); + const std::string internal_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" + + file_ + "|" + StreamableToString(line_) + "|" + + StreamableToString(death_test_index) + "|" + + StreamableToString(pipe_fd[1]); + Arguments args; + args.AddArguments(GetArgvsForDeathTestChildProcess()); + args.AddArgument(filter_flag.c_str()); + args.AddArgument(internal_flag.c_str()); + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // See the comment in NoExecDeathTest::AssumeRole for why the next line + // is necessary. + FlushInfoLog(); + + const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); + set_child_pid(child_pid); + set_read_fd(pipe_fd[0]); + set_spawned(true); + return OVERSEE_TEST; +} + +# endif // !GTEST_OS_WINDOWS + +// Creates a concrete DeathTest-derived class that depends on the +// --gtest_death_test_style flag, and sets the pointer pointed to +// by the "test" argument to its address. If the test should be +// skipped, sets that pointer to NULL. Returns true, unless the +// flag is set to an invalid value. +bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, + const char* file, int line, + DeathTest** test) { + UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const int death_test_index = impl->current_test_info() + ->increment_death_test_count(); + + if (flag != NULL) { + if (death_test_index > flag->index()) { + DeathTest::set_last_death_test_message( + "Death test count (" + StreamableToString(death_test_index) + + ") somehow exceeded expected maximum (" + + StreamableToString(flag->index()) + ")"); + return false; + } + + if (!(flag->file() == file && flag->line() == line && + flag->index() == death_test_index)) { + *test = NULL; + return true; + } + } + +# if GTEST_OS_WINDOWS + + if (GTEST_FLAG(death_test_style) == "threadsafe" || + GTEST_FLAG(death_test_style) == "fast") { + *test = new WindowsDeathTest(statement, regex, file, line); + } + +# else + + if (GTEST_FLAG(death_test_style) == "threadsafe") { + *test = new ExecDeathTest(statement, regex, file, line); + } else if (GTEST_FLAG(death_test_style) == "fast") { + *test = new NoExecDeathTest(statement, regex); + } + +# endif // GTEST_OS_WINDOWS + + else { // NOLINT - this is more readable than unbalanced brackets inside #if. + DeathTest::set_last_death_test_message( + "Unknown death test style \"" + GTEST_FLAG(death_test_style) + + "\" encountered"); + return false; + } + + return true; +} + +// Splits a given string on a given delimiter, populating a given +// vector with the fields. GTEST_HAS_DEATH_TEST implies that we have +// ::std::string, so we can use it here. +static void SplitString(const ::std::string& str, char delimiter, + ::std::vector< ::std::string>* dest) { + ::std::vector< ::std::string> parsed; + ::std::string::size_type pos = 0; + while (::testing::internal::AlwaysTrue()) { + const ::std::string::size_type colon = str.find(delimiter, pos); + if (colon == ::std::string::npos) { + parsed.push_back(str.substr(pos)); + break; + } else { + parsed.push_back(str.substr(pos, colon - pos)); + pos = colon + 1; + } + } + dest->swap(parsed); +} + +# if GTEST_OS_WINDOWS +// Recreates the pipe and event handles from the provided parameters, +// signals the event, and returns a file descriptor wrapped around the pipe +// handle. This function is called in the child process only. +int GetStatusFileDescriptor(unsigned int parent_process_id, + size_t write_handle_as_size_t, + size_t event_handle_as_size_t) { + AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE, + FALSE, // Non-inheritable. + parent_process_id)); + if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) { + DeathTestAbort("Unable to open parent process " + + StreamableToString(parent_process_id)); + } + + // TODO(vladl@google.com): Replace the following check with a + // compile-time assertion when available. + GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t)); + + const HANDLE write_handle = + reinterpret_cast(write_handle_as_size_t); + HANDLE dup_write_handle; + + // The newly initialized handle is accessible only in in the parent + // process. To obtain one accessible within the child, we need to use + // DuplicateHandle. + if (!::DuplicateHandle(parent_process_handle.Get(), write_handle, + ::GetCurrentProcess(), &dup_write_handle, + 0x0, // Requested privileges ignored since + // DUPLICATE_SAME_ACCESS is used. + FALSE, // Request non-inheritable handler. + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort("Unable to duplicate the pipe handle " + + StreamableToString(write_handle_as_size_t) + + " from the parent process " + + StreamableToString(parent_process_id)); + } + + const HANDLE event_handle = reinterpret_cast(event_handle_as_size_t); + HANDLE dup_event_handle; + + if (!::DuplicateHandle(parent_process_handle.Get(), event_handle, + ::GetCurrentProcess(), &dup_event_handle, + 0x0, + FALSE, + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort("Unable to duplicate the event handle " + + StreamableToString(event_handle_as_size_t) + + " from the parent process " + + StreamableToString(parent_process_id)); + } + + const int write_fd = + ::_open_osfhandle(reinterpret_cast(dup_write_handle), O_APPEND); + if (write_fd == -1) { + DeathTestAbort("Unable to convert pipe handle " + + StreamableToString(write_handle_as_size_t) + + " to a file descriptor"); + } + + // Signals the parent that the write end of the pipe has been acquired + // so the parent can release its own write end. + ::SetEvent(dup_event_handle); + + return write_fd; +} +# endif // GTEST_OS_WINDOWS + +// Returns a newly created InternalRunDeathTestFlag object with fields +// initialized from the GTEST_FLAG(internal_run_death_test) flag if +// the flag is specified; otherwise returns NULL. +InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { + if (GTEST_FLAG(internal_run_death_test) == "") return NULL; + + // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we + // can use it here. + int line = -1; + int index = -1; + ::std::vector< ::std::string> fields; + SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields); + int write_fd = -1; + +# if GTEST_OS_WINDOWS + + unsigned int parent_process_id = 0; + size_t write_handle_as_size_t = 0; + size_t event_handle_as_size_t = 0; + + if (fields.size() != 6 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &parent_process_id) + || !ParseNaturalNumber(fields[4], &write_handle_as_size_t) + || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) { + DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + + GTEST_FLAG(internal_run_death_test)); + } + write_fd = GetStatusFileDescriptor(parent_process_id, + write_handle_as_size_t, + event_handle_as_size_t); +# else + + if (fields.size() != 4 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &write_fd)) { + DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + + GTEST_FLAG(internal_run_death_test)); + } + +# endif // GTEST_OS_WINDOWS + + return new InternalRunDeathTestFlag(fields[0], line, index, write_fd); +} + +} // namespace internal + +#endif // GTEST_HAS_DEATH_TEST + +} // namespace testing +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: keith.ray@gmail.com (Keith Ray) + + +#include + +#if GTEST_OS_WINDOWS_MOBILE +# include +#elif GTEST_OS_WINDOWS +# include +# include +#elif GTEST_OS_SYMBIAN +// Symbian OpenC has PATH_MAX in sys/syslimits.h +# include +#else +# include +# include // Some Linux distributions define PATH_MAX here. +#endif // GTEST_OS_WINDOWS_MOBILE + +#if GTEST_OS_WINDOWS +# define GTEST_PATH_MAX_ _MAX_PATH +#elif defined(PATH_MAX) +# define GTEST_PATH_MAX_ PATH_MAX +#elif defined(_XOPEN_PATH_MAX) +# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX +#else +# define GTEST_PATH_MAX_ _POSIX_PATH_MAX +#endif // GTEST_OS_WINDOWS + + +namespace testing { +namespace internal { + +#if GTEST_OS_WINDOWS +// On Windows, '\\' is the standard path separator, but many tools and the +// Windows API also accept '/' as an alternate path separator. Unless otherwise +// noted, a file path can contain either kind of path separators, or a mixture +// of them. +const char kPathSeparator = '\\'; +const char kAlternatePathSeparator = '/'; +const char kPathSeparatorString[] = "\\"; +const char kAlternatePathSeparatorString[] = "/"; +# if GTEST_OS_WINDOWS_MOBILE +// Windows CE doesn't have a current directory. You should not use +// the current directory in tests on Windows CE, but this at least +// provides a reasonable fallback. +const char kCurrentDirectoryString[] = "\\"; +// Windows CE doesn't define INVALID_FILE_ATTRIBUTES +const DWORD kInvalidFileAttributes = 0xffffffff; +# else +const char kCurrentDirectoryString[] = ".\\"; +# endif // GTEST_OS_WINDOWS_MOBILE +#else +const char kPathSeparator = '/'; +const char kPathSeparatorString[] = "/"; +const char kCurrentDirectoryString[] = "./"; +#endif // GTEST_OS_WINDOWS + +// Returns whether the given character is a valid path separator. +static bool IsPathSeparator(char c) { +#if GTEST_HAS_ALT_PATH_SEP_ + return (c == kPathSeparator) || (c == kAlternatePathSeparator); +#else + return c == kPathSeparator; +#endif +} + +// Returns the current working directory, or "" if unsuccessful. +FilePath FilePath::GetCurrentDir() { +#if GTEST_OS_WINDOWS_MOBILE + // Windows CE doesn't have a current directory, so we just return + // something reasonable. + return FilePath(kCurrentDirectoryString); +#elif GTEST_OS_WINDOWS + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; + return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); +#else + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; + return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); +#endif // GTEST_OS_WINDOWS_MOBILE +} + +// Returns a copy of the FilePath with the case-insensitive extension removed. +// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns +// FilePath("dir/file"). If a case-insensitive extension is not +// found, returns a copy of the original FilePath. +FilePath FilePath::RemoveExtension(const char* extension) const { + const std::string dot_extension = std::string(".") + extension; + if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) { + return FilePath(pathname_.substr( + 0, pathname_.length() - dot_extension.length())); + } + return *this; +} + +// Returns a pointer to the last occurence of a valid path separator in +// the FilePath. On Windows, for example, both '/' and '\' are valid path +// separators. Returns NULL if no path separator was found. +const char* FilePath::FindLastPathSeparator() const { + const char* const last_sep = strrchr(c_str(), kPathSeparator); +#if GTEST_HAS_ALT_PATH_SEP_ + const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator); + // Comparing two pointers of which only one is NULL is undefined. + if (last_alt_sep != NULL && + (last_sep == NULL || last_alt_sep > last_sep)) { + return last_alt_sep; + } +#endif + return last_sep; +} + +// Returns a copy of the FilePath with the directory part removed. +// Example: FilePath("path/to/file").RemoveDirectoryName() returns +// FilePath("file"). If there is no directory part ("just_a_file"), it returns +// the FilePath unmodified. If there is no file part ("just_a_dir/") it +// returns an empty FilePath (""). +// On Windows platform, '\' is the path separator, otherwise it is '/'. +FilePath FilePath::RemoveDirectoryName() const { + const char* const last_sep = FindLastPathSeparator(); + return last_sep ? FilePath(last_sep + 1) : *this; +} + +// RemoveFileName returns the directory path with the filename removed. +// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". +// If the FilePath is "a_file" or "/a_file", RemoveFileName returns +// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does +// not have a file, like "just/a/dir/", it returns the FilePath unmodified. +// On Windows platform, '\' is the path separator, otherwise it is '/'. +FilePath FilePath::RemoveFileName() const { + const char* const last_sep = FindLastPathSeparator(); + std::string dir; + if (last_sep) { + dir = std::string(c_str(), last_sep + 1 - c_str()); + } else { + dir = kCurrentDirectoryString; + } + return FilePath(dir); +} + +// Helper functions for naming files in a directory for xml output. + +// Given directory = "dir", base_name = "test", number = 0, +// extension = "xml", returns "dir/test.xml". If number is greater +// than zero (e.g., 12), returns "dir/test_12.xml". +// On Windows platform, uses \ as the separator rather than /. +FilePath FilePath::MakeFileName(const FilePath& directory, + const FilePath& base_name, + int number, + const char* extension) { + std::string file; + if (number == 0) { + file = base_name.string() + "." + extension; + } else { + file = base_name.string() + "_" + StreamableToString(number) + + "." + extension; + } + return ConcatPaths(directory, FilePath(file)); +} + +// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml". +// On Windows, uses \ as the separator rather than /. +FilePath FilePath::ConcatPaths(const FilePath& directory, + const FilePath& relative_path) { + if (directory.IsEmpty()) + return relative_path; + const FilePath dir(directory.RemoveTrailingPathSeparator()); + return FilePath(dir.string() + kPathSeparator + relative_path.string()); +} + +// Returns true if pathname describes something findable in the file-system, +// either a file, directory, or whatever. +bool FilePath::FileOrDirectoryExists() const { +#if GTEST_OS_WINDOWS_MOBILE + LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str()); + const DWORD attributes = GetFileAttributes(unicode); + delete [] unicode; + return attributes != kInvalidFileAttributes; +#else + posix::StatStruct file_stat; + return posix::Stat(pathname_.c_str(), &file_stat) == 0; +#endif // GTEST_OS_WINDOWS_MOBILE +} + +// Returns true if pathname describes a directory in the file-system +// that exists. +bool FilePath::DirectoryExists() const { + bool result = false; +#if GTEST_OS_WINDOWS + // Don't strip off trailing separator if path is a root directory on + // Windows (like "C:\\"). + const FilePath& path(IsRootDirectory() ? *this : + RemoveTrailingPathSeparator()); +#else + const FilePath& path(*this); +#endif + +#if GTEST_OS_WINDOWS_MOBILE + LPCWSTR unicode = String::AnsiToUtf16(path.c_str()); + const DWORD attributes = GetFileAttributes(unicode); + delete [] unicode; + if ((attributes != kInvalidFileAttributes) && + (attributes & FILE_ATTRIBUTE_DIRECTORY)) { + result = true; + } +#else + posix::StatStruct file_stat; + result = posix::Stat(path.c_str(), &file_stat) == 0 && + posix::IsDir(file_stat); +#endif // GTEST_OS_WINDOWS_MOBILE + + return result; +} + +// Returns true if pathname describes a root directory. (Windows has one +// root directory per disk drive.) +bool FilePath::IsRootDirectory() const { +#if GTEST_OS_WINDOWS + // TODO(wan@google.com): on Windows a network share like + // \\server\share can be a root directory, although it cannot be the + // current directory. Handle this properly. + return pathname_.length() == 3 && IsAbsolutePath(); +#else + return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); +#endif +} + +// Returns true if pathname describes an absolute path. +bool FilePath::IsAbsolutePath() const { + const char* const name = pathname_.c_str(); +#if GTEST_OS_WINDOWS + return pathname_.length() >= 3 && + ((name[0] >= 'a' && name[0] <= 'z') || + (name[0] >= 'A' && name[0] <= 'Z')) && + name[1] == ':' && + IsPathSeparator(name[2]); +#else + return IsPathSeparator(name[0]); +#endif +} + +// Returns a pathname for a file that does not currently exist. The pathname +// will be directory/base_name.extension or +// directory/base_name_.extension if directory/base_name.extension +// already exists. The number will be incremented until a pathname is found +// that does not already exist. +// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. +// There could be a race condition if two or more processes are calling this +// function at the same time -- they could both pick the same filename. +FilePath FilePath::GenerateUniqueFileName(const FilePath& directory, + const FilePath& base_name, + const char* extension) { + FilePath full_pathname; + int number = 0; + do { + full_pathname.Set(MakeFileName(directory, base_name, number++, extension)); + } while (full_pathname.FileOrDirectoryExists()); + return full_pathname; +} + +// Returns true if FilePath ends with a path separator, which indicates that +// it is intended to represent a directory. Returns false otherwise. +// This does NOT check that a directory (or file) actually exists. +bool FilePath::IsDirectory() const { + return !pathname_.empty() && + IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]); +} + +// Create directories so that path exists. Returns true if successful or if +// the directories already exist; returns false if unable to create directories +// for any reason. +bool FilePath::CreateDirectoriesRecursively() const { + if (!this->IsDirectory()) { + return false; + } + + if (pathname_.length() == 0 || this->DirectoryExists()) { + return true; + } + + const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName()); + return parent.CreateDirectoriesRecursively() && this->CreateFolder(); +} + +// Create the directory so that path exists. Returns true if successful or +// if the directory already exists; returns false if unable to create the +// directory for any reason, including if the parent directory does not +// exist. Not named "CreateDirectory" because that's a macro on Windows. +bool FilePath::CreateFolder() const { +#if GTEST_OS_WINDOWS_MOBILE + FilePath removed_sep(this->RemoveTrailingPathSeparator()); + LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); + int result = CreateDirectory(unicode, NULL) ? 0 : -1; + delete [] unicode; +#elif GTEST_OS_WINDOWS + int result = _mkdir(pathname_.c_str()); +#else + int result = mkdir(pathname_.c_str(), 0777); +#endif // GTEST_OS_WINDOWS_MOBILE + + if (result == -1) { + return this->DirectoryExists(); // An error is OK if the directory exists. + } + return true; // No error. +} + +// If input name has a trailing separator character, remove it and return the +// name, otherwise return the name string unmodified. +// On Windows platform, uses \ as the separator, other platforms use /. +FilePath FilePath::RemoveTrailingPathSeparator() const { + return IsDirectory() + ? FilePath(pathname_.substr(0, pathname_.length() - 1)) + : *this; +} + +// Removes any redundant separators that might be in the pathname. +// For example, "bar///foo" becomes "bar/foo". Does not eliminate other +// redundancies that might be in a pathname involving "." or "..". +// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share). +void FilePath::Normalize() { + if (pathname_.c_str() == NULL) { + pathname_ = ""; + return; + } + const char* src = pathname_.c_str(); + char* const dest = new char[pathname_.length() + 1]; + char* dest_ptr = dest; + memset(dest_ptr, 0, pathname_.length() + 1); + + while (*src != '\0') { + *dest_ptr = *src; + if (!IsPathSeparator(*src)) { + src++; + } else { +#if GTEST_HAS_ALT_PATH_SEP_ + if (*dest_ptr == kAlternatePathSeparator) { + *dest_ptr = kPathSeparator; + } +#endif + while (IsPathSeparator(*src)) + src++; + } + dest_ptr++; + } + *dest_ptr = '\0'; + pathname_ = dest; + delete[] dest; +} + +} // namespace internal +} // namespace testing +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + + +#include +#include +#include +#include + +#if GTEST_OS_WINDOWS_MOBILE +# include // For TerminateProcess() +#elif GTEST_OS_WINDOWS +# include +# include +#else +# include +#endif // GTEST_OS_WINDOWS_MOBILE + +#if GTEST_OS_MAC +# include +# include +# include +#endif // GTEST_OS_MAC + +#if GTEST_OS_QNX +# include +# include +#endif // GTEST_OS_QNX + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { +namespace internal { + +#if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC and C++Builder do not provide a definition of STDERR_FILENO. +const int kStdOutFileno = 1; +const int kStdErrFileno = 2; +#else +const int kStdOutFileno = STDOUT_FILENO; +const int kStdErrFileno = STDERR_FILENO; +#endif // _MSC_VER + +#if GTEST_OS_MAC + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + const task_t task = mach_task_self(); + mach_msg_type_number_t thread_count; + thread_act_array_t thread_list; + const kern_return_t status = task_threads(task, &thread_list, &thread_count); + if (status == KERN_SUCCESS) { + // task_threads allocates resources in thread_list and we need to free them + // to avoid leaks. + vm_deallocate(task, + reinterpret_cast(thread_list), + sizeof(thread_t) * thread_count); + return static_cast(thread_count); + } else { + return 0; + } +} + +#elif GTEST_OS_QNX + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + const int fd = open("/proc/self/as", O_RDONLY); + if (fd < 0) { + return 0; + } + procfs_info process_info; + const int status = + devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL); + close(fd); + if (status == EOK) { + return static_cast(process_info.num_threads); + } else { + return 0; + } +} + +#else + +size_t GetThreadCount() { + // There's no portable way to detect the number of threads, so we just + // return 0 to indicate that we cannot detect it. + return 0; +} + +#endif // GTEST_OS_MAC + +#if GTEST_USES_POSIX_RE + +// Implements RE. Currently only needed for death tests. + +RE::~RE() { + if (is_valid_) { + // regfree'ing an invalid regex might crash because the content + // of the regex is undefined. Since the regex's are essentially + // the same, one cannot be valid (or invalid) without the other + // being so too. + regfree(&partial_regex_); + regfree(&full_regex_); + } + free(const_cast(pattern_)); +} + +// Returns true iff regular expression re matches the entire str. +bool RE::FullMatch(const char* str, const RE& re) { + if (!re.is_valid_) return false; + + regmatch_t match; + return regexec(&re.full_regex_, str, 1, &match, 0) == 0; +} + +// Returns true iff regular expression re matches a substring of str +// (including str itself). +bool RE::PartialMatch(const char* str, const RE& re) { + if (!re.is_valid_) return false; + + regmatch_t match; + return regexec(&re.partial_regex_, str, 1, &match, 0) == 0; +} + +// Initializes an RE from its string representation. +void RE::Init(const char* regex) { + pattern_ = posix::StrDup(regex); + + // Reserves enough bytes to hold the regular expression used for a + // full match. + const size_t full_regex_len = strlen(regex) + 10; + char* const full_pattern = new char[full_regex_len]; + + snprintf(full_pattern, full_regex_len, "^(%s)$", regex); + is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0; + // We want to call regcomp(&partial_regex_, ...) even if the + // previous expression returns false. Otherwise partial_regex_ may + // not be properly initialized can may cause trouble when it's + // freed. + // + // Some implementation of POSIX regex (e.g. on at least some + // versions of Cygwin) doesn't accept the empty string as a valid + // regex. We change it to an equivalent form "()" to be safe. + if (is_valid_) { + const char* const partial_regex = (*regex == '\0') ? "()" : regex; + is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0; + } + EXPECT_TRUE(is_valid_) + << "Regular expression \"" << regex + << "\" is not a valid POSIX Extended regular expression."; + + delete[] full_pattern; +} + +#elif GTEST_USES_SIMPLE_RE + +// Returns true iff ch appears anywhere in str (excluding the +// terminating '\0' character). +bool IsInSet(char ch, const char* str) { + return ch != '\0' && strchr(str, ch) != NULL; +} + +// Returns true iff ch belongs to the given classification. Unlike +// similar functions in , these aren't affected by the +// current locale. +bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; } +bool IsAsciiPunct(char ch) { + return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"); +} +bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); } +bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); } +bool IsAsciiWordChar(char ch) { + return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || + ('0' <= ch && ch <= '9') || ch == '_'; +} + +// Returns true iff "\\c" is a supported escape sequence. +bool IsValidEscape(char c) { + return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW")); +} + +// Returns true iff the given atom (specified by escaped and pattern) +// matches ch. The result is undefined if the atom is invalid. +bool AtomMatchesChar(bool escaped, char pattern_char, char ch) { + if (escaped) { // "\\p" where p is pattern_char. + switch (pattern_char) { + case 'd': return IsAsciiDigit(ch); + case 'D': return !IsAsciiDigit(ch); + case 'f': return ch == '\f'; + case 'n': return ch == '\n'; + case 'r': return ch == '\r'; + case 's': return IsAsciiWhiteSpace(ch); + case 'S': return !IsAsciiWhiteSpace(ch); + case 't': return ch == '\t'; + case 'v': return ch == '\v'; + case 'w': return IsAsciiWordChar(ch); + case 'W': return !IsAsciiWordChar(ch); + } + return IsAsciiPunct(pattern_char) && pattern_char == ch; + } + + return (pattern_char == '.' && ch != '\n') || pattern_char == ch; +} + +// Helper function used by ValidateRegex() to format error messages. +std::string FormatRegexSyntaxError(const char* regex, int index) { + return (Message() << "Syntax error at index " << index + << " in simple regular expression \"" << regex << "\": ").GetString(); +} + +// Generates non-fatal failures and returns false if regex is invalid; +// otherwise returns true. +bool ValidateRegex(const char* regex) { + if (regex == NULL) { + // TODO(wan@google.com): fix the source file location in the + // assertion failures to match where the regex is used in user + // code. + ADD_FAILURE() << "NULL is not a valid simple regular expression."; + return false; + } + + bool is_valid = true; + + // True iff ?, *, or + can follow the previous atom. + bool prev_repeatable = false; + for (int i = 0; regex[i]; i++) { + if (regex[i] == '\\') { // An escape sequence + i++; + if (regex[i] == '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "'\\' cannot appear at the end."; + return false; + } + + if (!IsValidEscape(regex[i])) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "invalid escape sequence \"\\" << regex[i] << "\"."; + is_valid = false; + } + prev_repeatable = true; + } else { // Not an escape sequence. + const char ch = regex[i]; + + if (ch == '^' && i > 0) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'^' can only appear at the beginning."; + is_valid = false; + } else if (ch == '$' && regex[i + 1] != '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'$' can only appear at the end."; + is_valid = false; + } else if (IsInSet(ch, "()[]{}|")) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' is unsupported."; + is_valid = false; + } else if (IsRepeat(ch) && !prev_repeatable) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' can only follow a repeatable token."; + is_valid = false; + } + + prev_repeatable = !IsInSet(ch, "^$?*+"); + } + } + + return is_valid; +} + +// Matches a repeated regex atom followed by a valid simple regular +// expression. The regex atom is defined as c if escaped is false, +// or \c otherwise. repeat is the repetition meta character (?, *, +// or +). The behavior is undefined if str contains too many +// characters to be indexable by size_t, in which case the test will +// probably time out anyway. We are fine with this limitation as +// std::string has it too. +bool MatchRepetitionAndRegexAtHead( + bool escaped, char c, char repeat, const char* regex, + const char* str) { + const size_t min_count = (repeat == '+') ? 1 : 0; + const size_t max_count = (repeat == '?') ? 1 : + static_cast(-1) - 1; + // We cannot call numeric_limits::max() as it conflicts with the + // max() macro on Windows. + + for (size_t i = 0; i <= max_count; ++i) { + // We know that the atom matches each of the first i characters in str. + if (i >= min_count && MatchRegexAtHead(regex, str + i)) { + // We have enough matches at the head, and the tail matches too. + // Since we only care about *whether* the pattern matches str + // (as opposed to *how* it matches), there is no need to find a + // greedy match. + return true; + } + if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) + return false; + } + return false; +} + +// Returns true iff regex matches a prefix of str. regex must be a +// valid simple regular expression and not start with "^", or the +// result is undefined. +bool MatchRegexAtHead(const char* regex, const char* str) { + if (*regex == '\0') // An empty regex matches a prefix of anything. + return true; + + // "$" only matches the end of a string. Note that regex being + // valid guarantees that there's nothing after "$" in it. + if (*regex == '$') + return *str == '\0'; + + // Is the first thing in regex an escape sequence? + const bool escaped = *regex == '\\'; + if (escaped) + ++regex; + if (IsRepeat(regex[1])) { + // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so + // here's an indirect recursion. It terminates as the regex gets + // shorter in each recursion. + return MatchRepetitionAndRegexAtHead( + escaped, regex[0], regex[1], regex + 2, str); + } else { + // regex isn't empty, isn't "$", and doesn't start with a + // repetition. We match the first atom of regex with the first + // character of str and recurse. + return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) && + MatchRegexAtHead(regex + 1, str + 1); + } +} + +// Returns true iff regex matches any substring of str. regex must be +// a valid simple regular expression, or the result is undefined. +// +// The algorithm is recursive, but the recursion depth doesn't exceed +// the regex length, so we won't need to worry about running out of +// stack space normally. In rare cases the time complexity can be +// exponential with respect to the regex length + the string length, +// but usually it's must faster (often close to linear). +bool MatchRegexAnywhere(const char* regex, const char* str) { + if (regex == NULL || str == NULL) + return false; + + if (*regex == '^') + return MatchRegexAtHead(regex + 1, str); + + // A successful match can be anywhere in str. + do { + if (MatchRegexAtHead(regex, str)) + return true; + } while (*str++ != '\0'); + return false; +} + +// Implements the RE class. + +RE::~RE() { + free(const_cast(pattern_)); + free(const_cast(full_pattern_)); +} + +// Returns true iff regular expression re matches the entire str. +bool RE::FullMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); +} + +// Returns true iff regular expression re matches a substring of str +// (including str itself). +bool RE::PartialMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); +} + +// Initializes an RE from its string representation. +void RE::Init(const char* regex) { + pattern_ = full_pattern_ = NULL; + if (regex != NULL) { + pattern_ = posix::StrDup(regex); + } + + is_valid_ = ValidateRegex(regex); + if (!is_valid_) { + // No need to calculate the full pattern when the regex is invalid. + return; + } + + const size_t len = strlen(regex); + // Reserves enough bytes to hold the regular expression used for a + // full match: we need space to prepend a '^', append a '$', and + // terminate the string with '\0'. + char* buffer = static_cast(malloc(len + 3)); + full_pattern_ = buffer; + + if (*regex != '^') + *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'. + + // We don't use snprintf or strncpy, as they trigger a warning when + // compiled with VC++ 8.0. + memcpy(buffer, regex, len); + buffer += len; + + if (len == 0 || regex[len - 1] != '$') + *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'. + + *buffer = '\0'; +} + +#endif // GTEST_USES_POSIX_RE + +const char kUnknownFile[] = "unknown file"; + +// Formats a source file path and a line number as they would appear +// in an error message from the compiler used to compile this code. +GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { + const std::string file_name(file == NULL ? kUnknownFile : file); + + if (line < 0) { + return file_name + ":"; + } +#ifdef _MSC_VER + return file_name + "(" + StreamableToString(line) + "):"; +#else + return file_name + ":" + StreamableToString(line) + ":"; +#endif // _MSC_VER +} + +// Formats a file location for compiler-independent XML output. +// Although this function is not platform dependent, we put it next to +// FormatFileLocation in order to contrast the two functions. +// Note that FormatCompilerIndependentFileLocation() does NOT append colon +// to the file location it produces, unlike FormatFileLocation(). +GTEST_API_ ::std::string FormatCompilerIndependentFileLocation( + const char* file, int line) { + const std::string file_name(file == NULL ? kUnknownFile : file); + + if (line < 0) + return file_name; + else + return file_name + ":" + StreamableToString(line); +} + + +GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line) + : severity_(severity) { + const char* const marker = + severity == GTEST_INFO ? "[ INFO ]" : + severity == GTEST_WARNING ? "[WARNING]" : + severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]"; + GetStream() << ::std::endl << marker << " " + << FormatFileLocation(file, line).c_str() << ": "; +} + +// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. +GTestLog::~GTestLog() { + GetStream() << ::std::endl; + if (severity_ == GTEST_FATAL) { + fflush(stderr); + posix::Abort(); + } +} +// Disable Microsoft deprecation warnings for POSIX functions called from +// this class (creat, dup, dup2, and close) +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4996) +#endif // _MSC_VER + +#if GTEST_HAS_STREAM_REDIRECTION + +// Object that captures an output stream (stdout/stderr). +class CapturedStream { + public: + // The ctor redirects the stream to a temporary file. + explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) { +# if GTEST_OS_WINDOWS + char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT + char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT + + ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path); + const UINT success = ::GetTempFileNameA(temp_dir_path, + "gtest_redir", + 0, // Generate unique file name. + temp_file_path); + GTEST_CHECK_(success != 0) + << "Unable to create a temporary file in " << temp_dir_path; + const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE); + GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " + << temp_file_path; + filename_ = temp_file_path; +# else + // There's no guarantee that a test has write access to the current + // directory, so we create the temporary file in the /tmp directory + // instead. We use /tmp on most systems, and /sdcard on Android. + // That's because Android doesn't have /tmp. +# if GTEST_OS_LINUX_ANDROID + // Note: Android applications are expected to call the framework's + // Context.getExternalStorageDirectory() method through JNI to get + // the location of the world-writable SD Card directory. However, + // this requires a Context handle, which cannot be retrieved + // globally from native code. Doing so also precludes running the + // code as part of a regular standalone executable, which doesn't + // run in a Dalvik process (e.g. when running it through 'adb shell'). + // + // The location /sdcard is directly accessible from native code + // and is the only location (unofficially) supported by the Android + // team. It's generally a symlink to the real SD Card mount point + // which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or + // other OEM-customized locations. Never rely on these, and always + // use /sdcard. + char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX"; +# else + char name_template[] = "/tmp/captured_stream.XXXXXX"; +# endif // GTEST_OS_LINUX_ANDROID + const int captured_fd = mkstemp(name_template); + filename_ = name_template; +# endif // GTEST_OS_WINDOWS + fflush(NULL); + dup2(captured_fd, fd_); + close(captured_fd); + } + + ~CapturedStream() { + remove(filename_.c_str()); + } + + std::string GetCapturedString() { + if (uncaptured_fd_ != -1) { + // Restores the original stream. + fflush(NULL); + dup2(uncaptured_fd_, fd_); + close(uncaptured_fd_); + uncaptured_fd_ = -1; + } + + FILE* const file = posix::FOpen(filename_.c_str(), "r"); + const std::string content = ReadEntireFile(file); + posix::FClose(file); + return content; + } + + private: + // Reads the entire content of a file as an std::string. + static std::string ReadEntireFile(FILE* file); + + // Returns the size (in bytes) of a file. + static size_t GetFileSize(FILE* file); + + const int fd_; // A stream to capture. + int uncaptured_fd_; + // Name of the temporary file holding the stderr output. + ::std::string filename_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); +}; + +// Returns the size (in bytes) of a file. +size_t CapturedStream::GetFileSize(FILE* file) { + fseek(file, 0, SEEK_END); + return static_cast(ftell(file)); +} + +// Reads the entire content of a file as a string. +std::string CapturedStream::ReadEntireFile(FILE* file) { + const size_t file_size = GetFileSize(file); + char* const buffer = new char[file_size]; + + size_t bytes_last_read = 0; // # of bytes read in the last fread() + size_t bytes_read = 0; // # of bytes read so far + + fseek(file, 0, SEEK_SET); + + // Keeps reading the file until we cannot read further or the + // pre-determined file size is reached. + do { + bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file); + bytes_read += bytes_last_read; + } while (bytes_last_read > 0 && bytes_read < file_size); + + const std::string content(buffer, bytes_read); + delete[] buffer; + + return content; +} + +# ifdef _MSC_VER +# pragma warning(pop) +# endif // _MSC_VER + +static CapturedStream* g_captured_stderr = NULL; +static CapturedStream* g_captured_stdout = NULL; + +// Starts capturing an output stream (stdout/stderr). +void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { + if (*stream != NULL) { + GTEST_LOG_(FATAL) << "Only one " << stream_name + << " capturer can exist at a time."; + } + *stream = new CapturedStream(fd); +} + +// Stops capturing the output stream and returns the captured string. +std::string GetCapturedStream(CapturedStream** captured_stream) { + const std::string content = (*captured_stream)->GetCapturedString(); + + delete *captured_stream; + *captured_stream = NULL; + + return content; +} + +// Starts capturing stdout. +void CaptureStdout() { + CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout); +} + +// Starts capturing stderr. +void CaptureStderr() { + CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr); +} + +// Stops capturing stdout and returns the captured string. +std::string GetCapturedStdout() { + return GetCapturedStream(&g_captured_stdout); +} + +// Stops capturing stderr and returns the captured string. +std::string GetCapturedStderr() { + return GetCapturedStream(&g_captured_stderr); +} + +#endif // GTEST_HAS_STREAM_REDIRECTION + +#if GTEST_HAS_DEATH_TEST + +// A copy of all command line arguments. Set by InitGoogleTest(). +::std::vector g_argvs; + +static const ::std::vector* g_injected_test_argvs = + NULL; // Owned. + +void SetInjectableArgvs(const ::std::vector* argvs) { + if (g_injected_test_argvs != argvs) + delete g_injected_test_argvs; + g_injected_test_argvs = argvs; +} + +const ::std::vector& GetInjectableArgvs() { + if (g_injected_test_argvs != NULL) { + return *g_injected_test_argvs; + } + return g_argvs; +} +#endif // GTEST_HAS_DEATH_TEST + +#if GTEST_OS_WINDOWS_MOBILE +namespace posix { +void Abort() { + DebugBreak(); + TerminateProcess(GetCurrentProcess(), 1); +} +} // namespace posix +#endif // GTEST_OS_WINDOWS_MOBILE + +// Returns the name of the environment variable corresponding to the +// given flag. For example, FlagToEnvVar("foo") will return +// "GTEST_FOO" in the open-source version. +static std::string FlagToEnvVar(const char* flag) { + const std::string full_flag = + (Message() << GTEST_FLAG_PREFIX_ << flag).GetString(); + + Message env_var; + for (size_t i = 0; i != full_flag.length(); i++) { + env_var << ToUpper(full_flag.c_str()[i]); + } + + return env_var.GetString(); +} + +// Parses 'str' for a 32-bit signed integer. If successful, writes +// the result to *value and returns true; otherwise leaves *value +// unchanged and returns false. +bool ParseInt32(const Message& src_text, const char* str, Int32* value) { + // Parses the environment variable as a decimal integer. + char* end = NULL; + const long long_value = strtol(str, &end, 10); // NOLINT + + // Has strtol() consumed all characters in the string? + if (*end != '\0') { + // No - an invalid character was encountered. + Message msg; + msg << "WARNING: " << src_text + << " is expected to be a 32-bit integer, but actually" + << " has value \"" << str << "\".\n"; + printf("%s", msg.GetString().c_str()); + fflush(stdout); + return false; + } + + // Is the parsed value in the range of an Int32? + const Int32 result = static_cast(long_value); + if (long_value == LONG_MAX || long_value == LONG_MIN || + // The parsed value overflows as a long. (strtol() returns + // LONG_MAX or LONG_MIN when the input overflows.) + result != long_value + // The parsed value overflows as an Int32. + ) { + Message msg; + msg << "WARNING: " << src_text + << " is expected to be a 32-bit integer, but actually" + << " has value " << str << ", which overflows.\n"; + printf("%s", msg.GetString().c_str()); + fflush(stdout); + return false; + } + + *value = result; + return true; +} + +// Reads and returns the Boolean environment variable corresponding to +// the given flag; if it's not set, returns default_value. +// +// The value is considered true iff it's not "0". +bool BoolFromGTestEnv(const char* flag, bool default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const string_value = posix::GetEnv(env_var.c_str()); + return string_value == NULL ? + default_value : strcmp(string_value, "0") != 0; +} + +// Reads and returns a 32-bit integer stored in the environment +// variable corresponding to the given flag; if it isn't set or +// doesn't represent a valid 32-bit integer, returns default_value. +Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const string_value = posix::GetEnv(env_var.c_str()); + if (string_value == NULL) { + // The environment variable is not set. + return default_value; + } + + Int32 result = default_value; + if (!ParseInt32(Message() << "Environment variable " << env_var, + string_value, &result)) { + printf("The default value %s is used.\n", + (Message() << default_value).GetString().c_str()); + fflush(stdout); + return default_value; + } + + return result; +} + +// Reads and returns the string environment variable corresponding to +// the given flag; if it's not set, returns default_value. +const char* StringFromGTestEnv(const char* flag, const char* default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const value = posix::GetEnv(env_var.c_str()); + return value == NULL ? default_value : value; +} + +} // namespace internal +} // namespace testing +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Test - The Google C++ Testing Framework +// +// This file implements a universal value printer that can print a +// value of any type T: +// +// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); +// +// It uses the << operator when possible, and prints the bytes in the +// object otherwise. A user can override its behavior for a class +// type Foo by defining either operator<<(::std::ostream&, const Foo&) +// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that +// defines Foo. + +#include +#include +#include // NOLINT +#include + +namespace testing { + +namespace { + +using ::std::ostream; + +// Prints a segment of bytes in the given object. +void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, + size_t count, ostream* os) { + char text[5] = ""; + for (size_t i = 0; i != count; i++) { + const size_t j = start + i; + if (i != 0) { + // Organizes the bytes into groups of 2 for easy parsing by + // human. + if ((j % 2) == 0) + *os << ' '; + else + *os << '-'; + } + GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]); + *os << text; + } +} + +// Prints the bytes in the given value to the given ostream. +void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, + ostream* os) { + // Tells the user how big the object is. + *os << count << "-byte object <"; + + const size_t kThreshold = 132; + const size_t kChunkSize = 64; + // If the object size is bigger than kThreshold, we'll have to omit + // some details by printing only the first and the last kChunkSize + // bytes. + // TODO(wan): let the user control the threshold using a flag. + if (count < kThreshold) { + PrintByteSegmentInObjectTo(obj_bytes, 0, count, os); + } else { + PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os); + *os << " ... "; + // Rounds up to 2-byte boundary. + const size_t resume_pos = (count - kChunkSize + 1)/2*2; + PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os); + } + *os << ">"; +} + +} // namespace + +namespace internal2 { + +// Delegates to PrintBytesInObjectToImpl() to print the bytes in the +// given object. The delegation simplifies the implementation, which +// uses the << operator and thus is easier done outside of the +// ::testing::internal namespace, which contains a << operator that +// sometimes conflicts with the one in STL. +void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, + ostream* os) { + PrintBytesInObjectToImpl(obj_bytes, count, os); +} + +} // namespace internal2 + +namespace internal { + +// Depending on the value of a char (or wchar_t), we print it in one +// of three formats: +// - as is if it's a printable ASCII (e.g. 'a', '2', ' '), +// - as a hexidecimal escape sequence (e.g. '\x7F'), or +// - as a special escape sequence (e.g. '\r', '\n'). +enum CharFormat { + kAsIs, + kHexEscape, + kSpecialEscape +}; + +// Returns true if c is a printable ASCII character. We test the +// value of c directly instead of calling isprint(), which is buggy on +// Windows Mobile. +inline bool IsPrintableAscii(wchar_t c) { + return 0x20 <= c && c <= 0x7E; +} + +// Prints a wide or narrow char c as a character literal without the +// quotes, escaping it when necessary; returns how c was formatted. +// The template argument UnsignedChar is the unsigned version of Char, +// which is the type of c. +template +static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { + switch (static_cast(c)) { + case L'\0': + *os << "\\0"; + break; + case L'\'': + *os << "\\'"; + break; + case L'\\': + *os << "\\\\"; + break; + case L'\a': + *os << "\\a"; + break; + case L'\b': + *os << "\\b"; + break; + case L'\f': + *os << "\\f"; + break; + case L'\n': + *os << "\\n"; + break; + case L'\r': + *os << "\\r"; + break; + case L'\t': + *os << "\\t"; + break; + case L'\v': + *os << "\\v"; + break; + default: + if (IsPrintableAscii(c)) { + *os << static_cast(c); + return kAsIs; + } else { + *os << "\\x" + String::FormatHexInt(static_cast(c)); + return kHexEscape; + } + } + return kSpecialEscape; +} + +// Prints a wchar_t c as if it's part of a string literal, escaping it when +// necessary; returns how c was formatted. +static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) { + switch (c) { + case L'\'': + *os << "'"; + return kAsIs; + case L'"': + *os << "\\\""; + return kSpecialEscape; + default: + return PrintAsCharLiteralTo(c, os); + } +} + +// Prints a char c as if it's part of a string literal, escaping it when +// necessary; returns how c was formatted. +static CharFormat PrintAsStringLiteralTo(char c, ostream* os) { + return PrintAsStringLiteralTo( + static_cast(static_cast(c)), os); +} + +// Prints a wide or narrow character c and its code. '\0' is printed +// as "'\\0'", other unprintable characters are also properly escaped +// using the standard C++ escape sequence. The template argument +// UnsignedChar is the unsigned version of Char, which is the type of c. +template +void PrintCharAndCodeTo(Char c, ostream* os) { + // First, print c as a literal in the most readable form we can find. + *os << ((sizeof(c) > 1) ? "L'" : "'"); + const CharFormat format = PrintAsCharLiteralTo(c, os); + *os << "'"; + + // To aid user debugging, we also print c's code in decimal, unless + // it's 0 (in which case c was printed as '\\0', making the code + // obvious). + if (c == 0) + return; + *os << " (" << static_cast(c); + + // For more convenience, we print c's code again in hexidecimal, + // unless c was already printed in the form '\x##' or the code is in + // [1, 9]. + if (format == kHexEscape || (1 <= c && c <= 9)) { + // Do nothing. + } else { + *os << ", 0x" << String::FormatHexInt(static_cast(c)); + } + *os << ")"; +} + +void PrintTo(unsigned char c, ::std::ostream* os) { + PrintCharAndCodeTo(c, os); +} +void PrintTo(signed char c, ::std::ostream* os) { + PrintCharAndCodeTo(c, os); +} + +// Prints a wchar_t as a symbol if it is printable or as its internal +// code otherwise and also as its code. L'\0' is printed as "L'\\0'". +void PrintTo(wchar_t wc, ostream* os) { + PrintCharAndCodeTo(wc, os); +} + +// Prints the given array of characters to the ostream. CharType must be either +// char or wchar_t. +// The array starts at begin, the length is len, it may include '\0' characters +// and may not be NUL-terminated. +template +static void PrintCharsAsStringTo( + const CharType* begin, size_t len, ostream* os) { + const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\""; + *os << kQuoteBegin; + bool is_previous_hex = false; + for (size_t index = 0; index < len; ++index) { + const CharType cur = begin[index]; + if (is_previous_hex && IsXDigit(cur)) { + // Previous character is of '\x..' form and this character can be + // interpreted as another hexadecimal digit in its number. Break string to + // disambiguate. + *os << "\" " << kQuoteBegin; + } + is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape; + } + *os << "\""; +} + +// Prints a (const) char/wchar_t array of 'len' elements, starting at address +// 'begin'. CharType must be either char or wchar_t. +template +static void UniversalPrintCharArray( + const CharType* begin, size_t len, ostream* os) { + // The code + // const char kFoo[] = "foo"; + // generates an array of 4, not 3, elements, with the last one being '\0'. + // + // Therefore when printing a char array, we don't print the last element if + // it's '\0', such that the output matches the string literal as it's + // written in the source code. + if (len > 0 && begin[len - 1] == '\0') { + PrintCharsAsStringTo(begin, len - 1, os); + return; + } + + // If, however, the last element in the array is not '\0', e.g. + // const char kFoo[] = { 'f', 'o', 'o' }; + // we must print the entire array. We also print a message to indicate + // that the array is not NUL-terminated. + PrintCharsAsStringTo(begin, len, os); + *os << " (no terminating NUL)"; +} + +// Prints a (const) char array of 'len' elements, starting at address 'begin'. +void UniversalPrintArray(const char* begin, size_t len, ostream* os) { + UniversalPrintCharArray(begin, len, os); +} + +// Prints a (const) wchar_t array of 'len' elements, starting at address +// 'begin'. +void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) { + UniversalPrintCharArray(begin, len, os); +} + +// Prints the given C string to the ostream. +void PrintTo(const char* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << ImplicitCast_(s) << " pointing to "; + PrintCharsAsStringTo(s, strlen(s), os); + } +} + +// MSVC compiler can be configured to define whar_t as a typedef +// of unsigned short. Defining an overload for const wchar_t* in that case +// would cause pointers to unsigned shorts be printed as wide strings, +// possibly accessing more memory than intended and causing invalid +// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when +// wchar_t is implemented as a native type. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +// Prints the given wide C string to the ostream. +void PrintTo(const wchar_t* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << ImplicitCast_(s) << " pointing to "; + PrintCharsAsStringTo(s, wcslen(s), os); + } +} +#endif // wchar_t is native + +// Prints a ::string object. +#if GTEST_HAS_GLOBAL_STRING +void PrintStringTo(const ::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_STRING + +void PrintStringTo(const ::std::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} + +// Prints a ::wstring object. +#if GTEST_HAS_GLOBAL_WSTRING +void PrintWideStringTo(const ::wstring& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +#if GTEST_HAS_STD_WSTRING +void PrintWideStringTo(const ::std::wstring& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_STD_WSTRING + +} // namespace internal + +} // namespace testing +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: mheule@google.com (Markus Heule) +// +// The Google C++ Testing Framework (Google Test) + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { + +using internal::GetUnitTestImpl; + +// Gets the summary of the failure message by omitting the stack trace +// in it. +std::string TestPartResult::ExtractSummary(const char* message) { + const char* const stack_trace = strstr(message, internal::kStackTraceMarker); + return stack_trace == NULL ? message : + std::string(message, stack_trace); +} + +// Prints a TestPartResult object. +std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { + return os + << result.file_name() << ":" << result.line_number() << ": " + << (result.type() == TestPartResult::kSuccess ? "Success" : + result.type() == TestPartResult::kFatalFailure ? "Fatal failure" : + "Non-fatal failure") << ":\n" + << result.message() << std::endl; +} + +// Appends a TestPartResult to the array. +void TestPartResultArray::Append(const TestPartResult& result) { + array_.push_back(result); +} + +// Returns the TestPartResult at the given index (0-based). +const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { + if (index < 0 || index >= size()) { + printf("\nInvalid index (%d) into TestPartResultArray.\n", index); + internal::posix::Abort(); + } + + return array_[index]; +} + +// Returns the number of TestPartResult objects in the array. +int TestPartResultArray::size() const { + return static_cast(array_.size()); +} + +namespace internal { + +HasNewFatalFailureHelper::HasNewFatalFailureHelper() + : has_new_fatal_failure_(false), + original_reporter_(GetUnitTestImpl()-> + GetTestPartResultReporterForCurrentThread()) { + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); +} + +HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( + original_reporter_); +} + +void HasNewFatalFailureHelper::ReportTestPartResult( + const TestPartResult& result) { + if (result.fatally_failed()) + has_new_fatal_failure_ = true; + original_reporter_->ReportTestPartResult(result); +} + +} // namespace internal + +} // namespace testing +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + + +namespace testing { +namespace internal { + +#if GTEST_HAS_TYPED_TEST_P + +// Skips to the first non-space char in str. Returns an empty string if str +// contains only whitespace characters. +static const char* SkipSpaces(const char* str) { + while (IsSpace(*str)) + str++; + return str; +} + +// Verifies that registered_tests match the test names in +// defined_test_names_; returns registered_tests if successful, or +// aborts the program otherwise. +const char* TypedTestCasePState::VerifyRegisteredTestNames( + const char* file, int line, const char* registered_tests) { + typedef ::std::set::const_iterator DefinedTestIter; + registered_ = true; + + // Skip initial whitespace in registered_tests since some + // preprocessors prefix stringizied literals with whitespace. + registered_tests = SkipSpaces(registered_tests); + + Message errors; + ::std::set tests; + for (const char* names = registered_tests; names != NULL; + names = SkipComma(names)) { + const std::string name = GetPrefixUntilComma(names); + if (tests.count(name) != 0) { + errors << "Test " << name << " is listed more than once.\n"; + continue; + } + + bool found = false; + for (DefinedTestIter it = defined_test_names_.begin(); + it != defined_test_names_.end(); + ++it) { + if (name == *it) { + found = true; + break; + } + } + + if (found) { + tests.insert(name); + } else { + errors << "No test named " << name + << " can be found in this test case.\n"; + } + } + + for (DefinedTestIter it = defined_test_names_.begin(); + it != defined_test_names_.end(); + ++it) { + if (tests.count(*it) == 0) { + errors << "You forgot to list test " << *it << ".\n"; + } + } + + const std::string& errors_str = errors.GetString(); + if (errors_str != "") { + fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), + errors_str.c_str()); + fflush(stderr); + posix::Abort(); + } + + return registered_tests; +} + +#endif // GTEST_HAS_TYPED_TEST_P + +} // namespace internal +} // namespace testing diff --git a/Engine/lib/gtest/fused-src/gtest/gtest.h b/Engine/lib/gtest/fused-src/gtest/gtest.h new file mode 100644 index 000000000..4f3804f70 --- /dev/null +++ b/Engine/lib/gtest/fused-src/gtest/gtest.h @@ -0,0 +1,20061 @@ +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the public API for Google Test. It should be +// included by any test program that uses Google Test. +// +// IMPORTANT NOTE: Due to limitation of the C++ language, we have to +// leave some internal implementation details in this header file. +// They are clearly marked by comments like this: +// +// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +// +// Such code is NOT meant to be used by a user directly, and is subject +// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user +// program! +// +// Acknowledgment: Google Test borrowed the idea of automatic test +// registration from Barthelemy Dagenais' (barthelemy@prologique.com) +// easyUnit framework. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_H_ + +#include +#include +#include + +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file declares functions and macros used internally by +// Google Test. They are subject to change without notice. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ + +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: wan@google.com (Zhanyong Wan) +// +// Low-level types and utilities for porting Google Test to various +// platforms. They are subject to change without notice. DO NOT USE +// THEM IN USER CODE. +// +// This file is fundamental to Google Test. All other Google Test source +// files are expected to #include this. Therefore, it cannot #include +// any other Google Test header. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ + +// The user can define the following macros in the build script to +// control Google Test's behavior. If the user doesn't define a macro +// in this list, Google Test will define it. +// +// GTEST_HAS_CLONE - Define it to 1/0 to indicate that clone(2) +// is/isn't available. +// GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions +// are enabled. +// GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string +// is/isn't available (some systems define +// ::string, which is different to std::string). +// GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string +// is/isn't available (some systems define +// ::wstring, which is different to std::wstring). +// GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular +// expressions are/aren't available. +// GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that +// is/isn't available. +// GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't +// enabled. +// GTEST_HAS_STD_WSTRING - Define it to 1/0 to indicate that +// std::wstring does/doesn't work (Google Test can +// be used where std::wstring is unavailable). +// GTEST_HAS_TR1_TUPLE - Define it to 1/0 to indicate tr1::tuple +// is/isn't available. +// GTEST_HAS_SEH - Define it to 1/0 to indicate whether the +// compiler supports Microsoft's "Structured +// Exception Handling". +// GTEST_HAS_STREAM_REDIRECTION +// - Define it to 1/0 to indicate whether the +// platform supports I/O stream redirection using +// dup() and dup2(). +// GTEST_USE_OWN_TR1_TUPLE - Define it to 1/0 to indicate whether Google +// Test's own tr1 tuple implementation should be +// used. Unused when the user sets +// GTEST_HAS_TR1_TUPLE to 0. +// GTEST_LANG_CXX11 - Define it to 1/0 to indicate that Google Test +// is building in C++11/C++98 mode. +// GTEST_LINKED_AS_SHARED_LIBRARY +// - Define to 1 when compiling tests that use +// Google Test as a shared library (known as +// DLL on Windows). +// GTEST_CREATE_SHARED_LIBRARY +// - Define to 1 when compiling Google Test itself +// as a shared library. + +// This header defines the following utilities: +// +// Macros indicating the current platform (defined to 1 if compiled on +// the given platform; otherwise undefined): +// GTEST_OS_AIX - IBM AIX +// GTEST_OS_CYGWIN - Cygwin +// GTEST_OS_HPUX - HP-UX +// GTEST_OS_LINUX - Linux +// GTEST_OS_LINUX_ANDROID - Google Android +// GTEST_OS_MAC - Mac OS X +// GTEST_OS_IOS - iOS +// GTEST_OS_IOS_SIMULATOR - iOS simulator +// GTEST_OS_NACL - Google Native Client (NaCl) +// GTEST_OS_OPENBSD - OpenBSD +// GTEST_OS_QNX - QNX +// GTEST_OS_SOLARIS - Sun Solaris +// GTEST_OS_SYMBIAN - Symbian +// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile) +// GTEST_OS_WINDOWS_DESKTOP - Windows Desktop +// GTEST_OS_WINDOWS_MINGW - MinGW +// GTEST_OS_WINDOWS_MOBILE - Windows Mobile +// GTEST_OS_ZOS - z/OS +// +// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the +// most stable support. Since core members of the Google Test project +// don't have access to other platforms, support for them may be less +// stable. If you notice any problems on your platform, please notify +// googletestframework@googlegroups.com (patches for fixing them are +// even more welcome!). +// +// Note that it is possible that none of the GTEST_OS_* macros are defined. +// +// Macros indicating available Google Test features (defined to 1 if +// the corresponding feature is supported; otherwise undefined): +// GTEST_HAS_COMBINE - the Combine() function (for value-parameterized +// tests) +// GTEST_HAS_DEATH_TEST - death tests +// GTEST_HAS_PARAM_TEST - value-parameterized tests +// GTEST_HAS_TYPED_TEST - typed tests +// GTEST_HAS_TYPED_TEST_P - type-parameterized tests +// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with +// GTEST_HAS_POSIX_RE (see above) which users can +// define themselves. +// GTEST_USES_SIMPLE_RE - our own simple regex is used; +// the above two are mutually exclusive. +// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ(). +// +// Macros for basic C++ coding: +// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning. +// GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a +// variable don't have to be used. +// GTEST_DISALLOW_ASSIGN_ - disables operator=. +// GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=. +// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used. +// +// Synchronization: +// Mutex, MutexLock, ThreadLocal, GetThreadCount() +// - synchronization primitives. +// GTEST_IS_THREADSAFE - defined to 1 to indicate that the above +// synchronization primitives have real implementations +// and Google Test is thread-safe; or 0 otherwise. +// +// Template meta programming: +// is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only. +// IteratorTraits - partial implementation of std::iterator_traits, which +// is not available in libCstd when compiled with Sun C++. +// +// Smart pointers: +// scoped_ptr - as in TR2. +// +// Regular expressions: +// RE - a simple regular expression class using the POSIX +// Extended Regular Expression syntax on UNIX-like +// platforms, or a reduced regular exception syntax on +// other platforms, including Windows. +// +// Logging: +// GTEST_LOG_() - logs messages at the specified severity level. +// LogToStderr() - directs all log messages to stderr. +// FlushInfoLog() - flushes informational log messages. +// +// Stdout and stderr capturing: +// CaptureStdout() - starts capturing stdout. +// GetCapturedStdout() - stops capturing stdout and returns the captured +// string. +// CaptureStderr() - starts capturing stderr. +// GetCapturedStderr() - stops capturing stderr and returns the captured +// string. +// +// Integer types: +// TypeWithSize - maps an integer to a int type. +// Int32, UInt32, Int64, UInt64, TimeInMillis +// - integers of known sizes. +// BiggestInt - the biggest signed integer type. +// +// Command-line utilities: +// GTEST_FLAG() - references a flag. +// GTEST_DECLARE_*() - declares a flag. +// GTEST_DEFINE_*() - defines a flag. +// GetInjectableArgvs() - returns the command line as a vector of strings. +// +// Environment variable utilities: +// GetEnv() - gets the value of an environment variable. +// BoolFromGTestEnv() - parses a bool environment variable. +// Int32FromGTestEnv() - parses an Int32 environment variable. +// StringFromGTestEnv() - parses a string environment variable. + +#include // for isspace, etc +#include // for ptrdiff_t +#include +#include +#include +#ifndef _WIN32_WCE +# include +# include +#endif // !_WIN32_WCE + +#if defined __APPLE__ +# include +# include +#endif + +#include // NOLINT +#include // NOLINT +#include // NOLINT + +#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com" +#define GTEST_FLAG_PREFIX_ "gtest_" +#define GTEST_FLAG_PREFIX_DASH_ "gtest-" +#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_" +#define GTEST_NAME_ "Google Test" +#define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/" + +// Determines the version of gcc that is used to compile this. +#ifdef __GNUC__ +// 40302 means version 4.3.2. +# define GTEST_GCC_VER_ \ + (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__) +#endif // __GNUC__ + +// Determines the platform on which Google Test is compiled. +#ifdef __CYGWIN__ +# define GTEST_OS_CYGWIN 1 +#elif defined __SYMBIAN32__ +# define GTEST_OS_SYMBIAN 1 +#elif defined _WIN32 +# define GTEST_OS_WINDOWS 1 +# ifdef _WIN32_WCE +# define GTEST_OS_WINDOWS_MOBILE 1 +# elif defined(__MINGW__) || defined(__MINGW32__) +# define GTEST_OS_WINDOWS_MINGW 1 +# else +# define GTEST_OS_WINDOWS_DESKTOP 1 +# endif // _WIN32_WCE +#elif defined __APPLE__ +# define GTEST_OS_MAC 1 +# if TARGET_OS_IPHONE +# define GTEST_OS_IOS 1 +# if TARGET_IPHONE_SIMULATOR +# define GTEST_OS_IOS_SIMULATOR 1 +# endif +# endif +#elif defined __linux__ +# define GTEST_OS_LINUX 1 +# if defined __ANDROID__ +# define GTEST_OS_LINUX_ANDROID 1 +# endif +#elif defined __MVS__ +# define GTEST_OS_ZOS 1 +#elif defined(__sun) && defined(__SVR4) +# define GTEST_OS_SOLARIS 1 +#elif defined(_AIX) +# define GTEST_OS_AIX 1 +#elif defined(__hpux) +# define GTEST_OS_HPUX 1 +#elif defined __native_client__ +# define GTEST_OS_NACL 1 +#elif defined __OpenBSD__ +# define GTEST_OS_OPENBSD 1 +#elif defined __QNX__ +# define GTEST_OS_QNX 1 +#endif // __CYGWIN__ + +#ifndef GTEST_LANG_CXX11 +// gcc and clang define __GXX_EXPERIMENTAL_CXX0X__ when +// -std={c,gnu}++{0x,11} is passed. The C++11 standard specifies a +// value for __cplusplus, and recent versions of clang, gcc, and +// probably other compilers set that too in C++11 mode. +# if __GXX_EXPERIMENTAL_CXX0X__ || __cplusplus >= 201103L +// Compiling in at least C++11 mode. +# define GTEST_LANG_CXX11 1 +# else +# define GTEST_LANG_CXX11 0 +# endif +#endif + +// Brings in definitions for functions used in the testing::internal::posix +// namespace (read, write, close, chdir, isatty, stat). We do not currently +// use them on Windows Mobile. +#if !GTEST_OS_WINDOWS +// This assumes that non-Windows OSes provide unistd.h. For OSes where this +// is not the case, we need to include headers that provide the functions +// mentioned above. +# include +# include +#elif !GTEST_OS_WINDOWS_MOBILE +# include +# include +#endif + +#if GTEST_OS_LINUX_ANDROID +// Used to define __ANDROID_API__ matching the target NDK API level. +# include // NOLINT +#endif + +// Defines this to true iff Google Test can use POSIX regular expressions. +#ifndef GTEST_HAS_POSIX_RE +# if GTEST_OS_LINUX_ANDROID +// On Android, is only available starting with Gingerbread. +# define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9) +# else +# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS) +# endif +#endif + +#if GTEST_HAS_POSIX_RE + +// On some platforms, needs someone to define size_t, and +// won't compile otherwise. We can #include it here as we already +// included , which is guaranteed to define size_t through +// . +# include // NOLINT + +# define GTEST_USES_POSIX_RE 1 + +#elif GTEST_OS_WINDOWS + +// is not available on Windows. Use our own simple regex +// implementation instead. +# define GTEST_USES_SIMPLE_RE 1 + +#else + +// may not be available on this platform. Use our own +// simple regex implementation instead. +# define GTEST_USES_SIMPLE_RE 1 + +#endif // GTEST_HAS_POSIX_RE + +#ifndef GTEST_HAS_EXCEPTIONS +// The user didn't tell us whether exceptions are enabled, so we need +// to figure it out. +# if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS +// macro to enable exceptions, so we'll do the same. +// Assumes that exceptions are enabled by default. +# ifndef _HAS_EXCEPTIONS +# define _HAS_EXCEPTIONS 1 +# endif // _HAS_EXCEPTIONS +# define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS +# elif defined(__GNUC__) && __EXCEPTIONS +// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__SUNPRO_CC) +// Sun Pro CC supports exceptions. However, there is no compile-time way of +// detecting whether they are enabled or not. Therefore, we assume that +// they are enabled unless the user tells us otherwise. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__IBMCPP__) && __EXCEPTIONS +// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__HP_aCC) +// Exception handling is in effect by default in HP aCC compiler. It has to +// be turned of by +noeh compiler option if desired. +# define GTEST_HAS_EXCEPTIONS 1 +# else +// For other compilers, we assume exceptions are disabled to be +// conservative. +# define GTEST_HAS_EXCEPTIONS 0 +# endif // defined(_MSC_VER) || defined(__BORLANDC__) +#endif // GTEST_HAS_EXCEPTIONS + +#if !defined(GTEST_HAS_STD_STRING) +// Even though we don't use this macro any longer, we keep it in case +// some clients still depend on it. +# define GTEST_HAS_STD_STRING 1 +#elif !GTEST_HAS_STD_STRING +// The user told us that ::std::string isn't available. +# error "Google Test cannot be used where ::std::string isn't available." +#endif // !defined(GTEST_HAS_STD_STRING) + +#ifndef GTEST_HAS_GLOBAL_STRING +// The user didn't tell us whether ::string is available, so we need +// to figure it out. + +# define GTEST_HAS_GLOBAL_STRING 0 + +#endif // GTEST_HAS_GLOBAL_STRING + +#ifndef GTEST_HAS_STD_WSTRING +// The user didn't tell us whether ::std::wstring is available, so we need +// to figure it out. +// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring +// is available. + +// Cygwin 1.7 and below doesn't support ::std::wstring. +// Solaris' libc++ doesn't support it either. Android has +// no support for it at least as recent as Froyo (2.2). +# define GTEST_HAS_STD_WSTRING \ + (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS)) + +#endif // GTEST_HAS_STD_WSTRING + +#ifndef GTEST_HAS_GLOBAL_WSTRING +// The user didn't tell us whether ::wstring is available, so we need +// to figure it out. +# define GTEST_HAS_GLOBAL_WSTRING \ + (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING) +#endif // GTEST_HAS_GLOBAL_WSTRING + +// Determines whether RTTI is available. +#ifndef GTEST_HAS_RTTI +// The user didn't tell us whether RTTI is enabled, so we need to +// figure it out. + +# ifdef _MSC_VER + +# ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled. +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif + +// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled. +# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302) + +# ifdef __GXX_RTTI +// When building against STLport with the Android NDK and with +// -frtti -fno-exceptions, the build fails at link time with undefined +// references to __cxa_bad_typeid. Note sure if STL or toolchain bug, +// so disable RTTI when detected. +# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) && \ + !defined(__EXCEPTIONS) +# define GTEST_HAS_RTTI 0 +# else +# define GTEST_HAS_RTTI 1 +# endif // GTEST_OS_LINUX_ANDROID && __STLPORT_MAJOR && !__EXCEPTIONS +# else +# define GTEST_HAS_RTTI 0 +# endif // __GXX_RTTI + +// Clang defines __GXX_RTTI starting with version 3.0, but its manual recommends +// using has_feature instead. has_feature(cxx_rtti) is supported since 2.7, the +// first version with C++ support. +# elif defined(__clang__) + +# define GTEST_HAS_RTTI __has_feature(cxx_rtti) + +// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if +// both the typeid and dynamic_cast features are present. +# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900) + +# ifdef __RTTI_ALL__ +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif + +# else + +// For all other compilers, we assume RTTI is enabled. +# define GTEST_HAS_RTTI 1 + +# endif // _MSC_VER + +#endif // GTEST_HAS_RTTI + +// It's this header's responsibility to #include when RTTI +// is enabled. +#if GTEST_HAS_RTTI +# include +#endif + +// Determines whether Google Test can use the pthreads library. +#ifndef GTEST_HAS_PTHREAD +// The user didn't tell us explicitly, so we assume pthreads support is +// available on Linux and Mac. +// +// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0 +// to your compiler flags. +# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX \ + || GTEST_OS_QNX) +#endif // GTEST_HAS_PTHREAD + +#if GTEST_HAS_PTHREAD +// gtest-port.h guarantees to #include when GTEST_HAS_PTHREAD is +// true. +# include // NOLINT + +// For timespec and nanosleep, used below. +# include // NOLINT +#endif + +// Determines whether Google Test can use tr1/tuple. You can define +// this macro to 0 to prevent Google Test from using tuple (any +// feature depending on tuple with be disabled in this mode). +#ifndef GTEST_HAS_TR1_TUPLE +# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) +// STLport, provided with the Android NDK, has neither or . +# define GTEST_HAS_TR1_TUPLE 0 +# else +// The user didn't tell us not to do it, so we assume it's OK. +# define GTEST_HAS_TR1_TUPLE 1 +# endif +#endif // GTEST_HAS_TR1_TUPLE + +// Determines whether Google Test's own tr1 tuple implementation +// should be used. +#ifndef GTEST_USE_OWN_TR1_TUPLE +// The user didn't tell us, so we need to figure it out. + +// We use our own TR1 tuple if we aren't sure the user has an +// implementation of it already. At this time, libstdc++ 4.0.0+ and +// MSVC 2010 are the only mainstream standard libraries that come +// with a TR1 tuple implementation. NVIDIA's CUDA NVCC compiler +// pretends to be GCC by defining __GNUC__ and friends, but cannot +// compile GCC's tuple implementation. MSVC 2008 (9.0) provides TR1 +// tuple in a 323 MB Feature Pack download, which we cannot assume the +// user has. QNX's QCC compiler is a modified GCC but it doesn't +// support TR1 tuple. libc++ only provides std::tuple, in C++11 mode, +// and it can be used with some compilers that define __GNUC__. +# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000) \ + && !GTEST_OS_QNX && !defined(_LIBCPP_VERSION)) || _MSC_VER >= 1600 +# define GTEST_ENV_HAS_TR1_TUPLE_ 1 +# endif + +// C++11 specifies that provides std::tuple. Use that if gtest is used +// in C++11 mode and libstdc++ isn't very old (binaries targeting OS X 10.6 +// can build with clang but need to use gcc4.2's libstdc++). +# if GTEST_LANG_CXX11 && (!defined(__GLIBCXX__) || __GLIBCXX__ > 20110325) +# define GTEST_ENV_HAS_STD_TUPLE_ 1 +# endif + +# if GTEST_ENV_HAS_TR1_TUPLE_ || GTEST_ENV_HAS_STD_TUPLE_ +# define GTEST_USE_OWN_TR1_TUPLE 0 +# else +# define GTEST_USE_OWN_TR1_TUPLE 1 +# endif + +#endif // GTEST_USE_OWN_TR1_TUPLE + +// To avoid conditional compilation everywhere, we make it +// gtest-port.h's responsibility to #include the header implementing +// tr1/tuple. +#if GTEST_HAS_TR1_TUPLE + +# if GTEST_USE_OWN_TR1_TUPLE +// This file was GENERATED by command: +// pump.py gtest-tuple.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2009 Google Inc. +// All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Implements a subset of TR1 tuple needed by Google Test and Google Mock. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ + +#include // For ::std::pair. + +// The compiler used in Symbian has a bug that prevents us from declaring the +// tuple template as a friend (it complains that tuple is redefined). This +// hack bypasses the bug by declaring the members that should otherwise be +// private as public. +// Sun Studio versions < 12 also have the above bug. +#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) +# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: +#else +# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ + template friend class tuple; \ + private: +#endif + +// GTEST_n_TUPLE_(T) is the type of an n-tuple. +#define GTEST_0_TUPLE_(T) tuple<> +#define GTEST_1_TUPLE_(T) tuple +#define GTEST_2_TUPLE_(T) tuple +#define GTEST_3_TUPLE_(T) tuple +#define GTEST_4_TUPLE_(T) tuple +#define GTEST_5_TUPLE_(T) tuple +#define GTEST_6_TUPLE_(T) tuple +#define GTEST_7_TUPLE_(T) tuple +#define GTEST_8_TUPLE_(T) tuple +#define GTEST_9_TUPLE_(T) tuple +#define GTEST_10_TUPLE_(T) tuple + +// GTEST_n_TYPENAMES_(T) declares a list of n typenames. +#define GTEST_0_TYPENAMES_(T) +#define GTEST_1_TYPENAMES_(T) typename T##0 +#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1 +#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2 +#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3 +#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4 +#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5 +#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6 +#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, typename T##7 +#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, \ + typename T##7, typename T##8 +#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, \ + typename T##7, typename T##8, typename T##9 + +// In theory, defining stuff in the ::std namespace is undefined +// behavior. We can do this as we are playing the role of a standard +// library vendor. +namespace std { +namespace tr1 { + +template +class tuple; + +// Anything in namespace gtest_internal is Google Test's INTERNAL +// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code. +namespace gtest_internal { + +// ByRef::type is T if T is a reference; otherwise it's const T&. +template +struct ByRef { typedef const T& type; }; // NOLINT +template +struct ByRef { typedef T& type; }; // NOLINT + +// A handy wrapper for ByRef. +#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef::type + +// AddRef::type is T if T is a reference; otherwise it's T&. This +// is the same as tr1::add_reference::type. +template +struct AddRef { typedef T& type; }; // NOLINT +template +struct AddRef { typedef T& type; }; // NOLINT + +// A handy wrapper for AddRef. +#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef::type + +// A helper for implementing get(). +template class Get; + +// A helper for implementing tuple_element. kIndexValid is true +// iff k < the number of fields in tuple type T. +template +struct TupleElement; + +template +struct TupleElement { + typedef T0 type; +}; + +template +struct TupleElement { + typedef T1 type; +}; + +template +struct TupleElement { + typedef T2 type; +}; + +template +struct TupleElement { + typedef T3 type; +}; + +template +struct TupleElement { + typedef T4 type; +}; + +template +struct TupleElement { + typedef T5 type; +}; + +template +struct TupleElement { + typedef T6 type; +}; + +template +struct TupleElement { + typedef T7 type; +}; + +template +struct TupleElement { + typedef T8 type; +}; + +template +struct TupleElement { + typedef T9 type; +}; + +} // namespace gtest_internal + +template <> +class tuple<> { + public: + tuple() {} + tuple(const tuple& /* t */) {} + tuple& operator=(const tuple& /* t */) { return *this; } +}; + +template +class GTEST_1_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {} + + tuple(const tuple& t) : f0_(t.f0_) {} + + template + tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_1_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) { + f0_ = t.f0_; + return *this; + } + + T0 f0_; +}; + +template +class GTEST_2_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0), + f1_(f1) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {} + + template + tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {} + template + tuple(const ::std::pair& p) : f0_(p.first), f1_(p.second) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_2_TUPLE_(U)& t) { + return CopyFrom(t); + } + template + tuple& operator=(const ::std::pair& p) { + f0_ = p.first; + f1_ = p.second; + return *this; + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + return *this; + } + + T0 f0_; + T1 f1_; +}; + +template +class GTEST_3_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} + + template + tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_3_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; +}; + +template +class GTEST_4_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {} + + template + tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_4_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; +}; + +template +class GTEST_5_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, + GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_) {} + + template + tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_5_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; +}; + +template +class GTEST_6_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_) {} + + template + tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_6_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; +}; + +template +class GTEST_7_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3), f4_(f4), f5_(f5), f6_(f6) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} + + template + tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_7_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; +}; + +template +class GTEST_8_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, + GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5), f6_(f6), f7_(f7) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} + + template + tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_8_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; +}; + +template +class GTEST_9_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, + GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5), f6_(f6), f7_(f7), f8_(f8) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} + + template + tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_9_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + f8_ = t.f8_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; + T8 f8_; +}; + +template +class tuple { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(), + f9_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, + GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {} + + template + tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), + f9_(t.f9_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_10_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + f8_ = t.f8_; + f9_ = t.f9_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; + T8 f8_; + T9 f9_; +}; + +// 6.1.3.2 Tuple creation functions. + +// Known limitations: we don't support passing an +// std::tr1::reference_wrapper to make_tuple(). And we don't +// implement tie(). + +inline tuple<> make_tuple() { return tuple<>(); } + +template +inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) { + return GTEST_1_TUPLE_(T)(f0); +} + +template +inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) { + return GTEST_2_TUPLE_(T)(f0, f1); +} + +template +inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) { + return GTEST_3_TUPLE_(T)(f0, f1, f2); +} + +template +inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3) { + return GTEST_4_TUPLE_(T)(f0, f1, f2, f3); +} + +template +inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4) { + return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4); +} + +template +inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5) { + return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5); +} + +template +inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6) { + return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6); +} + +template +inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) { + return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7); +} + +template +inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, + const T8& f8) { + return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8); +} + +template +inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, + const T8& f8, const T9& f9) { + return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9); +} + +// 6.1.3.3 Tuple helper classes. + +template struct tuple_size; + +template +struct tuple_size { + static const int value = 0; +}; + +template +struct tuple_size { + static const int value = 1; +}; + +template +struct tuple_size { + static const int value = 2; +}; + +template +struct tuple_size { + static const int value = 3; +}; + +template +struct tuple_size { + static const int value = 4; +}; + +template +struct tuple_size { + static const int value = 5; +}; + +template +struct tuple_size { + static const int value = 6; +}; + +template +struct tuple_size { + static const int value = 7; +}; + +template +struct tuple_size { + static const int value = 8; +}; + +template +struct tuple_size { + static const int value = 9; +}; + +template +struct tuple_size { + static const int value = 10; +}; + +template +struct tuple_element { + typedef typename gtest_internal::TupleElement< + k < (tuple_size::value), k, Tuple>::type type; +}; + +#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element::type + +// 6.1.3.4 Element access. + +namespace gtest_internal { + +template <> +class Get<0> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + Field(Tuple& t) { return t.f0_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + ConstField(const Tuple& t) { return t.f0_; } +}; + +template <> +class Get<1> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + Field(Tuple& t) { return t.f1_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + ConstField(const Tuple& t) { return t.f1_; } +}; + +template <> +class Get<2> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + Field(Tuple& t) { return t.f2_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + ConstField(const Tuple& t) { return t.f2_; } +}; + +template <> +class Get<3> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + Field(Tuple& t) { return t.f3_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + ConstField(const Tuple& t) { return t.f3_; } +}; + +template <> +class Get<4> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + Field(Tuple& t) { return t.f4_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + ConstField(const Tuple& t) { return t.f4_; } +}; + +template <> +class Get<5> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + Field(Tuple& t) { return t.f5_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + ConstField(const Tuple& t) { return t.f5_; } +}; + +template <> +class Get<6> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + Field(Tuple& t) { return t.f6_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + ConstField(const Tuple& t) { return t.f6_; } +}; + +template <> +class Get<7> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + Field(Tuple& t) { return t.f7_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + ConstField(const Tuple& t) { return t.f7_; } +}; + +template <> +class Get<8> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + Field(Tuple& t) { return t.f8_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + ConstField(const Tuple& t) { return t.f8_; } +}; + +template <> +class Get<9> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + Field(Tuple& t) { return t.f9_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + ConstField(const Tuple& t) { return t.f9_; } +}; + +} // namespace gtest_internal + +template +GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get::Field(t); +} + +template +GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(const GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get::ConstField(t); +} + +// 6.1.3.5 Relational operators + +// We only implement == and !=, as we don't have a need for the rest yet. + +namespace gtest_internal { + +// SameSizeTuplePrefixComparator::Eq(t1, t2) returns true if the +// first k fields of t1 equals the first k fields of t2. +// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if +// k1 != k2. +template +struct SameSizeTuplePrefixComparator; + +template <> +struct SameSizeTuplePrefixComparator<0, 0> { + template + static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { + return true; + } +}; + +template +struct SameSizeTuplePrefixComparator { + template + static bool Eq(const Tuple1& t1, const Tuple2& t2) { + return SameSizeTuplePrefixComparator::Eq(t1, t2) && + ::std::tr1::get(t1) == ::std::tr1::get(t2); + } +}; + +} // namespace gtest_internal + +template +inline bool operator==(const GTEST_10_TUPLE_(T)& t, + const GTEST_10_TUPLE_(U)& u) { + return gtest_internal::SameSizeTuplePrefixComparator< + tuple_size::value, + tuple_size::value>::Eq(t, u); +} + +template +inline bool operator!=(const GTEST_10_TUPLE_(T)& t, + const GTEST_10_TUPLE_(U)& u) { return !(t == u); } + +// 6.1.4 Pairs. +// Unimplemented. + +} // namespace tr1 +} // namespace std + +#undef GTEST_0_TUPLE_ +#undef GTEST_1_TUPLE_ +#undef GTEST_2_TUPLE_ +#undef GTEST_3_TUPLE_ +#undef GTEST_4_TUPLE_ +#undef GTEST_5_TUPLE_ +#undef GTEST_6_TUPLE_ +#undef GTEST_7_TUPLE_ +#undef GTEST_8_TUPLE_ +#undef GTEST_9_TUPLE_ +#undef GTEST_10_TUPLE_ + +#undef GTEST_0_TYPENAMES_ +#undef GTEST_1_TYPENAMES_ +#undef GTEST_2_TYPENAMES_ +#undef GTEST_3_TYPENAMES_ +#undef GTEST_4_TYPENAMES_ +#undef GTEST_5_TYPENAMES_ +#undef GTEST_6_TYPENAMES_ +#undef GTEST_7_TYPENAMES_ +#undef GTEST_8_TYPENAMES_ +#undef GTEST_9_TYPENAMES_ +#undef GTEST_10_TYPENAMES_ + +#undef GTEST_DECLARE_TUPLE_AS_FRIEND_ +#undef GTEST_BY_REF_ +#undef GTEST_ADD_REF_ +#undef GTEST_TUPLE_ELEMENT_ + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ +# elif GTEST_ENV_HAS_STD_TUPLE_ +# include +// C++11 puts its tuple into the ::std namespace rather than +// ::std::tr1. gtest expects tuple to live in ::std::tr1, so put it there. +// This causes undefined behavior, but supported compilers react in +// the way we intend. +namespace std { +namespace tr1 { +using ::std::get; +using ::std::make_tuple; +using ::std::tuple; +using ::std::tuple_element; +using ::std::tuple_size; +} +} + +# elif GTEST_OS_SYMBIAN + +// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to +// use STLport's tuple implementation, which unfortunately doesn't +// work as the copy of STLport distributed with Symbian is incomplete. +// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to +// use its own tuple implementation. +# ifdef BOOST_HAS_TR1_TUPLE +# undef BOOST_HAS_TR1_TUPLE +# endif // BOOST_HAS_TR1_TUPLE + +// This prevents , which defines +// BOOST_HAS_TR1_TUPLE, from being #included by Boost's . +# define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED +# include + +# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000) +// GCC 4.0+ implements tr1/tuple in the header. This does +// not conform to the TR1 spec, which requires the header to be . + +# if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 +// Until version 4.3.2, gcc has a bug that causes , +// which is #included by , to not compile when RTTI is +// disabled. _TR1_FUNCTIONAL is the header guard for +// . Hence the following #define is a hack to prevent +// from being included. +# define _TR1_FUNCTIONAL 1 +# include +# undef _TR1_FUNCTIONAL // Allows the user to #include + // if he chooses to. +# else +# include // NOLINT +# endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 + +# else +// If the compiler is not GCC 4.0+, we assume the user is using a +// spec-conforming TR1 implementation. +# include // NOLINT +# endif // GTEST_USE_OWN_TR1_TUPLE + +#endif // GTEST_HAS_TR1_TUPLE + +// Determines whether clone(2) is supported. +// Usually it will only be available on Linux, excluding +// Linux on the Itanium architecture. +// Also see http://linux.die.net/man/2/clone. +#ifndef GTEST_HAS_CLONE +// The user didn't tell us, so we need to figure it out. + +# if GTEST_OS_LINUX && !defined(__ia64__) +# if GTEST_OS_LINUX_ANDROID +// On Android, clone() is only available on ARM starting with Gingerbread. +# if defined(__arm__) && __ANDROID_API__ >= 9 +# define GTEST_HAS_CLONE 1 +# else +# define GTEST_HAS_CLONE 0 +# endif +# else +# define GTEST_HAS_CLONE 1 +# endif +# else +# define GTEST_HAS_CLONE 0 +# endif // GTEST_OS_LINUX && !defined(__ia64__) + +#endif // GTEST_HAS_CLONE + +// Determines whether to support stream redirection. This is used to test +// output correctness and to implement death tests. +#ifndef GTEST_HAS_STREAM_REDIRECTION +// By default, we assume that stream redirection is supported on all +// platforms except known mobile ones. +# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN +# define GTEST_HAS_STREAM_REDIRECTION 0 +# else +# define GTEST_HAS_STREAM_REDIRECTION 1 +# endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN +#endif // GTEST_HAS_STREAM_REDIRECTION + +// Determines whether to support death tests. +// Google Test does not support death tests for VC 7.1 and earlier as +// abort() in a VC 7.1 application compiled as GUI in debug config +// pops up a dialog window that cannot be suppressed programmatically. +#if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ + (GTEST_OS_MAC && !GTEST_OS_IOS) || GTEST_OS_IOS_SIMULATOR || \ + (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \ + GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \ + GTEST_OS_OPENBSD || GTEST_OS_QNX) +# define GTEST_HAS_DEATH_TEST 1 +# include // NOLINT +#endif + +// We don't support MSVC 7.1 with exceptions disabled now. Therefore +// all the compilers we care about are adequate for supporting +// value-parameterized tests. +#define GTEST_HAS_PARAM_TEST 1 + +// Determines whether to support type-driven tests. + +// Typed tests need and variadic macros, which GCC, VC++ 8.0, +// Sun Pro CC, IBM Visual Age, and HP aCC support. +#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \ + defined(__IBMCPP__) || defined(__HP_aCC) +# define GTEST_HAS_TYPED_TEST 1 +# define GTEST_HAS_TYPED_TEST_P 1 +#endif + +// Determines whether to support Combine(). This only makes sense when +// value-parameterized tests are enabled. The implementation doesn't +// work on Sun Studio since it doesn't understand templated conversion +// operators. +#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC) +# define GTEST_HAS_COMBINE 1 +#endif + +// Determines whether the system compiler uses UTF-16 for encoding wide strings. +#define GTEST_WIDE_STRING_USES_UTF16_ \ + (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX) + +// Determines whether test results can be streamed to a socket. +#if GTEST_OS_LINUX +# define GTEST_CAN_STREAM_RESULTS_ 1 +#endif + +// Defines some utility macros. + +// The GNU compiler emits a warning if nested "if" statements are followed by +// an "else" statement and braces are not used to explicitly disambiguate the +// "else" binding. This leads to problems with code like: +// +// if (gate) +// ASSERT_*(condition) << "Some message"; +// +// The "switch (0) case 0:" idiom is used to suppress this. +#ifdef __INTEL_COMPILER +# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ +#else +# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default: // NOLINT +#endif + +// Use this annotation at the end of a struct/class definition to +// prevent the compiler from optimizing away instances that are never +// used. This is useful when all interesting logic happens inside the +// c'tor and / or d'tor. Example: +// +// struct Foo { +// Foo() { ... } +// } GTEST_ATTRIBUTE_UNUSED_; +// +// Also use it after a variable or parameter declaration to tell the +// compiler the variable/parameter does not have to be used. +#if defined(__GNUC__) && !defined(COMPILER_ICC) +# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused)) +#else +# define GTEST_ATTRIBUTE_UNUSED_ +#endif + +// A macro to disallow operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_ASSIGN_(type)\ + void operator=(type const &) + +// A macro to disallow copy constructor and operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\ + type(type const &);\ + GTEST_DISALLOW_ASSIGN_(type) + +// Tell the compiler to warn about unused return values for functions declared +// with this macro. The macro should be used on function declarations +// following the argument list: +// +// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_; +#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC) +# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result)) +#else +# define GTEST_MUST_USE_RESULT_ +#endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC + +// Determine whether the compiler supports Microsoft's Structured Exception +// Handling. This is supported by several Windows compilers but generally +// does not exist on any other system. +#ifndef GTEST_HAS_SEH +// The user didn't tell us, so we need to figure it out. + +# if defined(_MSC_VER) || defined(__BORLANDC__) +// These two compilers are known to support SEH. +# define GTEST_HAS_SEH 1 +# else +// Assume no SEH. +# define GTEST_HAS_SEH 0 +# endif + +#endif // GTEST_HAS_SEH + +#ifdef _MSC_VER + +# if GTEST_LINKED_AS_SHARED_LIBRARY +# define GTEST_API_ __declspec(dllimport) +# elif GTEST_CREATE_SHARED_LIBRARY +# define GTEST_API_ __declspec(dllexport) +# endif + +#endif // _MSC_VER + +#ifndef GTEST_API_ +# define GTEST_API_ +#endif + +#ifdef __GNUC__ +// Ask the compiler to never inline a given function. +# define GTEST_NO_INLINE_ __attribute__((noinline)) +#else +# define GTEST_NO_INLINE_ +#endif + +// _LIBCPP_VERSION is defined by the libc++ library from the LLVM project. +#if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) +# define GTEST_HAS_CXXABI_H_ 1 +#else +# define GTEST_HAS_CXXABI_H_ 0 +#endif + +namespace testing { + +class Message; + +namespace internal { + +// A secret type that Google Test users don't know about. It has no +// definition on purpose. Therefore it's impossible to create a +// Secret object, which is what we want. +class Secret; + +// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time +// expression is true. For example, you could use it to verify the +// size of a static array: +// +// GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES, +// content_type_names_incorrect_size); +// +// or to make sure a struct is smaller than a certain size: +// +// GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large); +// +// The second argument to the macro is the name of the variable. If +// the expression is false, most compilers will issue a warning/error +// containing the name of the variable. + +template +struct CompileAssert { +}; + +#define GTEST_COMPILE_ASSERT_(expr, msg) \ + typedef ::testing::internal::CompileAssert<(static_cast(expr))> \ + msg[static_cast(expr) ? 1 : -1] GTEST_ATTRIBUTE_UNUSED_ + +// Implementation details of GTEST_COMPILE_ASSERT_: +// +// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1 +// elements (and thus is invalid) when the expression is false. +// +// - The simpler definition +// +// #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1] +// +// does not work, as gcc supports variable-length arrays whose sizes +// are determined at run-time (this is gcc's extension and not part +// of the C++ standard). As a result, gcc fails to reject the +// following code with the simple definition: +// +// int foo; +// GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is +// // not a compile-time constant. +// +// - By using the type CompileAssert<(bool(expr))>, we ensures that +// expr is a compile-time constant. (Template arguments must be +// determined at compile-time.) +// +// - The outter parentheses in CompileAssert<(bool(expr))> are necessary +// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written +// +// CompileAssert +// +// instead, these compilers will refuse to compile +// +// GTEST_COMPILE_ASSERT_(5 > 0, some_message); +// +// (They seem to think the ">" in "5 > 0" marks the end of the +// template argument list.) +// +// - The array size is (bool(expr) ? 1 : -1), instead of simply +// +// ((expr) ? 1 : -1). +// +// This is to avoid running into a bug in MS VC 7.1, which +// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. + +// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h. +// +// This template is declared, but intentionally undefined. +template +struct StaticAssertTypeEqHelper; + +template +struct StaticAssertTypeEqHelper {}; + +#if GTEST_HAS_GLOBAL_STRING +typedef ::string string; +#else +typedef ::std::string string; +#endif // GTEST_HAS_GLOBAL_STRING + +#if GTEST_HAS_GLOBAL_WSTRING +typedef ::wstring wstring; +#elif GTEST_HAS_STD_WSTRING +typedef ::std::wstring wstring; +#endif // GTEST_HAS_GLOBAL_WSTRING + +// A helper for suppressing warnings on constant condition. It just +// returns 'condition'. +GTEST_API_ bool IsTrue(bool condition); + +// Defines scoped_ptr. + +// This implementation of scoped_ptr is PARTIAL - it only contains +// enough stuff to satisfy Google Test's need. +template +class scoped_ptr { + public: + typedef T element_type; + + explicit scoped_ptr(T* p = NULL) : ptr_(p) {} + ~scoped_ptr() { reset(); } + + T& operator*() const { return *ptr_; } + T* operator->() const { return ptr_; } + T* get() const { return ptr_; } + + T* release() { + T* const ptr = ptr_; + ptr_ = NULL; + return ptr; + } + + void reset(T* p = NULL) { + if (p != ptr_) { + if (IsTrue(sizeof(T) > 0)) { // Makes sure T is a complete type. + delete ptr_; + } + ptr_ = p; + } + } + + private: + T* ptr_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr); +}; + +// Defines RE. + +// A simple C++ wrapper for . It uses the POSIX Extended +// Regular Expression syntax. +class GTEST_API_ RE { + public: + // A copy constructor is required by the Standard to initialize object + // references from r-values. + RE(const RE& other) { Init(other.pattern()); } + + // Constructs an RE from a string. + RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT + +#if GTEST_HAS_GLOBAL_STRING + + RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT + +#endif // GTEST_HAS_GLOBAL_STRING + + RE(const char* regex) { Init(regex); } // NOLINT + ~RE(); + + // Returns the string representation of the regex. + const char* pattern() const { return pattern_; } + + // FullMatch(str, re) returns true iff regular expression re matches + // the entire str. + // PartialMatch(str, re) returns true iff regular expression re + // matches a substring of str (including str itself). + // + // TODO(wan@google.com): make FullMatch() and PartialMatch() work + // when str contains NUL characters. + static bool FullMatch(const ::std::string& str, const RE& re) { + return FullMatch(str.c_str(), re); + } + static bool PartialMatch(const ::std::string& str, const RE& re) { + return PartialMatch(str.c_str(), re); + } + +#if GTEST_HAS_GLOBAL_STRING + + static bool FullMatch(const ::string& str, const RE& re) { + return FullMatch(str.c_str(), re); + } + static bool PartialMatch(const ::string& str, const RE& re) { + return PartialMatch(str.c_str(), re); + } + +#endif // GTEST_HAS_GLOBAL_STRING + + static bool FullMatch(const char* str, const RE& re); + static bool PartialMatch(const char* str, const RE& re); + + private: + void Init(const char* regex); + + // We use a const char* instead of an std::string, as Google Test used to be + // used where std::string is not available. TODO(wan@google.com): change to + // std::string. + const char* pattern_; + bool is_valid_; + +#if GTEST_USES_POSIX_RE + + regex_t full_regex_; // For FullMatch(). + regex_t partial_regex_; // For PartialMatch(). + +#else // GTEST_USES_SIMPLE_RE + + const char* full_pattern_; // For FullMatch(); + +#endif + + GTEST_DISALLOW_ASSIGN_(RE); +}; + +// Formats a source file path and a line number as they would appear +// in an error message from the compiler used to compile this code. +GTEST_API_ ::std::string FormatFileLocation(const char* file, int line); + +// Formats a file location for compiler-independent XML output. +// Although this function is not platform dependent, we put it next to +// FormatFileLocation in order to contrast the two functions. +GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file, + int line); + +// Defines logging utilities: +// GTEST_LOG_(severity) - logs messages at the specified severity level. The +// message itself is streamed into the macro. +// LogToStderr() - directs all log messages to stderr. +// FlushInfoLog() - flushes informational log messages. + +enum GTestLogSeverity { + GTEST_INFO, + GTEST_WARNING, + GTEST_ERROR, + GTEST_FATAL +}; + +// Formats log entry severity, provides a stream object for streaming the +// log message, and terminates the message with a newline when going out of +// scope. +class GTEST_API_ GTestLog { + public: + GTestLog(GTestLogSeverity severity, const char* file, int line); + + // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. + ~GTestLog(); + + ::std::ostream& GetStream() { return ::std::cerr; } + + private: + const GTestLogSeverity severity_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog); +}; + +#define GTEST_LOG_(severity) \ + ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \ + __FILE__, __LINE__).GetStream() + +inline void LogToStderr() {} +inline void FlushInfoLog() { fflush(NULL); } + +// INTERNAL IMPLEMENTATION - DO NOT USE. +// +// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition +// is not satisfied. +// Synopsys: +// GTEST_CHECK_(boolean_condition); +// or +// GTEST_CHECK_(boolean_condition) << "Additional message"; +// +// This checks the condition and if the condition is not satisfied +// it prints message about the condition violation, including the +// condition itself, plus additional message streamed into it, if any, +// and then it aborts the program. It aborts the program irrespective of +// whether it is built in the debug mode or not. +#define GTEST_CHECK_(condition) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::IsTrue(condition)) \ + ; \ + else \ + GTEST_LOG_(FATAL) << "Condition " #condition " failed. " + +// An all-mode assert to verify that the given POSIX-style function +// call returns 0 (indicating success). Known limitation: this +// doesn't expand to a balanced 'if' statement, so enclose the macro +// in {} if you need to use it as the only statement in an 'if' +// branch. +#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \ + if (const int gtest_error = (posix_call)) \ + GTEST_LOG_(FATAL) << #posix_call << "failed with error " \ + << gtest_error + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Use ImplicitCast_ as a safe version of static_cast for upcasting in +// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a +// const Foo*). When you use ImplicitCast_, the compiler checks that +// the cast is safe. Such explicit ImplicitCast_s are necessary in +// surprisingly many situations where C++ demands an exact type match +// instead of an argument type convertable to a target type. +// +// The syntax for using ImplicitCast_ is the same as for static_cast: +// +// ImplicitCast_(expr) +// +// ImplicitCast_ would have been part of the C++ standard library, +// but the proposal was submitted too late. It will probably make +// its way into the language in the future. +// +// This relatively ugly name is intentional. It prevents clashes with +// similar functions users may have (e.g., implicit_cast). The internal +// namespace alone is not enough because the function can be found by ADL. +template +inline To ImplicitCast_(To x) { return x; } + +// When you upcast (that is, cast a pointer from type Foo to type +// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts +// always succeed. When you downcast (that is, cast a pointer from +// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because +// how do you know the pointer is really of type SubclassOfFoo? It +// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, +// when you downcast, you should use this macro. In debug mode, we +// use dynamic_cast<> to double-check the downcast is legal (we die +// if it's not). In normal mode, we do the efficient static_cast<> +// instead. Thus, it's important to test in debug mode to make sure +// the cast is legal! +// This is the only place in the code we should use dynamic_cast<>. +// In particular, you SHOULDN'T be using dynamic_cast<> in order to +// do RTTI (eg code like this: +// if (dynamic_cast(foo)) HandleASubclass1Object(foo); +// if (dynamic_cast(foo)) HandleASubclass2Object(foo); +// You should design the code some other way not to need this. +// +// This relatively ugly name is intentional. It prevents clashes with +// similar functions users may have (e.g., down_cast). The internal +// namespace alone is not enough because the function can be found by ADL. +template // use like this: DownCast_(foo); +inline To DownCast_(From* f) { // so we only accept pointers + // Ensures that To is a sub-type of From *. This test is here only + // for compile-time type checking, and has no overhead in an + // optimized build at run-time, as it will be optimized away + // completely. + if (false) { + const To to = NULL; + ::testing::internal::ImplicitCast_(to); + } + +#if GTEST_HAS_RTTI + // RTTI: debug mode only! + GTEST_CHECK_(f == NULL || dynamic_cast(f) != NULL); +#endif + return static_cast(f); +} + +// Downcasts the pointer of type Base to Derived. +// Derived must be a subclass of Base. The parameter MUST +// point to a class of type Derived, not any subclass of it. +// When RTTI is available, the function performs a runtime +// check to enforce this. +template +Derived* CheckedDowncastToActualType(Base* base) { +#if GTEST_HAS_RTTI + GTEST_CHECK_(typeid(*base) == typeid(Derived)); + return dynamic_cast(base); // NOLINT +#else + return static_cast(base); // Poor man's downcast. +#endif +} + +#if GTEST_HAS_STREAM_REDIRECTION + +// Defines the stderr capturer: +// CaptureStdout - starts capturing stdout. +// GetCapturedStdout - stops capturing stdout and returns the captured string. +// CaptureStderr - starts capturing stderr. +// GetCapturedStderr - stops capturing stderr and returns the captured string. +// +GTEST_API_ void CaptureStdout(); +GTEST_API_ std::string GetCapturedStdout(); +GTEST_API_ void CaptureStderr(); +GTEST_API_ std::string GetCapturedStderr(); + +#endif // GTEST_HAS_STREAM_REDIRECTION + + +#if GTEST_HAS_DEATH_TEST + +const ::std::vector& GetInjectableArgvs(); +void SetInjectableArgvs(const ::std::vector* + new_argvs); + +// A copy of all command line arguments. Set by InitGoogleTest(). +extern ::std::vector g_argvs; + +#endif // GTEST_HAS_DEATH_TEST + +// Defines synchronization primitives. + +#if GTEST_HAS_PTHREAD + +// Sleeps for (roughly) n milli-seconds. This function is only for +// testing Google Test's own constructs. Don't use it in user tests, +// either directly or indirectly. +inline void SleepMilliseconds(int n) { + const timespec time = { + 0, // 0 seconds. + n * 1000L * 1000L, // And n ms. + }; + nanosleep(&time, NULL); +} + +// Allows a controller thread to pause execution of newly created +// threads until notified. Instances of this class must be created +// and destroyed in the controller thread. +// +// This class is only for testing Google Test's own constructs. Do not +// use it in user tests, either directly or indirectly. +class Notification { + public: + Notification() : notified_(false) { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); + } + ~Notification() { + pthread_mutex_destroy(&mutex_); + } + + // Notifies all threads created with this notification to start. Must + // be called from the controller thread. + void Notify() { + pthread_mutex_lock(&mutex_); + notified_ = true; + pthread_mutex_unlock(&mutex_); + } + + // Blocks until the controller thread notifies. Must be called from a test + // thread. + void WaitForNotification() { + for (;;) { + pthread_mutex_lock(&mutex_); + const bool notified = notified_; + pthread_mutex_unlock(&mutex_); + if (notified) + break; + SleepMilliseconds(10); + } + } + + private: + pthread_mutex_t mutex_; + bool notified_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification); +}; + +// As a C-function, ThreadFuncWithCLinkage cannot be templated itself. +// Consequently, it cannot select a correct instantiation of ThreadWithParam +// in order to call its Run(). Introducing ThreadWithParamBase as a +// non-templated base class for ThreadWithParam allows us to bypass this +// problem. +class ThreadWithParamBase { + public: + virtual ~ThreadWithParamBase() {} + virtual void Run() = 0; +}; + +// pthread_create() accepts a pointer to a function type with the C linkage. +// According to the Standard (7.5/1), function types with different linkages +// are different even if they are otherwise identical. Some compilers (for +// example, SunStudio) treat them as different types. Since class methods +// cannot be defined with C-linkage we need to define a free C-function to +// pass into pthread_create(). +extern "C" inline void* ThreadFuncWithCLinkage(void* thread) { + static_cast(thread)->Run(); + return NULL; +} + +// Helper class for testing Google Test's multi-threading constructs. +// To use it, write: +// +// void ThreadFunc(int param) { /* Do things with param */ } +// Notification thread_can_start; +// ... +// // The thread_can_start parameter is optional; you can supply NULL. +// ThreadWithParam thread(&ThreadFunc, 5, &thread_can_start); +// thread_can_start.Notify(); +// +// These classes are only for testing Google Test's own constructs. Do +// not use them in user tests, either directly or indirectly. +template +class ThreadWithParam : public ThreadWithParamBase { + public: + typedef void (*UserThreadFunc)(T); + + ThreadWithParam( + UserThreadFunc func, T param, Notification* thread_can_start) + : func_(func), + param_(param), + thread_can_start_(thread_can_start), + finished_(false) { + ThreadWithParamBase* const base = this; + // The thread can be created only after all fields except thread_ + // have been initialized. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base)); + } + ~ThreadWithParam() { Join(); } + + void Join() { + if (!finished_) { + GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0)); + finished_ = true; + } + } + + virtual void Run() { + if (thread_can_start_ != NULL) + thread_can_start_->WaitForNotification(); + func_(param_); + } + + private: + const UserThreadFunc func_; // User-supplied thread function. + const T param_; // User-supplied parameter to the thread function. + // When non-NULL, used to block execution until the controller thread + // notifies. + Notification* const thread_can_start_; + bool finished_; // true iff we know that the thread function has finished. + pthread_t thread_; // The native thread object. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam); +}; + +// MutexBase and Mutex implement mutex on pthreads-based platforms. They +// are used in conjunction with class MutexLock: +// +// Mutex mutex; +// ... +// MutexLock lock(&mutex); // Acquires the mutex and releases it at the end +// // of the current scope. +// +// MutexBase implements behavior for both statically and dynamically +// allocated mutexes. Do not use MutexBase directly. Instead, write +// the following to define a static mutex: +// +// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex); +// +// You can forward declare a static mutex like this: +// +// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex); +// +// To create a dynamic mutex, just define an object of type Mutex. +class MutexBase { + public: + // Acquires this mutex. + void Lock() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_)); + owner_ = pthread_self(); + has_owner_ = true; + } + + // Releases this mutex. + void Unlock() { + // Since the lock is being released the owner_ field should no longer be + // considered valid. We don't protect writing to has_owner_ here, as it's + // the caller's responsibility to ensure that the current thread holds the + // mutex when this is called. + has_owner_ = false; + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_)); + } + + // Does nothing if the current thread holds the mutex. Otherwise, crashes + // with high probability. + void AssertHeld() const { + GTEST_CHECK_(has_owner_ && pthread_equal(owner_, pthread_self())) + << "The current thread is not holding the mutex @" << this; + } + + // A static mutex may be used before main() is entered. It may even + // be used before the dynamic initialization stage. Therefore we + // must be able to initialize a static mutex object at link time. + // This means MutexBase has to be a POD and its member variables + // have to be public. + public: + pthread_mutex_t mutex_; // The underlying pthread mutex. + // has_owner_ indicates whether the owner_ field below contains a valid thread + // ID and is therefore safe to inspect (e.g., to use in pthread_equal()). All + // accesses to the owner_ field should be protected by a check of this field. + // An alternative might be to memset() owner_ to all zeros, but there's no + // guarantee that a zero'd pthread_t is necessarily invalid or even different + // from pthread_self(). + bool has_owner_; + pthread_t owner_; // The thread holding the mutex. +}; + +// Forward-declares a static mutex. +# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::MutexBase mutex + +// Defines and statically (i.e. at link time) initializes a static mutex. +// The initialization list here does not explicitly initialize each field, +// instead relying on default initialization for the unspecified fields. In +// particular, the owner_ field (a pthread_t) is not explicitly initialized. +// This allows initialization to work whether pthread_t is a scalar or struct. +// The flag -Wmissing-field-initializers must not be specified for this to work. +# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \ + ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, false } + +// The Mutex class can only be used for mutexes created at runtime. It +// shares its API with MutexBase otherwise. +class Mutex : public MutexBase { + public: + Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); + has_owner_ = false; + } + ~Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_)); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex); +}; + +// We cannot name this class MutexLock as the ctor declaration would +// conflict with a macro named MutexLock, which is defined on some +// platforms. Hence the typedef trick below. +class GTestMutexLock { + public: + explicit GTestMutexLock(MutexBase* mutex) + : mutex_(mutex) { mutex_->Lock(); } + + ~GTestMutexLock() { mutex_->Unlock(); } + + private: + MutexBase* const mutex_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock); +}; + +typedef GTestMutexLock MutexLock; + +// Helpers for ThreadLocal. + +// pthread_key_create() requires DeleteThreadLocalValue() to have +// C-linkage. Therefore it cannot be templatized to access +// ThreadLocal. Hence the need for class +// ThreadLocalValueHolderBase. +class ThreadLocalValueHolderBase { + public: + virtual ~ThreadLocalValueHolderBase() {} +}; + +// Called by pthread to delete thread-local data stored by +// pthread_setspecific(). +extern "C" inline void DeleteThreadLocalValue(void* value_holder) { + delete static_cast(value_holder); +} + +// Implements thread-local storage on pthreads-based systems. +// +// // Thread 1 +// ThreadLocal tl(100); // 100 is the default value for each thread. +// +// // Thread 2 +// tl.set(150); // Changes the value for thread 2 only. +// EXPECT_EQ(150, tl.get()); +// +// // Thread 1 +// EXPECT_EQ(100, tl.get()); // In thread 1, tl has the original value. +// tl.set(200); +// EXPECT_EQ(200, tl.get()); +// +// The template type argument T must have a public copy constructor. +// In addition, the default ThreadLocal constructor requires T to have +// a public default constructor. +// +// An object managed for a thread by a ThreadLocal instance is deleted +// when the thread exits. Or, if the ThreadLocal instance dies in +// that thread, when the ThreadLocal dies. It's the user's +// responsibility to ensure that all other threads using a ThreadLocal +// have exited when it dies, or the per-thread objects for those +// threads will not be deleted. +// +// Google Test only uses global ThreadLocal objects. That means they +// will die after main() has returned. Therefore, no per-thread +// object managed by Google Test will be leaked as long as all threads +// using Google Test have exited when main() returns. +template +class ThreadLocal { + public: + ThreadLocal() : key_(CreateKey()), + default_() {} + explicit ThreadLocal(const T& value) : key_(CreateKey()), + default_(value) {} + + ~ThreadLocal() { + // Destroys the managed object for the current thread, if any. + DeleteThreadLocalValue(pthread_getspecific(key_)); + + // Releases resources associated with the key. This will *not* + // delete managed objects for other threads. + GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_)); + } + + T* pointer() { return GetOrCreateValue(); } + const T* pointer() const { return GetOrCreateValue(); } + const T& get() const { return *pointer(); } + void set(const T& value) { *pointer() = value; } + + private: + // Holds a value of type T. + class ValueHolder : public ThreadLocalValueHolderBase { + public: + explicit ValueHolder(const T& value) : value_(value) {} + + T* pointer() { return &value_; } + + private: + T value_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder); + }; + + static pthread_key_t CreateKey() { + pthread_key_t key; + // When a thread exits, DeleteThreadLocalValue() will be called on + // the object managed for that thread. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_key_create(&key, &DeleteThreadLocalValue)); + return key; + } + + T* GetOrCreateValue() const { + ThreadLocalValueHolderBase* const holder = + static_cast(pthread_getspecific(key_)); + if (holder != NULL) { + return CheckedDowncastToActualType(holder)->pointer(); + } + + ValueHolder* const new_holder = new ValueHolder(default_); + ThreadLocalValueHolderBase* const holder_base = new_holder; + GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base)); + return new_holder->pointer(); + } + + // A key pthreads uses for looking up per-thread values. + const pthread_key_t key_; + const T default_; // The default value for each thread. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); +}; + +# define GTEST_IS_THREADSAFE 1 + +#else // GTEST_HAS_PTHREAD + +// A dummy implementation of synchronization primitives (mutex, lock, +// and thread-local variable). Necessary for compiling Google Test where +// mutex is not supported - using Google Test in multiple threads is not +// supported on such platforms. + +class Mutex { + public: + Mutex() {} + void Lock() {} + void Unlock() {} + void AssertHeld() const {} +}; + +# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::Mutex mutex + +# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex + +class GTestMutexLock { + public: + explicit GTestMutexLock(Mutex*) {} // NOLINT +}; + +typedef GTestMutexLock MutexLock; + +template +class ThreadLocal { + public: + ThreadLocal() : value_() {} + explicit ThreadLocal(const T& value) : value_(value) {} + T* pointer() { return &value_; } + const T* pointer() const { return &value_; } + const T& get() const { return value_; } + void set(const T& value) { value_ = value; } + private: + T value_; +}; + +// The above synchronization primitives have dummy implementations. +// Therefore Google Test is not thread-safe. +# define GTEST_IS_THREADSAFE 0 + +#endif // GTEST_HAS_PTHREAD + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +GTEST_API_ size_t GetThreadCount(); + +// Passing non-POD classes through ellipsis (...) crashes the ARM +// compiler and generates a warning in Sun Studio. The Nokia Symbian +// and the IBM XL C/C++ compiler try to instantiate a copy constructor +// for objects passed through ellipsis (...), failing for uncopyable +// objects. We define this to ensure that only POD is passed through +// ellipsis on these systems. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC) +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). +# define GTEST_ELLIPSIS_NEEDS_POD_ 1 +#else +# define GTEST_CAN_COMPARE_NULL 1 +#endif + +// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between +// const T& and const T* in a function template. These compilers +// _can_ decide between class template specializations for T and T*, +// so a tr1::type_traits-like is_pointer works. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) +# define GTEST_NEEDS_IS_POINTER_ 1 +#endif + +template +struct bool_constant { + typedef bool_constant type; + static const bool value = bool_value; +}; +template const bool bool_constant::value; + +typedef bool_constant false_type; +typedef bool_constant true_type; + +template +struct is_pointer : public false_type {}; + +template +struct is_pointer : public true_type {}; + +template +struct IteratorTraits { + typedef typename Iterator::value_type value_type; +}; + +template +struct IteratorTraits { + typedef T value_type; +}; + +template +struct IteratorTraits { + typedef T value_type; +}; + +#if GTEST_OS_WINDOWS +# define GTEST_PATH_SEP_ "\\" +# define GTEST_HAS_ALT_PATH_SEP_ 1 +// The biggest signed integer type the compiler supports. +typedef __int64 BiggestInt; +#else +# define GTEST_PATH_SEP_ "/" +# define GTEST_HAS_ALT_PATH_SEP_ 0 +typedef long long BiggestInt; // NOLINT +#endif // GTEST_OS_WINDOWS + +// Utilities for char. + +// isspace(int ch) and friends accept an unsigned char or EOF. char +// may be signed, depending on the compiler (or compiler flags). +// Therefore we need to cast a char to unsigned char before calling +// isspace(), etc. + +inline bool IsAlpha(char ch) { + return isalpha(static_cast(ch)) != 0; +} +inline bool IsAlNum(char ch) { + return isalnum(static_cast(ch)) != 0; +} +inline bool IsDigit(char ch) { + return isdigit(static_cast(ch)) != 0; +} +inline bool IsLower(char ch) { + return islower(static_cast(ch)) != 0; +} +inline bool IsSpace(char ch) { + return isspace(static_cast(ch)) != 0; +} +inline bool IsUpper(char ch) { + return isupper(static_cast(ch)) != 0; +} +inline bool IsXDigit(char ch) { + return isxdigit(static_cast(ch)) != 0; +} +inline bool IsXDigit(wchar_t ch) { + const unsigned char low_byte = static_cast(ch); + return ch == low_byte && isxdigit(low_byte) != 0; +} + +inline char ToLower(char ch) { + return static_cast(tolower(static_cast(ch))); +} +inline char ToUpper(char ch) { + return static_cast(toupper(static_cast(ch))); +} + +// The testing::internal::posix namespace holds wrappers for common +// POSIX functions. These wrappers hide the differences between +// Windows/MSVC and POSIX systems. Since some compilers define these +// standard functions as macros, the wrapper cannot have the same name +// as the wrapped function. + +namespace posix { + +// Functions with a different name on Windows. + +#if GTEST_OS_WINDOWS + +typedef struct _stat StatStruct; + +# ifdef __BORLANDC__ +inline int IsATTY(int fd) { return isatty(fd); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +# else // !__BORLANDC__ +# if GTEST_OS_WINDOWS_MOBILE +inline int IsATTY(int /* fd */) { return 0; } +# else +inline int IsATTY(int fd) { return _isatty(fd); } +# endif // GTEST_OS_WINDOWS_MOBILE +inline int StrCaseCmp(const char* s1, const char* s2) { + return _stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return _strdup(src); } +# endif // __BORLANDC__ + +# if GTEST_OS_WINDOWS_MOBILE +inline int FileNo(FILE* file) { return reinterpret_cast(_fileno(file)); } +// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this +// time and thus not defined there. +# else +inline int FileNo(FILE* file) { return _fileno(file); } +inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); } +inline int RmDir(const char* dir) { return _rmdir(dir); } +inline bool IsDir(const StatStruct& st) { + return (_S_IFDIR & st.st_mode) != 0; +} +# endif // GTEST_OS_WINDOWS_MOBILE + +#else + +typedef struct stat StatStruct; + +inline int FileNo(FILE* file) { return fileno(file); } +inline int IsATTY(int fd) { return isatty(fd); } +inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return strcasecmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +inline int RmDir(const char* dir) { return rmdir(dir); } +inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } + +#endif // GTEST_OS_WINDOWS + +// Functions deprecated by MSVC 8.0. + +#ifdef _MSC_VER +// Temporarily disable warning 4996 (deprecated function). +# pragma warning(push) +# pragma warning(disable:4996) +#endif + +inline const char* StrNCpy(char* dest, const char* src, size_t n) { + return strncpy(dest, src, n); +} + +// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and +// StrError() aren't needed on Windows CE at this time and thus not +// defined there. + +#if !GTEST_OS_WINDOWS_MOBILE +inline int ChDir(const char* dir) { return chdir(dir); } +#endif +inline FILE* FOpen(const char* path, const char* mode) { + return fopen(path, mode); +} +#if !GTEST_OS_WINDOWS_MOBILE +inline FILE *FReopen(const char* path, const char* mode, FILE* stream) { + return freopen(path, mode, stream); +} +inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); } +#endif +inline int FClose(FILE* fp) { return fclose(fp); } +#if !GTEST_OS_WINDOWS_MOBILE +inline int Read(int fd, void* buf, unsigned int count) { + return static_cast(read(fd, buf, count)); +} +inline int Write(int fd, const void* buf, unsigned int count) { + return static_cast(write(fd, buf, count)); +} +inline int Close(int fd) { return close(fd); } +inline const char* StrError(int errnum) { return strerror(errnum); } +#endif +inline const char* GetEnv(const char* name) { +#if GTEST_OS_WINDOWS_MOBILE + // We are on Windows CE, which has no environment variables. + return NULL; +#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9) + // Environment variables which we programmatically clear will be set to the + // empty string rather than unset (NULL). Handle that case. + const char* const env = getenv(name); + return (env != NULL && env[0] != '\0') ? env : NULL; +#else + return getenv(name); +#endif +} + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif + +#if GTEST_OS_WINDOWS_MOBILE +// Windows CE has no C library. The abort() function is used in +// several places in Google Test. This implementation provides a reasonable +// imitation of standard behaviour. +void Abort(); +#else +inline void Abort() { abort(); } +#endif // GTEST_OS_WINDOWS_MOBILE + +} // namespace posix + +// MSVC "deprecates" snprintf and issues warnings wherever it is used. In +// order to avoid these warnings, we need to use _snprintf or _snprintf_s on +// MSVC-based platforms. We map the GTEST_SNPRINTF_ macro to the appropriate +// function in order to achieve that. We use macro definition here because +// snprintf is a variadic function. +#if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE +// MSVC 2005 and above support variadic macros. +# define GTEST_SNPRINTF_(buffer, size, format, ...) \ + _snprintf_s(buffer, size, size, format, __VA_ARGS__) +#elif defined(_MSC_VER) +// Windows CE does not define _snprintf_s and MSVC prior to 2005 doesn't +// complain about _snprintf. +# define GTEST_SNPRINTF_ _snprintf +#else +# define GTEST_SNPRINTF_ snprintf +#endif + +// The maximum number a BiggestInt can represent. This definition +// works no matter BiggestInt is represented in one's complement or +// two's complement. +// +// We cannot rely on numeric_limits in STL, as __int64 and long long +// are not part of standard C++ and numeric_limits doesn't need to be +// defined for them. +const BiggestInt kMaxBiggestInt = + ~(static_cast(1) << (8*sizeof(BiggestInt) - 1)); + +// This template class serves as a compile-time function from size to +// type. It maps a size in bytes to a primitive type with that +// size. e.g. +// +// TypeWithSize<4>::UInt +// +// is typedef-ed to be unsigned int (unsigned integer made up of 4 +// bytes). +// +// Such functionality should belong to STL, but I cannot find it +// there. +// +// Google Test uses this class in the implementation of floating-point +// comparison. +// +// For now it only handles UInt (unsigned int) as that's all Google Test +// needs. Other types can be easily added in the future if need +// arises. +template +class TypeWithSize { + public: + // This prevents the user from using TypeWithSize with incorrect + // values of N. + typedef void UInt; +}; + +// The specialization for size 4. +template <> +class TypeWithSize<4> { + public: + // unsigned int has size 4 in both gcc and MSVC. + // + // As base/basictypes.h doesn't compile on Windows, we cannot use + // uint32, uint64, and etc here. + typedef int Int; + typedef unsigned int UInt; +}; + +// The specialization for size 8. +template <> +class TypeWithSize<8> { + public: +#if GTEST_OS_WINDOWS + typedef __int64 Int; + typedef unsigned __int64 UInt; +#else + typedef long long Int; // NOLINT + typedef unsigned long long UInt; // NOLINT +#endif // GTEST_OS_WINDOWS +}; + +// Integer types of known sizes. +typedef TypeWithSize<4>::Int Int32; +typedef TypeWithSize<4>::UInt UInt32; +typedef TypeWithSize<8>::Int Int64; +typedef TypeWithSize<8>::UInt UInt64; +typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. + +// Utilities for command line flags and environment variables. + +// Macro for referencing flags. +#define GTEST_FLAG(name) FLAGS_gtest_##name + +// Macros for declaring flags. +#define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name) +#define GTEST_DECLARE_int32_(name) \ + GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name) +#define GTEST_DECLARE_string_(name) \ + GTEST_API_ extern ::std::string GTEST_FLAG(name) + +// Macros for defining flags. +#define GTEST_DEFINE_bool_(name, default_val, doc) \ + GTEST_API_ bool GTEST_FLAG(name) = (default_val) +#define GTEST_DEFINE_int32_(name, default_val, doc) \ + GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val) +#define GTEST_DEFINE_string_(name, default_val, doc) \ + GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val) + +// Thread annotations +#define GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks) +#define GTEST_LOCK_EXCLUDED_(locks) + +// Parses 'str' for a 32-bit signed integer. If successful, writes the result +// to *value and returns true; otherwise leaves *value unchanged and returns +// false. +// TODO(chandlerc): Find a better way to refactor flag and environment parsing +// out of both gtest-port.cc and gtest.cc to avoid exporting this utility +// function. +bool ParseInt32(const Message& src_text, const char* str, Int32* value); + +// Parses a bool/Int32/string from the environment variable +// corresponding to the given Google Test flag. +bool BoolFromGTestEnv(const char* flag, bool default_val); +GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val); +const char* StringFromGTestEnv(const char* flag, const char* default_val); + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ + +#if GTEST_OS_LINUX +# include +# include +# include +# include +#endif // GTEST_OS_LINUX + +#if GTEST_HAS_EXCEPTIONS +# include +#endif + +#include +#include +#include +#include +#include +#include + +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the Message class. +// +// IMPORTANT NOTE: Due to limitation of the C++ language, we have to +// leave some internal implementation details in this header file. +// They are clearly marked by comments like this: +// +// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +// +// Such code is NOT meant to be used by a user directly, and is subject +// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user +// program! + +#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ + +#include + + +// Ensures that there is at least one operator<< in the global namespace. +// See Message& operator<<(...) below for why. +void operator<<(const testing::internal::Secret&, int); + +namespace testing { + +// The Message class works like an ostream repeater. +// +// Typical usage: +// +// 1. You stream a bunch of values to a Message object. +// It will remember the text in a stringstream. +// 2. Then you stream the Message object to an ostream. +// This causes the text in the Message to be streamed +// to the ostream. +// +// For example; +// +// testing::Message foo; +// foo << 1 << " != " << 2; +// std::cout << foo; +// +// will print "1 != 2". +// +// Message is not intended to be inherited from. In particular, its +// destructor is not virtual. +// +// Note that stringstream behaves differently in gcc and in MSVC. You +// can stream a NULL char pointer to it in the former, but not in the +// latter (it causes an access violation if you do). The Message +// class hides this difference by treating a NULL char pointer as +// "(null)". +class GTEST_API_ Message { + private: + // The type of basic IO manipulators (endl, ends, and flush) for + // narrow streams. + typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&); + + public: + // Constructs an empty Message. + Message(); + + // Copy constructor. + Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT + *ss_ << msg.GetString(); + } + + // Constructs a Message from a C-string. + explicit Message(const char* str) : ss_(new ::std::stringstream) { + *ss_ << str; + } + +#if GTEST_OS_SYMBIAN + // Streams a value (either a pointer or not) to this object. + template + inline Message& operator <<(const T& value) { + StreamHelper(typename internal::is_pointer::type(), value); + return *this; + } +#else + // Streams a non-pointer value to this object. + template + inline Message& operator <<(const T& val) { + // Some libraries overload << for STL containers. These + // overloads are defined in the global namespace instead of ::std. + // + // C++'s symbol lookup rule (i.e. Koenig lookup) says that these + // overloads are visible in either the std namespace or the global + // namespace, but not other namespaces, including the testing + // namespace which Google Test's Message class is in. + // + // To allow STL containers (and other types that has a << operator + // defined in the global namespace) to be used in Google Test + // assertions, testing::Message must access the custom << operator + // from the global namespace. With this using declaration, + // overloads of << defined in the global namespace and those + // visible via Koenig lookup are both exposed in this function. + using ::operator <<; + *ss_ << val; + return *this; + } + + // Streams a pointer value to this object. + // + // This function is an overload of the previous one. When you + // stream a pointer to a Message, this definition will be used as it + // is more specialized. (The C++ Standard, section + // [temp.func.order].) If you stream a non-pointer, then the + // previous definition will be used. + // + // The reason for this overload is that streaming a NULL pointer to + // ostream is undefined behavior. Depending on the compiler, you + // may get "0", "(nil)", "(null)", or an access violation. To + // ensure consistent result across compilers, we always treat NULL + // as "(null)". + template + inline Message& operator <<(T* const& pointer) { // NOLINT + if (pointer == NULL) { + *ss_ << "(null)"; + } else { + *ss_ << pointer; + } + return *this; + } +#endif // GTEST_OS_SYMBIAN + + // Since the basic IO manipulators are overloaded for both narrow + // and wide streams, we have to provide this specialized definition + // of operator <<, even though its body is the same as the + // templatized version above. Without this definition, streaming + // endl or other basic IO manipulators to Message will confuse the + // compiler. + Message& operator <<(BasicNarrowIoManip val) { + *ss_ << val; + return *this; + } + + // Instead of 1/0, we want to see true/false for bool values. + Message& operator <<(bool b) { + return *this << (b ? "true" : "false"); + } + + // These two overloads allow streaming a wide C string to a Message + // using the UTF-8 encoding. + Message& operator <<(const wchar_t* wide_c_str); + Message& operator <<(wchar_t* wide_c_str); + +#if GTEST_HAS_STD_WSTRING + // Converts the given wide string to a narrow string using the UTF-8 + // encoding, and streams the result to this Message object. + Message& operator <<(const ::std::wstring& wstr); +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_WSTRING + // Converts the given wide string to a narrow string using the UTF-8 + // encoding, and streams the result to this Message object. + Message& operator <<(const ::wstring& wstr); +#endif // GTEST_HAS_GLOBAL_WSTRING + + // Gets the text streamed to this object so far as an std::string. + // Each '\0' character in the buffer is replaced with "\\0". + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + std::string GetString() const; + + private: + +#if GTEST_OS_SYMBIAN + // These are needed as the Nokia Symbian Compiler cannot decide between + // const T& and const T* in a function template. The Nokia compiler _can_ + // decide between class template specializations for T and T*, so a + // tr1::type_traits-like is_pointer works, and we can overload on that. + template + inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) { + if (pointer == NULL) { + *ss_ << "(null)"; + } else { + *ss_ << pointer; + } + } + template + inline void StreamHelper(internal::false_type /*is_pointer*/, + const T& value) { + // See the comments in Message& operator <<(const T&) above for why + // we need this using statement. + using ::operator <<; + *ss_ << value; + } +#endif // GTEST_OS_SYMBIAN + + // We'll hold the text streamed to this object here. + const internal::scoped_ptr< ::std::stringstream> ss_; + + // We declare (but don't implement) this to prevent the compiler + // from implementing the assignment operator. + void operator=(const Message&); +}; + +// Streams a Message to an ostream. +inline std::ostream& operator <<(std::ostream& os, const Message& sb) { + return os << sb.GetString(); +} + +namespace internal { + +// Converts a streamable value to an std::string. A NULL pointer is +// converted to "(null)". When the input value is a ::string, +// ::std::string, ::wstring, or ::std::wstring object, each NUL +// character in it is replaced with "\\0". +template +std::string StreamableToString(const T& streamable) { + return (Message() << streamable).GetString(); +} + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file declares the String class and functions used internally by +// Google Test. They are subject to change without notice. They should not used +// by code external to Google Test. +// +// This header file is #included by . +// It should not be #included by other files. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ + +#ifdef __BORLANDC__ +// string.h is not guaranteed to provide strcpy on C++ Builder. +# include +#endif + +#include +#include + + +namespace testing { +namespace internal { + +// String - an abstract class holding static string utilities. +class GTEST_API_ String { + public: + // Static utility methods + + // Clones a 0-terminated C string, allocating memory using new. The + // caller is responsible for deleting the return value using + // delete[]. Returns the cloned string, or NULL if the input is + // NULL. + // + // This is different from strdup() in string.h, which allocates + // memory using malloc(). + static const char* CloneCString(const char* c_str); + +#if GTEST_OS_WINDOWS_MOBILE + // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be + // able to pass strings to Win32 APIs on CE we need to convert them + // to 'Unicode', UTF-16. + + // Creates a UTF-16 wide string from the given ANSI string, allocating + // memory using new. The caller is responsible for deleting the return + // value using delete[]. Returns the wide string, or NULL if the + // input is NULL. + // + // The wide string is created using the ANSI codepage (CP_ACP) to + // match the behaviour of the ANSI versions of Win32 calls and the + // C runtime. + static LPCWSTR AnsiToUtf16(const char* c_str); + + // Creates an ANSI string from the given wide string, allocating + // memory using new. The caller is responsible for deleting the return + // value using delete[]. Returns the ANSI string, or NULL if the + // input is NULL. + // + // The returned string is created using the ANSI codepage (CP_ACP) to + // match the behaviour of the ANSI versions of Win32 calls and the + // C runtime. + static const char* Utf16ToAnsi(LPCWSTR utf16_str); +#endif + + // Compares two C strings. Returns true iff they have the same content. + // + // Unlike strcmp(), this function can handle NULL argument(s). A + // NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool CStringEquals(const char* lhs, const char* rhs); + + // Converts a wide C string to a String using the UTF-8 encoding. + // NULL will be converted to "(null)". If an error occurred during + // the conversion, "(failed to convert from wide string)" is + // returned. + static std::string ShowWideCString(const wchar_t* wide_c_str); + + // Compares two wide C strings. Returns true iff they have the same + // content. + // + // Unlike wcscmp(), this function can handle NULL argument(s). A + // NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); + + // Compares two C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike strcasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool CaseInsensitiveCStringEquals(const char* lhs, + const char* rhs); + + // Compares two wide C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike wcscasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL wide C string, + // including the empty string. + // NB: The implementations on different platforms slightly differ. + // On windows, this method uses _wcsicmp which compares according to LC_CTYPE + // environment variable. On GNU platform this method uses wcscasecmp + // which compares according to LC_CTYPE category of the current locale. + // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the + // current locale. + static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs, + const wchar_t* rhs); + + // Returns true iff the given string ends with the given suffix, ignoring + // case. Any string is considered to end with an empty suffix. + static bool EndsWithCaseInsensitive( + const std::string& str, const std::string& suffix); + + // Formats an int value as "%02d". + static std::string FormatIntWidth2(int value); // "%02d" for width == 2 + + // Formats an int value as "%X". + static std::string FormatHexInt(int value); + + // Formats a byte as "%02X". + static std::string FormatByte(unsigned char value); + + private: + String(); // Not meant to be instantiated. +}; // class String + +// Gets the content of the stringstream's buffer as an std::string. Each '\0' +// character in the buffer is replaced with "\\0". +GTEST_API_ std::string StringStreamToString(::std::stringstream* stream); + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: keith.ray@gmail.com (Keith Ray) +// +// Google Test filepath utilities +// +// This header file declares classes and functions used internally by +// Google Test. They are subject to change without notice. +// +// This file is #included in . +// Do not include this header file separately! + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ + + +namespace testing { +namespace internal { + +// FilePath - a class for file and directory pathname manipulation which +// handles platform-specific conventions (like the pathname separator). +// Used for helper functions for naming files in a directory for xml output. +// Except for Set methods, all methods are const or static, which provides an +// "immutable value object" -- useful for peace of mind. +// A FilePath with a value ending in a path separator ("like/this/") represents +// a directory, otherwise it is assumed to represent a file. In either case, +// it may or may not represent an actual file or directory in the file system. +// Names are NOT checked for syntax correctness -- no checking for illegal +// characters, malformed paths, etc. + +class GTEST_API_ FilePath { + public: + FilePath() : pathname_("") { } + FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { } + + explicit FilePath(const std::string& pathname) : pathname_(pathname) { + Normalize(); + } + + FilePath& operator=(const FilePath& rhs) { + Set(rhs); + return *this; + } + + void Set(const FilePath& rhs) { + pathname_ = rhs.pathname_; + } + + const std::string& string() const { return pathname_; } + const char* c_str() const { return pathname_.c_str(); } + + // Returns the current working directory, or "" if unsuccessful. + static FilePath GetCurrentDir(); + + // Given directory = "dir", base_name = "test", number = 0, + // extension = "xml", returns "dir/test.xml". If number is greater + // than zero (e.g., 12), returns "dir/test_12.xml". + // On Windows platform, uses \ as the separator rather than /. + static FilePath MakeFileName(const FilePath& directory, + const FilePath& base_name, + int number, + const char* extension); + + // Given directory = "dir", relative_path = "test.xml", + // returns "dir/test.xml". + // On Windows, uses \ as the separator rather than /. + static FilePath ConcatPaths(const FilePath& directory, + const FilePath& relative_path); + + // Returns a pathname for a file that does not currently exist. The pathname + // will be directory/base_name.extension or + // directory/base_name_.extension if directory/base_name.extension + // already exists. The number will be incremented until a pathname is found + // that does not already exist. + // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. + // There could be a race condition if two or more processes are calling this + // function at the same time -- they could both pick the same filename. + static FilePath GenerateUniqueFileName(const FilePath& directory, + const FilePath& base_name, + const char* extension); + + // Returns true iff the path is "". + bool IsEmpty() const { return pathname_.empty(); } + + // If input name has a trailing separator character, removes it and returns + // the name, otherwise return the name string unmodified. + // On Windows platform, uses \ as the separator, other platforms use /. + FilePath RemoveTrailingPathSeparator() const; + + // Returns a copy of the FilePath with the directory part removed. + // Example: FilePath("path/to/file").RemoveDirectoryName() returns + // FilePath("file"). If there is no directory part ("just_a_file"), it returns + // the FilePath unmodified. If there is no file part ("just_a_dir/") it + // returns an empty FilePath (""). + // On Windows platform, '\' is the path separator, otherwise it is '/'. + FilePath RemoveDirectoryName() const; + + // RemoveFileName returns the directory path with the filename removed. + // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". + // If the FilePath is "a_file" or "/a_file", RemoveFileName returns + // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does + // not have a file, like "just/a/dir/", it returns the FilePath unmodified. + // On Windows platform, '\' is the path separator, otherwise it is '/'. + FilePath RemoveFileName() const; + + // Returns a copy of the FilePath with the case-insensitive extension removed. + // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns + // FilePath("dir/file"). If a case-insensitive extension is not + // found, returns a copy of the original FilePath. + FilePath RemoveExtension(const char* extension) const; + + // Creates directories so that path exists. Returns true if successful or if + // the directories already exist; returns false if unable to create + // directories for any reason. Will also return false if the FilePath does + // not represent a directory (that is, it doesn't end with a path separator). + bool CreateDirectoriesRecursively() const; + + // Create the directory so that path exists. Returns true if successful or + // if the directory already exists; returns false if unable to create the + // directory for any reason, including if the parent directory does not + // exist. Not named "CreateDirectory" because that's a macro on Windows. + bool CreateFolder() const; + + // Returns true if FilePath describes something in the file-system, + // either a file, directory, or whatever, and that something exists. + bool FileOrDirectoryExists() const; + + // Returns true if pathname describes a directory in the file-system + // that exists. + bool DirectoryExists() const; + + // Returns true if FilePath ends with a path separator, which indicates that + // it is intended to represent a directory. Returns false otherwise. + // This does NOT check that a directory (or file) actually exists. + bool IsDirectory() const; + + // Returns true if pathname describes a root directory. (Windows has one + // root directory per disk drive.) + bool IsRootDirectory() const; + + // Returns true if pathname describes an absolute path. + bool IsAbsolutePath() const; + + private: + // Replaces multiple consecutive separators with a single separator. + // For example, "bar///foo" becomes "bar/foo". Does not eliminate other + // redundancies that might be in a pathname involving "." or "..". + // + // A pathname with multiple consecutive separators may occur either through + // user error or as a result of some scripts or APIs that generate a pathname + // with a trailing separator. On other platforms the same API or script + // may NOT generate a pathname with a trailing "/". Then elsewhere that + // pathname may have another "/" and pathname components added to it, + // without checking for the separator already being there. + // The script language and operating system may allow paths like "foo//bar" + // but some of the functions in FilePath will not handle that correctly. In + // particular, RemoveTrailingPathSeparator() only removes one separator, and + // it is called in CreateDirectoriesRecursively() assuming that it will change + // a pathname from directory syntax (trailing separator) to filename syntax. + // + // On Windows this method also replaces the alternate path separator '/' with + // the primary path separator '\\', so that for example "bar\\/\\foo" becomes + // "bar\\foo". + + void Normalize(); + + // Returns a pointer to the last occurence of a valid path separator in + // the FilePath. On Windows, for example, both '/' and '\' are valid path + // separators. Returns NULL if no path separator was found. + const char* FindLastPathSeparator() const; + + std::string pathname_; +}; // class FilePath + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +// This file was GENERATED by command: +// pump.py gtest-type-util.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Type utilities needed for implementing typed and type-parameterized +// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +// Currently we support at most 50 types in a list, and at most 50 +// type-parameterized tests in one type-parameterized test case. +// Please contact googletestframework@googlegroups.com if you need +// more. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ + + +// #ifdef __GNUC__ is too general here. It is possible to use gcc without using +// libstdc++ (which is where cxxabi.h comes from). +# if GTEST_HAS_CXXABI_H_ +# include +# elif defined(__HP_aCC) +# include +# endif // GTEST_HASH_CXXABI_H_ + +namespace testing { +namespace internal { + +// GetTypeName() returns a human-readable name of type T. +// NB: This function is also used in Google Mock, so don't move it inside of +// the typed-test-only section below. +template +std::string GetTypeName() { +# if GTEST_HAS_RTTI + + const char* const name = typeid(T).name(); +# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) + int status = 0; + // gcc's implementation of typeid(T).name() mangles the type name, + // so we have to demangle it. +# if GTEST_HAS_CXXABI_H_ + using abi::__cxa_demangle; +# endif // GTEST_HAS_CXXABI_H_ + char* const readable_name = __cxa_demangle(name, 0, 0, &status); + const std::string name_str(status == 0 ? readable_name : name); + free(readable_name); + return name_str; +# else + return name; +# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC + +# else + + return ""; + +# endif // GTEST_HAS_RTTI +} + +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// AssertyTypeEq::type is defined iff T1 and T2 are the same +// type. This can be used as a compile-time assertion to ensure that +// two types are equal. + +template +struct AssertTypeEq; + +template +struct AssertTypeEq { + typedef bool type; +}; + +// A unique type used as the default value for the arguments of class +// template Types. This allows us to simulate variadic templates +// (e.g. Types, Type, and etc), which C++ doesn't +// support directly. +struct None {}; + +// The following family of struct and struct templates are used to +// represent type lists. In particular, TypesN +// represents a type list with N types (T1, T2, ..., and TN) in it. +// Except for Types0, every struct in the family has two member types: +// Head for the first type in the list, and Tail for the rest of the +// list. + +// The empty type list. +struct Types0 {}; + +// Type lists of length 1, 2, 3, and so on. + +template +struct Types1 { + typedef T1 Head; + typedef Types0 Tail; +}; +template +struct Types2 { + typedef T1 Head; + typedef Types1 Tail; +}; + +template +struct Types3 { + typedef T1 Head; + typedef Types2 Tail; +}; + +template +struct Types4 { + typedef T1 Head; + typedef Types3 Tail; +}; + +template +struct Types5 { + typedef T1 Head; + typedef Types4 Tail; +}; + +template +struct Types6 { + typedef T1 Head; + typedef Types5 Tail; +}; + +template +struct Types7 { + typedef T1 Head; + typedef Types6 Tail; +}; + +template +struct Types8 { + typedef T1 Head; + typedef Types7 Tail; +}; + +template +struct Types9 { + typedef T1 Head; + typedef Types8 Tail; +}; + +template +struct Types10 { + typedef T1 Head; + typedef Types9 Tail; +}; + +template +struct Types11 { + typedef T1 Head; + typedef Types10 Tail; +}; + +template +struct Types12 { + typedef T1 Head; + typedef Types11 Tail; +}; + +template +struct Types13 { + typedef T1 Head; + typedef Types12 Tail; +}; + +template +struct Types14 { + typedef T1 Head; + typedef Types13 Tail; +}; + +template +struct Types15 { + typedef T1 Head; + typedef Types14 Tail; +}; + +template +struct Types16 { + typedef T1 Head; + typedef Types15 Tail; +}; + +template +struct Types17 { + typedef T1 Head; + typedef Types16 Tail; +}; + +template +struct Types18 { + typedef T1 Head; + typedef Types17 Tail; +}; + +template +struct Types19 { + typedef T1 Head; + typedef Types18 Tail; +}; + +template +struct Types20 { + typedef T1 Head; + typedef Types19 Tail; +}; + +template +struct Types21 { + typedef T1 Head; + typedef Types20 Tail; +}; + +template +struct Types22 { + typedef T1 Head; + typedef Types21 Tail; +}; + +template +struct Types23 { + typedef T1 Head; + typedef Types22 Tail; +}; + +template +struct Types24 { + typedef T1 Head; + typedef Types23 Tail; +}; + +template +struct Types25 { + typedef T1 Head; + typedef Types24 Tail; +}; + +template +struct Types26 { + typedef T1 Head; + typedef Types25 Tail; +}; + +template +struct Types27 { + typedef T1 Head; + typedef Types26 Tail; +}; + +template +struct Types28 { + typedef T1 Head; + typedef Types27 Tail; +}; + +template +struct Types29 { + typedef T1 Head; + typedef Types28 Tail; +}; + +template +struct Types30 { + typedef T1 Head; + typedef Types29 Tail; +}; + +template +struct Types31 { + typedef T1 Head; + typedef Types30 Tail; +}; + +template +struct Types32 { + typedef T1 Head; + typedef Types31 Tail; +}; + +template +struct Types33 { + typedef T1 Head; + typedef Types32 Tail; +}; + +template +struct Types34 { + typedef T1 Head; + typedef Types33 Tail; +}; + +template +struct Types35 { + typedef T1 Head; + typedef Types34 Tail; +}; + +template +struct Types36 { + typedef T1 Head; + typedef Types35 Tail; +}; + +template +struct Types37 { + typedef T1 Head; + typedef Types36 Tail; +}; + +template +struct Types38 { + typedef T1 Head; + typedef Types37 Tail; +}; + +template +struct Types39 { + typedef T1 Head; + typedef Types38 Tail; +}; + +template +struct Types40 { + typedef T1 Head; + typedef Types39 Tail; +}; + +template +struct Types41 { + typedef T1 Head; + typedef Types40 Tail; +}; + +template +struct Types42 { + typedef T1 Head; + typedef Types41 Tail; +}; + +template +struct Types43 { + typedef T1 Head; + typedef Types42 Tail; +}; + +template +struct Types44 { + typedef T1 Head; + typedef Types43 Tail; +}; + +template +struct Types45 { + typedef T1 Head; + typedef Types44 Tail; +}; + +template +struct Types46 { + typedef T1 Head; + typedef Types45 Tail; +}; + +template +struct Types47 { + typedef T1 Head; + typedef Types46 Tail; +}; + +template +struct Types48 { + typedef T1 Head; + typedef Types47 Tail; +}; + +template +struct Types49 { + typedef T1 Head; + typedef Types48 Tail; +}; + +template +struct Types50 { + typedef T1 Head; + typedef Types49 Tail; +}; + + +} // namespace internal + +// We don't want to require the users to write TypesN<...> directly, +// as that would require them to count the length. Types<...> is much +// easier to write, but generates horrible messages when there is a +// compiler error, as gcc insists on printing out each template +// argument, even if it has the default value (this means Types +// will appear as Types in the compiler +// errors). +// +// Our solution is to combine the best part of the two approaches: a +// user would write Types, and Google Test will translate +// that to TypesN internally to make error messages +// readable. The translation is done by the 'type' member of the +// Types template. +template +struct Types { + typedef internal::Types50 type; +}; + +template <> +struct Types { + typedef internal::Types0 type; +}; +template +struct Types { + typedef internal::Types1 type; +}; +template +struct Types { + typedef internal::Types2 type; +}; +template +struct Types { + typedef internal::Types3 type; +}; +template +struct Types { + typedef internal::Types4 type; +}; +template +struct Types { + typedef internal::Types5 type; +}; +template +struct Types { + typedef internal::Types6 type; +}; +template +struct Types { + typedef internal::Types7 type; +}; +template +struct Types { + typedef internal::Types8 type; +}; +template +struct Types { + typedef internal::Types9 type; +}; +template +struct Types { + typedef internal::Types10 type; +}; +template +struct Types { + typedef internal::Types11 type; +}; +template +struct Types { + typedef internal::Types12 type; +}; +template +struct Types { + typedef internal::Types13 type; +}; +template +struct Types { + typedef internal::Types14 type; +}; +template +struct Types { + typedef internal::Types15 type; +}; +template +struct Types { + typedef internal::Types16 type; +}; +template +struct Types { + typedef internal::Types17 type; +}; +template +struct Types { + typedef internal::Types18 type; +}; +template +struct Types { + typedef internal::Types19 type; +}; +template +struct Types { + typedef internal::Types20 type; +}; +template +struct Types { + typedef internal::Types21 type; +}; +template +struct Types { + typedef internal::Types22 type; +}; +template +struct Types { + typedef internal::Types23 type; +}; +template +struct Types { + typedef internal::Types24 type; +}; +template +struct Types { + typedef internal::Types25 type; +}; +template +struct Types { + typedef internal::Types26 type; +}; +template +struct Types { + typedef internal::Types27 type; +}; +template +struct Types { + typedef internal::Types28 type; +}; +template +struct Types { + typedef internal::Types29 type; +}; +template +struct Types { + typedef internal::Types30 type; +}; +template +struct Types { + typedef internal::Types31 type; +}; +template +struct Types { + typedef internal::Types32 type; +}; +template +struct Types { + typedef internal::Types33 type; +}; +template +struct Types { + typedef internal::Types34 type; +}; +template +struct Types { + typedef internal::Types35 type; +}; +template +struct Types { + typedef internal::Types36 type; +}; +template +struct Types { + typedef internal::Types37 type; +}; +template +struct Types { + typedef internal::Types38 type; +}; +template +struct Types { + typedef internal::Types39 type; +}; +template +struct Types { + typedef internal::Types40 type; +}; +template +struct Types { + typedef internal::Types41 type; +}; +template +struct Types { + typedef internal::Types42 type; +}; +template +struct Types { + typedef internal::Types43 type; +}; +template +struct Types { + typedef internal::Types44 type; +}; +template +struct Types { + typedef internal::Types45 type; +}; +template +struct Types { + typedef internal::Types46 type; +}; +template +struct Types { + typedef internal::Types47 type; +}; +template +struct Types { + typedef internal::Types48 type; +}; +template +struct Types { + typedef internal::Types49 type; +}; + +namespace internal { + +# define GTEST_TEMPLATE_ template class + +// The template "selector" struct TemplateSel is used to +// represent Tmpl, which must be a class template with one type +// parameter, as a type. TemplateSel::Bind::type is defined +// as the type Tmpl. This allows us to actually instantiate the +// template "selected" by TemplateSel. +// +// This trick is necessary for simulating typedef for class templates, +// which C++ doesn't support directly. +template +struct TemplateSel { + template + struct Bind { + typedef Tmpl type; + }; +}; + +# define GTEST_BIND_(TmplSel, T) \ + TmplSel::template Bind::type + +// A unique struct template used as the default value for the +// arguments of class template Templates. This allows us to simulate +// variadic templates (e.g. Templates, Templates, +// and etc), which C++ doesn't support directly. +template +struct NoneT {}; + +// The following family of struct and struct templates are used to +// represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except +// for Templates0, every struct in the family has two member types: +// Head for the selector of the first template in the list, and Tail +// for the rest of the list. + +// The empty template list. +struct Templates0 {}; + +// Template lists of length 1, 2, 3, and so on. + +template +struct Templates1 { + typedef TemplateSel Head; + typedef Templates0 Tail; +}; +template +struct Templates2 { + typedef TemplateSel Head; + typedef Templates1 Tail; +}; + +template +struct Templates3 { + typedef TemplateSel Head; + typedef Templates2 Tail; +}; + +template +struct Templates4 { + typedef TemplateSel Head; + typedef Templates3 Tail; +}; + +template +struct Templates5 { + typedef TemplateSel Head; + typedef Templates4 Tail; +}; + +template +struct Templates6 { + typedef TemplateSel Head; + typedef Templates5 Tail; +}; + +template +struct Templates7 { + typedef TemplateSel Head; + typedef Templates6 Tail; +}; + +template +struct Templates8 { + typedef TemplateSel Head; + typedef Templates7 Tail; +}; + +template +struct Templates9 { + typedef TemplateSel Head; + typedef Templates8 Tail; +}; + +template +struct Templates10 { + typedef TemplateSel Head; + typedef Templates9 Tail; +}; + +template +struct Templates11 { + typedef TemplateSel Head; + typedef Templates10 Tail; +}; + +template +struct Templates12 { + typedef TemplateSel Head; + typedef Templates11 Tail; +}; + +template +struct Templates13 { + typedef TemplateSel Head; + typedef Templates12 Tail; +}; + +template +struct Templates14 { + typedef TemplateSel Head; + typedef Templates13 Tail; +}; + +template +struct Templates15 { + typedef TemplateSel Head; + typedef Templates14 Tail; +}; + +template +struct Templates16 { + typedef TemplateSel Head; + typedef Templates15 Tail; +}; + +template +struct Templates17 { + typedef TemplateSel Head; + typedef Templates16 Tail; +}; + +template +struct Templates18 { + typedef TemplateSel Head; + typedef Templates17 Tail; +}; + +template +struct Templates19 { + typedef TemplateSel Head; + typedef Templates18 Tail; +}; + +template +struct Templates20 { + typedef TemplateSel Head; + typedef Templates19 Tail; +}; + +template +struct Templates21 { + typedef TemplateSel Head; + typedef Templates20 Tail; +}; + +template +struct Templates22 { + typedef TemplateSel Head; + typedef Templates21 Tail; +}; + +template +struct Templates23 { + typedef TemplateSel Head; + typedef Templates22 Tail; +}; + +template +struct Templates24 { + typedef TemplateSel Head; + typedef Templates23 Tail; +}; + +template +struct Templates25 { + typedef TemplateSel Head; + typedef Templates24 Tail; +}; + +template +struct Templates26 { + typedef TemplateSel Head; + typedef Templates25 Tail; +}; + +template +struct Templates27 { + typedef TemplateSel Head; + typedef Templates26 Tail; +}; + +template +struct Templates28 { + typedef TemplateSel Head; + typedef Templates27 Tail; +}; + +template +struct Templates29 { + typedef TemplateSel Head; + typedef Templates28 Tail; +}; + +template +struct Templates30 { + typedef TemplateSel Head; + typedef Templates29 Tail; +}; + +template +struct Templates31 { + typedef TemplateSel Head; + typedef Templates30 Tail; +}; + +template +struct Templates32 { + typedef TemplateSel Head; + typedef Templates31 Tail; +}; + +template +struct Templates33 { + typedef TemplateSel Head; + typedef Templates32 Tail; +}; + +template +struct Templates34 { + typedef TemplateSel Head; + typedef Templates33 Tail; +}; + +template +struct Templates35 { + typedef TemplateSel Head; + typedef Templates34 Tail; +}; + +template +struct Templates36 { + typedef TemplateSel Head; + typedef Templates35 Tail; +}; + +template +struct Templates37 { + typedef TemplateSel Head; + typedef Templates36 Tail; +}; + +template +struct Templates38 { + typedef TemplateSel Head; + typedef Templates37 Tail; +}; + +template +struct Templates39 { + typedef TemplateSel Head; + typedef Templates38 Tail; +}; + +template +struct Templates40 { + typedef TemplateSel Head; + typedef Templates39 Tail; +}; + +template +struct Templates41 { + typedef TemplateSel Head; + typedef Templates40 Tail; +}; + +template +struct Templates42 { + typedef TemplateSel Head; + typedef Templates41 Tail; +}; + +template +struct Templates43 { + typedef TemplateSel Head; + typedef Templates42 Tail; +}; + +template +struct Templates44 { + typedef TemplateSel Head; + typedef Templates43 Tail; +}; + +template +struct Templates45 { + typedef TemplateSel Head; + typedef Templates44 Tail; +}; + +template +struct Templates46 { + typedef TemplateSel Head; + typedef Templates45 Tail; +}; + +template +struct Templates47 { + typedef TemplateSel Head; + typedef Templates46 Tail; +}; + +template +struct Templates48 { + typedef TemplateSel Head; + typedef Templates47 Tail; +}; + +template +struct Templates49 { + typedef TemplateSel Head; + typedef Templates48 Tail; +}; + +template +struct Templates50 { + typedef TemplateSel Head; + typedef Templates49 Tail; +}; + + +// We don't want to require the users to write TemplatesN<...> directly, +// as that would require them to count the length. Templates<...> is much +// easier to write, but generates horrible messages when there is a +// compiler error, as gcc insists on printing out each template +// argument, even if it has the default value (this means Templates +// will appear as Templates in the compiler +// errors). +// +// Our solution is to combine the best part of the two approaches: a +// user would write Templates, and Google Test will translate +// that to TemplatesN internally to make error messages +// readable. The translation is done by the 'type' member of the +// Templates template. +template +struct Templates { + typedef Templates50 type; +}; + +template <> +struct Templates { + typedef Templates0 type; +}; +template +struct Templates { + typedef Templates1 type; +}; +template +struct Templates { + typedef Templates2 type; +}; +template +struct Templates { + typedef Templates3 type; +}; +template +struct Templates { + typedef Templates4 type; +}; +template +struct Templates { + typedef Templates5 type; +}; +template +struct Templates { + typedef Templates6 type; +}; +template +struct Templates { + typedef Templates7 type; +}; +template +struct Templates { + typedef Templates8 type; +}; +template +struct Templates { + typedef Templates9 type; +}; +template +struct Templates { + typedef Templates10 type; +}; +template +struct Templates { + typedef Templates11 type; +}; +template +struct Templates { + typedef Templates12 type; +}; +template +struct Templates { + typedef Templates13 type; +}; +template +struct Templates { + typedef Templates14 type; +}; +template +struct Templates { + typedef Templates15 type; +}; +template +struct Templates { + typedef Templates16 type; +}; +template +struct Templates { + typedef Templates17 type; +}; +template +struct Templates { + typedef Templates18 type; +}; +template +struct Templates { + typedef Templates19 type; +}; +template +struct Templates { + typedef Templates20 type; +}; +template +struct Templates { + typedef Templates21 type; +}; +template +struct Templates { + typedef Templates22 type; +}; +template +struct Templates { + typedef Templates23 type; +}; +template +struct Templates { + typedef Templates24 type; +}; +template +struct Templates { + typedef Templates25 type; +}; +template +struct Templates { + typedef Templates26 type; +}; +template +struct Templates { + typedef Templates27 type; +}; +template +struct Templates { + typedef Templates28 type; +}; +template +struct Templates { + typedef Templates29 type; +}; +template +struct Templates { + typedef Templates30 type; +}; +template +struct Templates { + typedef Templates31 type; +}; +template +struct Templates { + typedef Templates32 type; +}; +template +struct Templates { + typedef Templates33 type; +}; +template +struct Templates { + typedef Templates34 type; +}; +template +struct Templates { + typedef Templates35 type; +}; +template +struct Templates { + typedef Templates36 type; +}; +template +struct Templates { + typedef Templates37 type; +}; +template +struct Templates { + typedef Templates38 type; +}; +template +struct Templates { + typedef Templates39 type; +}; +template +struct Templates { + typedef Templates40 type; +}; +template +struct Templates { + typedef Templates41 type; +}; +template +struct Templates { + typedef Templates42 type; +}; +template +struct Templates { + typedef Templates43 type; +}; +template +struct Templates { + typedef Templates44 type; +}; +template +struct Templates { + typedef Templates45 type; +}; +template +struct Templates { + typedef Templates46 type; +}; +template +struct Templates { + typedef Templates47 type; +}; +template +struct Templates { + typedef Templates48 type; +}; +template +struct Templates { + typedef Templates49 type; +}; + +// The TypeList template makes it possible to use either a single type +// or a Types<...> list in TYPED_TEST_CASE() and +// INSTANTIATE_TYPED_TEST_CASE_P(). + +template +struct TypeList { + typedef Types1 type; +}; + +template +struct TypeList > { + typedef typename Types::type type; +}; + +#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ + +// Due to C++ preprocessor weirdness, we need double indirection to +// concatenate two tokens when one of them is __LINE__. Writing +// +// foo ## __LINE__ +// +// will result in the token foo__LINE__, instead of foo followed by +// the current line number. For more details, see +// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6 +#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar) +#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar + +class ProtocolMessage; +namespace proto2 { class Message; } + +namespace testing { + +// Forward declarations. + +class AssertionResult; // Result of an assertion. +class Message; // Represents a failure message. +class Test; // Represents a test. +class TestInfo; // Information about a test. +class TestPartResult; // Result of a test part. +class UnitTest; // A collection of test cases. + +template +::std::string PrintToString(const T& value); + +namespace internal { + +struct TraceInfo; // Information about a trace point. +class ScopedTrace; // Implements scoped trace. +class TestInfoImpl; // Opaque implementation of TestInfo +class UnitTestImpl; // Opaque implementation of UnitTest + +// How many times InitGoogleTest() has been called. +GTEST_API_ extern int g_init_gtest_count; + +// The text used in failure messages to indicate the start of the +// stack trace. +GTEST_API_ extern const char kStackTraceMarker[]; + +// Two overloaded helpers for checking at compile time whether an +// expression is a null pointer literal (i.e. NULL or any 0-valued +// compile-time integral constant). Their return values have +// different sizes, so we can use sizeof() to test which version is +// picked by the compiler. These helpers have no implementations, as +// we only need their signatures. +// +// Given IsNullLiteralHelper(x), the compiler will pick the first +// version if x can be implicitly converted to Secret*, and pick the +// second version otherwise. Since Secret is a secret and incomplete +// type, the only expression a user can write that has type Secret* is +// a null pointer literal. Therefore, we know that x is a null +// pointer literal if and only if the first version is picked by the +// compiler. +char IsNullLiteralHelper(Secret* p); +char (&IsNullLiteralHelper(...))[2]; // NOLINT + +// A compile-time bool constant that is true if and only if x is a +// null pointer literal (i.e. NULL or any 0-valued compile-time +// integral constant). +#ifdef GTEST_ELLIPSIS_NEEDS_POD_ +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). +# define GTEST_IS_NULL_LITERAL_(x) false +#else +# define GTEST_IS_NULL_LITERAL_(x) \ + (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1) +#endif // GTEST_ELLIPSIS_NEEDS_POD_ + +// Appends the user-supplied message to the Google-Test-generated message. +GTEST_API_ std::string AppendUserMessage( + const std::string& gtest_msg, const Message& user_msg); + +#if GTEST_HAS_EXCEPTIONS + +// This exception is thrown by (and only by) a failed Google Test +// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions +// are enabled). We derive it from std::runtime_error, which is for +// errors presumably detectable only at run time. Since +// std::runtime_error inherits from std::exception, many testing +// frameworks know how to extract and print the message inside it. +class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error { + public: + explicit GoogleTestFailureException(const TestPartResult& failure); +}; + +#endif // GTEST_HAS_EXCEPTIONS + +// A helper class for creating scoped traces in user programs. +class GTEST_API_ ScopedTrace { + public: + // The c'tor pushes the given source file location and message onto + // a trace stack maintained by Google Test. + ScopedTrace(const char* file, int line, const Message& message); + + // The d'tor pops the info pushed by the c'tor. + // + // Note that the d'tor is not virtual in order to be efficient. + // Don't inherit from ScopedTrace! + ~ScopedTrace(); + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace); +} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its + // c'tor and d'tor. Therefore it doesn't + // need to be used otherwise. + +// Constructs and returns the message for an equality assertion +// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. +// +// The first four parameters are the expressions used in the assertion +// and their values, as strings. For example, for ASSERT_EQ(foo, bar) +// where foo is 5 and bar is 6, we have: +// +// expected_expression: "foo" +// actual_expression: "bar" +// expected_value: "5" +// actual_value: "6" +// +// The ignoring_case parameter is true iff the assertion is a +// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will +// be inserted into the message. +GTEST_API_ AssertionResult EqFailure(const char* expected_expression, + const char* actual_expression, + const std::string& expected_value, + const std::string& actual_value, + bool ignoring_case); + +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +GTEST_API_ std::string GetBoolAssertionFailureMessage( + const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value); + +// This template class represents an IEEE floating-point number +// (either single-precision or double-precision, depending on the +// template parameters). +// +// The purpose of this class is to do more sophisticated number +// comparison. (Due to round-off error, etc, it's very unlikely that +// two floating-points will be equal exactly. Hence a naive +// comparison by the == operation often doesn't work.) +// +// Format of IEEE floating-point: +// +// The most-significant bit being the leftmost, an IEEE +// floating-point looks like +// +// sign_bit exponent_bits fraction_bits +// +// Here, sign_bit is a single bit that designates the sign of the +// number. +// +// For float, there are 8 exponent bits and 23 fraction bits. +// +// For double, there are 11 exponent bits and 52 fraction bits. +// +// More details can be found at +// http://en.wikipedia.org/wiki/IEEE_floating-point_standard. +// +// Template parameter: +// +// RawType: the raw floating-point type (either float or double) +template +class FloatingPoint { + public: + // Defines the unsigned integer type that has the same size as the + // floating point number. + typedef typename TypeWithSize::UInt Bits; + + // Constants. + + // # of bits in a number. + static const size_t kBitCount = 8*sizeof(RawType); + + // # of fraction bits in a number. + static const size_t kFractionBitCount = + std::numeric_limits::digits - 1; + + // # of exponent bits in a number. + static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount; + + // The mask for the sign bit. + static const Bits kSignBitMask = static_cast(1) << (kBitCount - 1); + + // The mask for the fraction bits. + static const Bits kFractionBitMask = + ~static_cast(0) >> (kExponentBitCount + 1); + + // The mask for the exponent bits. + static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask); + + // How many ULP's (Units in the Last Place) we want to tolerate when + // comparing two numbers. The larger the value, the more error we + // allow. A 0 value means that two numbers must be exactly the same + // to be considered equal. + // + // The maximum error of a single floating-point operation is 0.5 + // units in the last place. On Intel CPU's, all floating-point + // calculations are done with 80-bit precision, while double has 64 + // bits. Therefore, 4 should be enough for ordinary use. + // + // See the following article for more details on ULP: + // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ + static const size_t kMaxUlps = 4; + + // Constructs a FloatingPoint from a raw floating-point number. + // + // On an Intel CPU, passing a non-normalized NAN (Not a Number) + // around may change its bits, although the new value is guaranteed + // to be also a NAN. Therefore, don't expect this constructor to + // preserve the bits in x when x is a NAN. + explicit FloatingPoint(const RawType& x) { u_.value_ = x; } + + // Static methods + + // Reinterprets a bit pattern as a floating-point number. + // + // This function is needed to test the AlmostEquals() method. + static RawType ReinterpretBits(const Bits bits) { + FloatingPoint fp(0); + fp.u_.bits_ = bits; + return fp.u_.value_; + } + + // Returns the floating-point number that represent positive infinity. + static RawType Infinity() { + return ReinterpretBits(kExponentBitMask); + } + + // Returns the maximum representable finite floating-point number. + static RawType Max(); + + // Non-static methods + + // Returns the bits that represents this number. + const Bits &bits() const { return u_.bits_; } + + // Returns the exponent bits of this number. + Bits exponent_bits() const { return kExponentBitMask & u_.bits_; } + + // Returns the fraction bits of this number. + Bits fraction_bits() const { return kFractionBitMask & u_.bits_; } + + // Returns the sign bit of this number. + Bits sign_bit() const { return kSignBitMask & u_.bits_; } + + // Returns true iff this is NAN (not a number). + bool is_nan() const { + // It's a NAN if the exponent bits are all ones and the fraction + // bits are not entirely zeros. + return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0); + } + + // Returns true iff this number is at most kMaxUlps ULP's away from + // rhs. In particular, this function: + // + // - returns false if either number is (or both are) NAN. + // - treats really large numbers as almost equal to infinity. + // - thinks +0.0 and -0.0 are 0 DLP's apart. + bool AlmostEquals(const FloatingPoint& rhs) const { + // The IEEE standard says that any comparison operation involving + // a NAN must return false. + if (is_nan() || rhs.is_nan()) return false; + + return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) + <= kMaxUlps; + } + + private: + // The data type used to store the actual floating-point number. + union FloatingPointUnion { + RawType value_; // The raw floating-point number. + Bits bits_; // The bits that represent the number. + }; + + // Converts an integer from the sign-and-magnitude representation to + // the biased representation. More precisely, let N be 2 to the + // power of (kBitCount - 1), an integer x is represented by the + // unsigned number x + N. + // + // For instance, + // + // -N + 1 (the most negative number representable using + // sign-and-magnitude) is represented by 1; + // 0 is represented by N; and + // N - 1 (the biggest number representable using + // sign-and-magnitude) is represented by 2N - 1. + // + // Read http://en.wikipedia.org/wiki/Signed_number_representations + // for more details on signed number representations. + static Bits SignAndMagnitudeToBiased(const Bits &sam) { + if (kSignBitMask & sam) { + // sam represents a negative number. + return ~sam + 1; + } else { + // sam represents a positive number. + return kSignBitMask | sam; + } + } + + // Given two numbers in the sign-and-magnitude representation, + // returns the distance between them as an unsigned number. + static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1, + const Bits &sam2) { + const Bits biased1 = SignAndMagnitudeToBiased(sam1); + const Bits biased2 = SignAndMagnitudeToBiased(sam2); + return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1); + } + + FloatingPointUnion u_; +}; + +// We cannot use std::numeric_limits::max() as it clashes with the max() +// macro defined by . +template <> +inline float FloatingPoint::Max() { return FLT_MAX; } +template <> +inline double FloatingPoint::Max() { return DBL_MAX; } + +// Typedefs the instances of the FloatingPoint template class that we +// care to use. +typedef FloatingPoint Float; +typedef FloatingPoint Double; + +// In order to catch the mistake of putting tests that use different +// test fixture classes in the same test case, we need to assign +// unique IDs to fixture classes and compare them. The TypeId type is +// used to hold such IDs. The user should treat TypeId as an opaque +// type: the only operation allowed on TypeId values is to compare +// them for equality using the == operator. +typedef const void* TypeId; + +template +class TypeIdHelper { + public: + // dummy_ must not have a const type. Otherwise an overly eager + // compiler (e.g. MSVC 7.1 & 8.0) may try to merge + // TypeIdHelper::dummy_ for different Ts as an "optimization". + static bool dummy_; +}; + +template +bool TypeIdHelper::dummy_ = false; + +// GetTypeId() returns the ID of type T. Different values will be +// returned for different types. Calling the function twice with the +// same type argument is guaranteed to return the same ID. +template +TypeId GetTypeId() { + // The compiler is required to allocate a different + // TypeIdHelper::dummy_ variable for each T used to instantiate + // the template. Therefore, the address of dummy_ is guaranteed to + // be unique. + return &(TypeIdHelper::dummy_); +} + +// Returns the type ID of ::testing::Test. Always call this instead +// of GetTypeId< ::testing::Test>() to get the type ID of +// ::testing::Test, as the latter may give the wrong result due to a +// suspected linker bug when compiling Google Test as a Mac OS X +// framework. +GTEST_API_ TypeId GetTestTypeId(); + +// Defines the abstract factory interface that creates instances +// of a Test object. +class TestFactoryBase { + public: + virtual ~TestFactoryBase() {} + + // Creates a test instance to run. The instance is both created and destroyed + // within TestInfoImpl::Run() + virtual Test* CreateTest() = 0; + + protected: + TestFactoryBase() {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase); +}; + +// This class provides implementation of TeastFactoryBase interface. +// It is used in TEST and TEST_F macros. +template +class TestFactoryImpl : public TestFactoryBase { + public: + virtual Test* CreateTest() { return new TestClass; } +}; + +#if GTEST_OS_WINDOWS + +// Predicate-formatters for implementing the HRESULT checking macros +// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED} +// We pass a long instead of HRESULT to avoid causing an +// include dependency for the HRESULT type. +GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr, + long hr); // NOLINT +GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr, + long hr); // NOLINT + +#endif // GTEST_OS_WINDOWS + +// Types of SetUpTestCase() and TearDownTestCase() functions. +typedef void (*SetUpTestCaseFunc)(); +typedef void (*TearDownTestCaseFunc)(); + +// Creates a new TestInfo object and registers it with Google Test; +// returns the created object. +// +// Arguments: +// +// test_case_name: name of the test case +// name: name of the test +// type_param the name of the test's type parameter, or NULL if +// this is not a typed or a type-parameterized test. +// value_param text representation of the test's value parameter, +// or NULL if this is not a type-parameterized test. +// fixture_class_id: ID of the test fixture class +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +// factory: pointer to the factory that creates a test object. +// The newly created TestInfo instance will assume +// ownership of the factory object. +GTEST_API_ TestInfo* MakeAndRegisterTestInfo( + const char* test_case_name, + const char* name, + const char* type_param, + const char* value_param, + TypeId fixture_class_id, + SetUpTestCaseFunc set_up_tc, + TearDownTestCaseFunc tear_down_tc, + TestFactoryBase* factory); + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr); + +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// State of the definition of a type-parameterized test case. +class GTEST_API_ TypedTestCasePState { + public: + TypedTestCasePState() : registered_(false) {} + + // Adds the given test name to defined_test_names_ and return true + // if the test case hasn't been registered; otherwise aborts the + // program. + bool AddTestName(const char* file, int line, const char* case_name, + const char* test_name) { + if (registered_) { + fprintf(stderr, "%s Test %s must be defined before " + "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n", + FormatFileLocation(file, line).c_str(), test_name, case_name); + fflush(stderr); + posix::Abort(); + } + defined_test_names_.insert(test_name); + return true; + } + + // Verifies that registered_tests match the test names in + // defined_test_names_; returns registered_tests if successful, or + // aborts the program otherwise. + const char* VerifyRegisteredTestNames( + const char* file, int line, const char* registered_tests); + + private: + bool registered_; + ::std::set defined_test_names_; +}; + +// Skips to the first non-space char after the first comma in 'str'; +// returns NULL if no comma is found in 'str'. +inline const char* SkipComma(const char* str) { + const char* comma = strchr(str, ','); + if (comma == NULL) { + return NULL; + } + while (IsSpace(*(++comma))) {} + return comma; +} + +// Returns the prefix of 'str' before the first comma in it; returns +// the entire string if it contains no comma. +inline std::string GetPrefixUntilComma(const char* str) { + const char* comma = strchr(str, ','); + return comma == NULL ? str : std::string(str, comma); +} + +// TypeParameterizedTest::Register() +// registers a list of type-parameterized tests with Google Test. The +// return value is insignificant - we just need to return something +// such that we can call this function in a namespace scope. +// +// Implementation note: The GTEST_TEMPLATE_ macro declares a template +// template parameter. It's defined in gtest-type-util.h. +template +class TypeParameterizedTest { + public: + // 'index' is the index of the test in the type list 'Types' + // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase, + // Types). Valid values for 'index' are [0, N - 1] where N is the + // length of Types. + static bool Register(const char* prefix, const char* case_name, + const char* test_names, int index) { + typedef typename Types::Head Type; + typedef Fixture FixtureClass; + typedef typename GTEST_BIND_(TestSel, Type) TestClass; + + // First, registers the first type-parameterized test in the type + // list. + MakeAndRegisterTestInfo( + (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + "/" + + StreamableToString(index)).c_str(), + GetPrefixUntilComma(test_names).c_str(), + GetTypeName().c_str(), + NULL, // No value parameter. + GetTypeId(), + TestClass::SetUpTestCase, + TestClass::TearDownTestCase, + new TestFactoryImpl); + + // Next, recurses (at compile time) with the tail of the type list. + return TypeParameterizedTest + ::Register(prefix, case_name, test_names, index + 1); + } +}; + +// The base case for the compile time recursion. +template +class TypeParameterizedTest { + public: + static bool Register(const char* /*prefix*/, const char* /*case_name*/, + const char* /*test_names*/, int /*index*/) { + return true; + } +}; + +// TypeParameterizedTestCase::Register() +// registers *all combinations* of 'Tests' and 'Types' with Google +// Test. The return value is insignificant - we just need to return +// something such that we can call this function in a namespace scope. +template +class TypeParameterizedTestCase { + public: + static bool Register(const char* prefix, const char* case_name, + const char* test_names) { + typedef typename Tests::Head Head; + + // First, register the first test in 'Test' for each type in 'Types'. + TypeParameterizedTest::Register( + prefix, case_name, test_names, 0); + + // Next, recurses (at compile time) with the tail of the test list. + return TypeParameterizedTestCase + ::Register(prefix, case_name, SkipComma(test_names)); + } +}; + +// The base case for the compile time recursion. +template +class TypeParameterizedTestCase { + public: + static bool Register(const char* /*prefix*/, const char* /*case_name*/, + const char* /*test_names*/) { + return true; + } +}; + +#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// Returns the current OS stack trace as an std::string. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in +// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. +GTEST_API_ std::string GetCurrentOsStackTraceExceptTop( + UnitTest* unit_test, int skip_count); + +// Helpers for suppressing warnings on unreachable code or constant +// condition. + +// Always returns true. +GTEST_API_ bool AlwaysTrue(); + +// Always returns false. +inline bool AlwaysFalse() { return !AlwaysTrue(); } + +// Helper for suppressing false warning from Clang on a const char* +// variable declared in a conditional expression always being NULL in +// the else branch. +struct GTEST_API_ ConstCharPtr { + ConstCharPtr(const char* str) : value(str) {} + operator bool() const { return true; } + const char* value; +}; + +// A simple Linear Congruential Generator for generating random +// numbers with a uniform distribution. Unlike rand() and srand(), it +// doesn't use global state (and therefore can't interfere with user +// code). Unlike rand_r(), it's portable. An LCG isn't very random, +// but it's good enough for our purposes. +class GTEST_API_ Random { + public: + static const UInt32 kMaxRange = 1u << 31; + + explicit Random(UInt32 seed) : state_(seed) {} + + void Reseed(UInt32 seed) { state_ = seed; } + + // Generates a random number from [0, range). Crashes if 'range' is + // 0 or greater than kMaxRange. + UInt32 Generate(UInt32 range); + + private: + UInt32 state_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(Random); +}; + +// Defining a variable of type CompileAssertTypesEqual will cause a +// compiler error iff T1 and T2 are different types. +template +struct CompileAssertTypesEqual; + +template +struct CompileAssertTypesEqual { +}; + +// Removes the reference from a type if it is a reference type, +// otherwise leaves it unchanged. This is the same as +// tr1::remove_reference, which is not widely available yet. +template +struct RemoveReference { typedef T type; }; // NOLINT +template +struct RemoveReference { typedef T type; }; // NOLINT + +// A handy wrapper around RemoveReference that works when the argument +// T depends on template parameters. +#define GTEST_REMOVE_REFERENCE_(T) \ + typename ::testing::internal::RemoveReference::type + +// Removes const from a type if it is a const type, otherwise leaves +// it unchanged. This is the same as tr1::remove_const, which is not +// widely available yet. +template +struct RemoveConst { typedef T type; }; // NOLINT +template +struct RemoveConst { typedef T type; }; // NOLINT + +// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above +// definition to fail to remove the const in 'const int[3]' and 'const +// char[3][4]'. The following specialization works around the bug. +template +struct RemoveConst { + typedef typename RemoveConst::type type[N]; +}; + +#if defined(_MSC_VER) && _MSC_VER < 1400 +// This is the only specialization that allows VC++ 7.1 to remove const in +// 'const int[3] and 'const int[3][4]'. However, it causes trouble with GCC +// and thus needs to be conditionally compiled. +template +struct RemoveConst { + typedef typename RemoveConst::type type[N]; +}; +#endif + +// A handy wrapper around RemoveConst that works when the argument +// T depends on template parameters. +#define GTEST_REMOVE_CONST_(T) \ + typename ::testing::internal::RemoveConst::type + +// Turns const U&, U&, const U, and U all into U. +#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ + GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T)) + +// Adds reference to a type if it is not a reference type, +// otherwise leaves it unchanged. This is the same as +// tr1::add_reference, which is not widely available yet. +template +struct AddReference { typedef T& type; }; // NOLINT +template +struct AddReference { typedef T& type; }; // NOLINT + +// A handy wrapper around AddReference that works when the argument T +// depends on template parameters. +#define GTEST_ADD_REFERENCE_(T) \ + typename ::testing::internal::AddReference::type + +// Adds a reference to const on top of T as necessary. For example, +// it transforms +// +// char ==> const char& +// const char ==> const char& +// char& ==> const char& +// const char& ==> const char& +// +// The argument T must depend on some template parameters. +#define GTEST_REFERENCE_TO_CONST_(T) \ + GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T)) + +// ImplicitlyConvertible::value is a compile-time bool +// constant that's true iff type From can be implicitly converted to +// type To. +template +class ImplicitlyConvertible { + private: + // We need the following helper functions only for their types. + // They have no implementations. + + // MakeFrom() is an expression whose type is From. We cannot simply + // use From(), as the type From may not have a public default + // constructor. + static From MakeFrom(); + + // These two functions are overloaded. Given an expression + // Helper(x), the compiler will pick the first version if x can be + // implicitly converted to type To; otherwise it will pick the + // second version. + // + // The first version returns a value of size 1, and the second + // version returns a value of size 2. Therefore, by checking the + // size of Helper(x), which can be done at compile time, we can tell + // which version of Helper() is used, and hence whether x can be + // implicitly converted to type To. + static char Helper(To); + static char (&Helper(...))[2]; // NOLINT + + // We have to put the 'public' section after the 'private' section, + // or MSVC refuses to compile the code. + public: + // MSVC warns about implicitly converting from double to int for + // possible loss of data, so we need to temporarily disable the + // warning. +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4244) // Temporarily disables warning 4244. + + static const bool value = + sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; +# pragma warning(pop) // Restores the warning state. +#elif defined(__BORLANDC__) + // C++Builder cannot use member overload resolution during template + // instantiation. The simplest workaround is to use its C++0x type traits + // functions (C++Builder 2009 and above only). + static const bool value = __is_convertible(From, To); +#else + static const bool value = + sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; +#endif // _MSV_VER +}; +template +const bool ImplicitlyConvertible::value; + +// IsAProtocolMessage::value is a compile-time bool constant that's +// true iff T is type ProtocolMessage, proto2::Message, or a subclass +// of those. +template +struct IsAProtocolMessage + : public bool_constant< + ImplicitlyConvertible::value || + ImplicitlyConvertible::value> { +}; + +// When the compiler sees expression IsContainerTest(0), if C is an +// STL-style container class, the first overload of IsContainerTest +// will be viable (since both C::iterator* and C::const_iterator* are +// valid types and NULL can be implicitly converted to them). It will +// be picked over the second overload as 'int' is a perfect match for +// the type of argument 0. If C::iterator or C::const_iterator is not +// a valid type, the first overload is not viable, and the second +// overload will be picked. Therefore, we can determine whether C is +// a container class by checking the type of IsContainerTest(0). +// The value of the expression is insignificant. +// +// Note that we look for both C::iterator and C::const_iterator. The +// reason is that C++ injects the name of a class as a member of the +// class itself (e.g. you can refer to class iterator as either +// 'iterator' or 'iterator::iterator'). If we look for C::iterator +// only, for example, we would mistakenly think that a class named +// iterator is an STL container. +// +// Also note that the simpler approach of overloading +// IsContainerTest(typename C::const_iterator*) and +// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++. +typedef int IsContainer; +template +IsContainer IsContainerTest(int /* dummy */, + typename C::iterator* /* it */ = NULL, + typename C::const_iterator* /* const_it */ = NULL) { + return 0; +} + +typedef char IsNotContainer; +template +IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; } + +// EnableIf::type is void when 'Cond' is true, and +// undefined when 'Cond' is false. To use SFINAE to make a function +// overload only apply when a particular expression is true, add +// "typename EnableIf::type* = 0" as the last parameter. +template struct EnableIf; +template<> struct EnableIf { typedef void type; }; // NOLINT + +// Utilities for native arrays. + +// ArrayEq() compares two k-dimensional native arrays using the +// elements' operator==, where k can be any integer >= 0. When k is +// 0, ArrayEq() degenerates into comparing a single pair of values. + +template +bool ArrayEq(const T* lhs, size_t size, const U* rhs); + +// This generic version is used when k is 0. +template +inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; } + +// This overload is used when k >= 1. +template +inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) { + return internal::ArrayEq(lhs, N, rhs); +} + +// This helper reduces code bloat. If we instead put its logic inside +// the previous ArrayEq() function, arrays with different sizes would +// lead to different copies of the template code. +template +bool ArrayEq(const T* lhs, size_t size, const U* rhs) { + for (size_t i = 0; i != size; i++) { + if (!internal::ArrayEq(lhs[i], rhs[i])) + return false; + } + return true; +} + +// Finds the first element in the iterator range [begin, end) that +// equals elem. Element may be a native array type itself. +template +Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) { + for (Iter it = begin; it != end; ++it) { + if (internal::ArrayEq(*it, elem)) + return it; + } + return end; +} + +// CopyArray() copies a k-dimensional native array using the elements' +// operator=, where k can be any integer >= 0. When k is 0, +// CopyArray() degenerates into copying a single value. + +template +void CopyArray(const T* from, size_t size, U* to); + +// This generic version is used when k is 0. +template +inline void CopyArray(const T& from, U* to) { *to = from; } + +// This overload is used when k >= 1. +template +inline void CopyArray(const T(&from)[N], U(*to)[N]) { + internal::CopyArray(from, N, *to); +} + +// This helper reduces code bloat. If we instead put its logic inside +// the previous CopyArray() function, arrays with different sizes +// would lead to different copies of the template code. +template +void CopyArray(const T* from, size_t size, U* to) { + for (size_t i = 0; i != size; i++) { + internal::CopyArray(from[i], to + i); + } +} + +// The relation between an NativeArray object (see below) and the +// native array it represents. +enum RelationToSource { + kReference, // The NativeArray references the native array. + kCopy // The NativeArray makes a copy of the native array and + // owns the copy. +}; + +// Adapts a native array to a read-only STL-style container. Instead +// of the complete STL container concept, this adaptor only implements +// members useful for Google Mock's container matchers. New members +// should be added as needed. To simplify the implementation, we only +// support Element being a raw type (i.e. having no top-level const or +// reference modifier). It's the client's responsibility to satisfy +// this requirement. Element can be an array type itself (hence +// multi-dimensional arrays are supported). +template +class NativeArray { + public: + // STL-style container typedefs. + typedef Element value_type; + typedef Element* iterator; + typedef const Element* const_iterator; + + // Constructs from a native array. + NativeArray(const Element* array, size_t count, RelationToSource relation) { + Init(array, count, relation); + } + + // Copy constructor. + NativeArray(const NativeArray& rhs) { + Init(rhs.array_, rhs.size_, rhs.relation_to_source_); + } + + ~NativeArray() { + // Ensures that the user doesn't instantiate NativeArray with a + // const or reference type. + static_cast(StaticAssertTypeEqHelper()); + if (relation_to_source_ == kCopy) + delete[] array_; + } + + // STL-style container methods. + size_t size() const { return size_; } + const_iterator begin() const { return array_; } + const_iterator end() const { return array_ + size_; } + bool operator==(const NativeArray& rhs) const { + return size() == rhs.size() && + ArrayEq(begin(), size(), rhs.begin()); + } + + private: + // Initializes this object; makes a copy of the input array if + // 'relation' is kCopy. + void Init(const Element* array, size_t a_size, RelationToSource relation) { + if (relation == kReference) { + array_ = array; + } else { + Element* const copy = new Element[a_size]; + CopyArray(array, a_size, copy); + array_ = copy; + } + size_ = a_size; + relation_to_source_ = relation; + } + + const Element* array_; + size_t size_; + RelationToSource relation_to_source_; + + GTEST_DISALLOW_ASSIGN_(NativeArray); +}; + +} // namespace internal +} // namespace testing + +#define GTEST_MESSAGE_AT_(file, line, message, result_type) \ + ::testing::internal::AssertHelper(result_type, file, line, message) \ + = ::testing::Message() + +#define GTEST_MESSAGE_(message, result_type) \ + GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type) + +#define GTEST_FATAL_FAILURE_(message) \ + return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure) + +#define GTEST_NONFATAL_FAILURE_(message) \ + GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure) + +#define GTEST_SUCCESS_(message) \ + GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess) + +// Suppresses MSVC warnings 4072 (unreachable code) for the code following +// statement if it returns or throws (or doesn't return or throw in some +// situations). +#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ + if (::testing::internal::AlwaysTrue()) { statement; } + +#define GTEST_TEST_THROW_(statement, expected_exception, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::ConstCharPtr gtest_msg = "") { \ + bool gtest_caught_expected = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (expected_exception const&) { \ + gtest_caught_expected = true; \ + } \ + catch (...) { \ + gtest_msg.value = \ + "Expected: " #statement " throws an exception of type " \ + #expected_exception ".\n Actual: it throws a different type."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + if (!gtest_caught_expected) { \ + gtest_msg.value = \ + "Expected: " #statement " throws an exception of type " \ + #expected_exception ".\n Actual: it throws nothing."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ + fail(gtest_msg.value) + +#define GTEST_TEST_NO_THROW_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (...) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \ + fail("Expected: " #statement " doesn't throw an exception.\n" \ + " Actual: it throws.") + +#define GTEST_TEST_ANY_THROW_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + bool gtest_caught_any = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (...) { \ + gtest_caught_any = true; \ + } \ + if (!gtest_caught_any) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \ + fail("Expected: " #statement " throws an exception.\n" \ + " Actual: it doesn't.") + + +// Implements Boolean test assertions such as EXPECT_TRUE. expression can be +// either a boolean expression or an AssertionResult. text is a textual +// represenation of expression as it was passed into the EXPECT_TRUE. +#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const ::testing::AssertionResult gtest_ar_ = \ + ::testing::AssertionResult(expression)) \ + ; \ + else \ + fail(::testing::internal::GetBoolAssertionFailureMessage(\ + gtest_ar_, text, #actual, #expected).c_str()) + +#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \ + fail("Expected: " #statement " doesn't generate new fatal " \ + "failures in the current thread.\n" \ + " Actual: it does.") + +// Expands to the name of the class that implements the given test. +#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ + test_case_name##_##test_name##_Test + +// Helper macro for defining tests. +#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\ +class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\ + public:\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ + private:\ + virtual void TestBody();\ + static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\ + GTEST_DISALLOW_COPY_AND_ASSIGN_(\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\ +};\ +\ +::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\ + ::test_info_ =\ + ::testing::internal::MakeAndRegisterTestInfo(\ + #test_case_name, #test_name, NULL, NULL, \ + (parent_id), \ + parent_class::SetUpTestCase, \ + parent_class::TearDownTestCase, \ + new ::testing::internal::TestFactoryImpl<\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\ +void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the public API for death tests. It is +// #included by gtest.h so a user doesn't need to include this +// directly. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ + +// Copyright 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines internal utilities needed for implementing +// death tests. They are subject to change without notice. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ + + +#include + +namespace testing { +namespace internal { + +GTEST_DECLARE_string_(internal_run_death_test); + +// Names of the flags (needed for parsing Google Test flags). +const char kDeathTestStyleFlag[] = "death_test_style"; +const char kDeathTestUseFork[] = "death_test_use_fork"; +const char kInternalRunDeathTestFlag[] = "internal_run_death_test"; + +#if GTEST_HAS_DEATH_TEST + +// DeathTest is a class that hides much of the complexity of the +// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method +// returns a concrete class that depends on the prevailing death test +// style, as defined by the --gtest_death_test_style and/or +// --gtest_internal_run_death_test flags. + +// In describing the results of death tests, these terms are used with +// the corresponding definitions: +// +// exit status: The integer exit information in the format specified +// by wait(2) +// exit code: The integer code passed to exit(3), _exit(2), or +// returned from main() +class GTEST_API_ DeathTest { + public: + // Create returns false if there was an error determining the + // appropriate action to take for the current death test; for example, + // if the gtest_death_test_style flag is set to an invalid value. + // The LastMessage method will return a more detailed message in that + // case. Otherwise, the DeathTest pointer pointed to by the "test" + // argument is set. If the death test should be skipped, the pointer + // is set to NULL; otherwise, it is set to the address of a new concrete + // DeathTest object that controls the execution of the current test. + static bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test); + DeathTest(); + virtual ~DeathTest() { } + + // A helper class that aborts a death test when it's deleted. + class ReturnSentinel { + public: + explicit ReturnSentinel(DeathTest* test) : test_(test) { } + ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); } + private: + DeathTest* const test_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel); + } GTEST_ATTRIBUTE_UNUSED_; + + // An enumeration of possible roles that may be taken when a death + // test is encountered. EXECUTE means that the death test logic should + // be executed immediately. OVERSEE means that the program should prepare + // the appropriate environment for a child process to execute the death + // test, then wait for it to complete. + enum TestRole { OVERSEE_TEST, EXECUTE_TEST }; + + // An enumeration of the three reasons that a test might be aborted. + enum AbortReason { + TEST_ENCOUNTERED_RETURN_STATEMENT, + TEST_THREW_EXCEPTION, + TEST_DID_NOT_DIE + }; + + // Assumes one of the above roles. + virtual TestRole AssumeRole() = 0; + + // Waits for the death test to finish and returns its status. + virtual int Wait() = 0; + + // Returns true if the death test passed; that is, the test process + // exited during the test, its exit status matches a user-supplied + // predicate, and its stderr output matches a user-supplied regular + // expression. + // The user-supplied predicate may be a macro expression rather + // than a function pointer or functor, or else Wait and Passed could + // be combined. + virtual bool Passed(bool exit_status_ok) = 0; + + // Signals that the death test did not die as expected. + virtual void Abort(AbortReason reason) = 0; + + // Returns a human-readable outcome message regarding the outcome of + // the last death test. + static const char* LastMessage(); + + static void set_last_death_test_message(const std::string& message); + + private: + // A string containing a description of the outcome of the last death test. + static std::string last_death_test_message_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest); +}; + +// Factory interface for death tests. May be mocked out for testing. +class DeathTestFactory { + public: + virtual ~DeathTestFactory() { } + virtual bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test) = 0; +}; + +// A concrete DeathTestFactory implementation for normal use. +class DefaultDeathTestFactory : public DeathTestFactory { + public: + virtual bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test); +}; + +// Returns true if exit_status describes a process that was terminated +// by a signal, or exited normally with a nonzero exit code. +GTEST_API_ bool ExitedUnsuccessfully(int exit_status); + +// Traps C++ exceptions escaping statement and reports them as test +// failures. Note that trapping SEH exceptions is not implemented here. +# if GTEST_HAS_EXCEPTIONS +# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } catch (const ::std::exception& gtest_exception) { \ + fprintf(\ + stderr, \ + "\n%s: Caught std::exception-derived exception escaping the " \ + "death test statement. Exception message: %s\n", \ + ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \ + gtest_exception.what()); \ + fflush(stderr); \ + death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ + } catch (...) { \ + death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ + } + +# else +# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) + +# endif + +// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*, +// ASSERT_EXIT*, and EXPECT_EXIT*. +# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + const ::testing::internal::RE& gtest_regex = (regex); \ + ::testing::internal::DeathTest* gtest_dt; \ + if (!::testing::internal::DeathTest::Create(#statement, >est_regex, \ + __FILE__, __LINE__, >est_dt)) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + if (gtest_dt != NULL) { \ + ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \ + gtest_dt_ptr(gtest_dt); \ + switch (gtest_dt->AssumeRole()) { \ + case ::testing::internal::DeathTest::OVERSEE_TEST: \ + if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + break; \ + case ::testing::internal::DeathTest::EXECUTE_TEST: { \ + ::testing::internal::DeathTest::ReturnSentinel \ + gtest_sentinel(gtest_dt); \ + GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \ + gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \ + break; \ + } \ + default: \ + break; \ + } \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \ + fail(::testing::internal::DeathTest::LastMessage()) +// The symbol "fail" here expands to something into which a message +// can be streamed. + +// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in +// NDEBUG mode. In this case we need the statements to be executed, the regex is +// ignored, and the macro must accept a streamed message even though the message +// is never printed. +# define GTEST_EXECUTE_STATEMENT_(statement, regex) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } else \ + ::testing::Message() + +// A class representing the parsed contents of the +// --gtest_internal_run_death_test flag, as it existed when +// RUN_ALL_TESTS was called. +class InternalRunDeathTestFlag { + public: + InternalRunDeathTestFlag(const std::string& a_file, + int a_line, + int an_index, + int a_write_fd) + : file_(a_file), line_(a_line), index_(an_index), + write_fd_(a_write_fd) {} + + ~InternalRunDeathTestFlag() { + if (write_fd_ >= 0) + posix::Close(write_fd_); + } + + const std::string& file() const { return file_; } + int line() const { return line_; } + int index() const { return index_; } + int write_fd() const { return write_fd_; } + + private: + std::string file_; + int line_; + int index_; + int write_fd_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag); +}; + +// Returns a newly created InternalRunDeathTestFlag object with fields +// initialized from the GTEST_FLAG(internal_run_death_test) flag if +// the flag is specified; otherwise returns NULL. +InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag(); + +#else // GTEST_HAS_DEATH_TEST + +// This macro is used for implementing macros such as +// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where +// death tests are not supported. Those macros must compile on such systems +// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on +// systems that support death tests. This allows one to write such a macro +// on a system that does not support death tests and be sure that it will +// compile on a death-test supporting system. +// +// Parameters: +// statement - A statement that a macro such as EXPECT_DEATH would test +// for program termination. This macro has to make sure this +// statement is compiled but not executed, to ensure that +// EXPECT_DEATH_IF_SUPPORTED compiles with a certain +// parameter iff EXPECT_DEATH compiles with it. +// regex - A regex that a macro such as EXPECT_DEATH would use to test +// the output of statement. This parameter has to be +// compiled but not evaluated by this macro, to ensure that +// this macro only accepts expressions that a macro such as +// EXPECT_DEATH would accept. +// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED +// and a return statement for ASSERT_DEATH_IF_SUPPORTED. +// This ensures that ASSERT_DEATH_IF_SUPPORTED will not +// compile inside functions where ASSERT_DEATH doesn't +// compile. +// +// The branch that has an always false condition is used to ensure that +// statement and regex are compiled (and thus syntactically correct) but +// never executed. The unreachable code macro protects the terminator +// statement from generating an 'unreachable code' warning in case +// statement unconditionally returns or throws. The Message constructor at +// the end allows the syntax of streaming additional messages into the +// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH. +# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + GTEST_LOG_(WARNING) \ + << "Death tests are not supported on this platform.\n" \ + << "Statement '" #statement "' cannot be verified."; \ + } else if (::testing::internal::AlwaysFalse()) { \ + ::testing::internal::RE::PartialMatch(".*", (regex)); \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + terminator; \ + } else \ + ::testing::Message() + +#endif // GTEST_HAS_DEATH_TEST + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ + +namespace testing { + +// This flag controls the style of death tests. Valid values are "threadsafe", +// meaning that the death test child process will re-execute the test binary +// from the start, running only a single death test, or "fast", +// meaning that the child process will execute the test logic immediately +// after forking. +GTEST_DECLARE_string_(death_test_style); + +#if GTEST_HAS_DEATH_TEST + +namespace internal { + +// Returns a Boolean value indicating whether the caller is currently +// executing in the context of the death test child process. Tools such as +// Valgrind heap checkers may need this to modify their behavior in death +// tests. IMPORTANT: This is an internal utility. Using it may break the +// implementation of death tests. User code MUST NOT use it. +GTEST_API_ bool InDeathTestChild(); + +} // namespace internal + +// The following macros are useful for writing death tests. + +// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is +// executed: +// +// 1. It generates a warning if there is more than one active +// thread. This is because it's safe to fork() or clone() only +// when there is a single thread. +// +// 2. The parent process clone()s a sub-process and runs the death +// test in it; the sub-process exits with code 0 at the end of the +// death test, if it hasn't exited already. +// +// 3. The parent process waits for the sub-process to terminate. +// +// 4. The parent process checks the exit code and error message of +// the sub-process. +// +// Examples: +// +// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number"); +// for (int i = 0; i < 5; i++) { +// EXPECT_DEATH(server.ProcessRequest(i), +// "Invalid request .* in ProcessRequest()") +// << "Failed to die on request " << i; +// } +// +// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting"); +// +// bool KilledBySIGHUP(int exit_code) { +// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP; +// } +// +// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!"); +// +// On the regular expressions used in death tests: +// +// On POSIX-compliant systems (*nix), we use the library, +// which uses the POSIX extended regex syntax. +// +// On other platforms (e.g. Windows), we only support a simple regex +// syntax implemented as part of Google Test. This limited +// implementation should be enough most of the time when writing +// death tests; though it lacks many features you can find in PCRE +// or POSIX extended regex syntax. For example, we don't support +// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and +// repetition count ("x{5,7}"), among others. +// +// Below is the syntax that we do support. We chose it to be a +// subset of both PCRE and POSIX extended regex, so it's easy to +// learn wherever you come from. In the following: 'A' denotes a +// literal character, period (.), or a single \\ escape sequence; +// 'x' and 'y' denote regular expressions; 'm' and 'n' are for +// natural numbers. +// +// c matches any literal character c +// \\d matches any decimal digit +// \\D matches any character that's not a decimal digit +// \\f matches \f +// \\n matches \n +// \\r matches \r +// \\s matches any ASCII whitespace, including \n +// \\S matches any character that's not a whitespace +// \\t matches \t +// \\v matches \v +// \\w matches any letter, _, or decimal digit +// \\W matches any character that \\w doesn't match +// \\c matches any literal character c, which must be a punctuation +// . matches any single character except \n +// A? matches 0 or 1 occurrences of A +// A* matches 0 or many occurrences of A +// A+ matches 1 or many occurrences of A +// ^ matches the beginning of a string (not that of each line) +// $ matches the end of a string (not that of each line) +// xy matches x followed by y +// +// If you accidentally use PCRE or POSIX extended regex features +// not implemented by us, you will get a run-time failure. In that +// case, please try to rewrite your regular expression within the +// above syntax. +// +// This implementation is *not* meant to be as highly tuned or robust +// as a compiled regex library, but should perform well enough for a +// death test, which already incurs significant overhead by launching +// a child process. +// +// Known caveats: +// +// A "threadsafe" style death test obtains the path to the test +// program from argv[0] and re-executes it in the sub-process. For +// simplicity, the current implementation doesn't search the PATH +// when launching the sub-process. This means that the user must +// invoke the test program via a path that contains at least one +// path separator (e.g. path/to/foo_test and +// /absolute/path/to/bar_test are fine, but foo_test is not). This +// is rarely a problem as people usually don't put the test binary +// directory in PATH. +// +// TODO(wan@google.com): make thread-safe death tests search the PATH. + +// Asserts that a given statement causes the program to exit, with an +// integer exit status that satisfies predicate, and emitting error output +// that matches regex. +# define ASSERT_EXIT(statement, predicate, regex) \ + GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_) + +// Like ASSERT_EXIT, but continues on to successive tests in the +// test case, if any: +# define EXPECT_EXIT(statement, predicate, regex) \ + GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_) + +// Asserts that a given statement causes the program to exit, either by +// explicitly exiting with a nonzero exit code or being killed by a +// signal, and emitting error output that matches regex. +# define ASSERT_DEATH(statement, regex) \ + ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) + +// Like ASSERT_DEATH, but continues on to successive tests in the +// test case, if any: +# define EXPECT_DEATH(statement, regex) \ + EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) + +// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*: + +// Tests that an exit code describes a normal exit with a given exit code. +class GTEST_API_ ExitedWithCode { + public: + explicit ExitedWithCode(int exit_code); + bool operator()(int exit_status) const; + private: + // No implementation - assignment is unsupported. + void operator=(const ExitedWithCode& other); + + const int exit_code_; +}; + +# if !GTEST_OS_WINDOWS +// Tests that an exit code describes an exit due to termination by a +// given signal. +class GTEST_API_ KilledBySignal { + public: + explicit KilledBySignal(int signum); + bool operator()(int exit_status) const; + private: + const int signum_; +}; +# endif // !GTEST_OS_WINDOWS + +// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode. +// The death testing framework causes this to have interesting semantics, +// since the sideeffects of the call are only visible in opt mode, and not +// in debug mode. +// +// In practice, this can be used to test functions that utilize the +// LOG(DFATAL) macro using the following style: +// +// int DieInDebugOr12(int* sideeffect) { +// if (sideeffect) { +// *sideeffect = 12; +// } +// LOG(DFATAL) << "death"; +// return 12; +// } +// +// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) { +// int sideeffect = 0; +// // Only asserts in dbg. +// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death"); +// +// #ifdef NDEBUG +// // opt-mode has sideeffect visible. +// EXPECT_EQ(12, sideeffect); +// #else +// // dbg-mode no visible sideeffect. +// EXPECT_EQ(0, sideeffect); +// #endif +// } +// +// This will assert that DieInDebugReturn12InOpt() crashes in debug +// mode, usually due to a DCHECK or LOG(DFATAL), but returns the +// appropriate fallback value (12 in this case) in opt mode. If you +// need to test that a function has appropriate side-effects in opt +// mode, include assertions against the side-effects. A general +// pattern for this is: +// +// EXPECT_DEBUG_DEATH({ +// // Side-effects here will have an effect after this statement in +// // opt mode, but none in debug mode. +// EXPECT_EQ(12, DieInDebugOr12(&sideeffect)); +// }, "death"); +// +# ifdef NDEBUG + +# define EXPECT_DEBUG_DEATH(statement, regex) \ + GTEST_EXECUTE_STATEMENT_(statement, regex) + +# define ASSERT_DEBUG_DEATH(statement, regex) \ + GTEST_EXECUTE_STATEMENT_(statement, regex) + +# else + +# define EXPECT_DEBUG_DEATH(statement, regex) \ + EXPECT_DEATH(statement, regex) + +# define ASSERT_DEBUG_DEATH(statement, regex) \ + ASSERT_DEATH(statement, regex) + +# endif // NDEBUG for EXPECT_DEBUG_DEATH +#endif // GTEST_HAS_DEATH_TEST + +// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and +// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if +// death tests are supported; otherwise they just issue a warning. This is +// useful when you are combining death test assertions with normal test +// assertions in one test. +#if GTEST_HAS_DEATH_TEST +# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + EXPECT_DEATH(statement, regex) +# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + ASSERT_DEATH(statement, regex) +#else +# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, ) +# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return) +#endif + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +// This file was GENERATED by command: +// pump.py gtest-param-test.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: vladl@google.com (Vlad Losev) +// +// Macros and functions for implementing parameterized tests +// in Google C++ Testing Framework (Google Test) +// +// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ + + +// Value-parameterized tests allow you to test your code with different +// parameters without writing multiple copies of the same test. +// +// Here is how you use value-parameterized tests: + +#if 0 + +// To write value-parameterized tests, first you should define a fixture +// class. It is usually derived from testing::TestWithParam (see below for +// another inheritance scheme that's sometimes useful in more complicated +// class hierarchies), where the type of your parameter values. +// TestWithParam is itself derived from testing::Test. T can be any +// copyable type. If it's a raw pointer, you are responsible for managing the +// lifespan of the pointed values. + +class FooTest : public ::testing::TestWithParam { + // You can implement all the usual class fixture members here. +}; + +// Then, use the TEST_P macro to define as many parameterized tests +// for this fixture as you want. The _P suffix is for "parameterized" +// or "pattern", whichever you prefer to think. + +TEST_P(FooTest, DoesBlah) { + // Inside a test, access the test parameter with the GetParam() method + // of the TestWithParam class: + EXPECT_TRUE(foo.Blah(GetParam())); + ... +} + +TEST_P(FooTest, HasBlahBlah) { + ... +} + +// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test +// case with any set of parameters you want. Google Test defines a number +// of functions for generating test parameters. They return what we call +// (surprise!) parameter generators. Here is a summary of them, which +// are all in the testing namespace: +// +// +// Range(begin, end [, step]) - Yields values {begin, begin+step, +// begin+step+step, ...}. The values do not +// include end. step defaults to 1. +// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}. +// ValuesIn(container) - Yields values from a C-style array, an STL +// ValuesIn(begin,end) container, or an iterator range [begin, end). +// Bool() - Yields sequence {false, true}. +// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product +// for the math savvy) of the values generated +// by the N generators. +// +// For more details, see comments at the definitions of these functions below +// in this file. +// +// The following statement will instantiate tests from the FooTest test case +// each with parameter values "meeny", "miny", and "moe". + +INSTANTIATE_TEST_CASE_P(InstantiationName, + FooTest, + Values("meeny", "miny", "moe")); + +// To distinguish different instances of the pattern, (yes, you +// can instantiate it more then once) the first argument to the +// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the +// actual test case name. Remember to pick unique prefixes for different +// instantiations. The tests from the instantiation above will have +// these names: +// +// * InstantiationName/FooTest.DoesBlah/0 for "meeny" +// * InstantiationName/FooTest.DoesBlah/1 for "miny" +// * InstantiationName/FooTest.DoesBlah/2 for "moe" +// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny" +// * InstantiationName/FooTest.HasBlahBlah/1 for "miny" +// * InstantiationName/FooTest.HasBlahBlah/2 for "moe" +// +// You can use these names in --gtest_filter. +// +// This statement will instantiate all tests from FooTest again, each +// with parameter values "cat" and "dog": + +const char* pets[] = {"cat", "dog"}; +INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); + +// The tests from the instantiation above will have these names: +// +// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat" +// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog" +// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat" +// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog" +// +// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests +// in the given test case, whether their definitions come before or +// AFTER the INSTANTIATE_TEST_CASE_P statement. +// +// Please also note that generator expressions (including parameters to the +// generators) are evaluated in InitGoogleTest(), after main() has started. +// This allows the user on one hand, to adjust generator parameters in order +// to dynamically determine a set of tests to run and on the other hand, +// give the user a chance to inspect the generated tests with Google Test +// reflection API before RUN_ALL_TESTS() is executed. +// +// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc +// for more examples. +// +// In the future, we plan to publish the API for defining new parameter +// generators. But for now this interface remains part of the internal +// implementation and is subject to change. +// +// +// A parameterized test fixture must be derived from testing::Test and from +// testing::WithParamInterface, where T is the type of the parameter +// values. Inheriting from TestWithParam satisfies that requirement because +// TestWithParam inherits from both Test and WithParamInterface. In more +// complicated hierarchies, however, it is occasionally useful to inherit +// separately from Test and WithParamInterface. For example: + +class BaseTest : public ::testing::Test { + // You can inherit all the usual members for a non-parameterized test + // fixture here. +}; + +class DerivedTest : public BaseTest, public ::testing::WithParamInterface { + // The usual test fixture members go here too. +}; + +TEST_F(BaseTest, HasFoo) { + // This is an ordinary non-parameterized test. +} + +TEST_P(DerivedTest, DoesBlah) { + // GetParam works just the same here as if you inherit from TestWithParam. + EXPECT_TRUE(foo.Blah(GetParam())); +} + +#endif // 0 + + +#if !GTEST_OS_SYMBIAN +# include +#endif + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: vladl@google.com (Vlad Losev) + +// Type and function utilities for implementing parameterized tests. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ + +#include +#include +#include + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +// Copyright 2003 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Dan Egnor (egnor@google.com) +// +// A "smart" pointer type with reference tracking. Every pointer to a +// particular object is kept on a circular linked list. When the last pointer +// to an object is destroyed or reassigned, the object is deleted. +// +// Used properly, this deletes the object when the last reference goes away. +// There are several caveats: +// - Like all reference counting schemes, cycles lead to leaks. +// - Each smart pointer is actually two pointers (8 bytes instead of 4). +// - Every time a pointer is assigned, the entire list of pointers to that +// object is traversed. This class is therefore NOT SUITABLE when there +// will often be more than two or three pointers to a particular object. +// - References are only tracked as long as linked_ptr<> objects are copied. +// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS +// will happen (double deletion). +// +// A good use of this class is storing object references in STL containers. +// You can safely put linked_ptr<> in a vector<>. +// Other uses may not be as good. +// +// Note: If you use an incomplete type with linked_ptr<>, the class +// *containing* linked_ptr<> must have a constructor and destructor (even +// if they do nothing!). +// +// Bill Gibbons suggested we use something like this. +// +// Thread Safety: +// Unlike other linked_ptr implementations, in this implementation +// a linked_ptr object is thread-safe in the sense that: +// - it's safe to copy linked_ptr objects concurrently, +// - it's safe to copy *from* a linked_ptr and read its underlying +// raw pointer (e.g. via get()) concurrently, and +// - it's safe to write to two linked_ptrs that point to the same +// shared object concurrently. +// TODO(wan@google.com): rename this to safe_linked_ptr to avoid +// confusion with normal linked_ptr. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ + +#include +#include + + +namespace testing { +namespace internal { + +// Protects copying of all linked_ptr objects. +GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex); + +// This is used internally by all instances of linked_ptr<>. It needs to be +// a non-template class because different types of linked_ptr<> can refer to +// the same object (linked_ptr(obj) vs linked_ptr(obj)). +// So, it needs to be possible for different types of linked_ptr to participate +// in the same circular linked list, so we need a single class type here. +// +// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr. +class linked_ptr_internal { + public: + // Create a new circle that includes only this instance. + void join_new() { + next_ = this; + } + + // Many linked_ptr operations may change p.link_ for some linked_ptr + // variable p in the same circle as this object. Therefore we need + // to prevent two such operations from occurring concurrently. + // + // Note that different types of linked_ptr objects can coexist in a + // circle (e.g. linked_ptr, linked_ptr, and + // linked_ptr). Therefore we must use a single mutex to + // protect all linked_ptr objects. This can create serious + // contention in production code, but is acceptable in a testing + // framework. + + // Join an existing circle. + void join(linked_ptr_internal const* ptr) + GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { + MutexLock lock(&g_linked_ptr_mutex); + + linked_ptr_internal const* p = ptr; + while (p->next_ != ptr) p = p->next_; + p->next_ = this; + next_ = ptr; + } + + // Leave whatever circle we're part of. Returns true if we were the + // last member of the circle. Once this is done, you can join() another. + bool depart() + GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { + MutexLock lock(&g_linked_ptr_mutex); + + if (next_ == this) return true; + linked_ptr_internal const* p = next_; + while (p->next_ != this) p = p->next_; + p->next_ = next_; + return false; + } + + private: + mutable linked_ptr_internal const* next_; +}; + +template +class linked_ptr { + public: + typedef T element_type; + + // Take over ownership of a raw pointer. This should happen as soon as + // possible after the object is created. + explicit linked_ptr(T* ptr = NULL) { capture(ptr); } + ~linked_ptr() { depart(); } + + // Copy an existing linked_ptr<>, adding ourselves to the list of references. + template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } + linked_ptr(linked_ptr const& ptr) { // NOLINT + assert(&ptr != this); + copy(&ptr); + } + + // Assignment releases the old value and acquires the new. + template linked_ptr& operator=(linked_ptr const& ptr) { + depart(); + copy(&ptr); + return *this; + } + + linked_ptr& operator=(linked_ptr const& ptr) { + if (&ptr != this) { + depart(); + copy(&ptr); + } + return *this; + } + + // Smart pointer members. + void reset(T* ptr = NULL) { + depart(); + capture(ptr); + } + T* get() const { return value_; } + T* operator->() const { return value_; } + T& operator*() const { return *value_; } + + bool operator==(T* p) const { return value_ == p; } + bool operator!=(T* p) const { return value_ != p; } + template + bool operator==(linked_ptr const& ptr) const { + return value_ == ptr.get(); + } + template + bool operator!=(linked_ptr const& ptr) const { + return value_ != ptr.get(); + } + + private: + template + friend class linked_ptr; + + T* value_; + linked_ptr_internal link_; + + void depart() { + if (link_.depart()) delete value_; + } + + void capture(T* ptr) { + value_ = ptr; + link_.join_new(); + } + + template void copy(linked_ptr const* ptr) { + value_ = ptr->get(); + if (value_) + link_.join(&ptr->link_); + else + link_.join_new(); + } +}; + +template inline +bool operator==(T* ptr, const linked_ptr& x) { + return ptr == x.get(); +} + +template inline +bool operator!=(T* ptr, const linked_ptr& x) { + return ptr != x.get(); +} + +// A function to convert T* into linked_ptr +// Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation +// for linked_ptr >(new FooBarBaz(arg)) +template +linked_ptr make_linked_ptr(T* ptr) { + return linked_ptr(ptr); +} + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Test - The Google C++ Testing Framework +// +// This file implements a universal value printer that can print a +// value of any type T: +// +// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); +// +// A user can teach this function how to print a class type T by +// defining either operator<<() or PrintTo() in the namespace that +// defines T. More specifically, the FIRST defined function in the +// following list will be used (assuming T is defined in namespace +// foo): +// +// 1. foo::PrintTo(const T&, ostream*) +// 2. operator<<(ostream&, const T&) defined in either foo or the +// global namespace. +// +// If none of the above is defined, it will print the debug string of +// the value if it is a protocol buffer, or print the raw bytes in the +// value otherwise. +// +// To aid debugging: when T is a reference type, the address of the +// value is also printed; when T is a (const) char pointer, both the +// pointer value and the NUL-terminated string it points to are +// printed. +// +// We also provide some convenient wrappers: +// +// // Prints a value to a string. For a (const or not) char +// // pointer, the NUL-terminated string (but not the pointer) is +// // printed. +// std::string ::testing::PrintToString(const T& value); +// +// // Prints a value tersely: for a reference type, the referenced +// // value (but not the address) is printed; for a (const or not) char +// // pointer, the NUL-terminated string (but not the pointer) is +// // printed. +// void ::testing::internal::UniversalTersePrint(const T& value, ostream*); +// +// // Prints value using the type inferred by the compiler. The difference +// // from UniversalTersePrint() is that this function prints both the +// // pointer and the NUL-terminated string for a (const or not) char pointer. +// void ::testing::internal::UniversalPrint(const T& value, ostream*); +// +// // Prints the fields of a tuple tersely to a string vector, one +// // element for each field. Tuple support must be enabled in +// // gtest-port.h. +// std::vector UniversalTersePrintTupleFieldsToStrings( +// const Tuple& value); +// +// Known limitation: +// +// The print primitives print the elements of an STL-style container +// using the compiler-inferred type of *iter where iter is a +// const_iterator of the container. When const_iterator is an input +// iterator but not a forward iterator, this inferred type may not +// match value_type, and the print output may be incorrect. In +// practice, this is rarely a problem as for most containers +// const_iterator is a forward iterator. We'll fix this if there's an +// actual need for it. Note that this fix cannot rely on value_type +// being defined as many user-defined container types don't have +// value_type. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ + +#include // NOLINT +#include +#include +#include +#include + +namespace testing { + +// Definitions in the 'internal' and 'internal2' name spaces are +// subject to change without notice. DO NOT USE THEM IN USER CODE! +namespace internal2 { + +// Prints the given number of bytes in the given object to the given +// ostream. +GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, + size_t count, + ::std::ostream* os); + +// For selecting which printer to use when a given type has neither << +// nor PrintTo(). +enum TypeKind { + kProtobuf, // a protobuf type + kConvertibleToInteger, // a type implicitly convertible to BiggestInt + // (e.g. a named or unnamed enum type) + kOtherType // anything else +}; + +// TypeWithoutFormatter::PrintValue(value, os) is called +// by the universal printer to print a value of type T when neither +// operator<< nor PrintTo() is defined for T, where kTypeKind is the +// "kind" of T as defined by enum TypeKind. +template +class TypeWithoutFormatter { + public: + // This default version is called when kTypeKind is kOtherType. + static void PrintValue(const T& value, ::std::ostream* os) { + PrintBytesInObjectTo(reinterpret_cast(&value), + sizeof(value), os); + } +}; + +// We print a protobuf using its ShortDebugString() when the string +// doesn't exceed this many characters; otherwise we print it using +// DebugString() for better readability. +const size_t kProtobufOneLinerMaxLength = 50; + +template +class TypeWithoutFormatter { + public: + static void PrintValue(const T& value, ::std::ostream* os) { + const ::testing::internal::string short_str = value.ShortDebugString(); + const ::testing::internal::string pretty_str = + short_str.length() <= kProtobufOneLinerMaxLength ? + short_str : ("\n" + value.DebugString()); + *os << ("<" + pretty_str + ">"); + } +}; + +template +class TypeWithoutFormatter { + public: + // Since T has no << operator or PrintTo() but can be implicitly + // converted to BiggestInt, we print it as a BiggestInt. + // + // Most likely T is an enum type (either named or unnamed), in which + // case printing it as an integer is the desired behavior. In case + // T is not an enum, printing it as an integer is the best we can do + // given that it has no user-defined printer. + static void PrintValue(const T& value, ::std::ostream* os) { + const internal::BiggestInt kBigInt = value; + *os << kBigInt; + } +}; + +// Prints the given value to the given ostream. If the value is a +// protocol message, its debug string is printed; if it's an enum or +// of a type implicitly convertible to BiggestInt, it's printed as an +// integer; otherwise the bytes in the value are printed. This is +// what UniversalPrinter::Print() does when it knows nothing about +// type T and T has neither << operator nor PrintTo(). +// +// A user can override this behavior for a class type Foo by defining +// a << operator in the namespace where Foo is defined. +// +// We put this operator in namespace 'internal2' instead of 'internal' +// to simplify the implementation, as much code in 'internal' needs to +// use << in STL, which would conflict with our own << were it defined +// in 'internal'. +// +// Note that this operator<< takes a generic std::basic_ostream type instead of the more restricted std::ostream. If +// we define it to take an std::ostream instead, we'll get an +// "ambiguous overloads" compiler error when trying to print a type +// Foo that supports streaming to std::basic_ostream, as the compiler cannot tell whether +// operator<<(std::ostream&, const T&) or +// operator<<(std::basic_stream, const Foo&) is more +// specific. +template +::std::basic_ostream& operator<<( + ::std::basic_ostream& os, const T& x) { + TypeWithoutFormatter::value ? kProtobuf : + internal::ImplicitlyConvertible::value ? + kConvertibleToInteger : kOtherType)>::PrintValue(x, &os); + return os; +} + +} // namespace internal2 +} // namespace testing + +// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up +// magic needed for implementing UniversalPrinter won't work. +namespace testing_internal { + +// Used to print a value that is not an STL-style container when the +// user doesn't define PrintTo() for it. +template +void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) { + // With the following statement, during unqualified name lookup, + // testing::internal2::operator<< appears as if it was declared in + // the nearest enclosing namespace that contains both + // ::testing_internal and ::testing::internal2, i.e. the global + // namespace. For more details, refer to the C++ Standard section + // 7.3.4-1 [namespace.udir]. This allows us to fall back onto + // testing::internal2::operator<< in case T doesn't come with a << + // operator. + // + // We cannot write 'using ::testing::internal2::operator<<;', which + // gcc 3.3 fails to compile due to a compiler bug. + using namespace ::testing::internal2; // NOLINT + + // Assuming T is defined in namespace foo, in the next statement, + // the compiler will consider all of: + // + // 1. foo::operator<< (thanks to Koenig look-up), + // 2. ::operator<< (as the current namespace is enclosed in ::), + // 3. testing::internal2::operator<< (thanks to the using statement above). + // + // The operator<< whose type matches T best will be picked. + // + // We deliberately allow #2 to be a candidate, as sometimes it's + // impossible to define #1 (e.g. when foo is ::std, defining + // anything in it is undefined behavior unless you are a compiler + // vendor.). + *os << value; +} + +} // namespace testing_internal + +namespace testing { +namespace internal { + +// UniversalPrinter::Print(value, ostream_ptr) prints the given +// value to the given ostream. The caller must ensure that +// 'ostream_ptr' is not NULL, or the behavior is undefined. +// +// We define UniversalPrinter as a class template (as opposed to a +// function template), as we need to partially specialize it for +// reference types, which cannot be done with function templates. +template +class UniversalPrinter; + +template +void UniversalPrint(const T& value, ::std::ostream* os); + +// Used to print an STL-style container when the user doesn't define +// a PrintTo() for it. +template +void DefaultPrintTo(IsContainer /* dummy */, + false_type /* is not a pointer */, + const C& container, ::std::ostream* os) { + const size_t kMaxCount = 32; // The maximum number of elements to print. + *os << '{'; + size_t count = 0; + for (typename C::const_iterator it = container.begin(); + it != container.end(); ++it, ++count) { + if (count > 0) { + *os << ','; + if (count == kMaxCount) { // Enough has been printed. + *os << " ..."; + break; + } + } + *os << ' '; + // We cannot call PrintTo(*it, os) here as PrintTo() doesn't + // handle *it being a native array. + internal::UniversalPrint(*it, os); + } + + if (count > 0) { + *os << ' '; + } + *os << '}'; +} + +// Used to print a pointer that is neither a char pointer nor a member +// pointer, when the user doesn't define PrintTo() for it. (A member +// variable pointer or member function pointer doesn't really point to +// a location in the address space. Their representation is +// implementation-defined. Therefore they will be printed as raw +// bytes.) +template +void DefaultPrintTo(IsNotContainer /* dummy */, + true_type /* is a pointer */, + T* p, ::std::ostream* os) { + if (p == NULL) { + *os << "NULL"; + } else { + // C++ doesn't allow casting from a function pointer to any object + // pointer. + // + // IsTrue() silences warnings: "Condition is always true", + // "unreachable code". + if (IsTrue(ImplicitlyConvertible::value)) { + // T is not a function type. We just call << to print p, + // relying on ADL to pick up user-defined << for their pointer + // types, if any. + *os << p; + } else { + // T is a function type, so '*os << p' doesn't do what we want + // (it just prints p as bool). We want to print p as a const + // void*. However, we cannot cast it to const void* directly, + // even using reinterpret_cast, as earlier versions of gcc + // (e.g. 3.4.5) cannot compile the cast when p is a function + // pointer. Casting to UInt64 first solves the problem. + *os << reinterpret_cast( + reinterpret_cast(p)); + } + } +} + +// Used to print a non-container, non-pointer value when the user +// doesn't define PrintTo() for it. +template +void DefaultPrintTo(IsNotContainer /* dummy */, + false_type /* is not a pointer */, + const T& value, ::std::ostream* os) { + ::testing_internal::DefaultPrintNonContainerTo(value, os); +} + +// Prints the given value using the << operator if it has one; +// otherwise prints the bytes in it. This is what +// UniversalPrinter::Print() does when PrintTo() is not specialized +// or overloaded for type T. +// +// A user can override this behavior for a class type Foo by defining +// an overload of PrintTo() in the namespace where Foo is defined. We +// give the user this option as sometimes defining a << operator for +// Foo is not desirable (e.g. the coding style may prevent doing it, +// or there is already a << operator but it doesn't do what the user +// wants). +template +void PrintTo(const T& value, ::std::ostream* os) { + // DefaultPrintTo() is overloaded. The type of its first two + // arguments determine which version will be picked. If T is an + // STL-style container, the version for container will be called; if + // T is a pointer, the pointer version will be called; otherwise the + // generic version will be called. + // + // Note that we check for container types here, prior to we check + // for protocol message types in our operator<<. The rationale is: + // + // For protocol messages, we want to give people a chance to + // override Google Mock's format by defining a PrintTo() or + // operator<<. For STL containers, other formats can be + // incompatible with Google Mock's format for the container + // elements; therefore we check for container types here to ensure + // that our format is used. + // + // The second argument of DefaultPrintTo() is needed to bypass a bug + // in Symbian's C++ compiler that prevents it from picking the right + // overload between: + // + // PrintTo(const T& x, ...); + // PrintTo(T* x, ...); + DefaultPrintTo(IsContainerTest(0), is_pointer(), value, os); +} + +// The following list of PrintTo() overloads tells +// UniversalPrinter::Print() how to print standard types (built-in +// types, strings, plain arrays, and pointers). + +// Overloads for various char types. +GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os); +GTEST_API_ void PrintTo(signed char c, ::std::ostream* os); +inline void PrintTo(char c, ::std::ostream* os) { + // When printing a plain char, we always treat it as unsigned. This + // way, the output won't be affected by whether the compiler thinks + // char is signed or not. + PrintTo(static_cast(c), os); +} + +// Overloads for other simple built-in types. +inline void PrintTo(bool x, ::std::ostream* os) { + *os << (x ? "true" : "false"); +} + +// Overload for wchar_t type. +// Prints a wchar_t as a symbol if it is printable or as its internal +// code otherwise and also as its decimal code (except for L'\0'). +// The L'\0' char is printed as "L'\\0'". The decimal code is printed +// as signed integer when wchar_t is implemented by the compiler +// as a signed type and is printed as an unsigned integer when wchar_t +// is implemented as an unsigned type. +GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os); + +// Overloads for C strings. +GTEST_API_ void PrintTo(const char* s, ::std::ostream* os); +inline void PrintTo(char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} + +// signed/unsigned char is often used for representing binary data, so +// we print pointers to it as void* to be safe. +inline void PrintTo(const signed char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(signed char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(const unsigned char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(unsigned char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} + +// MSVC can be configured to define wchar_t as a typedef of unsigned +// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native +// type. When wchar_t is a typedef, defining an overload for const +// wchar_t* would cause unsigned short* be printed as a wide string, +// possibly causing invalid memory accesses. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +// Overloads for wide C strings +GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os); +inline void PrintTo(wchar_t* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +#endif + +// Overload for C arrays. Multi-dimensional arrays are printed +// properly. + +// Prints the given number of elements in an array, without printing +// the curly braces. +template +void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) { + UniversalPrint(a[0], os); + for (size_t i = 1; i != count; i++) { + *os << ", "; + UniversalPrint(a[i], os); + } +} + +// Overloads for ::string and ::std::string. +#if GTEST_HAS_GLOBAL_STRING +GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os); +inline void PrintTo(const ::string& s, ::std::ostream* os) { + PrintStringTo(s, os); +} +#endif // GTEST_HAS_GLOBAL_STRING + +GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os); +inline void PrintTo(const ::std::string& s, ::std::ostream* os) { + PrintStringTo(s, os); +} + +// Overloads for ::wstring and ::std::wstring. +#if GTEST_HAS_GLOBAL_WSTRING +GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os); +inline void PrintTo(const ::wstring& s, ::std::ostream* os) { + PrintWideStringTo(s, os); +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +#if GTEST_HAS_STD_WSTRING +GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os); +inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { + PrintWideStringTo(s, os); +} +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_TR1_TUPLE +// Overload for ::std::tr1::tuple. Needed for printing function arguments, +// which are packed as tuples. + +// Helper function for printing a tuple. T must be instantiated with +// a tuple type. +template +void PrintTupleTo(const T& t, ::std::ostream* os); + +// Overloaded PrintTo() for tuples of various arities. We support +// tuples of up-to 10 fields. The following implementation works +// regardless of whether tr1::tuple is implemented using the +// non-standard variadic template feature or not. + +inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo( + const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} +#endif // GTEST_HAS_TR1_TUPLE + +// Overload for std::pair. +template +void PrintTo(const ::std::pair& value, ::std::ostream* os) { + *os << '('; + // We cannot use UniversalPrint(value.first, os) here, as T1 may be + // a reference type. The same for printing value.second. + UniversalPrinter::Print(value.first, os); + *os << ", "; + UniversalPrinter::Print(value.second, os); + *os << ')'; +} + +// Implements printing a non-reference type T by letting the compiler +// pick the right overload of PrintTo() for T. +template +class UniversalPrinter { + public: + // MSVC warns about adding const to a function type, so we want to + // disable the warning. +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4180) // Temporarily disables warning 4180. +#endif // _MSC_VER + + // Note: we deliberately don't call this PrintTo(), as that name + // conflicts with ::testing::internal::PrintTo in the body of the + // function. + static void Print(const T& value, ::std::ostream* os) { + // By default, ::testing::internal::PrintTo() is used for printing + // the value. + // + // Thanks to Koenig look-up, if T is a class and has its own + // PrintTo() function defined in its namespace, that function will + // be visible here. Since it is more specific than the generic ones + // in ::testing::internal, it will be picked by the compiler in the + // following statement - exactly what we want. + PrintTo(value, os); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif // _MSC_VER +}; + +// UniversalPrintArray(begin, len, os) prints an array of 'len' +// elements, starting at address 'begin'. +template +void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { + if (len == 0) { + *os << "{}"; + } else { + *os << "{ "; + const size_t kThreshold = 18; + const size_t kChunkSize = 8; + // If the array has more than kThreshold elements, we'll have to + // omit some details by printing only the first and the last + // kChunkSize elements. + // TODO(wan@google.com): let the user control the threshold using a flag. + if (len <= kThreshold) { + PrintRawArrayTo(begin, len, os); + } else { + PrintRawArrayTo(begin, kChunkSize, os); + *os << ", ..., "; + PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os); + } + *os << " }"; + } +} +// This overload prints a (const) char array compactly. +GTEST_API_ void UniversalPrintArray( + const char* begin, size_t len, ::std::ostream* os); + +// This overload prints a (const) wchar_t array compactly. +GTEST_API_ void UniversalPrintArray( + const wchar_t* begin, size_t len, ::std::ostream* os); + +// Implements printing an array type T[N]. +template +class UniversalPrinter { + public: + // Prints the given array, omitting some elements when there are too + // many. + static void Print(const T (&a)[N], ::std::ostream* os) { + UniversalPrintArray(a, N, os); + } +}; + +// Implements printing a reference type T&. +template +class UniversalPrinter { + public: + // MSVC warns about adding const to a function type, so we want to + // disable the warning. +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4180) // Temporarily disables warning 4180. +#endif // _MSC_VER + + static void Print(const T& value, ::std::ostream* os) { + // Prints the address of the value. We use reinterpret_cast here + // as static_cast doesn't compile when T is a function type. + *os << "@" << reinterpret_cast(&value) << " "; + + // Then prints the value itself. + UniversalPrint(value, os); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif // _MSC_VER +}; + +// Prints a value tersely: for a reference type, the referenced value +// (but not the address) is printed; for a (const) char pointer, the +// NUL-terminated string (but not the pointer) is printed. + +template +class UniversalTersePrinter { + public: + static void Print(const T& value, ::std::ostream* os) { + UniversalPrint(value, os); + } +}; +template +class UniversalTersePrinter { + public: + static void Print(const T& value, ::std::ostream* os) { + UniversalPrint(value, os); + } +}; +template +class UniversalTersePrinter { + public: + static void Print(const T (&value)[N], ::std::ostream* os) { + UniversalPrinter::Print(value, os); + } +}; +template <> +class UniversalTersePrinter { + public: + static void Print(const char* str, ::std::ostream* os) { + if (str == NULL) { + *os << "NULL"; + } else { + UniversalPrint(string(str), os); + } + } +}; +template <> +class UniversalTersePrinter { + public: + static void Print(char* str, ::std::ostream* os) { + UniversalTersePrinter::Print(str, os); + } +}; + +#if GTEST_HAS_STD_WSTRING +template <> +class UniversalTersePrinter { + public: + static void Print(const wchar_t* str, ::std::ostream* os) { + if (str == NULL) { + *os << "NULL"; + } else { + UniversalPrint(::std::wstring(str), os); + } + } +}; +#endif + +template <> +class UniversalTersePrinter { + public: + static void Print(wchar_t* str, ::std::ostream* os) { + UniversalTersePrinter::Print(str, os); + } +}; + +template +void UniversalTersePrint(const T& value, ::std::ostream* os) { + UniversalTersePrinter::Print(value, os); +} + +// Prints a value using the type inferred by the compiler. The +// difference between this and UniversalTersePrint() is that for a +// (const) char pointer, this prints both the pointer and the +// NUL-terminated string. +template +void UniversalPrint(const T& value, ::std::ostream* os) { + // A workarond for the bug in VC++ 7.1 that prevents us from instantiating + // UniversalPrinter with T directly. + typedef T T1; + UniversalPrinter::Print(value, os); +} + +#if GTEST_HAS_TR1_TUPLE +typedef ::std::vector Strings; + +// This helper template allows PrintTo() for tuples and +// UniversalTersePrintTupleFieldsToStrings() to be defined by +// induction on the number of tuple fields. The idea is that +// TuplePrefixPrinter::PrintPrefixTo(t, os) prints the first N +// fields in tuple t, and can be defined in terms of +// TuplePrefixPrinter. + +// The inductive case. +template +struct TuplePrefixPrinter { + // Prints the first N fields of a tuple. + template + static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { + TuplePrefixPrinter::PrintPrefixTo(t, os); + *os << ", "; + UniversalPrinter::type> + ::Print(::std::tr1::get(t), os); + } + + // Tersely prints the first N fields of a tuple to a string vector, + // one element for each field. + template + static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { + TuplePrefixPrinter::TersePrintPrefixToStrings(t, strings); + ::std::stringstream ss; + UniversalTersePrint(::std::tr1::get(t), &ss); + strings->push_back(ss.str()); + } +}; + +// Base cases. +template <> +struct TuplePrefixPrinter<0> { + template + static void PrintPrefixTo(const Tuple&, ::std::ostream*) {} + + template + static void TersePrintPrefixToStrings(const Tuple&, Strings*) {} +}; +// We have to specialize the entire TuplePrefixPrinter<> class +// template here, even though the definition of +// TersePrintPrefixToStrings() is the same as the generic version, as +// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't +// support specializing a method template of a class template. +template <> +struct TuplePrefixPrinter<1> { + template + static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { + UniversalPrinter::type>:: + Print(::std::tr1::get<0>(t), os); + } + + template + static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { + ::std::stringstream ss; + UniversalTersePrint(::std::tr1::get<0>(t), &ss); + strings->push_back(ss.str()); + } +}; + +// Helper function for printing a tuple. T must be instantiated with +// a tuple type. +template +void PrintTupleTo(const T& t, ::std::ostream* os) { + *os << "("; + TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: + PrintPrefixTo(t, os); + *os << ")"; +} + +// Prints the fields of a tuple tersely to a string vector, one +// element for each field. See the comment before +// UniversalTersePrint() for how we define "tersely". +template +Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { + Strings result; + TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: + TersePrintPrefixToStrings(value, &result); + return result; +} +#endif // GTEST_HAS_TR1_TUPLE + +} // namespace internal + +template +::std::string PrintToString(const T& value) { + ::std::stringstream ss; + internal::UniversalTersePrinter::Print(value, &ss); + return ss.str(); +} + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ + +#if GTEST_HAS_PARAM_TEST + +namespace testing { +namespace internal { + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Outputs a message explaining invalid registration of different +// fixture class for the same test case. This may happen when +// TEST_P macro is used to define two tests with the same name +// but in different namespaces. +GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name, + const char* file, int line); + +template class ParamGeneratorInterface; +template class ParamGenerator; + +// Interface for iterating over elements provided by an implementation +// of ParamGeneratorInterface. +template +class ParamIteratorInterface { + public: + virtual ~ParamIteratorInterface() {} + // A pointer to the base generator instance. + // Used only for the purposes of iterator comparison + // to make sure that two iterators belong to the same generator. + virtual const ParamGeneratorInterface* BaseGenerator() const = 0; + // Advances iterator to point to the next element + // provided by the generator. The caller is responsible + // for not calling Advance() on an iterator equal to + // BaseGenerator()->End(). + virtual void Advance() = 0; + // Clones the iterator object. Used for implementing copy semantics + // of ParamIterator. + virtual ParamIteratorInterface* Clone() const = 0; + // Dereferences the current iterator and provides (read-only) access + // to the pointed value. It is the caller's responsibility not to call + // Current() on an iterator equal to BaseGenerator()->End(). + // Used for implementing ParamGenerator::operator*(). + virtual const T* Current() const = 0; + // Determines whether the given iterator and other point to the same + // element in the sequence generated by the generator. + // Used for implementing ParamGenerator::operator==(). + virtual bool Equals(const ParamIteratorInterface& other) const = 0; +}; + +// Class iterating over elements provided by an implementation of +// ParamGeneratorInterface. It wraps ParamIteratorInterface +// and implements the const forward iterator concept. +template +class ParamIterator { + public: + typedef T value_type; + typedef const T& reference; + typedef ptrdiff_t difference_type; + + // ParamIterator assumes ownership of the impl_ pointer. + ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {} + ParamIterator& operator=(const ParamIterator& other) { + if (this != &other) + impl_.reset(other.impl_->Clone()); + return *this; + } + + const T& operator*() const { return *impl_->Current(); } + const T* operator->() const { return impl_->Current(); } + // Prefix version of operator++. + ParamIterator& operator++() { + impl_->Advance(); + return *this; + } + // Postfix version of operator++. + ParamIterator operator++(int /*unused*/) { + ParamIteratorInterface* clone = impl_->Clone(); + impl_->Advance(); + return ParamIterator(clone); + } + bool operator==(const ParamIterator& other) const { + return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_); + } + bool operator!=(const ParamIterator& other) const { + return !(*this == other); + } + + private: + friend class ParamGenerator; + explicit ParamIterator(ParamIteratorInterface* impl) : impl_(impl) {} + scoped_ptr > impl_; +}; + +// ParamGeneratorInterface is the binary interface to access generators +// defined in other translation units. +template +class ParamGeneratorInterface { + public: + typedef T ParamType; + + virtual ~ParamGeneratorInterface() {} + + // Generator interface definition + virtual ParamIteratorInterface* Begin() const = 0; + virtual ParamIteratorInterface* End() const = 0; +}; + +// Wraps ParamGeneratorInterface and provides general generator syntax +// compatible with the STL Container concept. +// This class implements copy initialization semantics and the contained +// ParamGeneratorInterface instance is shared among all copies +// of the original object. This is possible because that instance is immutable. +template +class ParamGenerator { + public: + typedef ParamIterator iterator; + + explicit ParamGenerator(ParamGeneratorInterface* impl) : impl_(impl) {} + ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {} + + ParamGenerator& operator=(const ParamGenerator& other) { + impl_ = other.impl_; + return *this; + } + + iterator begin() const { return iterator(impl_->Begin()); } + iterator end() const { return iterator(impl_->End()); } + + private: + linked_ptr > impl_; +}; + +// Generates values from a range of two comparable values. Can be used to +// generate sequences of user-defined types that implement operator+() and +// operator<(). +// This class is used in the Range() function. +template +class RangeGenerator : public ParamGeneratorInterface { + public: + RangeGenerator(T begin, T end, IncrementT step) + : begin_(begin), end_(end), + step_(step), end_index_(CalculateEndIndex(begin, end, step)) {} + virtual ~RangeGenerator() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, begin_, 0, step_); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, end_, end_index_, step_); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, T value, int index, + IncrementT step) + : base_(base), value_(value), index_(index), step_(step) {} + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + virtual void Advance() { + value_ = value_ + step_; + index_++; + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const T* Current() const { return &value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const int other_index = + CheckedDowncastToActualType(&other)->index_; + return index_ == other_index; + } + + private: + Iterator(const Iterator& other) + : ParamIteratorInterface(), + base_(other.base_), value_(other.value_), index_(other.index_), + step_(other.step_) {} + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + T value_; + int index_; + const IncrementT step_; + }; // class RangeGenerator::Iterator + + static int CalculateEndIndex(const T& begin, + const T& end, + const IncrementT& step) { + int end_index = 0; + for (T i = begin; i < end; i = i + step) + end_index++; + return end_index; + } + + // No implementation - assignment is unsupported. + void operator=(const RangeGenerator& other); + + const T begin_; + const T end_; + const IncrementT step_; + // The index for the end() iterator. All the elements in the generated + // sequence are indexed (0-based) to aid iterator comparison. + const int end_index_; +}; // class RangeGenerator + + +// Generates values from a pair of STL-style iterators. Used in the +// ValuesIn() function. The elements are copied from the source range +// since the source can be located on the stack, and the generator +// is likely to persist beyond that stack frame. +template +class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { + public: + template + ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end) + : container_(begin, end) {} + virtual ~ValuesInIteratorRangeGenerator() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, container_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, container_.end()); + } + + private: + typedef typename ::std::vector ContainerType; + + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + typename ContainerType::const_iterator iterator) + : base_(base), iterator_(iterator) {} + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + virtual void Advance() { + ++iterator_; + value_.reset(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + // We need to use cached value referenced by iterator_ because *iterator_ + // can return a temporary object (and of type other then T), so just + // having "return &*iterator_;" doesn't work. + // value_ is updated here and not in Advance() because Advance() + // can advance iterator_ beyond the end of the range, and we cannot + // detect that fact. The client code, on the other hand, is + // responsible for not calling Current() on an out-of-range iterator. + virtual const T* Current() const { + if (value_.get() == NULL) + value_.reset(new T(*iterator_)); + return value_.get(); + } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + return iterator_ == + CheckedDowncastToActualType(&other)->iterator_; + } + + private: + Iterator(const Iterator& other) + // The explicit constructor call suppresses a false warning + // emitted by gcc when supplied with the -Wextra option. + : ParamIteratorInterface(), + base_(other.base_), + iterator_(other.iterator_) {} + + const ParamGeneratorInterface* const base_; + typename ContainerType::const_iterator iterator_; + // A cached value of *iterator_. We keep it here to allow access by + // pointer in the wrapping iterator's operator->(). + // value_ needs to be mutable to be accessed in Current(). + // Use of scoped_ptr helps manage cached value's lifetime, + // which is bound by the lifespan of the iterator itself. + mutable scoped_ptr value_; + }; // class ValuesInIteratorRangeGenerator::Iterator + + // No implementation - assignment is unsupported. + void operator=(const ValuesInIteratorRangeGenerator& other); + + const ContainerType container_; +}; // class ValuesInIteratorRangeGenerator + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Stores a parameter value and later creates tests parameterized with that +// value. +template +class ParameterizedTestFactory : public TestFactoryBase { + public: + typedef typename TestClass::ParamType ParamType; + explicit ParameterizedTestFactory(ParamType parameter) : + parameter_(parameter) {} + virtual Test* CreateTest() { + TestClass::SetParam(¶meter_); + return new TestClass(); + } + + private: + const ParamType parameter_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// TestMetaFactoryBase is a base class for meta-factories that create +// test factories for passing into MakeAndRegisterTestInfo function. +template +class TestMetaFactoryBase { + public: + virtual ~TestMetaFactoryBase() {} + + virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0; +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// TestMetaFactory creates test factories for passing into +// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives +// ownership of test factory pointer, same factory object cannot be passed +// into that method twice. But ParameterizedTestCaseInfo is going to call +// it for each Test/Parameter value combination. Thus it needs meta factory +// creator class. +template +class TestMetaFactory + : public TestMetaFactoryBase { + public: + typedef typename TestCase::ParamType ParamType; + + TestMetaFactory() {} + + virtual TestFactoryBase* CreateTestFactory(ParamType parameter) { + return new ParameterizedTestFactory(parameter); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseInfoBase is a generic interface +// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase +// accumulates test information provided by TEST_P macro invocations +// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations +// and uses that information to register all resulting test instances +// in RegisterTests method. The ParameterizeTestCaseRegistry class holds +// a collection of pointers to the ParameterizedTestCaseInfo objects +// and calls RegisterTests() on each of them when asked. +class ParameterizedTestCaseInfoBase { + public: + virtual ~ParameterizedTestCaseInfoBase() {} + + // Base part of test case name for display purposes. + virtual const string& GetTestCaseName() const = 0; + // Test case id to verify identity. + virtual TypeId GetTestCaseTypeId() const = 0; + // UnitTest class invokes this method to register tests in this + // test case right before running them in RUN_ALL_TESTS macro. + // This method should not be called more then once on any single + // instance of a ParameterizedTestCaseInfoBase derived class. + virtual void RegisterTests() = 0; + + protected: + ParameterizedTestCaseInfoBase() {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P +// macro invocations for a particular test case and generators +// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that +// test case. It registers tests with all values generated by all +// generators when asked. +template +class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { + public: + // ParamType and GeneratorCreationFunc are private types but are required + // for declarations of public methods AddTestPattern() and + // AddTestCaseInstantiation(). + typedef typename TestCase::ParamType ParamType; + // A function that returns an instance of appropriate generator type. + typedef ParamGenerator(GeneratorCreationFunc)(); + + explicit ParameterizedTestCaseInfo(const char* name) + : test_case_name_(name) {} + + // Test case base name for display purposes. + virtual const string& GetTestCaseName() const { return test_case_name_; } + // Test case id to verify identity. + virtual TypeId GetTestCaseTypeId() const { return GetTypeId(); } + // TEST_P macro uses AddTestPattern() to record information + // about a single test in a LocalTestInfo structure. + // test_case_name is the base name of the test case (without invocation + // prefix). test_base_name is the name of an individual test without + // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is + // test case base name and DoBar is test base name. + void AddTestPattern(const char* test_case_name, + const char* test_base_name, + TestMetaFactoryBase* meta_factory) { + tests_.push_back(linked_ptr(new TestInfo(test_case_name, + test_base_name, + meta_factory))); + } + // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information + // about a generator. + int AddTestCaseInstantiation(const string& instantiation_name, + GeneratorCreationFunc* func, + const char* /* file */, + int /* line */) { + instantiations_.push_back(::std::make_pair(instantiation_name, func)); + return 0; // Return value used only to run this method in namespace scope. + } + // UnitTest class invokes this method to register tests in this test case + // test cases right before running tests in RUN_ALL_TESTS macro. + // This method should not be called more then once on any single + // instance of a ParameterizedTestCaseInfoBase derived class. + // UnitTest has a guard to prevent from calling this method more then once. + virtual void RegisterTests() { + for (typename TestInfoContainer::iterator test_it = tests_.begin(); + test_it != tests_.end(); ++test_it) { + linked_ptr test_info = *test_it; + for (typename InstantiationContainer::iterator gen_it = + instantiations_.begin(); gen_it != instantiations_.end(); + ++gen_it) { + const string& instantiation_name = gen_it->first; + ParamGenerator generator((*gen_it->second)()); + + string test_case_name; + if ( !instantiation_name.empty() ) + test_case_name = instantiation_name + "/"; + test_case_name += test_info->test_case_base_name; + + int i = 0; + for (typename ParamGenerator::iterator param_it = + generator.begin(); + param_it != generator.end(); ++param_it, ++i) { + Message test_name_stream; + test_name_stream << test_info->test_base_name << "/" << i; + MakeAndRegisterTestInfo( + test_case_name.c_str(), + test_name_stream.GetString().c_str(), + NULL, // No type parameter. + PrintToString(*param_it).c_str(), + GetTestCaseTypeId(), + TestCase::SetUpTestCase, + TestCase::TearDownTestCase, + test_info->test_meta_factory->CreateTestFactory(*param_it)); + } // for param_it + } // for gen_it + } // for test_it + } // RegisterTests + + private: + // LocalTestInfo structure keeps information about a single test registered + // with TEST_P macro. + struct TestInfo { + TestInfo(const char* a_test_case_base_name, + const char* a_test_base_name, + TestMetaFactoryBase* a_test_meta_factory) : + test_case_base_name(a_test_case_base_name), + test_base_name(a_test_base_name), + test_meta_factory(a_test_meta_factory) {} + + const string test_case_base_name; + const string test_base_name; + const scoped_ptr > test_meta_factory; + }; + typedef ::std::vector > TestInfoContainer; + // Keeps pairs of + // received from INSTANTIATE_TEST_CASE_P macros. + typedef ::std::vector > + InstantiationContainer; + + const string test_case_name_; + TestInfoContainer tests_; + InstantiationContainer instantiations_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo); +}; // class ParameterizedTestCaseInfo + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase +// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P +// macros use it to locate their corresponding ParameterizedTestCaseInfo +// descriptors. +class ParameterizedTestCaseRegistry { + public: + ParameterizedTestCaseRegistry() {} + ~ParameterizedTestCaseRegistry() { + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + delete *it; + } + } + + // Looks up or creates and returns a structure containing information about + // tests and instantiations of a particular test case. + template + ParameterizedTestCaseInfo* GetTestCasePatternHolder( + const char* test_case_name, + const char* file, + int line) { + ParameterizedTestCaseInfo* typed_test_info = NULL; + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + if ((*it)->GetTestCaseName() == test_case_name) { + if ((*it)->GetTestCaseTypeId() != GetTypeId()) { + // Complain about incorrect usage of Google Test facilities + // and terminate the program since we cannot guaranty correct + // test case setup and tear-down in this case. + ReportInvalidTestCaseType(test_case_name, file, line); + posix::Abort(); + } else { + // At this point we are sure that the object we found is of the same + // type we are looking for, so we downcast it to that type + // without further checks. + typed_test_info = CheckedDowncastToActualType< + ParameterizedTestCaseInfo >(*it); + } + break; + } + } + if (typed_test_info == NULL) { + typed_test_info = new ParameterizedTestCaseInfo(test_case_name); + test_case_infos_.push_back(typed_test_info); + } + return typed_test_info; + } + void RegisterTests() { + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + (*it)->RegisterTests(); + } + } + + private: + typedef ::std::vector TestCaseInfoContainer; + + TestCaseInfoContainer test_case_infos_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry); +}; + +} // namespace internal +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +// This file was GENERATED by command: +// pump.py gtest-param-util-generated.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: vladl@google.com (Vlad Losev) + +// Type and function utilities for implementing parameterized tests. +// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +// Currently Google Test supports at most 50 arguments in Values, +// and at most 10 arguments in Combine. Please contact +// googletestframework@googlegroups.com if you need more. +// Please note that the number of arguments to Combine is limited +// by the maximum arity of the implementation of tr1::tuple which is +// currently set at 10. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. + +#if GTEST_HAS_PARAM_TEST + +namespace testing { + +// Forward declarations of ValuesIn(), which is implemented in +// include/gtest/gtest-param-test.h. +template +internal::ParamGenerator< + typename ::testing::internal::IteratorTraits::value_type> +ValuesIn(ForwardIterator begin, ForwardIterator end); + +template +internal::ParamGenerator ValuesIn(const T (&array)[N]); + +template +internal::ParamGenerator ValuesIn( + const Container& container); + +namespace internal { + +// Used in the Values() function to provide polymorphic capabilities. +template +class ValueArray1 { + public: + explicit ValueArray1(T1 v1) : v1_(v1) {} + + template + operator ParamGenerator() const { return ValuesIn(&v1_, &v1_ + 1); } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray1& other); + + const T1 v1_; +}; + +template +class ValueArray2 { + public: + ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray2& other); + + const T1 v1_; + const T2 v2_; +}; + +template +class ValueArray3 { + public: + ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray3& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; +}; + +template +class ValueArray4 { + public: + ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray4& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; +}; + +template +class ValueArray5 { + public: + ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray5& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; +}; + +template +class ValueArray6 { + public: + ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray6& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; +}; + +template +class ValueArray7 { + public: + ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray7& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; +}; + +template +class ValueArray8 { + public: + ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray8& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; +}; + +template +class ValueArray9 { + public: + ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray9& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; +}; + +template +class ValueArray10 { + public: + ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray10& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; +}; + +template +class ValueArray11 { + public: + ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray11& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; +}; + +template +class ValueArray12 { + public: + ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray12& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; +}; + +template +class ValueArray13 { + public: + ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray13& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; +}; + +template +class ValueArray14 { + public: + ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray14& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; +}; + +template +class ValueArray15 { + public: + ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray15& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; +}; + +template +class ValueArray16 { + public: + ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray16& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; +}; + +template +class ValueArray17 { + public: + ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray17& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; +}; + +template +class ValueArray18 { + public: + ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray18& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; +}; + +template +class ValueArray19 { + public: + ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray19& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; +}; + +template +class ValueArray20 { + public: + ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray20& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; +}; + +template +class ValueArray21 { + public: + ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray21& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; +}; + +template +class ValueArray22 { + public: + ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray22& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; +}; + +template +class ValueArray23 { + public: + ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray23& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; +}; + +template +class ValueArray24 { + public: + ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray24& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; +}; + +template +class ValueArray25 { + public: + ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray25& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; +}; + +template +class ValueArray26 { + public: + ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray26& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; +}; + +template +class ValueArray27 { + public: + ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray27& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; +}; + +template +class ValueArray28 { + public: + ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray28& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; +}; + +template +class ValueArray29 { + public: + ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray29& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; +}; + +template +class ValueArray30 { + public: + ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray30& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; +}; + +template +class ValueArray31 { + public: + ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray31& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; +}; + +template +class ValueArray32 { + public: + ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray32& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; +}; + +template +class ValueArray33 { + public: + ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, + T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray33& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; +}; + +template +class ValueArray34 { + public: + ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray34& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; +}; + +template +class ValueArray35 { + public: + ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), + v32_(v32), v33_(v33), v34_(v34), v35_(v35) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray35& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; +}; + +template +class ValueArray36 { + public: + ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), + v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray36& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; +}; + +template +class ValueArray37 { + public: + ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), + v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), + v36_(v36), v37_(v37) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray37& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; +}; + +template +class ValueArray38 { + public: + ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray38& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; +}; + +template +class ValueArray39 { + public: + ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray39& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; +}; + +template +class ValueArray40 { + public: + ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), + v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), + v40_(v40) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray40& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; +}; + +template +class ValueArray41 { + public: + ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, + T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray41& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; +}; + +template +class ValueArray42 { + public: + ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray42& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; +}; + +template +class ValueArray43 { + public: + ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), + v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), + v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray43& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; +}; + +template +class ValueArray44 { + public: + ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), + v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), + v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), + v43_(v43), v44_(v44) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray44& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; +}; + +template +class ValueArray45 { + public: + ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), + v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), + v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), + v42_(v42), v43_(v43), v44_(v44), v45_(v45) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray45& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; +}; + +template +class ValueArray46 { + public: + ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), + v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray46& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; +}; + +template +class ValueArray47 { + public: + ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), + v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46), + v47_(v47) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray47& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; +}; + +template +class ValueArray48 { + public: + ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), + v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), + v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), + v46_(v46), v47_(v47), v48_(v48) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_), + static_cast(v48_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray48& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; +}; + +template +class ValueArray49 { + public: + ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, + T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), + v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_), + static_cast(v48_), static_cast(v49_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray49& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; + const T49 v49_; +}; + +template +class ValueArray50 { + public: + ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49, + T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), + v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_), + static_cast(v48_), static_cast(v49_), static_cast(v50_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray50& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; + const T49 v49_; + const T50 v50_; +}; + +# if GTEST_HAS_COMBINE +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Generates values from the Cartesian product of values produced +// by the argument generators. +// +template +class CartesianProductGenerator2 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator2(const ParamGenerator& g1, + const ParamGenerator& g2) + : g1_(g1), g2_(g2) {} + virtual ~CartesianProductGenerator2() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current2_; + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + ParamType current_value_; + }; // class CartesianProductGenerator2::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator2& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; +}; // class CartesianProductGenerator2 + + +template +class CartesianProductGenerator3 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator3(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3) + : g1_(g1), g2_(g2), g3_(g3) {} + virtual ~CartesianProductGenerator3() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current3_; + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + ParamType current_value_; + }; // class CartesianProductGenerator3::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator3& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; +}; // class CartesianProductGenerator3 + + +template +class CartesianProductGenerator4 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator4(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} + virtual ~CartesianProductGenerator4() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current4_; + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + ParamType current_value_; + }; // class CartesianProductGenerator4::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator4& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; +}; // class CartesianProductGenerator4 + + +template +class CartesianProductGenerator5 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator5(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} + virtual ~CartesianProductGenerator5() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current5_; + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + ParamType current_value_; + }; // class CartesianProductGenerator5::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator5& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; +}; // class CartesianProductGenerator5 + + +template +class CartesianProductGenerator6 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator6(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} + virtual ~CartesianProductGenerator6() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current6_; + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + ParamType current_value_; + }; // class CartesianProductGenerator6::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator6& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; +}; // class CartesianProductGenerator6 + + +template +class CartesianProductGenerator7 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator7(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} + virtual ~CartesianProductGenerator7() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current7_; + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + ParamType current_value_; + }; // class CartesianProductGenerator7::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator7& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; +}; // class CartesianProductGenerator7 + + +template +class CartesianProductGenerator8 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator8(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), + g8_(g8) {} + virtual ~CartesianProductGenerator8() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current8_; + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + ParamType current_value_; + }; // class CartesianProductGenerator8::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator8& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; +}; // class CartesianProductGenerator8 + + +template +class CartesianProductGenerator9 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator9(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8, const ParamGenerator& g9) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9) {} + virtual ~CartesianProductGenerator9() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end(), g9_, g9_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8, + const ParamGenerator& g9, + const typename ParamGenerator::iterator& current9) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8), + begin9_(g9.begin()), end9_(g9.end()), current9_(current9) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current9_; + if (current9_ == end9_) { + current9_ = begin9_; + ++current8_; + } + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_ && + current9_ == typed_other->current9_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_), + begin9_(other.begin9_), + end9_(other.end9_), + current9_(other.current9_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_, + *current9_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_ || + current9_ == end9_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + const typename ParamGenerator::iterator begin9_; + const typename ParamGenerator::iterator end9_; + typename ParamGenerator::iterator current9_; + ParamType current_value_; + }; // class CartesianProductGenerator9::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator9& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; + const ParamGenerator g9_; +}; // class CartesianProductGenerator9 + + +template +class CartesianProductGenerator10 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator10(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8, const ParamGenerator& g9, + const ParamGenerator& g10) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9), g10_(g10) {} + virtual ~CartesianProductGenerator10() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end(), g9_, g9_.end(), g10_, g10_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8, + const ParamGenerator& g9, + const typename ParamGenerator::iterator& current9, + const ParamGenerator& g10, + const typename ParamGenerator::iterator& current10) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8), + begin9_(g9.begin()), end9_(g9.end()), current9_(current9), + begin10_(g10.begin()), end10_(g10.end()), current10_(current10) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current10_; + if (current10_ == end10_) { + current10_ = begin10_; + ++current9_; + } + if (current9_ == end9_) { + current9_ = begin9_; + ++current8_; + } + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_ && + current9_ == typed_other->current9_ && + current10_ == typed_other->current10_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_), + begin9_(other.begin9_), + end9_(other.end9_), + current9_(other.current9_), + begin10_(other.begin10_), + end10_(other.end10_), + current10_(other.current10_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_, + *current9_, *current10_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_ || + current9_ == end9_ || + current10_ == end10_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + const typename ParamGenerator::iterator begin9_; + const typename ParamGenerator::iterator end9_; + typename ParamGenerator::iterator current9_; + const typename ParamGenerator::iterator begin10_; + const typename ParamGenerator::iterator end10_; + typename ParamGenerator::iterator current10_; + ParamType current_value_; + }; // class CartesianProductGenerator10::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator10& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; + const ParamGenerator g9_; + const ParamGenerator g10_; +}; // class CartesianProductGenerator10 + + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Helper classes providing Combine() with polymorphic features. They allow +// casting CartesianProductGeneratorN to ParamGenerator if T is +// convertible to U. +// +template +class CartesianProductHolder2 { + public: +CartesianProductHolder2(const Generator1& g1, const Generator2& g2) + : g1_(g1), g2_(g2) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator2( + static_cast >(g1_), + static_cast >(g2_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder2& other); + + const Generator1 g1_; + const Generator2 g2_; +}; // class CartesianProductHolder2 + +template +class CartesianProductHolder3 { + public: +CartesianProductHolder3(const Generator1& g1, const Generator2& g2, + const Generator3& g3) + : g1_(g1), g2_(g2), g3_(g3) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator3( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder3& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; +}; // class CartesianProductHolder3 + +template +class CartesianProductHolder4 { + public: +CartesianProductHolder4(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator4( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder4& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; +}; // class CartesianProductHolder4 + +template +class CartesianProductHolder5 { + public: +CartesianProductHolder5(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator5( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder5& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; +}; // class CartesianProductHolder5 + +template +class CartesianProductHolder6 { + public: +CartesianProductHolder6(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator6( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder6& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; +}; // class CartesianProductHolder6 + +template +class CartesianProductHolder7 { + public: +CartesianProductHolder7(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator7( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder7& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; +}; // class CartesianProductHolder7 + +template +class CartesianProductHolder8 { + public: +CartesianProductHolder8(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), + g8_(g8) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator8( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder8& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; +}; // class CartesianProductHolder8 + +template +class CartesianProductHolder9 { + public: +CartesianProductHolder9(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8, + const Generator9& g9) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator9( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_), + static_cast >(g9_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder9& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; + const Generator9 g9_; +}; // class CartesianProductHolder9 + +template +class CartesianProductHolder10 { + public: +CartesianProductHolder10(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8, + const Generator9& g9, const Generator10& g10) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9), g10_(g10) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator10( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_), + static_cast >(g9_), + static_cast >(g10_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder10& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; + const Generator9 g9_; + const Generator10 g10_; +}; // class CartesianProductHolder10 + +# endif // GTEST_HAS_COMBINE + +} // namespace internal +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ + +#if GTEST_HAS_PARAM_TEST + +namespace testing { + +// Functions producing parameter generators. +// +// Google Test uses these generators to produce parameters for value- +// parameterized tests. When a parameterized test case is instantiated +// with a particular generator, Google Test creates and runs tests +// for each element in the sequence produced by the generator. +// +// In the following sample, tests from test case FooTest are instantiated +// each three times with parameter values 3, 5, and 8: +// +// class FooTest : public TestWithParam { ... }; +// +// TEST_P(FooTest, TestThis) { +// } +// TEST_P(FooTest, TestThat) { +// } +// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8)); +// + +// Range() returns generators providing sequences of values in a range. +// +// Synopsis: +// Range(start, end) +// - returns a generator producing a sequence of values {start, start+1, +// start+2, ..., }. +// Range(start, end, step) +// - returns a generator producing a sequence of values {start, start+step, +// start+step+step, ..., }. +// Notes: +// * The generated sequences never include end. For example, Range(1, 5) +// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2) +// returns a generator producing {1, 3, 5, 7}. +// * start and end must have the same type. That type may be any integral or +// floating-point type or a user defined type satisfying these conditions: +// * It must be assignable (have operator=() defined). +// * It must have operator+() (operator+(int-compatible type) for +// two-operand version). +// * It must have operator<() defined. +// Elements in the resulting sequences will also have that type. +// * Condition start < end must be satisfied in order for resulting sequences +// to contain any elements. +// +template +internal::ParamGenerator Range(T start, T end, IncrementT step) { + return internal::ParamGenerator( + new internal::RangeGenerator(start, end, step)); +} + +template +internal::ParamGenerator Range(T start, T end) { + return Range(start, end, 1); +} + +// ValuesIn() function allows generation of tests with parameters coming from +// a container. +// +// Synopsis: +// ValuesIn(const T (&array)[N]) +// - returns a generator producing sequences with elements from +// a C-style array. +// ValuesIn(const Container& container) +// - returns a generator producing sequences with elements from +// an STL-style container. +// ValuesIn(Iterator begin, Iterator end) +// - returns a generator producing sequences with elements from +// a range [begin, end) defined by a pair of STL-style iterators. These +// iterators can also be plain C pointers. +// +// Please note that ValuesIn copies the values from the containers +// passed in and keeps them to generate tests in RUN_ALL_TESTS(). +// +// Examples: +// +// This instantiates tests from test case StringTest +// each with C-string values of "foo", "bar", and "baz": +// +// const char* strings[] = {"foo", "bar", "baz"}; +// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings)); +// +// This instantiates tests from test case StlStringTest +// each with STL strings with values "a" and "b": +// +// ::std::vector< ::std::string> GetParameterStrings() { +// ::std::vector< ::std::string> v; +// v.push_back("a"); +// v.push_back("b"); +// return v; +// } +// +// INSTANTIATE_TEST_CASE_P(CharSequence, +// StlStringTest, +// ValuesIn(GetParameterStrings())); +// +// +// This will also instantiate tests from CharTest +// each with parameter values 'a' and 'b': +// +// ::std::list GetParameterChars() { +// ::std::list list; +// list.push_back('a'); +// list.push_back('b'); +// return list; +// } +// ::std::list l = GetParameterChars(); +// INSTANTIATE_TEST_CASE_P(CharSequence2, +// CharTest, +// ValuesIn(l.begin(), l.end())); +// +template +internal::ParamGenerator< + typename ::testing::internal::IteratorTraits::value_type> +ValuesIn(ForwardIterator begin, ForwardIterator end) { + typedef typename ::testing::internal::IteratorTraits + ::value_type ParamType; + return internal::ParamGenerator( + new internal::ValuesInIteratorRangeGenerator(begin, end)); +} + +template +internal::ParamGenerator ValuesIn(const T (&array)[N]) { + return ValuesIn(array, array + N); +} + +template +internal::ParamGenerator ValuesIn( + const Container& container) { + return ValuesIn(container.begin(), container.end()); +} + +// Values() allows generating tests from explicitly specified list of +// parameters. +// +// Synopsis: +// Values(T v1, T v2, ..., T vN) +// - returns a generator producing sequences with elements v1, v2, ..., vN. +// +// For example, this instantiates tests from test case BarTest each +// with values "one", "two", and "three": +// +// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three")); +// +// This instantiates tests from test case BazTest each with values 1, 2, 3.5. +// The exact type of values will depend on the type of parameter in BazTest. +// +// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5)); +// +// Currently, Values() supports from 1 to 50 parameters. +// +template +internal::ValueArray1 Values(T1 v1) { + return internal::ValueArray1(v1); +} + +template +internal::ValueArray2 Values(T1 v1, T2 v2) { + return internal::ValueArray2(v1, v2); +} + +template +internal::ValueArray3 Values(T1 v1, T2 v2, T3 v3) { + return internal::ValueArray3(v1, v2, v3); +} + +template +internal::ValueArray4 Values(T1 v1, T2 v2, T3 v3, T4 v4) { + return internal::ValueArray4(v1, v2, v3, v4); +} + +template +internal::ValueArray5 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5) { + return internal::ValueArray5(v1, v2, v3, v4, v5); +} + +template +internal::ValueArray6 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6) { + return internal::ValueArray6(v1, v2, v3, v4, v5, v6); +} + +template +internal::ValueArray7 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7) { + return internal::ValueArray7(v1, v2, v3, v4, v5, + v6, v7); +} + +template +internal::ValueArray8 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) { + return internal::ValueArray8(v1, v2, v3, v4, + v5, v6, v7, v8); +} + +template +internal::ValueArray9 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) { + return internal::ValueArray9(v1, v2, v3, + v4, v5, v6, v7, v8, v9); +} + +template +internal::ValueArray10 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) { + return internal::ValueArray10(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10); +} + +template +internal::ValueArray11 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11) { + return internal::ValueArray11(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11); +} + +template +internal::ValueArray12 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12) { + return internal::ValueArray12(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12); +} + +template +internal::ValueArray13 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13) { + return internal::ValueArray13(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13); +} + +template +internal::ValueArray14 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) { + return internal::ValueArray14(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14); +} + +template +internal::ValueArray15 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) { + return internal::ValueArray15(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15); +} + +template +internal::ValueArray16 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16) { + return internal::ValueArray16(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16); +} + +template +internal::ValueArray17 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17) { + return internal::ValueArray17(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17); +} + +template +internal::ValueArray18 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18) { + return internal::ValueArray18(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18); +} + +template +internal::ValueArray19 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) { + return internal::ValueArray19(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19); +} + +template +internal::ValueArray20 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) { + return internal::ValueArray20(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20); +} + +template +internal::ValueArray21 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) { + return internal::ValueArray21(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21); +} + +template +internal::ValueArray22 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22) { + return internal::ValueArray22(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22); +} + +template +internal::ValueArray23 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23) { + return internal::ValueArray23(v1, v2, v3, + v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23); +} + +template +internal::ValueArray24 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24) { + return internal::ValueArray24(v1, v2, + v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, + v19, v20, v21, v22, v23, v24); +} + +template +internal::ValueArray25 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, + T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, + T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) { + return internal::ValueArray25(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, + v18, v19, v20, v21, v22, v23, v24, v25); +} + +template +internal::ValueArray26 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26) { + return internal::ValueArray26(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26); +} + +template +internal::ValueArray27 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27) { + return internal::ValueArray27(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27); +} + +template +internal::ValueArray28 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28) { + return internal::ValueArray28(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, + v28); +} + +template +internal::ValueArray29 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29) { + return internal::ValueArray29(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, + v27, v28, v29); +} + +template +internal::ValueArray30 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) { + return internal::ValueArray30(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, + v26, v27, v28, v29, v30); +} + +template +internal::ValueArray31 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) { + return internal::ValueArray31(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, + v25, v26, v27, v28, v29, v30, v31); +} + +template +internal::ValueArray32 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32) { + return internal::ValueArray32(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32); +} + +template +internal::ValueArray33 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33) { + return internal::ValueArray33(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33); +} + +template +internal::ValueArray34 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, + T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, + T31 v31, T32 v32, T33 v33, T34 v34) { + return internal::ValueArray34(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, + v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34); +} + +template +internal::ValueArray35 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) { + return internal::ValueArray35(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, + v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35); +} + +template +internal::ValueArray36 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) { + return internal::ValueArray36(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36); +} + +template +internal::ValueArray37 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37) { + return internal::ValueArray37(v1, v2, v3, + v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36, v37); +} + +template +internal::ValueArray38 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37, T38 v38) { + return internal::ValueArray38(v1, v2, + v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, + v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, + v33, v34, v35, v36, v37, v38); +} + +template +internal::ValueArray39 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37, T38 v38, T39 v39) { + return internal::ValueArray39(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, + v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, + v32, v33, v34, v35, v36, v37, v38, v39); +} + +template +internal::ValueArray40 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, + T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, + T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, + T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, + T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) { + return internal::ValueArray40(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, + v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40); +} + +template +internal::ValueArray41 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) { + return internal::ValueArray41(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, + v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41); +} + +template +internal::ValueArray42 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42) { + return internal::ValueArray42(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, + v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, + v42); +} + +template +internal::ValueArray43 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43) { + return internal::ValueArray43(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, + v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, + v41, v42, v43); +} + +template +internal::ValueArray44 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44) { + return internal::ValueArray44(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, + v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, + v40, v41, v42, v43, v44); +} + +template +internal::ValueArray45 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, + T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, + T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) { + return internal::ValueArray45(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, + v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, + v39, v40, v41, v42, v43, v44, v45); +} + +template +internal::ValueArray46 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) { + return internal::ValueArray46(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, + v38, v39, v40, v41, v42, v43, v44, v45, v46); +} + +template +internal::ValueArray47 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) { + return internal::ValueArray47(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, + v38, v39, v40, v41, v42, v43, v44, v45, v46, v47); +} + +template +internal::ValueArray48 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, + T48 v48) { + return internal::ValueArray48(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, + v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, + v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48); +} + +template +internal::ValueArray49 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, + T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, + T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, + T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, + T47 v47, T48 v48, T49 v49) { + return internal::ValueArray49(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, + v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, + v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49); +} + +template +internal::ValueArray50 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, + T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, + T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) { + return internal::ValueArray50(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, + v48, v49, v50); +} + +// Bool() allows generating tests with parameters in a set of (false, true). +// +// Synopsis: +// Bool() +// - returns a generator producing sequences with elements {false, true}. +// +// It is useful when testing code that depends on Boolean flags. Combinations +// of multiple flags can be tested when several Bool()'s are combined using +// Combine() function. +// +// In the following example all tests in the test case FlagDependentTest +// will be instantiated twice with parameters false and true. +// +// class FlagDependentTest : public testing::TestWithParam { +// virtual void SetUp() { +// external_flag = GetParam(); +// } +// } +// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool()); +// +inline internal::ParamGenerator Bool() { + return Values(false, true); +} + +# if GTEST_HAS_COMBINE +// Combine() allows the user to combine two or more sequences to produce +// values of a Cartesian product of those sequences' elements. +// +// Synopsis: +// Combine(gen1, gen2, ..., genN) +// - returns a generator producing sequences with elements coming from +// the Cartesian product of elements from the sequences generated by +// gen1, gen2, ..., genN. The sequence elements will have a type of +// tuple where T1, T2, ..., TN are the types +// of elements from sequences produces by gen1, gen2, ..., genN. +// +// Combine can have up to 10 arguments. This number is currently limited +// by the maximum number of elements in the tuple implementation used by Google +// Test. +// +// Example: +// +// This will instantiate tests in test case AnimalTest each one with +// the parameter values tuple("cat", BLACK), tuple("cat", WHITE), +// tuple("dog", BLACK), and tuple("dog", WHITE): +// +// enum Color { BLACK, GRAY, WHITE }; +// class AnimalTest +// : public testing::TestWithParam > {...}; +// +// TEST_P(AnimalTest, AnimalLooksNice) {...} +// +// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest, +// Combine(Values("cat", "dog"), +// Values(BLACK, WHITE))); +// +// This will instantiate tests in FlagDependentTest with all variations of two +// Boolean flags: +// +// class FlagDependentTest +// : public testing::TestWithParam > { +// virtual void SetUp() { +// // Assigns external_flag_1 and external_flag_2 values from the tuple. +// tie(external_flag_1, external_flag_2) = GetParam(); +// } +// }; +// +// TEST_P(FlagDependentTest, TestFeature1) { +// // Test your code using external_flag_1 and external_flag_2 here. +// } +// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest, +// Combine(Bool(), Bool())); +// +template +internal::CartesianProductHolder2 Combine( + const Generator1& g1, const Generator2& g2) { + return internal::CartesianProductHolder2( + g1, g2); +} + +template +internal::CartesianProductHolder3 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3) { + return internal::CartesianProductHolder3( + g1, g2, g3); +} + +template +internal::CartesianProductHolder4 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4) { + return internal::CartesianProductHolder4( + g1, g2, g3, g4); +} + +template +internal::CartesianProductHolder5 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5) { + return internal::CartesianProductHolder5( + g1, g2, g3, g4, g5); +} + +template +internal::CartesianProductHolder6 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6) { + return internal::CartesianProductHolder6( + g1, g2, g3, g4, g5, g6); +} + +template +internal::CartesianProductHolder7 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7) { + return internal::CartesianProductHolder7( + g1, g2, g3, g4, g5, g6, g7); +} + +template +internal::CartesianProductHolder8 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8) { + return internal::CartesianProductHolder8( + g1, g2, g3, g4, g5, g6, g7, g8); +} + +template +internal::CartesianProductHolder9 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8, const Generator9& g9) { + return internal::CartesianProductHolder9( + g1, g2, g3, g4, g5, g6, g7, g8, g9); +} + +template +internal::CartesianProductHolder10 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8, const Generator9& g9, + const Generator10& g10) { + return internal::CartesianProductHolder10( + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10); +} +# endif // GTEST_HAS_COMBINE + + + +# define TEST_P(test_case_name, test_name) \ + class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ + : public test_case_name { \ + public: \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \ + virtual void TestBody(); \ + private: \ + static int AddToRegistry() { \ + ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ + GetTestCasePatternHolder(\ + #test_case_name, __FILE__, __LINE__)->AddTestPattern(\ + #test_case_name, \ + #test_name, \ + new ::testing::internal::TestMetaFactory< \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \ + return 0; \ + } \ + static int gtest_registering_dummy_; \ + GTEST_DISALLOW_COPY_AND_ASSIGN_(\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ + }; \ + int GTEST_TEST_CLASS_NAME_(test_case_name, \ + test_name)::gtest_registering_dummy_ = \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \ + void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() + +# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ + ::testing::internal::ParamGenerator \ + gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \ + int gtest_##prefix##test_case_name##_dummy_ = \ + ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ + GetTestCasePatternHolder(\ + #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\ + #prefix, \ + >est_##prefix##test_case_name##_EvalGenerator_, \ + __FILE__, __LINE__) + +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +// Copyright 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// Google C++ Testing Framework definitions useful in production code. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ + +// When you need to test the private or protected members of a class, +// use the FRIEND_TEST macro to declare your tests as friends of the +// class. For example: +// +// class MyClass { +// private: +// void MyMethod(); +// FRIEND_TEST(MyClassTest, MyMethod); +// }; +// +// class MyClassTest : public testing::Test { +// // ... +// }; +// +// TEST_F(MyClassTest, MyMethod) { +// // Can call MyClass::MyMethod() here. +// } + +#define FRIEND_TEST(test_case_name, test_name)\ +friend class test_case_name##_##test_name##_Test + +#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: mheule@google.com (Markus Heule) +// + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ + +#include +#include + +namespace testing { + +// A copyable object representing the result of a test part (i.e. an +// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()). +// +// Don't inherit from TestPartResult as its destructor is not virtual. +class GTEST_API_ TestPartResult { + public: + // The possible outcomes of a test part (i.e. an assertion or an + // explicit SUCCEED(), FAIL(), or ADD_FAILURE()). + enum Type { + kSuccess, // Succeeded. + kNonFatalFailure, // Failed but the test can continue. + kFatalFailure // Failed and the test should be terminated. + }; + + // C'tor. TestPartResult does NOT have a default constructor. + // Always use this constructor (with parameters) to create a + // TestPartResult object. + TestPartResult(Type a_type, + const char* a_file_name, + int a_line_number, + const char* a_message) + : type_(a_type), + file_name_(a_file_name == NULL ? "" : a_file_name), + line_number_(a_line_number), + summary_(ExtractSummary(a_message)), + message_(a_message) { + } + + // Gets the outcome of the test part. + Type type() const { return type_; } + + // Gets the name of the source file where the test part took place, or + // NULL if it's unknown. + const char* file_name() const { + return file_name_.empty() ? NULL : file_name_.c_str(); + } + + // Gets the line in the source file where the test part took place, + // or -1 if it's unknown. + int line_number() const { return line_number_; } + + // Gets the summary of the failure message. + const char* summary() const { return summary_.c_str(); } + + // Gets the message associated with the test part. + const char* message() const { return message_.c_str(); } + + // Returns true iff the test part passed. + bool passed() const { return type_ == kSuccess; } + + // Returns true iff the test part failed. + bool failed() const { return type_ != kSuccess; } + + // Returns true iff the test part non-fatally failed. + bool nonfatally_failed() const { return type_ == kNonFatalFailure; } + + // Returns true iff the test part fatally failed. + bool fatally_failed() const { return type_ == kFatalFailure; } + + private: + Type type_; + + // Gets the summary of the failure message by omitting the stack + // trace in it. + static std::string ExtractSummary(const char* message); + + // The name of the source file where the test part took place, or + // "" if the source file is unknown. + std::string file_name_; + // The line in the source file where the test part took place, or -1 + // if the line number is unknown. + int line_number_; + std::string summary_; // The test failure summary. + std::string message_; // The test failure message. +}; + +// Prints a TestPartResult object. +std::ostream& operator<<(std::ostream& os, const TestPartResult& result); + +// An array of TestPartResult objects. +// +// Don't inherit from TestPartResultArray as its destructor is not +// virtual. +class GTEST_API_ TestPartResultArray { + public: + TestPartResultArray() {} + + // Appends the given TestPartResult to the array. + void Append(const TestPartResult& result); + + // Returns the TestPartResult at the given index (0-based). + const TestPartResult& GetTestPartResult(int index) const; + + // Returns the number of TestPartResult objects in the array. + int size() const; + + private: + std::vector array_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray); +}; + +// This interface knows how to report a test part result. +class TestPartResultReporterInterface { + public: + virtual ~TestPartResultReporterInterface() {} + + virtual void ReportTestPartResult(const TestPartResult& result) = 0; +}; + +namespace internal { + +// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a +// statement generates new fatal failures. To do so it registers itself as the +// current test part result reporter. Besides checking if fatal failures were +// reported, it only delegates the reporting to the former result reporter. +// The original result reporter is restored in the destructor. +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +class GTEST_API_ HasNewFatalFailureHelper + : public TestPartResultReporterInterface { + public: + HasNewFatalFailureHelper(); + virtual ~HasNewFatalFailureHelper(); + virtual void ReportTestPartResult(const TestPartResult& result); + bool has_new_fatal_failure() const { return has_new_fatal_failure_; } + private: + bool has_new_fatal_failure_; + TestPartResultReporterInterface* original_reporter_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper); +}; + +} // namespace internal + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ + +// This header implements typed tests and type-parameterized tests. + +// Typed (aka type-driven) tests repeat the same test for types in a +// list. You must know which types you want to test with when writing +// typed tests. Here's how you do it: + +#if 0 + +// First, define a fixture class template. It should be parameterized +// by a type. Remember to derive it from testing::Test. +template +class FooTest : public testing::Test { + public: + ... + typedef std::list List; + static T shared_; + T value_; +}; + +// Next, associate a list of types with the test case, which will be +// repeated for each type in the list. The typedef is necessary for +// the macro to parse correctly. +typedef testing::Types MyTypes; +TYPED_TEST_CASE(FooTest, MyTypes); + +// If the type list contains only one type, you can write that type +// directly without Types<...>: +// TYPED_TEST_CASE(FooTest, int); + +// Then, use TYPED_TEST() instead of TEST_F() to define as many typed +// tests for this test case as you want. +TYPED_TEST(FooTest, DoesBlah) { + // Inside a test, refer to TypeParam to get the type parameter. + // Since we are inside a derived class template, C++ requires use to + // visit the members of FooTest via 'this'. + TypeParam n = this->value_; + + // To visit static members of the fixture, add the TestFixture:: + // prefix. + n += TestFixture::shared_; + + // To refer to typedefs in the fixture, add the "typename + // TestFixture::" prefix. + typename TestFixture::List values; + values.push_back(n); + ... +} + +TYPED_TEST(FooTest, HasPropertyA) { ... } + +#endif // 0 + +// Type-parameterized tests are abstract test patterns parameterized +// by a type. Compared with typed tests, type-parameterized tests +// allow you to define the test pattern without knowing what the type +// parameters are. The defined pattern can be instantiated with +// different types any number of times, in any number of translation +// units. +// +// If you are designing an interface or concept, you can define a +// suite of type-parameterized tests to verify properties that any +// valid implementation of the interface/concept should have. Then, +// each implementation can easily instantiate the test suite to verify +// that it conforms to the requirements, without having to write +// similar tests repeatedly. Here's an example: + +#if 0 + +// First, define a fixture class template. It should be parameterized +// by a type. Remember to derive it from testing::Test. +template +class FooTest : public testing::Test { + ... +}; + +// Next, declare that you will define a type-parameterized test case +// (the _P suffix is for "parameterized" or "pattern", whichever you +// prefer): +TYPED_TEST_CASE_P(FooTest); + +// Then, use TYPED_TEST_P() to define as many type-parameterized tests +// for this type-parameterized test case as you want. +TYPED_TEST_P(FooTest, DoesBlah) { + // Inside a test, refer to TypeParam to get the type parameter. + TypeParam n = 0; + ... +} + +TYPED_TEST_P(FooTest, HasPropertyA) { ... } + +// Now the tricky part: you need to register all test patterns before +// you can instantiate them. The first argument of the macro is the +// test case name; the rest are the names of the tests in this test +// case. +REGISTER_TYPED_TEST_CASE_P(FooTest, + DoesBlah, HasPropertyA); + +// Finally, you are free to instantiate the pattern with the types you +// want. If you put the above code in a header file, you can #include +// it in multiple C++ source files and instantiate it multiple times. +// +// To distinguish different instances of the pattern, the first +// argument to the INSTANTIATE_* macro is a prefix that will be added +// to the actual test case name. Remember to pick unique prefixes for +// different instances. +typedef testing::Types MyTypes; +INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); + +// If the type list contains only one type, you can write that type +// directly without Types<...>: +// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int); + +#endif // 0 + + +// Implements typed tests. + +#if GTEST_HAS_TYPED_TEST + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the name of the typedef for the type parameters of the +// given test case. +# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_ + +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types) +# define TYPED_TEST_CASE(CaseName, Types) \ + typedef ::testing::internal::TypeList< Types >::type \ + GTEST_TYPE_PARAMS_(CaseName) + +# define TYPED_TEST(CaseName, TestName) \ + template \ + class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ + : public CaseName { \ + private: \ + typedef CaseName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + virtual void TestBody(); \ + }; \ + bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::internal::TypeParameterizedTest< \ + CaseName, \ + ::testing::internal::TemplateSel< \ + GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \ + GTEST_TYPE_PARAMS_(CaseName)>::Register(\ + "", #CaseName, #TestName, 0); \ + template \ + void GTEST_TEST_CLASS_NAME_(CaseName, TestName)::TestBody() + +#endif // GTEST_HAS_TYPED_TEST + +// Implements type-parameterized tests. + +#if GTEST_HAS_TYPED_TEST_P + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the namespace name that the type-parameterized tests for +// the given type-parameterized test case are defined in. The exact +// name of the namespace is subject to change without notice. +# define GTEST_CASE_NAMESPACE_(TestCaseName) \ + gtest_case_##TestCaseName##_ + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the name of the variable used to remember the names of +// the defined tests in the given test case. +# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \ + gtest_typed_test_case_p_state_##TestCaseName##_ + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY. +// +// Expands to the name of the variable used to remember the names of +// the registered tests in the given test case. +# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \ + gtest_registered_test_names_##TestCaseName##_ + +// The variables defined in the type-parameterized test macros are +// static as typically these macros are used in a .h file that can be +// #included in multiple translation units linked together. +# define TYPED_TEST_CASE_P(CaseName) \ + static ::testing::internal::TypedTestCasePState \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName) + +# define TYPED_TEST_P(CaseName, TestName) \ + namespace GTEST_CASE_NAMESPACE_(CaseName) { \ + template \ + class TestName : public CaseName { \ + private: \ + typedef CaseName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + virtual void TestBody(); \ + }; \ + static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\ + __FILE__, __LINE__, #CaseName, #TestName); \ + } \ + template \ + void GTEST_CASE_NAMESPACE_(CaseName)::TestName::TestBody() + +# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \ + namespace GTEST_CASE_NAMESPACE_(CaseName) { \ + typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ + } \ + static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\ + __FILE__, __LINE__, #__VA_ARGS__) + +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types) +# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \ + bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::internal::TypeParameterizedTestCase::type>::Register(\ + #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName)) + +#endif // GTEST_HAS_TYPED_TEST_P + +#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ + +// Depending on the platform, different string classes are available. +// On Linux, in addition to ::std::string, Google also makes use of +// class ::string, which has the same interface as ::std::string, but +// has a different implementation. +// +// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that +// ::string is available AND is a distinct type to ::std::string, or +// define it to 0 to indicate otherwise. +// +// If the user's ::std::string and ::string are the same class due to +// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0. +// +// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined +// heuristically. + +namespace testing { + +// Declares the flags. + +// This flag temporary enables the disabled tests. +GTEST_DECLARE_bool_(also_run_disabled_tests); + +// This flag brings the debugger on an assertion failure. +GTEST_DECLARE_bool_(break_on_failure); + +// This flag controls whether Google Test catches all test-thrown exceptions +// and logs them as failures. +GTEST_DECLARE_bool_(catch_exceptions); + +// This flag enables using colors in terminal output. Available values are +// "yes" to enable colors, "no" (disable colors), or "auto" (the default) +// to let Google Test decide. +GTEST_DECLARE_string_(color); + +// This flag sets up the filter to select by name using a glob pattern +// the tests to run. If the filter is not given all tests are executed. +GTEST_DECLARE_string_(filter); + +// This flag causes the Google Test to list tests. None of the tests listed +// are actually run if the flag is provided. +GTEST_DECLARE_bool_(list_tests); + +// This flag controls whether Google Test emits a detailed XML report to a file +// in addition to its normal textual output. +GTEST_DECLARE_string_(output); + +// This flags control whether Google Test prints the elapsed time for each +// test. +GTEST_DECLARE_bool_(print_time); + +// This flag specifies the random number seed. +GTEST_DECLARE_int32_(random_seed); + +// This flag sets how many times the tests are repeated. The default value +// is 1. If the value is -1 the tests are repeating forever. +GTEST_DECLARE_int32_(repeat); + +// This flag controls whether Google Test includes Google Test internal +// stack frames in failure stack traces. +GTEST_DECLARE_bool_(show_internal_stack_frames); + +// When this flag is specified, tests' order is randomized on every iteration. +GTEST_DECLARE_bool_(shuffle); + +// This flag specifies the maximum number of stack frames to be +// printed in a failure message. +GTEST_DECLARE_int32_(stack_trace_depth); + +// When this flag is specified, a failed assertion will throw an +// exception if exceptions are enabled, or exit the program with a +// non-zero code otherwise. +GTEST_DECLARE_bool_(throw_on_failure); + +// When this flag is set with a "host:port" string, on supported +// platforms test results are streamed to the specified port on +// the specified host machine. +GTEST_DECLARE_string_(stream_result_to); + +// The upper limit for valid stack trace depths. +const int kMaxStackTraceDepth = 100; + +namespace internal { + +class AssertHelper; +class DefaultGlobalTestPartResultReporter; +class ExecDeathTest; +class NoExecDeathTest; +class FinalSuccessChecker; +class GTestFlagSaver; +class StreamingListenerTest; +class TestResultAccessor; +class TestEventListenersAccessor; +class TestEventRepeater; +class UnitTestRecordPropertyTestHelper; +class WindowsDeathTest; +class UnitTestImpl* GetUnitTestImpl(); +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const std::string& message); + +} // namespace internal + +// The friend relationship of some of these classes is cyclic. +// If we don't forward declare them the compiler might confuse the classes +// in friendship clauses with same named classes on the scope. +class Test; +class TestCase; +class TestInfo; +class UnitTest; + +// A class for indicating whether an assertion was successful. When +// the assertion wasn't successful, the AssertionResult object +// remembers a non-empty message that describes how it failed. +// +// To create an instance of this class, use one of the factory functions +// (AssertionSuccess() and AssertionFailure()). +// +// This class is useful for two purposes: +// 1. Defining predicate functions to be used with Boolean test assertions +// EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts +// 2. Defining predicate-format functions to be +// used with predicate assertions (ASSERT_PRED_FORMAT*, etc). +// +// For example, if you define IsEven predicate: +// +// testing::AssertionResult IsEven(int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess(); +// else +// return testing::AssertionFailure() << n << " is odd"; +// } +// +// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5))) +// will print the message +// +// Value of: IsEven(Fib(5)) +// Actual: false (5 is odd) +// Expected: true +// +// instead of a more opaque +// +// Value of: IsEven(Fib(5)) +// Actual: false +// Expected: true +// +// in case IsEven is a simple Boolean predicate. +// +// If you expect your predicate to be reused and want to support informative +// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up +// about half as often as positive ones in our tests), supply messages for +// both success and failure cases: +// +// testing::AssertionResult IsEven(int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess() << n << " is even"; +// else +// return testing::AssertionFailure() << n << " is odd"; +// } +// +// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print +// +// Value of: IsEven(Fib(6)) +// Actual: true (8 is even) +// Expected: false +// +// NB: Predicates that support negative Boolean assertions have reduced +// performance in positive ones so be careful not to use them in tests +// that have lots (tens of thousands) of positive Boolean assertions. +// +// To use this class with EXPECT_PRED_FORMAT assertions such as: +// +// // Verifies that Foo() returns an even number. +// EXPECT_PRED_FORMAT1(IsEven, Foo()); +// +// you need to define: +// +// testing::AssertionResult IsEven(const char* expr, int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess(); +// else +// return testing::AssertionFailure() +// << "Expected: " << expr << " is even\n Actual: it's " << n; +// } +// +// If Foo() returns 5, you will see the following message: +// +// Expected: Foo() is even +// Actual: it's 5 +// +class GTEST_API_ AssertionResult { + public: + // Copy constructor. + // Used in EXPECT_TRUE/FALSE(assertion_result). + AssertionResult(const AssertionResult& other); + // Used in the EXPECT_TRUE/FALSE(bool_expression). + explicit AssertionResult(bool success) : success_(success) {} + + // Returns true iff the assertion succeeded. + operator bool() const { return success_; } // NOLINT + + // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. + AssertionResult operator!() const; + + // Returns the text streamed into this AssertionResult. Test assertions + // use it when they fail (i.e., the predicate's outcome doesn't match the + // assertion's expectation). When nothing has been streamed into the + // object, returns an empty string. + const char* message() const { + return message_.get() != NULL ? message_->c_str() : ""; + } + // TODO(vladl@google.com): Remove this after making sure no clients use it. + // Deprecated; please use message() instead. + const char* failure_message() const { return message(); } + + // Streams a custom failure message into this object. + template AssertionResult& operator<<(const T& value) { + AppendMessage(Message() << value); + return *this; + } + + // Allows streaming basic output manipulators such as endl or flush into + // this object. + AssertionResult& operator<<( + ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) { + AppendMessage(Message() << basic_manipulator); + return *this; + } + + private: + // Appends the contents of message to message_. + void AppendMessage(const Message& a_message) { + if (message_.get() == NULL) + message_.reset(new ::std::string); + message_->append(a_message.GetString().c_str()); + } + + // Stores result of the assertion predicate. + bool success_; + // Stores the message describing the condition in case the expectation + // construct is not satisfied with the predicate's outcome. + // Referenced via a pointer to avoid taking too much stack frame space + // with test assertions. + internal::scoped_ptr< ::std::string> message_; + + GTEST_DISALLOW_ASSIGN_(AssertionResult); +}; + +// Makes a successful assertion result. +GTEST_API_ AssertionResult AssertionSuccess(); + +// Makes a failed assertion result. +GTEST_API_ AssertionResult AssertionFailure(); + +// Makes a failed assertion result with the given failure message. +// Deprecated; use AssertionFailure() << msg. +GTEST_API_ AssertionResult AssertionFailure(const Message& msg); + +// The abstract class that all tests inherit from. +// +// In Google Test, a unit test program contains one or many TestCases, and +// each TestCase contains one or many Tests. +// +// When you define a test using the TEST macro, you don't need to +// explicitly derive from Test - the TEST macro automatically does +// this for you. +// +// The only time you derive from Test is when defining a test fixture +// to be used a TEST_F. For example: +// +// class FooTest : public testing::Test { +// protected: +// virtual void SetUp() { ... } +// virtual void TearDown() { ... } +// ... +// }; +// +// TEST_F(FooTest, Bar) { ... } +// TEST_F(FooTest, Baz) { ... } +// +// Test is not copyable. +class GTEST_API_ Test { + public: + friend class TestInfo; + + // Defines types for pointers to functions that set up and tear down + // a test case. + typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc; + typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc; + + // The d'tor is virtual as we intend to inherit from Test. + virtual ~Test(); + + // Sets up the stuff shared by all tests in this test case. + // + // Google Test will call Foo::SetUpTestCase() before running the first + // test in test case Foo. Hence a sub-class can define its own + // SetUpTestCase() method to shadow the one defined in the super + // class. + static void SetUpTestCase() {} + + // Tears down the stuff shared by all tests in this test case. + // + // Google Test will call Foo::TearDownTestCase() after running the last + // test in test case Foo. Hence a sub-class can define its own + // TearDownTestCase() method to shadow the one defined in the super + // class. + static void TearDownTestCase() {} + + // Returns true iff the current test has a fatal failure. + static bool HasFatalFailure(); + + // Returns true iff the current test has a non-fatal failure. + static bool HasNonfatalFailure(); + + // Returns true iff the current test has a (either fatal or + // non-fatal) failure. + static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); } + + // Logs a property for the current test, test case, or for the entire + // invocation of the test program when used outside of the context of a + // test case. Only the last value for a given key is remembered. These + // are public static so they can be called from utility functions that are + // not members of the test fixture. Calls to RecordProperty made during + // lifespan of the test (from the moment its constructor starts to the + // moment its destructor finishes) will be output in XML as attributes of + // the element. Properties recorded from fixture's + // SetUpTestCase or TearDownTestCase are logged as attributes of the + // corresponding element. Calls to RecordProperty made in the + // global context (before or after invocation of RUN_ALL_TESTS and from + // SetUp/TearDown method of Environment objects registered with Google + // Test) will be output as attributes of the element. + static void RecordProperty(const std::string& key, const std::string& value); + static void RecordProperty(const std::string& key, int value); + + protected: + // Creates a Test object. + Test(); + + // Sets up the test fixture. + virtual void SetUp(); + + // Tears down the test fixture. + virtual void TearDown(); + + private: + // Returns true iff the current test has the same fixture class as + // the first test in the current test case. + static bool HasSameFixtureClass(); + + // Runs the test after the test fixture has been set up. + // + // A sub-class must implement this to define the test logic. + // + // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM. + // Instead, use the TEST or TEST_F macro. + virtual void TestBody() = 0; + + // Sets up, executes, and tears down the test. + void Run(); + + // Deletes self. We deliberately pick an unusual name for this + // internal method to avoid clashing with names used in user TESTs. + void DeleteSelf_() { delete this; } + + // Uses a GTestFlagSaver to save and restore all Google Test flags. + const internal::GTestFlagSaver* const gtest_flag_saver_; + + // Often a user mis-spells SetUp() as Setup() and spends a long time + // wondering why it is never called by Google Test. The declaration of + // the following method is solely for catching such an error at + // compile time: + // + // - The return type is deliberately chosen to be not void, so it + // will be a conflict if a user declares void Setup() in his test + // fixture. + // + // - This method is private, so it will be another compiler error + // if a user calls it from his test fixture. + // + // DO NOT OVERRIDE THIS FUNCTION. + // + // If you see an error about overriding the following function or + // about it being private, you have mis-spelled SetUp() as Setup(). + struct Setup_should_be_spelled_SetUp {}; + virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } + + // We disallow copying Tests. + GTEST_DISALLOW_COPY_AND_ASSIGN_(Test); +}; + +typedef internal::TimeInMillis TimeInMillis; + +// A copyable object representing a user specified test property which can be +// output as a key/value string pair. +// +// Don't inherit from TestProperty as its destructor is not virtual. +class TestProperty { + public: + // C'tor. TestProperty does NOT have a default constructor. + // Always use this constructor (with parameters) to create a + // TestProperty object. + TestProperty(const std::string& a_key, const std::string& a_value) : + key_(a_key), value_(a_value) { + } + + // Gets the user supplied key. + const char* key() const { + return key_.c_str(); + } + + // Gets the user supplied value. + const char* value() const { + return value_.c_str(); + } + + // Sets a new value, overriding the one supplied in the constructor. + void SetValue(const std::string& new_value) { + value_ = new_value; + } + + private: + // The key supplied by the user. + std::string key_; + // The value supplied by the user. + std::string value_; +}; + +// The result of a single Test. This includes a list of +// TestPartResults, a list of TestProperties, a count of how many +// death tests there are in the Test, and how much time it took to run +// the Test. +// +// TestResult is not copyable. +class GTEST_API_ TestResult { + public: + // Creates an empty TestResult. + TestResult(); + + // D'tor. Do not inherit from TestResult. + ~TestResult(); + + // Gets the number of all test parts. This is the sum of the number + // of successful test parts and the number of failed test parts. + int total_part_count() const; + + // Returns the number of the test properties. + int test_property_count() const; + + // Returns true iff the test passed (i.e. no test part failed). + bool Passed() const { return !Failed(); } + + // Returns true iff the test failed. + bool Failed() const; + + // Returns true iff the test fatally failed. + bool HasFatalFailure() const; + + // Returns true iff the test has a non-fatal failure. + bool HasNonfatalFailure() const; + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test part result among all the results. i can range + // from 0 to test_property_count() - 1. If i is not in that range, aborts + // the program. + const TestPartResult& GetTestPartResult(int i) const; + + // Returns the i-th test property. i can range from 0 to + // test_property_count() - 1. If i is not in that range, aborts the + // program. + const TestProperty& GetTestProperty(int i) const; + + private: + friend class TestInfo; + friend class TestCase; + friend class UnitTest; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::ExecDeathTest; + friend class internal::TestResultAccessor; + friend class internal::UnitTestImpl; + friend class internal::WindowsDeathTest; + + // Gets the vector of TestPartResults. + const std::vector& test_part_results() const { + return test_part_results_; + } + + // Gets the vector of TestProperties. + const std::vector& test_properties() const { + return test_properties_; + } + + // Sets the elapsed time. + void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; } + + // Adds a test property to the list. The property is validated and may add + // a non-fatal failure if invalid (e.g., if it conflicts with reserved + // key names). If a property is already recorded for the same key, the + // value will be updated, rather than storing multiple values for the same + // key. xml_element specifies the element for which the property is being + // recorded and is used for validation. + void RecordProperty(const std::string& xml_element, + const TestProperty& test_property); + + // Adds a failure if the key is a reserved attribute of Google Test + // testcase tags. Returns true if the property is valid. + // TODO(russr): Validate attribute names are legal and human readable. + static bool ValidateTestProperty(const std::string& xml_element, + const TestProperty& test_property); + + // Adds a test part result to the list. + void AddTestPartResult(const TestPartResult& test_part_result); + + // Returns the death test count. + int death_test_count() const { return death_test_count_; } + + // Increments the death test count, returning the new count. + int increment_death_test_count() { return ++death_test_count_; } + + // Clears the test part results. + void ClearTestPartResults(); + + // Clears the object. + void Clear(); + + // Protects mutable state of the property vector and of owned + // properties, whose values may be updated. + internal::Mutex test_properites_mutex_; + + // The vector of TestPartResults + std::vector test_part_results_; + // The vector of TestProperties + std::vector test_properties_; + // Running count of death tests. + int death_test_count_; + // The elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + + // We disallow copying TestResult. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult); +}; // class TestResult + +// A TestInfo object stores the following information about a test: +// +// Test case name +// Test name +// Whether the test should be run +// A function pointer that creates the test object when invoked +// Test result +// +// The constructor of TestInfo registers itself with the UnitTest +// singleton such that the RUN_ALL_TESTS() macro knows which tests to +// run. +class GTEST_API_ TestInfo { + public: + // Destructs a TestInfo object. This function is not virtual, so + // don't inherit from TestInfo. + ~TestInfo(); + + // Returns the test case name. + const char* test_case_name() const { return test_case_name_.c_str(); } + + // Returns the test name. + const char* name() const { return name_.c_str(); } + + // Returns the name of the parameter type, or NULL if this is not a typed + // or a type-parameterized test. + const char* type_param() const { + if (type_param_.get() != NULL) + return type_param_->c_str(); + return NULL; + } + + // Returns the text representation of the value parameter, or NULL if this + // is not a value-parameterized test. + const char* value_param() const { + if (value_param_.get() != NULL) + return value_param_->c_str(); + return NULL; + } + + // Returns true if this test should run, that is if the test is not + // disabled (or it is disabled but the also_run_disabled_tests flag has + // been specified) and its full name matches the user-specified filter. + // + // Google Test allows the user to filter the tests by their full names. + // The full name of a test Bar in test case Foo is defined as + // "Foo.Bar". Only the tests that match the filter will run. + // + // A filter is a colon-separated list of glob (not regex) patterns, + // optionally followed by a '-' and a colon-separated list of + // negative patterns (tests to exclude). A test is run if it + // matches one of the positive patterns and does not match any of + // the negative patterns. + // + // For example, *A*:Foo.* is a filter that matches any string that + // contains the character 'A' or starts with "Foo.". + bool should_run() const { return should_run_; } + + // Returns true iff this test will appear in the XML report. + bool is_reportable() const { + // For now, the XML report includes all tests matching the filter. + // In the future, we may trim tests that are excluded because of + // sharding. + return matches_filter_; + } + + // Returns the result of the test. + const TestResult* result() const { return &result_; } + + private: +#if GTEST_HAS_DEATH_TEST + friend class internal::DefaultDeathTestFactory; +#endif // GTEST_HAS_DEATH_TEST + friend class Test; + friend class TestCase; + friend class internal::UnitTestImpl; + friend class internal::StreamingListenerTest; + friend TestInfo* internal::MakeAndRegisterTestInfo( + const char* test_case_name, + const char* name, + const char* type_param, + const char* value_param, + internal::TypeId fixture_class_id, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc, + internal::TestFactoryBase* factory); + + // Constructs a TestInfo object. The newly constructed instance assumes + // ownership of the factory object. + TestInfo(const std::string& test_case_name, + const std::string& name, + const char* a_type_param, // NULL if not a type-parameterized test + const char* a_value_param, // NULL if not a value-parameterized test + internal::TypeId fixture_class_id, + internal::TestFactoryBase* factory); + + // Increments the number of death tests encountered in this test so + // far. + int increment_death_test_count() { + return result_.increment_death_test_count(); + } + + // Creates the test object, runs it, records its result, and then + // deletes it. + void Run(); + + static void ClearTestResult(TestInfo* test_info) { + test_info->result_.Clear(); + } + + // These fields are immutable properties of the test. + const std::string test_case_name_; // Test case name + const std::string name_; // Test name + // Name of the parameter type, or NULL if this is not a typed or a + // type-parameterized test. + const internal::scoped_ptr type_param_; + // Text representation of the value parameter, or NULL if this is not a + // value-parameterized test. + const internal::scoped_ptr value_param_; + const internal::TypeId fixture_class_id_; // ID of the test fixture class + bool should_run_; // True iff this test should run + bool is_disabled_; // True iff this test is disabled + bool matches_filter_; // True if this test matches the + // user-specified filter. + internal::TestFactoryBase* const factory_; // The factory that creates + // the test object + + // This field is mutable and needs to be reset before running the + // test for the second time. + TestResult result_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo); +}; + +// A test case, which consists of a vector of TestInfos. +// +// TestCase is not copyable. +class GTEST_API_ TestCase { + public: + // Creates a TestCase with the given name. + // + // TestCase does NOT have a default constructor. Always use this + // constructor to create a TestCase object. + // + // Arguments: + // + // name: name of the test case + // a_type_param: the name of the test's type parameter, or NULL if + // this is not a type-parameterized test. + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + TestCase(const char* name, const char* a_type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc); + + // Destructor of TestCase. + virtual ~TestCase(); + + // Gets the name of the TestCase. + const char* name() const { return name_.c_str(); } + + // Returns the name of the parameter type, or NULL if this is not a + // type-parameterized test case. + const char* type_param() const { + if (type_param_.get() != NULL) + return type_param_->c_str(); + return NULL; + } + + // Returns true if any test in this test case should run. + bool should_run() const { return should_run_; } + + // Gets the number of successful tests in this test case. + int successful_test_count() const; + + // Gets the number of failed tests in this test case. + int failed_test_count() const; + + // Gets the number of disabled tests that will be reported in the XML report. + int reportable_disabled_test_count() const; + + // Gets the number of disabled tests in this test case. + int disabled_test_count() const; + + // Gets the number of tests to be printed in the XML report. + int reportable_test_count() const; + + // Get the number of tests in this test case that should run. + int test_to_run_count() const; + + // Gets the number of all tests in this test case. + int total_test_count() const; + + // Returns true iff the test case passed. + bool Passed() const { return !Failed(); } + + // Returns true iff the test case failed. + bool Failed() const { return failed_test_count() > 0; } + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + const TestInfo* GetTestInfo(int i) const; + + // Returns the TestResult that holds test properties recorded during + // execution of SetUpTestCase and TearDownTestCase. + const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; } + + private: + friend class Test; + friend class internal::UnitTestImpl; + + // Gets the (mutable) vector of TestInfos in this TestCase. + std::vector& test_info_list() { return test_info_list_; } + + // Gets the (immutable) vector of TestInfos in this TestCase. + const std::vector& test_info_list() const { + return test_info_list_; + } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + TestInfo* GetMutableTestInfo(int i); + + // Sets the should_run member. + void set_should_run(bool should) { should_run_ = should; } + + // Adds a TestInfo to this test case. Will delete the TestInfo upon + // destruction of the TestCase object. + void AddTestInfo(TestInfo * test_info); + + // Clears the results of all tests in this test case. + void ClearResult(); + + // Clears the results of all tests in the given test case. + static void ClearTestCaseResult(TestCase* test_case) { + test_case->ClearResult(); + } + + // Runs every test in this TestCase. + void Run(); + + // Runs SetUpTestCase() for this TestCase. This wrapper is needed + // for catching exceptions thrown from SetUpTestCase(). + void RunSetUpTestCase() { (*set_up_tc_)(); } + + // Runs TearDownTestCase() for this TestCase. This wrapper is + // needed for catching exceptions thrown from TearDownTestCase(). + void RunTearDownTestCase() { (*tear_down_tc_)(); } + + // Returns true iff test passed. + static bool TestPassed(const TestInfo* test_info) { + return test_info->should_run() && test_info->result()->Passed(); + } + + // Returns true iff test failed. + static bool TestFailed(const TestInfo* test_info) { + return test_info->should_run() && test_info->result()->Failed(); + } + + // Returns true iff the test is disabled and will be reported in the XML + // report. + static bool TestReportableDisabled(const TestInfo* test_info) { + return test_info->is_reportable() && test_info->is_disabled_; + } + + // Returns true iff test is disabled. + static bool TestDisabled(const TestInfo* test_info) { + return test_info->is_disabled_; + } + + // Returns true iff this test will appear in the XML report. + static bool TestReportable(const TestInfo* test_info) { + return test_info->is_reportable(); + } + + // Returns true if the given test should run. + static bool ShouldRunTest(const TestInfo* test_info) { + return test_info->should_run(); + } + + // Shuffles the tests in this test case. + void ShuffleTests(internal::Random* random); + + // Restores the test order to before the first shuffle. + void UnshuffleTests(); + + // Name of the test case. + std::string name_; + // Name of the parameter type, or NULL if this is not a typed or a + // type-parameterized test. + const internal::scoped_ptr type_param_; + // The vector of TestInfos in their original order. It owns the + // elements in the vector. + std::vector test_info_list_; + // Provides a level of indirection for the test list to allow easy + // shuffling and restoring the test order. The i-th element in this + // vector is the index of the i-th test in the shuffled test list. + std::vector test_indices_; + // Pointer to the function that sets up the test case. + Test::SetUpTestCaseFunc set_up_tc_; + // Pointer to the function that tears down the test case. + Test::TearDownTestCaseFunc tear_down_tc_; + // True iff any test in this test case should run. + bool should_run_; + // Elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + // Holds test properties recorded during execution of SetUpTestCase and + // TearDownTestCase. + TestResult ad_hoc_test_result_; + + // We disallow copying TestCases. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase); +}; + +// An Environment object is capable of setting up and tearing down an +// environment. The user should subclass this to define his own +// environment(s). +// +// An Environment object does the set-up and tear-down in virtual +// methods SetUp() and TearDown() instead of the constructor and the +// destructor, as: +// +// 1. You cannot safely throw from a destructor. This is a problem +// as in some cases Google Test is used where exceptions are enabled, and +// we may want to implement ASSERT_* using exceptions where they are +// available. +// 2. You cannot use ASSERT_* directly in a constructor or +// destructor. +class Environment { + public: + // The d'tor is virtual as we need to subclass Environment. + virtual ~Environment() {} + + // Override this to define how to set up the environment. + virtual void SetUp() {} + + // Override this to define how to tear down the environment. + virtual void TearDown() {} + private: + // If you see an error about overriding the following function or + // about it being private, you have mis-spelled SetUp() as Setup(). + struct Setup_should_be_spelled_SetUp {}; + virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } +}; + +// The interface for tracing execution of tests. The methods are organized in +// the order the corresponding events are fired. +class TestEventListener { + public: + virtual ~TestEventListener() {} + + // Fired before any test activity starts. + virtual void OnTestProgramStart(const UnitTest& unit_test) = 0; + + // Fired before each iteration of tests starts. There may be more than + // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration + // index, starting from 0. + virtual void OnTestIterationStart(const UnitTest& unit_test, + int iteration) = 0; + + // Fired before environment set-up for each iteration of tests starts. + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0; + + // Fired after environment set-up for each iteration of tests ends. + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0; + + // Fired before the test case starts. + virtual void OnTestCaseStart(const TestCase& test_case) = 0; + + // Fired before the test starts. + virtual void OnTestStart(const TestInfo& test_info) = 0; + + // Fired after a failed assertion or a SUCCEED() invocation. + virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0; + + // Fired after the test ends. + virtual void OnTestEnd(const TestInfo& test_info) = 0; + + // Fired after the test case ends. + virtual void OnTestCaseEnd(const TestCase& test_case) = 0; + + // Fired before environment tear-down for each iteration of tests starts. + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0; + + // Fired after environment tear-down for each iteration of tests ends. + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0; + + // Fired after each iteration of tests finishes. + virtual void OnTestIterationEnd(const UnitTest& unit_test, + int iteration) = 0; + + // Fired after all test activities have ended. + virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0; +}; + +// The convenience class for users who need to override just one or two +// methods and are not concerned that a possible change to a signature of +// the methods they override will not be caught during the build. For +// comments about each method please see the definition of TestEventListener +// above. +class EmptyTestEventListener : public TestEventListener { + public: + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} + virtual void OnTestStart(const TestInfo& /*test_info*/) {} + virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {} + virtual void OnTestEnd(const TestInfo& /*test_info*/) {} + virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} + virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} +}; + +// TestEventListeners lets users add listeners to track events in Google Test. +class GTEST_API_ TestEventListeners { + public: + TestEventListeners(); + ~TestEventListeners(); + + // Appends an event listener to the end of the list. Google Test assumes + // the ownership of the listener (i.e. it will delete the listener when + // the test program finishes). + void Append(TestEventListener* listener); + + // Removes the given event listener from the list and returns it. It then + // becomes the caller's responsibility to delete the listener. Returns + // NULL if the listener is not found in the list. + TestEventListener* Release(TestEventListener* listener); + + // Returns the standard listener responsible for the default console + // output. Can be removed from the listeners list to shut down default + // console output. Note that removing this object from the listener list + // with Release transfers its ownership to the caller and makes this + // function return NULL the next time. + TestEventListener* default_result_printer() const { + return default_result_printer_; + } + + // Returns the standard listener responsible for the default XML output + // controlled by the --gtest_output=xml flag. Can be removed from the + // listeners list by users who want to shut down the default XML output + // controlled by this flag and substitute it with custom one. Note that + // removing this object from the listener list with Release transfers its + // ownership to the caller and makes this function return NULL the next + // time. + TestEventListener* default_xml_generator() const { + return default_xml_generator_; + } + + private: + friend class TestCase; + friend class TestInfo; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::NoExecDeathTest; + friend class internal::TestEventListenersAccessor; + friend class internal::UnitTestImpl; + + // Returns repeater that broadcasts the TestEventListener events to all + // subscribers. + TestEventListener* repeater(); + + // Sets the default_result_printer attribute to the provided listener. + // The listener is also added to the listener list and previous + // default_result_printer is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultResultPrinter(TestEventListener* listener); + + // Sets the default_xml_generator attribute to the provided listener. The + // listener is also added to the listener list and previous + // default_xml_generator is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultXmlGenerator(TestEventListener* listener); + + // Controls whether events will be forwarded by the repeater to the + // listeners in the list. + bool EventForwardingEnabled() const; + void SuppressEventForwarding(); + + // The actual list of listeners. + internal::TestEventRepeater* repeater_; + // Listener responsible for the standard result output. + TestEventListener* default_result_printer_; + // Listener responsible for the creation of the XML output file. + TestEventListener* default_xml_generator_; + + // We disallow copying TestEventListeners. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners); +}; + +// A UnitTest consists of a vector of TestCases. +// +// This is a singleton class. The only instance of UnitTest is +// created when UnitTest::GetInstance() is first called. This +// instance is never deleted. +// +// UnitTest is not copyable. +// +// This class is thread-safe as long as the methods are called +// according to their specification. +class GTEST_API_ UnitTest { + public: + // Gets the singleton UnitTest object. The first time this method + // is called, a UnitTest object is constructed and returned. + // Consecutive calls will return the same object. + static UnitTest* GetInstance(); + + // Runs all tests in this UnitTest object and prints the result. + // Returns 0 if successful, or 1 otherwise. + // + // This method can only be called from the main thread. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + int Run() GTEST_MUST_USE_RESULT_; + + // Returns the working directory when the first TEST() or TEST_F() + // was executed. The UnitTest object owns the string. + const char* original_working_dir() const; + + // Returns the TestCase object for the test that's currently running, + // or NULL if no test is running. + const TestCase* current_test_case() const + GTEST_LOCK_EXCLUDED_(mutex_); + + // Returns the TestInfo object for the test that's currently running, + // or NULL if no test is running. + const TestInfo* current_test_info() const + GTEST_LOCK_EXCLUDED_(mutex_); + + // Returns the random seed used at the start of the current test run. + int random_seed() const; + +#if GTEST_HAS_PARAM_TEST + // Returns the ParameterizedTestCaseRegistry object used to keep track of + // value-parameterized tests and instantiate and register them. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + internal::ParameterizedTestCaseRegistry& parameterized_test_registry() + GTEST_LOCK_EXCLUDED_(mutex_); +#endif // GTEST_HAS_PARAM_TEST + + // Gets the number of successful test cases. + int successful_test_case_count() const; + + // Gets the number of failed test cases. + int failed_test_case_count() const; + + // Gets the number of all test cases. + int total_test_case_count() const; + + // Gets the number of all test cases that contain at least one test + // that should run. + int test_case_to_run_count() const; + + // Gets the number of successful tests. + int successful_test_count() const; + + // Gets the number of failed tests. + int failed_test_count() const; + + // Gets the number of disabled tests that will be reported in the XML report. + int reportable_disabled_test_count() const; + + // Gets the number of disabled tests. + int disabled_test_count() const; + + // Gets the number of tests to be printed in the XML report. + int reportable_test_count() const; + + // Gets the number of all tests. + int total_test_count() const; + + // Gets the number of tests that should run. + int test_to_run_count() const; + + // Gets the time of the test program start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp() const; + + // Gets the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const; + + // Returns true iff the unit test passed (i.e. all test cases passed). + bool Passed() const; + + // Returns true iff the unit test failed (i.e. some test case failed + // or something outside of all tests failed). + bool Failed() const; + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const; + + // Returns the TestResult containing information on test failures and + // properties logged outside of individual test cases. + const TestResult& ad_hoc_test_result() const; + + // Returns the list of event listeners that can be used to track events + // inside Google Test. + TestEventListeners& listeners(); + + private: + // Registers and returns a global test environment. When a test + // program is run, all global test environments will be set-up in + // the order they were registered. After all tests in the program + // have finished, all global test environments will be torn-down in + // the *reverse* order they were registered. + // + // The UnitTest object takes ownership of the given environment. + // + // This method can only be called from the main thread. + Environment* AddEnvironment(Environment* env); + + // Adds a TestPartResult to the current TestResult object. All + // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) + // eventually call this to report their results. The user code + // should use the assertion macros instead of calling this directly. + void AddTestPartResult(TestPartResult::Type result_type, + const char* file_name, + int line_number, + const std::string& message, + const std::string& os_stack_trace) + GTEST_LOCK_EXCLUDED_(mutex_); + + // Adds a TestProperty to the current TestResult object when invoked from + // inside a test, to current TestCase's ad_hoc_test_result_ when invoked + // from SetUpTestCase or TearDownTestCase, or to the global property set + // when invoked elsewhere. If the result already contains a property with + // the same key, the value will be updated. + void RecordProperty(const std::string& key, const std::string& value); + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i); + + // Accessors for the implementation object. + internal::UnitTestImpl* impl() { return impl_; } + const internal::UnitTestImpl* impl() const { return impl_; } + + // These classes and funcions are friends as they need to access private + // members of UnitTest. + friend class Test; + friend class internal::AssertHelper; + friend class internal::ScopedTrace; + friend class internal::StreamingListenerTest; + friend class internal::UnitTestRecordPropertyTestHelper; + friend Environment* AddGlobalTestEnvironment(Environment* env); + friend internal::UnitTestImpl* internal::GetUnitTestImpl(); + friend void internal::ReportFailureInUnknownLocation( + TestPartResult::Type result_type, + const std::string& message); + + // Creates an empty UnitTest. + UnitTest(); + + // D'tor + virtual ~UnitTest(); + + // Pushes a trace defined by SCOPED_TRACE() on to the per-thread + // Google Test trace stack. + void PushGTestTrace(const internal::TraceInfo& trace) + GTEST_LOCK_EXCLUDED_(mutex_); + + // Pops a trace from the per-thread Google Test trace stack. + void PopGTestTrace() + GTEST_LOCK_EXCLUDED_(mutex_); + + // Protects mutable state in *impl_. This is mutable as some const + // methods need to lock it too. + mutable internal::Mutex mutex_; + + // Opaque implementation object. This field is never changed once + // the object is constructed. We don't mark it as const here, as + // doing so will cause a warning in the constructor of UnitTest. + // Mutable state in *impl_ is protected by mutex_. + internal::UnitTestImpl* impl_; + + // We disallow copying UnitTest. + GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest); +}; + +// A convenient wrapper for adding an environment for the test +// program. +// +// You should call this before RUN_ALL_TESTS() is called, probably in +// main(). If you use gtest_main, you need to call this before main() +// starts for it to take effect. For example, you can define a global +// variable like this: +// +// testing::Environment* const foo_env = +// testing::AddGlobalTestEnvironment(new FooEnvironment); +// +// However, we strongly recommend you to write your own main() and +// call AddGlobalTestEnvironment() there, as relying on initialization +// of global variables makes the code harder to read and may cause +// problems when you register multiple environments from different +// translation units and the environments have dependencies among them +// (remember that the compiler doesn't guarantee the order in which +// global variables from different translation units are initialized). +inline Environment* AddGlobalTestEnvironment(Environment* env) { + return UnitTest::GetInstance()->AddEnvironment(env); +} + +// Initializes Google Test. This must be called before calling +// RUN_ALL_TESTS(). In particular, it parses a command line for the +// flags that Google Test recognizes. Whenever a Google Test flag is +// seen, it is removed from argv, and *argc is decremented. +// +// No value is returned. Instead, the Google Test flag variables are +// updated. +// +// Calling the function for the second time has no user-visible effect. +GTEST_API_ void InitGoogleTest(int* argc, char** argv); + +// This overloaded version can be used in Windows programs compiled in +// UNICODE mode. +GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv); + +namespace internal { + +// FormatForComparison::Format(value) formats a +// value of type ToPrint that is an operand of a comparison assertion +// (e.g. ASSERT_EQ). OtherOperand is the type of the other operand in +// the comparison, and is used to help determine the best way to +// format the value. In particular, when the value is a C string +// (char pointer) and the other operand is an STL string object, we +// want to format the C string as a string, since we know it is +// compared by value with the string object. If the value is a char +// pointer but the other operand is not an STL string object, we don't +// know whether the pointer is supposed to point to a NUL-terminated +// string, and thus want to print it as a pointer to be safe. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + +// The default case. +template +class FormatForComparison { + public: + static ::std::string Format(const ToPrint& value) { + return ::testing::PrintToString(value); + } +}; + +// Array. +template +class FormatForComparison { + public: + static ::std::string Format(const ToPrint* value) { + return FormatForComparison::Format(value); + } +}; + +// By default, print C string as pointers to be safe, as we don't know +// whether they actually point to a NUL-terminated string. + +#define GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(CharType) \ + template \ + class FormatForComparison { \ + public: \ + static ::std::string Format(CharType* value) { \ + return ::testing::PrintToString(static_cast(value)); \ + } \ + } + +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t); + +#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_ + +// If a C string is compared with an STL string object, we know it's meant +// to point to a NUL-terminated string, and thus can print it as a string. + +#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \ + template <> \ + class FormatForComparison { \ + public: \ + static ::std::string Format(CharType* value) { \ + return ::testing::PrintToString(value); \ + } \ + } + +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string); + +#if GTEST_HAS_GLOBAL_STRING +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::string); +#endif + +#if GTEST_HAS_GLOBAL_WSTRING +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::wstring); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::wstring); +#endif + +#if GTEST_HAS_STD_WSTRING +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring); +#endif + +#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_ + +// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc) +// operand to be used in a failure message. The type (but not value) +// of the other operand may affect the format. This allows us to +// print a char* as a raw pointer when it is compared against another +// char* or void*, and print it as a C string when it is compared +// against an std::string object, for example. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +template +std::string FormatForComparisonFailureMessage( + const T1& value, const T2& /* other_operand */) { + return FormatForComparison::Format(value); +} + +// The helper function for {ASSERT|EXPECT}_EQ. +template +AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual) { +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4389) // Temporarily disables warning on + // signed/unsigned mismatch. +#endif + + if (expected == actual) { + return AssertionSuccess(); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif + + return EqFailure(expected_expression, + actual_expression, + FormatForComparisonFailureMessage(expected, actual), + FormatForComparisonFailureMessage(actual, expected), + false); +} + +// With this overloaded version, we allow anonymous enums to be used +// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums +// can be implicitly cast to BiggestInt. +GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual); + +// The helper class for {ASSERT|EXPECT}_EQ. The template argument +// lhs_is_null_literal is true iff the first argument to ASSERT_EQ() +// is a null pointer literal. The following default implementation is +// for lhs_is_null_literal being false. +template +class EqHelper { + public: + // This templatized version is for the general case. + template + static AssertionResult Compare(const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } + + // With this overloaded version, we allow anonymous enums to be used + // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous + // enums can be implicitly cast to BiggestInt. + // + // Even though its body looks the same as the above version, we + // cannot merge the two, as it will make anonymous enums unhappy. + static AssertionResult Compare(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } +}; + +// This specialization is used when the first argument to ASSERT_EQ() +// is a null pointer literal, like NULL, false, or 0. +template <> +class EqHelper { + public: + // We define two overloaded versions of Compare(). The first + // version will be picked when the second argument to ASSERT_EQ() is + // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or + // EXPECT_EQ(false, a_bool). + template + static AssertionResult Compare( + const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual, + // The following line prevents this overload from being considered if T2 + // is not a pointer type. We need this because ASSERT_EQ(NULL, my_ptr) + // expands to Compare("", "", NULL, my_ptr), which requires a conversion + // to match the Secret* in the other overload, which would otherwise make + // this template match better. + typename EnableIf::value>::type* = 0) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } + + // This version will be picked when the second argument to ASSERT_EQ() is a + // pointer, e.g. ASSERT_EQ(NULL, a_pointer). + template + static AssertionResult Compare( + const char* expected_expression, + const char* actual_expression, + // We used to have a second template parameter instead of Secret*. That + // template parameter would deduce to 'long', making this a better match + // than the first overload even without the first overload's EnableIf. + // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to + // non-pointer argument" (even a deduced integral argument), so the old + // implementation caused warnings in user code. + Secret* /* expected (NULL) */, + T* actual) { + // We already know that 'expected' is a null pointer. + return CmpHelperEQ(expected_expression, actual_expression, + static_cast(NULL), actual); + } +}; + +// A macro for implementing the helper functions needed to implement +// ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste +// of similar code. +// +// For each templatized helper function, we also define an overloaded +// version for BiggestInt in order to reduce code bloat and allow +// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled +// with gcc 4. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ +template \ +AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ + const T1& val1, const T2& val2) {\ + if (val1 op val2) {\ + return AssertionSuccess();\ + } else {\ + return AssertionFailure() \ + << "Expected: (" << expr1 << ") " #op " (" << expr2\ + << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ + << " vs " << FormatForComparisonFailureMessage(val2, val1);\ + }\ +}\ +GTEST_API_ AssertionResult CmpHelper##op_name(\ + const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2) + +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + +// Implements the helper function for {ASSERT|EXPECT}_NE +GTEST_IMPL_CMP_HELPER_(NE, !=); +// Implements the helper function for {ASSERT|EXPECT}_LE +GTEST_IMPL_CMP_HELPER_(LE, <=); +// Implements the helper function for {ASSERT|EXPECT}_LT +GTEST_IMPL_CMP_HELPER_(LT, <); +// Implements the helper function for {ASSERT|EXPECT}_GE +GTEST_IMPL_CMP_HELPER_(GE, >=); +// Implements the helper function for {ASSERT|EXPECT}_GT +GTEST_IMPL_CMP_HELPER_(GT, >); + +#undef GTEST_IMPL_CMP_HELPER_ + +// The helper function for {ASSERT|EXPECT}_STREQ. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); + +// The helper function for {ASSERT|EXPECT}_STRCASEEQ. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); + +// The helper function for {ASSERT|EXPECT}_STRNE. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); + +// The helper function for {ASSERT|EXPECT}_STRCASENE. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); + + +// Helper function for *_STREQ on wide strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const wchar_t* expected, + const wchar_t* actual); + +// Helper function for *_STRNE on wide strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const wchar_t* s1, + const wchar_t* s2); + +} // namespace internal + +// IsSubstring() and IsNotSubstring() are intended to be used as the +// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by +// themselves. They check whether needle is a substring of haystack +// (NULL is considered a substring of itself only), and return an +// appropriate error message when they fail. +// +// The {needle,haystack}_expr arguments are the stringified +// expressions that generated the two real arguments. +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack); +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack); +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack); + +#if GTEST_HAS_STD_WSTRING +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack); +#endif // GTEST_HAS_STD_WSTRING + +namespace internal { + +// Helper template function for comparing floating-points. +// +// Template parameter: +// +// RawType: the raw floating-point type (either float or double) +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +template +AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression, + const char* actual_expression, + RawType expected, + RawType actual) { + const FloatingPoint lhs(expected), rhs(actual); + + if (lhs.AlmostEquals(rhs)) { + return AssertionSuccess(); + } + + ::std::stringstream expected_ss; + expected_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << expected; + + ::std::stringstream actual_ss; + actual_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << actual; + + return EqFailure(expected_expression, + actual_expression, + StringStreamToString(&expected_ss), + StringStreamToString(&actual_ss), + false); +} + +// Helper function for implementing ASSERT_NEAR. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1, + const char* expr2, + const char* abs_error_expr, + double val1, + double val2, + double abs_error); + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// A class that enables one to stream messages to assertion macros +class GTEST_API_ AssertHelper { + public: + // Constructor. + AssertHelper(TestPartResult::Type type, + const char* file, + int line, + const char* message); + ~AssertHelper(); + + // Message assignment is a semantic trick to enable assertion + // streaming; see the GTEST_MESSAGE_ macro below. + void operator=(const Message& message) const; + + private: + // We put our data in a struct so that the size of the AssertHelper class can + // be as small as possible. This is important because gcc is incapable of + // re-using stack space even for temporary variables, so every EXPECT_EQ + // reserves stack space for another AssertHelper. + struct AssertHelperData { + AssertHelperData(TestPartResult::Type t, + const char* srcfile, + int line_num, + const char* msg) + : type(t), file(srcfile), line(line_num), message(msg) { } + + TestPartResult::Type const type; + const char* const file; + int const line; + std::string const message; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData); + }; + + AssertHelperData* const data_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper); +}; + +} // namespace internal + +#if GTEST_HAS_PARAM_TEST +// The pure interface class that all value-parameterized tests inherit from. +// A value-parameterized class must inherit from both ::testing::Test and +// ::testing::WithParamInterface. In most cases that just means inheriting +// from ::testing::TestWithParam, but more complicated test hierarchies +// may need to inherit from Test and WithParamInterface at different levels. +// +// This interface has support for accessing the test parameter value via +// the GetParam() method. +// +// Use it with one of the parameter generator defining functions, like Range(), +// Values(), ValuesIn(), Bool(), and Combine(). +// +// class FooTest : public ::testing::TestWithParam { +// protected: +// FooTest() { +// // Can use GetParam() here. +// } +// virtual ~FooTest() { +// // Can use GetParam() here. +// } +// virtual void SetUp() { +// // Can use GetParam() here. +// } +// virtual void TearDown { +// // Can use GetParam() here. +// } +// }; +// TEST_P(FooTest, DoesBar) { +// // Can use GetParam() method here. +// Foo foo; +// ASSERT_TRUE(foo.DoesBar(GetParam())); +// } +// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10)); + +template +class WithParamInterface { + public: + typedef T ParamType; + virtual ~WithParamInterface() {} + + // The current parameter value. Is also available in the test fixture's + // constructor. This member function is non-static, even though it only + // references static data, to reduce the opportunity for incorrect uses + // like writing 'WithParamInterface::GetParam()' for a test that + // uses a fixture whose parameter type is int. + const ParamType& GetParam() const { + GTEST_CHECK_(parameter_ != NULL) + << "GetParam() can only be called inside a value-parameterized test " + << "-- did you intend to write TEST_P instead of TEST_F?"; + return *parameter_; + } + + private: + // Sets parameter value. The caller is responsible for making sure the value + // remains alive and unchanged throughout the current test. + static void SetParam(const ParamType* parameter) { + parameter_ = parameter; + } + + // Static value used for accessing parameter during a test lifetime. + static const ParamType* parameter_; + + // TestClass must be a subclass of WithParamInterface and Test. + template friend class internal::ParameterizedTestFactory; +}; + +template +const T* WithParamInterface::parameter_ = NULL; + +// Most value-parameterized classes can ignore the existence of +// WithParamInterface, and can just inherit from ::testing::TestWithParam. + +template +class TestWithParam : public Test, public WithParamInterface { +}; + +#endif // GTEST_HAS_PARAM_TEST + +// Macros for indicating success/failure in test code. + +// ADD_FAILURE unconditionally adds a failure to the current test. +// SUCCEED generates a success - it doesn't automatically make the +// current test successful, as a test is only successful when it has +// no failure. +// +// EXPECT_* verifies that a certain condition is satisfied. If not, +// it behaves like ADD_FAILURE. In particular: +// +// EXPECT_TRUE verifies that a Boolean condition is true. +// EXPECT_FALSE verifies that a Boolean condition is false. +// +// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except +// that they will also abort the current function on failure. People +// usually want the fail-fast behavior of FAIL and ASSERT_*, but those +// writing data-driven tests often find themselves using ADD_FAILURE +// and EXPECT_* more. + +// Generates a nonfatal failure with a generic message. +#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed") + +// Generates a nonfatal failure at the given source file location with +// a generic message. +#define ADD_FAILURE_AT(file, line) \ + GTEST_MESSAGE_AT_(file, line, "Failed", \ + ::testing::TestPartResult::kNonFatalFailure) + +// Generates a fatal failure with a generic message. +#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed") + +// Define this macro to 1 to omit the definition of FAIL(), which is a +// generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_FAIL +# define FAIL() GTEST_FAIL() +#endif + +// Generates a success with a generic message. +#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded") + +// Define this macro to 1 to omit the definition of SUCCEED(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_SUCCEED +# define SUCCEED() GTEST_SUCCEED() +#endif + +// Macros for testing exceptions. +// +// * {ASSERT|EXPECT}_THROW(statement, expected_exception): +// Tests that the statement throws the expected exception. +// * {ASSERT|EXPECT}_NO_THROW(statement): +// Tests that the statement doesn't throw any exception. +// * {ASSERT|EXPECT}_ANY_THROW(statement): +// Tests that the statement throws an exception. + +#define EXPECT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_) +#define EXPECT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_) +#define EXPECT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_) +#define ASSERT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_) +#define ASSERT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_) +#define ASSERT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_) + +// Boolean assertions. Condition can be either a Boolean expression or an +// AssertionResult. For more information on how to use AssertionResult with +// these macros see comments on that class. +#define EXPECT_TRUE(condition) \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ + GTEST_NONFATAL_FAILURE_) +#define EXPECT_FALSE(condition) \ + GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ + GTEST_NONFATAL_FAILURE_) +#define ASSERT_TRUE(condition) \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ + GTEST_FATAL_FAILURE_) +#define ASSERT_FALSE(condition) \ + GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ + GTEST_FATAL_FAILURE_) + +// Includes the auto-generated header that implements a family of +// generic predicate assertion macros. +// Copyright 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file is AUTOMATICALLY GENERATED on 10/31/2011 by command +// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND! +// +// Implements a family of generic predicate assertion macros. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ + +// Makes sure this header is not included before gtest.h. +#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ +# error Do not include gtest_pred_impl.h directly. Include gtest.h instead. +#endif // GTEST_INCLUDE_GTEST_GTEST_H_ + +// This header implements a family of generic predicate assertion +// macros: +// +// ASSERT_PRED_FORMAT1(pred_format, v1) +// ASSERT_PRED_FORMAT2(pred_format, v1, v2) +// ... +// +// where pred_format is a function or functor that takes n (in the +// case of ASSERT_PRED_FORMATn) values and their source expression +// text, and returns a testing::AssertionResult. See the definition +// of ASSERT_EQ in gtest.h for an example. +// +// If you don't care about formatting, you can use the more +// restrictive version: +// +// ASSERT_PRED1(pred, v1) +// ASSERT_PRED2(pred, v1, v2) +// ... +// +// where pred is an n-ary function or functor that returns bool, +// and the values v1, v2, ..., must support the << operator for +// streaming to std::ostream. +// +// We also define the EXPECT_* variations. +// +// For now we only support predicates whose arity is at most 5. +// Please email googletestframework@googlegroups.com if you need +// support for higher arities. + +// GTEST_ASSERT_ is the basic statement to which all of the assertions +// in this file reduce. Don't use this in your code. + +#define GTEST_ASSERT_(expression, on_failure) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const ::testing::AssertionResult gtest_ar = (expression)) \ + ; \ + else \ + on_failure(gtest_ar.failure_message()) + + +// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use +// this in your code. +template +AssertionResult AssertPred1Helper(const char* pred_text, + const char* e1, + Pred pred, + const T1& v1) { + if (pred(v1)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1. +// Don't use this in your code. +#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, v1), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use +// this in your code. +#define GTEST_PRED1_(pred, v1, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \ + #v1, \ + pred, \ + v1), on_failure) + +// Unary predicate assertion macros. +#define EXPECT_PRED_FORMAT1(pred_format, v1) \ + GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED1(pred, v1) \ + GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT1(pred_format, v1) \ + GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED1(pred, v1) \ + GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use +// this in your code. +template +AssertionResult AssertPred2Helper(const char* pred_text, + const char* e1, + const char* e2, + Pred pred, + const T1& v1, + const T2& v2) { + if (pred(v1, v2)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2. +// Don't use this in your code. +#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use +// this in your code. +#define GTEST_PRED2_(pred, v1, v2, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \ + #v1, \ + #v2, \ + pred, \ + v1, \ + v2), on_failure) + +// Binary predicate assertion macros. +#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED2(pred, v1, v2) \ + GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED2(pred, v1, v2) \ + GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use +// this in your code. +template +AssertionResult AssertPred3Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3) { + if (pred(v1, v2, v3)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3. +// Don't use this in your code. +#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use +// this in your code. +#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + pred, \ + v1, \ + v2, \ + v3), on_failure) + +// Ternary predicate assertion macros. +#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \ + GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED3(pred, v1, v2, v3) \ + GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \ + GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED3(pred, v1, v2, v3) \ + GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use +// this in your code. +template +AssertionResult AssertPred4Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + const char* e4, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3, + const T4& v4) { + if (pred(v1, v2, v3, v4)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ", " + << e4 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3 + << "\n" << e4 << " evaluates to " << v4; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4. +// Don't use this in your code. +#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use +// this in your code. +#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + #v4, \ + pred, \ + v1, \ + v2, \ + v3, \ + v4), on_failure) + +// 4-ary predicate assertion macros. +#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ + GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED4(pred, v1, v2, v3, v4) \ + GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ + GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED4(pred, v1, v2, v3, v4) \ + GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use +// this in your code. +template +AssertionResult AssertPred5Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + const char* e4, + const char* e5, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3, + const T4& v4, + const T5& v5) { + if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ", " + << e4 << ", " + << e5 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3 + << "\n" << e4 << " evaluates to " << v4 + << "\n" << e5 << " evaluates to " << v5; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5. +// Don't use this in your code. +#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use +// this in your code. +#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + #v4, \ + #v5, \ + pred, \ + v1, \ + v2, \ + v3, \ + v4, \ + v5), on_failure) + +// 5-ary predicate assertion macros. +#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ + GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \ + GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ + GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \ + GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) + + + +#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ + +// Macros for testing equalities and inequalities. +// +// * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual +// * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2 +// * {ASSERT|EXPECT}_LT(v1, v2): Tests that v1 < v2 +// * {ASSERT|EXPECT}_LE(v1, v2): Tests that v1 <= v2 +// * {ASSERT|EXPECT}_GT(v1, v2): Tests that v1 > v2 +// * {ASSERT|EXPECT}_GE(v1, v2): Tests that v1 >= v2 +// +// When they are not, Google Test prints both the tested expressions and +// their actual values. The values must be compatible built-in types, +// or you will get a compiler error. By "compatible" we mean that the +// values can be compared by the respective operator. +// +// Note: +// +// 1. It is possible to make a user-defined type work with +// {ASSERT|EXPECT}_??(), but that requires overloading the +// comparison operators and is thus discouraged by the Google C++ +// Usage Guide. Therefore, you are advised to use the +// {ASSERT|EXPECT}_TRUE() macro to assert that two objects are +// equal. +// +// 2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on +// pointers (in particular, C strings). Therefore, if you use it +// with two C strings, you are testing how their locations in memory +// are related, not how their content is related. To compare two C +// strings by content, use {ASSERT|EXPECT}_STR*(). +// +// 3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to +// {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you +// what the actual value is when it fails, and similarly for the +// other comparisons. +// +// 4. Do not depend on the order in which {ASSERT|EXPECT}_??() +// evaluate their arguments, which is undefined. +// +// 5. These macros evaluate their arguments exactly once. +// +// Examples: +// +// EXPECT_NE(5, Foo()); +// EXPECT_EQ(NULL, a_pointer); +// ASSERT_LT(i, array_size); +// ASSERT_GT(records.size(), 0) << "There is no record left."; + +#define EXPECT_EQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal:: \ + EqHelper::Compare, \ + expected, actual) +#define EXPECT_NE(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual) +#define EXPECT_LE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) +#define EXPECT_LT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) +#define EXPECT_GE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) +#define EXPECT_GT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) + +#define GTEST_ASSERT_EQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal:: \ + EqHelper::Compare, \ + expected, actual) +#define GTEST_ASSERT_NE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2) +#define GTEST_ASSERT_LE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) +#define GTEST_ASSERT_LT(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) +#define GTEST_ASSERT_GE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) +#define GTEST_ASSERT_GT(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) + +// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of +// ASSERT_XY(), which clashes with some users' own code. + +#if !GTEST_DONT_DEFINE_ASSERT_EQ +# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_NE +# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_LE +# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_LT +# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_GE +# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_GT +# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2) +#endif + +// C-string Comparisons. All tests treat NULL and any non-NULL string +// as different. Two NULLs are equal. +// +// * {ASSERT|EXPECT}_STREQ(s1, s2): Tests that s1 == s2 +// * {ASSERT|EXPECT}_STRNE(s1, s2): Tests that s1 != s2 +// * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case +// * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case +// +// For wide or narrow string objects, you can use the +// {ASSERT|EXPECT}_??() macros. +// +// Don't depend on the order in which the arguments are evaluated, +// which is undefined. +// +// These macros evaluate their arguments exactly once. + +#define EXPECT_STREQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) +#define EXPECT_STRNE(s1, s2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) +#define EXPECT_STRCASEEQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) +#define EXPECT_STRCASENE(s1, s2)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) + +#define ASSERT_STREQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) +#define ASSERT_STRNE(s1, s2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) +#define ASSERT_STRCASEEQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) +#define ASSERT_STRCASENE(s1, s2)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) + +// Macros for comparing floating-point numbers. +// +// * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual): +// Tests that two float values are almost equal. +// * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual): +// Tests that two double values are almost equal. +// * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error): +// Tests that v1 and v2 are within the given distance to each other. +// +// Google Test uses ULP-based comparison to automatically pick a default +// error bound that is appropriate for the operands. See the +// FloatingPoint template class in gtest-internal.h if you are +// interested in the implementation details. + +#define EXPECT_FLOAT_EQ(expected, actual)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define EXPECT_DOUBLE_EQ(expected, actual)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define ASSERT_FLOAT_EQ(expected, actual)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define ASSERT_DOUBLE_EQ(expected, actual)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define EXPECT_NEAR(val1, val2, abs_error)\ + EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + val1, val2, abs_error) + +#define ASSERT_NEAR(val1, val2, abs_error)\ + ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + val1, val2, abs_error) + +// These predicate format functions work on floating-point values, and +// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g. +// +// EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0); + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2, + float val1, float val2); +GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2, + double val1, double val2); + + +#if GTEST_OS_WINDOWS + +// Macros that test for HRESULT failure and success, these are only useful +// on Windows, and rely on Windows SDK macros and APIs to compile. +// +// * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr) +// +// When expr unexpectedly fails or succeeds, Google Test prints the +// expected result and the actual result with both a human-readable +// string representation of the error, if available, as well as the +// hex result code. +# define EXPECT_HRESULT_SUCCEEDED(expr) \ + EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) + +# define ASSERT_HRESULT_SUCCEEDED(expr) \ + ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) + +# define EXPECT_HRESULT_FAILED(expr) \ + EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) + +# define ASSERT_HRESULT_FAILED(expr) \ + ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) + +#endif // GTEST_OS_WINDOWS + +// Macros that execute statement and check that it doesn't generate new fatal +// failures in the current thread. +// +// * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement); +// +// Examples: +// +// EXPECT_NO_FATAL_FAILURE(Process()); +// ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed"; +// +#define ASSERT_NO_FATAL_FAILURE(statement) \ + GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_) +#define EXPECT_NO_FATAL_FAILURE(statement) \ + GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_) + +// Causes a trace (including the source file path, the current line +// number, and the given message) to be included in every test failure +// message generated by code in the current scope. The effect is +// undone when the control leaves the current scope. +// +// The message argument can be anything streamable to std::ostream. +// +// In the implementation, we include the current line number as part +// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s +// to appear in the same block - as long as they are on different +// lines. +#define SCOPED_TRACE(message) \ + ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\ + __FILE__, __LINE__, ::testing::Message() << (message)) + +// Compile-time assertion for type equality. +// StaticAssertTypeEq() compiles iff type1 and type2 are +// the same type. The value it returns is not interesting. +// +// Instead of making StaticAssertTypeEq a class template, we make it a +// function template that invokes a helper class template. This +// prevents a user from misusing StaticAssertTypeEq by +// defining objects of that type. +// +// CAVEAT: +// +// When used inside a method of a class template, +// StaticAssertTypeEq() is effective ONLY IF the method is +// instantiated. For example, given: +// +// template class Foo { +// public: +// void Bar() { testing::StaticAssertTypeEq(); } +// }; +// +// the code: +// +// void Test1() { Foo foo; } +// +// will NOT generate a compiler error, as Foo::Bar() is never +// actually instantiated. Instead, you need: +// +// void Test2() { Foo foo; foo.Bar(); } +// +// to cause a compiler error. +template +bool StaticAssertTypeEq() { + (void)internal::StaticAssertTypeEqHelper(); + return true; +} + +// Defines a test. +// +// The first parameter is the name of the test case, and the second +// parameter is the name of the test within the test case. +// +// The convention is to end the test case name with "Test". For +// example, a test case for the Foo class can be named FooTest. +// +// The user should put his test code between braces after using this +// macro. Example: +// +// TEST(FooTest, InitializesCorrectly) { +// Foo foo; +// EXPECT_TRUE(foo.StatusIsOK()); +// } + +// Note that we call GetTestTypeId() instead of GetTypeId< +// ::testing::Test>() here to get the type ID of testing::Test. This +// is to work around a suspected linker bug when using Google Test as +// a framework on Mac OS X. The bug causes GetTypeId< +// ::testing::Test>() to return different values depending on whether +// the call is from the Google Test framework itself or from user test +// code. GetTestTypeId() is guaranteed to always return the same +// value, as it always calls GetTypeId<>() from the Google Test +// framework. +#define GTEST_TEST(test_case_name, test_name)\ + GTEST_TEST_(test_case_name, test_name, \ + ::testing::Test, ::testing::internal::GetTestTypeId()) + +// Define this macro to 1 to omit the definition of TEST(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_TEST +# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name) +#endif + +// Defines a test that uses a test fixture. +// +// The first parameter is the name of the test fixture class, which +// also doubles as the test case name. The second parameter is the +// name of the test within the test case. +// +// A test fixture class must be declared earlier. The user should put +// his test code between braces after using this macro. Example: +// +// class FooTest : public testing::Test { +// protected: +// virtual void SetUp() { b_.AddElement(3); } +// +// Foo a_; +// Foo b_; +// }; +// +// TEST_F(FooTest, InitializesCorrectly) { +// EXPECT_TRUE(a_.StatusIsOK()); +// } +// +// TEST_F(FooTest, ReturnsElementCountCorrectly) { +// EXPECT_EQ(0, a_.size()); +// EXPECT_EQ(1, b_.size()); +// } + +#define TEST_F(test_fixture, test_name)\ + GTEST_TEST_(test_fixture, test_name, test_fixture, \ + ::testing::internal::GetTypeId()) + +} // namespace testing + +// Use this function in main() to run all tests. It returns 0 if all +// tests are successful, or 1 otherwise. +// +// RUN_ALL_TESTS() should be invoked after the command line has been +// parsed by InitGoogleTest(). +// +// This function was formerly a macro; thus, it is in the global +// namespace and has an all-caps name. +int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_; + +inline int RUN_ALL_TESTS() { + return ::testing::UnitTest::GetInstance()->Run(); +} + +#endif // GTEST_INCLUDE_GTEST_GTEST_H_ diff --git a/Engine/lib/gtest/fused-src/gtest/gtest_main.cc b/Engine/lib/gtest/fused-src/gtest/gtest_main.cc new file mode 100644 index 000000000..f30282255 --- /dev/null +++ b/Engine/lib/gtest/fused-src/gtest/gtest_main.cc @@ -0,0 +1,38 @@ +// Copyright 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "gtest/gtest.h" + +GTEST_API_ int main(int argc, char **argv) { + printf("Running main() from gtest_main.cc\n"); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/Engine/lib/libtheora/CHANGES b/Engine/lib/libtheora/CHANGES index 74183d91b..b30327e63 100644 --- a/Engine/lib/libtheora/CHANGES +++ b/Engine/lib/libtheora/CHANGES @@ -1,3 +1,65 @@ +libtheora 1.1.1 (2009 October 1) + + - Fix problems with MSVC inline assembly + - Add the missing encoder_disabled.c to the distribution + - build updates: autogen.sh should work better after switching systems + and the MSVC project now defaults to the dynamic runtime library + - Namespace some variables to avoid conflicts on wince. + +libtheora 1.1.0 (2009 September 24) + + - Fix various small issues with the example and telemetry code + - Fix handing a zero-byte packet as the first frame + - Documentation cleanup + - Two minor build fixes + +libtheora 1.1beta3 (2009 August 22) + + - Rate control fixes to smooth quality + - MSVC build now exports all of the 1.0 api + - Assorted small bug fixes + +libtheora 1.1beta2 (2009 August 12) + + - Fix a rate control problem with difficult input + - Build fixes for OpenBSD and Apple Xcode + - Examples now all use the 1.0 api + - TH_ENCCTL_SET_SPLEVEL works again + - Various bug fixes and source tree rearrangement + +libtheora 1.1beta1 (2009 August 5) + + - Support for two-pass encoding + - Performance optimization of both encoder and decoder + - Encoder supports dynamic adjustment of quality and + bitrate targets + - Encoder is generally more configurable, and all + rate control modes perform better + - Encoder now accepts 4:2:2 and 4:4:4 chroma sampling + - Decoder telemetry output shows quantization choice + and a breakdown of bitrate usage in the frame + - MSVC assembly optimizations up to date and functional + +libtheora 1.1alpha2 (2009 May 26) + + - Reduce lambda for small quantizers. + - New encoder fDCT does better on smooth gradients + - Use SATD for mode decisions (1-2% bitrate reduction) + - Assembly rewrite for new features and general speed up + - Share code between the encoder and decoder for performance + - Fix 4:2:2 decoding and telemetry + - MSVC project files updated, but assembly is disabled. + - New configure option --disable-spec to work around toolchain + detection failures. + - Limit symbol exports on MacOS X. + - Port remaining unit tests from the 1.0 release. + +libtheora 1.1alpha1 (2009 March 27) + + - Encoder rewrite with much improved vbr quality/bitrate and + better tracking of the target rate in cbr mode. + - MSVC project files do not work in this release. + libtheora 1.0 (2008 November 3) - Merge x86 assembly for forward DCT from Thusnelda branch. diff --git a/Engine/lib/libtheora/COPYING b/Engine/lib/libtheora/COPYING index 5a711972d..c8ccce4ff 100644 --- a/Engine/lib/libtheora/COPYING +++ b/Engine/lib/libtheora/COPYING @@ -1,4 +1,4 @@ -Copyright (C) 2002-2008 Xiph.Org Foundation and contributors. +Copyright (C) 2002-2009 Xiph.org Foundation Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -11,7 +11,7 @@ notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -- Neither the name of the Xiph.Org Foundation nor the names of its +- Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/Engine/lib/libtheora/LICENSE b/Engine/lib/libtheora/LICENSE new file mode 100644 index 000000000..5e5ec0846 --- /dev/null +++ b/Engine/lib/libtheora/LICENSE @@ -0,0 +1,18 @@ +Please see the file COPYING for the copyright license for this software. + +In addition to and irrespective of the copyright license associated +with this software, On2 Technologies, Inc. makes the following statement +regarding technology used in this software: + + On2 represents and warrants that it shall not assert any rights + relating to infringement of On2's registered patents, nor initiate + any litigation asserting such rights, against any person who, or + entity which utilizes the On2 VP3 Codec Software, including any + use, distribution, and sale of said Software; which make changes, + modifications, and improvements in said Software; and to use, + distribute, and sell said changes as well as applications for other + fields of use. + +This reference implementation is originally derived from the On2 VP3 +Codec Software, and the Theora video format is essentially compatible +with the VP3 video format, consisting of a backward-compatible superset. diff --git a/Engine/lib/libtheora/include/Makefile.am b/Engine/lib/libtheora/include/Makefile.am new file mode 100644 index 000000000..d5db4b40f --- /dev/null +++ b/Engine/lib/libtheora/include/Makefile.am @@ -0,0 +1,3 @@ +## Process this file with automake to produce Makefile.in + +SUBDIRS = theora diff --git a/Engine/lib/libtheora/include/Makefile.in b/Engine/lib/libtheora/include/Makefile.in new file mode 100644 index 000000000..805e6c29e --- /dev/null +++ b/Engine/lib/libtheora/include/Makefile.in @@ -0,0 +1,414 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AR = @AR@ +ARGZ_H = @ARGZ_H@ +AS = @AS@ +AWK = @AWK@ +BUILDABLE_EXAMPLES = @BUILDABLE_EXAMPLES@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +DEBUG = @DEBUG@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +F77 = @F77@ +GCJ = @GCJ@ +GCJFLAGS = @GCJFLAGS@ +GETOPT_OBJS = @GETOPT_OBJS@ +GREP = @GREP@ +HAVE_BIBTEX = @HAVE_BIBTEX@ +HAVE_DOXYGEN = @HAVE_DOXYGEN@ +HAVE_PDFLATEX = @HAVE_PDFLATEX@ +HAVE_PKG_CONFIG = @HAVE_PKG_CONFIG@ +HAVE_TRANSFIG = @HAVE_TRANSFIG@ +HAVE_VALGRIND = @HAVE_VALGRIND@ +INCLTDL = @INCLTDL@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBLTDL = @LIBLTDL@ +LIBM = @LIBM@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTDLDEPS = @LTDLDEPS@ +LTDLINCL = @LTDLINCL@ +LTDLOPEN = @LTDLOPEN@ +LT_CONFIG_H = @LT_CONFIG_H@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OGG_CFLAGS = @OGG_CFLAGS@ +OGG_LIBS = @OGG_LIBS@ +OSS_LIBS = @OSS_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PKG_CONFIG = @PKG_CONFIG@ +PNG_CFLAGS = @PNG_CFLAGS@ +PNG_LIBS = @PNG_LIBS@ +PROFILE = @PROFILE@ +RANLIB = @RANLIB@ +RC = @RC@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +STRIP = @STRIP@ +THDEC_LIB_AGE = @THDEC_LIB_AGE@ +THDEC_LIB_CURRENT = @THDEC_LIB_CURRENT@ +THDEC_LIB_REVISION = @THDEC_LIB_REVISION@ +THENC_LIB_AGE = @THENC_LIB_AGE@ +THENC_LIB_CURRENT = @THENC_LIB_CURRENT@ +THENC_LIB_REVISION = @THENC_LIB_REVISION@ +THEORADEC_LDFLAGS = @THEORADEC_LDFLAGS@ +THEORAENC_LDFLAGS = @THEORAENC_LDFLAGS@ +THEORA_LDFLAGS = @THEORA_LDFLAGS@ +TH_LIB_AGE = @TH_LIB_AGE@ +TH_LIB_CURRENT = @TH_LIB_CURRENT@ +TH_LIB_REVISION = @TH_LIB_REVISION@ +VALGRIND_ENVIRONMENT = @VALGRIND_ENVIRONMENT@ +VERSION = @VERSION@ +VORBISENC_LIBS = @VORBISENC_LIBS@ +VORBISFILE_LIBS = @VORBISFILE_LIBS@ +VORBIS_CFLAGS = @VORBIS_CFLAGS@ +VORBIS_LIBS = @VORBIS_LIBS@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +lt_ECHO = @lt_ECHO@ +ltdl_LIBOBJS = @ltdl_LIBOBJS@ +ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@ +sys_symbol_underscore = @sys_symbol_underscore@ + +SUBDIRS = theora +subdir = include +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = + +RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ + uninstall-info-recursive all-recursive install-data-recursive \ + install-exec-recursive installdirs-recursive install-recursive \ + uninstall-recursive check-recursive installcheck-recursive +DIST_COMMON = Makefile.am Makefile.in +DIST_SUBDIRS = $(SUBDIRS) +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu include/Makefile +Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" \ + distdir=../$(distdir)/$$subdir \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: + +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + +distclean-am: clean-am distclean-generic distclean-libtool \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ + clean-generic clean-libtool clean-recursive distclean \ + distclean-generic distclean-libtool distclean-recursive \ + distclean-tags distdir dvi dvi-am dvi-recursive info info-am \ + info-recursive install install-am install-data install-data-am \ + install-data-recursive install-exec install-exec-am \ + install-exec-recursive install-info install-info-am \ + install-info-recursive install-man install-recursive \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am installdirs-recursive maintainer-clean \ + maintainer-clean-generic maintainer-clean-recursive mostlyclean \ + mostlyclean-generic mostlyclean-libtool mostlyclean-recursive \ + tags tags-recursive uninstall uninstall-am uninstall-info-am \ + uninstall-info-recursive uninstall-recursive + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Engine/lib/libtheora/include/theora/Makefile.am b/Engine/lib/libtheora/include/theora/Makefile.am new file mode 100644 index 000000000..5479e82a5 --- /dev/null +++ b/Engine/lib/libtheora/include/theora/Makefile.am @@ -0,0 +1,7 @@ +## Process this file with automake to produce Makefile.in + +theoraincludedir = $(includedir)/theora + +theorainclude_HEADERS = theora.h theoradec.h theoraenc.h codec.h + +noinst_HEADERS = codec.h theoradec.h diff --git a/Engine/lib/libtheora/include/theora/Makefile.in b/Engine/lib/libtheora/include/theora/Makefile.in new file mode 100644 index 000000000..d20e60ab4 --- /dev/null +++ b/Engine/lib/libtheora/include/theora/Makefile.in @@ -0,0 +1,355 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AR = @AR@ +ARGZ_H = @ARGZ_H@ +AS = @AS@ +AWK = @AWK@ +BUILDABLE_EXAMPLES = @BUILDABLE_EXAMPLES@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +DEBUG = @DEBUG@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +F77 = @F77@ +GCJ = @GCJ@ +GCJFLAGS = @GCJFLAGS@ +GETOPT_OBJS = @GETOPT_OBJS@ +GREP = @GREP@ +HAVE_BIBTEX = @HAVE_BIBTEX@ +HAVE_DOXYGEN = @HAVE_DOXYGEN@ +HAVE_PDFLATEX = @HAVE_PDFLATEX@ +HAVE_PKG_CONFIG = @HAVE_PKG_CONFIG@ +HAVE_TRANSFIG = @HAVE_TRANSFIG@ +HAVE_VALGRIND = @HAVE_VALGRIND@ +INCLTDL = @INCLTDL@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBLTDL = @LIBLTDL@ +LIBM = @LIBM@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTDLDEPS = @LTDLDEPS@ +LTDLINCL = @LTDLINCL@ +LTDLOPEN = @LTDLOPEN@ +LT_CONFIG_H = @LT_CONFIG_H@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OGG_CFLAGS = @OGG_CFLAGS@ +OGG_LIBS = @OGG_LIBS@ +OSS_LIBS = @OSS_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PKG_CONFIG = @PKG_CONFIG@ +PNG_CFLAGS = @PNG_CFLAGS@ +PNG_LIBS = @PNG_LIBS@ +PROFILE = @PROFILE@ +RANLIB = @RANLIB@ +RC = @RC@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +STRIP = @STRIP@ +THDEC_LIB_AGE = @THDEC_LIB_AGE@ +THDEC_LIB_CURRENT = @THDEC_LIB_CURRENT@ +THDEC_LIB_REVISION = @THDEC_LIB_REVISION@ +THENC_LIB_AGE = @THENC_LIB_AGE@ +THENC_LIB_CURRENT = @THENC_LIB_CURRENT@ +THENC_LIB_REVISION = @THENC_LIB_REVISION@ +THEORADEC_LDFLAGS = @THEORADEC_LDFLAGS@ +THEORAENC_LDFLAGS = @THEORAENC_LDFLAGS@ +THEORA_LDFLAGS = @THEORA_LDFLAGS@ +TH_LIB_AGE = @TH_LIB_AGE@ +TH_LIB_CURRENT = @TH_LIB_CURRENT@ +TH_LIB_REVISION = @TH_LIB_REVISION@ +VALGRIND_ENVIRONMENT = @VALGRIND_ENVIRONMENT@ +VERSION = @VERSION@ +VORBISENC_LIBS = @VORBISENC_LIBS@ +VORBISFILE_LIBS = @VORBISFILE_LIBS@ +VORBIS_CFLAGS = @VORBIS_CFLAGS@ +VORBIS_LIBS = @VORBIS_LIBS@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +lt_ECHO = @lt_ECHO@ +ltdl_LIBOBJS = @ltdl_LIBOBJS@ +ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@ +sys_symbol_underscore = @sys_symbol_underscore@ + +theoraincludedir = $(includedir)/theora + +theorainclude_HEADERS = theora.h theoradec.h theoraenc.h codec.h + +noinst_HEADERS = codec.h theoradec.h +subdir = include/theora +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +HEADERS = $(noinst_HEADERS) $(theorainclude_HEADERS) + +DIST_COMMON = $(noinst_HEADERS) $(theorainclude_HEADERS) Makefile.am \ + Makefile.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu include/theora/Makefile +Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: +theoraincludeHEADERS_INSTALL = $(INSTALL_HEADER) +install-theoraincludeHEADERS: $(theorainclude_HEADERS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(theoraincludedir) + @list='$(theorainclude_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " $(theoraincludeHEADERS_INSTALL) $$d$$p $(DESTDIR)$(theoraincludedir)/$$f"; \ + $(theoraincludeHEADERS_INSTALL) $$d$$p $(DESTDIR)$(theoraincludedir)/$$f; \ + done + +uninstall-theoraincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(theorainclude_HEADERS)'; for p in $$list; do \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " rm -f $(DESTDIR)$(theoraincludedir)/$$f"; \ + rm -f $(DESTDIR)$(theoraincludedir)/$$f; \ + done + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) + +installdirs: + $(mkinstalldirs) $(DESTDIR)$(theoraincludedir) + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic distclean-libtool \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: install-theoraincludeHEADERS + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +uninstall-am: uninstall-info-am uninstall-theoraincludeHEADERS + +.PHONY: GTAGS all all-am check check-am clean clean-generic \ + clean-libtool distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip install-theoraincludeHEADERS installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool tags uninstall uninstall-am \ + uninstall-info-am uninstall-theoraincludeHEADERS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Engine/lib/libtheora/include/theora/codec.h b/Engine/lib/libtheora/include/theora/codec.h index afdc1b0fa..5c2669630 100644 --- a/Engine/lib/libtheora/include/theora/codec.h +++ b/Engine/lib/libtheora/include/theora/codec.h @@ -5,7 +5,7 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation http://www.xiph.org/ * * * ******************************************************************** @@ -24,10 +24,10 @@ * implementation for Theora, a free, * patent-unencumbered video codec. * Theora is derived from On2's VP3 codec with additional features and - * integration for Ogg multimedia formats by + * integration with Ogg multimedia formats by * the Xiph.Org Foundation. * Complete documentation of the format itself is available in - * the Theora + * the Theora * specification. * * \subsection Organization @@ -92,9 +92,9 @@ extern "C" { /*@}*/ /**The currently defined color space tags. - * See the Theora - * specification, Chapter 4, for exact details on the meaning of each of - * these color spaces.*/ + * See the Theora + * specification, Chapter 4, for exact details on the meaning + * of each of these color spaces.*/ typedef enum{ /**The color space was not specified at the encoder. It may be conveyed by an external means.*/ @@ -108,13 +108,13 @@ typedef enum{ }th_colorspace; /**The currently defined pixel format tags. - * See the Theora + * See the Theora * specification, Section 4.4, for details on the precise sample * locations.*/ typedef enum{ /**Chroma decimation by 2 in both the X and Y directions (4:2:0). - The Cb and Cr chroma planes are half the width and half the height of the - luma plane.*/ + The Cb and Cr chroma planes are half the width and half the + height of the luma plane.*/ TH_PF_420, /**Currently reserved.*/ TH_PF_RSVD, @@ -133,11 +133,11 @@ typedef enum{ /**A buffer for a single color plane in an uncompressed image. * This contains the image data in a left-to-right, top-down format. - * Each row of pixels is stored contiguously in memory, but successive rows - * need not be. + * Each row of pixels is stored contiguously in memory, but successive + * rows need not be. * Use \a stride to compute the offset of the next row. - * The encoder accepts both positive \a stride values (top-down in memory) and - * negative (bottom-up in memory). + * The encoder accepts both positive \a stride values (top-down in memory) + * and negative (bottom-up in memory). * The decoder currently always generates images with positive strides.*/ typedef struct{ /**The width of this plane.*/ @@ -151,18 +151,18 @@ typedef struct{ }th_img_plane; /**A complete image buffer for an uncompressed frame. - * The chroma planes may be decimated by a factor of two in either direction, - * as indicated by th_info#pixel_fmt. + * The chroma planes may be decimated by a factor of two in either + * direction, as indicated by th_info#pixel_fmt. * The width and height of the Y' plane must be multiples of 16. - * They may need to be cropped for display, using the rectangle specified by - * th_info#pic_x, th_info#pic_y, th_info#pic_width, and - * th_info#pic_height. + * They may need to be cropped for display, using the rectangle + * specified by th_info#pic_x, th_info#pic_y, th_info#pic_width, + * and th_info#pic_height. * All samples are 8 bits. * \note The term YUV often used to describe a colorspace is ambiguous. - * The exact parameters of the RGB to YUV conversion process aside, in many - * contexts the U and V channels actually have opposite meanings. - * To avoid this confusion, we are explicit: the name of the color channels are - * Y'CbCr, and they appear in that order, always. + * The exact parameters of the RGB to YUV conversion process aside, in + * many contexts the U and V channels actually have opposite meanings. + * To avoid this confusion, we are explicit: the name of the color + * channels are Y'CbCr, and they appear in that order, always. * The prime symbol denotes that the Y channel is non-linear. * Cb and Cr stand for "Chroma blue" and "Chroma red", respectively.*/ typedef th_img_plane th_ycbcr_buffer[3]; @@ -192,7 +192,7 @@ typedef th_img_plane th_ycbcr_buffer[3]; * * It is also generally recommended that the offsets and sizes should still be * multiples of 2 to avoid chroma sampling shifts when chroma is sub-sampled. - * See the Theora + * See the Theora * specification, Section 4.4, for more details. * * Frame rate, in frames per second, is stored as a rational fraction, as is @@ -230,8 +230,8 @@ typedef struct{ * #frame_height-#pic_height-#pic_y must be no larger than 255. * This slightly funny restriction is due to the fact that the offset is * specified from the top of the image for consistency with the standard - * graphics left-handed coordinate system used throughout this API, while it - * is stored in the encoded stream as an offset from the bottom.*/ + * graphics left-handed coordinate system used throughout this API, while + * it is stored in the encoded stream as an offset from the bottom.*/ ogg_uint32_t pic_y; /**\name Frame rate * The frame rate, as a fraction. @@ -259,9 +259,6 @@ typedef struct{ /**The target bit-rate in bits per second. If initializing an encoder with this struct, set this field to a non-zero value to activate CBR encoding by default.*/ - /*TODO: Current encoder does not support CBR mode, or anything like it. - We also don't really know what nominal rate each quality level - corresponds to yet.*/ int target_bitrate; /**The target quality level. Valid values range from 0 to 63, inclusive, with higher values giving @@ -314,7 +311,7 @@ typedef struct{ * A particular tag may occur more than once, and order is significant. * The character set encoding for the strings is always UTF-8, but the tag * names are limited to ASCII, and treated as case-insensitive. - * See the Theora + * See the Theora * specification, Section 6.3.3 for details. * * In filling in this structure, th_decode_headerin() will null-terminate diff --git a/Engine/lib/libtheora/include/theora/theora.h b/Engine/lib/libtheora/include/theora/theora.h index dbef71675..af6eb6f38 100644 --- a/Engine/lib/libtheora/include/theora/theora.h +++ b/Engine/lib/libtheora/include/theora/theora.h @@ -5,7 +5,7 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation http://www.xiph.org/ * * * ******************************************************************** @@ -27,11 +27,11 @@ extern "C" #include -/** \defgroup oldfuncs Legacy pre-1.0 C API */ -/* @{ */ - -/** \mainpage - * +/** \file + * The libtheora pre-1.0 legacy C API. + * + * \ingroup oldfuncs + * * \section intro Introduction * * This is the documentation for the libtheora legacy C API, declared in @@ -42,7 +42,7 @@ extern "C" * * libtheora is the reference implementation for * Theora, a free video codec. - * Theora is derived from On2's VP3 codec with improved integration for + * Theora is derived from On2's VP3 codec with improved integration with * Ogg multimedia formats by Xiph.Org. * * \section overview Overview @@ -114,21 +114,11 @@ extern "C" * checking beyond whether a header bit is present. Instead, use the * theora_decode_header() function and check the return value; or examine the * header bytes at the beginning of the Ogg page. - * - * \subsection example Example Decoder - * - * See - * examples/dump_video.c for a simple decoder implementation. - * - * \section encoding Encoding Process - * - * See - * examples/encoder_example.c for a simple encoder implementation. */ -/** \file - * The libtheora pre-1.0 legacy C API. - */ + +/** \defgroup oldfuncs Legacy pre-1.0 C API */ +/* @{ */ /** * A YUV buffer for passing uncompressed frames to and from the codec. @@ -292,14 +282,21 @@ typedef struct theora_comment{ /**\name theora_control() codes */ - -/**\anchor decctlcodes +/* \anchor decctlcodes_old * These are the available request codes for theora_control() * when called with a decoder instance. - * By convention, these are odd, to distinguish them from the - * \ref encctlcodes "encoder control codes". + * By convention decoder control codes are odd, to distinguish + * them from \ref encctlcodes_old "encoder control codes" which + * are even. + * + * Note that since the 1.0 release, both the legacy and the final + * implementation accept all the same control codes, but only the + * final API declares the newer codes. + * * Keep any experimental or vendor-specific values above \c 0x8000.*/ +/*@{*/ + /**Get the maximum post-processing level. * The decoder supports a post-processing filter that can improve * the appearance of the decoded images. This returns the highest @@ -324,9 +321,9 @@ typedef struct theora_comment{ * \param[in] buf ogg_uint32_t: The maximum distance between key * frames. * \param[out] buf ogg_uint32_t: The actual maximum distance set. - * \retval TH_FAULT \a theora_state or \a buf is NULL. - * \retval TH_EINVAL \a buf_sz is not sizeof(ogg_uint32_t). - * \retval TH_IMPL Not supported by this implementation.*/ + * \retval OC_FAULT \a theora_state or \a buf is NULL. + * \retval OC_EINVAL \a buf_sz is not sizeof(ogg_uint32_t). + * \retval OC_IMPL Not supported by this implementation.*/ #define TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE (4) /**Set the granule position. @@ -338,33 +335,23 @@ typedef struct theora_comment{ */ #define TH_DECCTL_SET_GRANPOS (5) +/**\anchor encctlcodes_old */ -/**\anchor encctlcodes - * These are the available request codes for theora_control() - * when called with an encoder instance. - * By convention, these are even, to distinguish them from the - * \ref decctlcodes "decoder control codes". - * Keep any experimental or vendor-specific values above \c 0x8000.*/ -/*@{*/ /**Sets the quantization parameters to use. * The parameters are copied, not stored by reference, so they can be freed * after this call. * NULL may be specified to revert to the default parameters. - * For the current encoder, scale[ci!=0][qi] must be no greater than - * scale[ci!=0][qi-1] and base[qti][pli][qi][ci] must be no - * greater than base[qti][pli][qi-1][ci]. - * These two conditions ensure that the actual quantizer for a given \a qti, - * \a pli, and \a ci does not increase as \a qi increases. * * \param[in] buf #th_quant_info - * \retval TH_FAULT \a theora_state is NULL. - * \retval TH_EINVAL Encoding has already begun, the quantization parameters - * do not meet one of the above stated conditions, \a buf - * is NULL and \a buf_sz is not zero, or \a buf - * is non-NULL and \a buf_sz is not - * sizeof(#th_quant_info). - * \retval TH_IMPL Not supported by this implementation.*/ + * \retval OC_FAULT \a theora_state is NULL. + * \retval OC_EINVAL Encoding has already begun, the quantization parameters + * are not acceptable to this version of the encoder, + * \a buf is NULL and \a buf_sz is not zero, + * or \a buf is non-NULL and \a buf_sz is + * not sizeof(#th_quant_info). + * \retval OC_IMPL Not supported by this implementation.*/ #define TH_ENCCTL_SET_QUANT_PARAMS (2) + /**Disables any encoder features that would prevent lossless transcoding back * to VP3. * This primarily means disabling block-level QI values and not using 4MV mode @@ -389,10 +376,11 @@ typedef struct theora_comment{ * 4:2:0, the picture region is smaller than the full frame, * or if encoding has begun, preventing the quantization * tables and codebooks from being set. - * \retval TH_FAULT \a theora_state or \a buf is NULL. - * \retval TH_EINVAL \a buf_sz is not sizeof(int). - * \retval TH_IMPL Not supported by this implementation.*/ + * \retval OC_FAULT \a theora_state or \a buf is NULL. + * \retval OC_EINVAL \a buf_sz is not sizeof(int). + * \retval OC_IMPL Not supported by this implementation.*/ #define TH_ENCCTL_SET_VP3_COMPATIBLE (10) + /**Gets the maximum speed level. * Higher speed levels favor quicker encoding over better quality per bit. * Depending on the encoding mode, and the internal algorithms used, quality @@ -402,25 +390,27 @@ typedef struct theora_comment{ * the current encoding mode (VBR vs. CQI, etc.). * * \param[out] buf int: The maximum encoding speed level. - * \retval TH_FAULT \a theora_state or \a buf is NULL. - * \retval TH_EINVAL \a buf_sz is not sizeof(int). - * \retval TH_IMPL Not supported by this implementation in the current + * \retval OC_FAULT \a theora_state or \a buf is NULL. + * \retval OC_EINVAL \a buf_sz is not sizeof(int). + * \retval OC_IMPL Not supported by this implementation in the current * encoding mode.*/ #define TH_ENCCTL_GET_SPLEVEL_MAX (12) + /**Sets the speed level. * By default a speed value of 1 is used. * * \param[in] buf int: The new encoding speed level. * 0 is slowest, larger values use less CPU. - * \retval TH_FAULT \a theora_state or \a buf is NULL. - * \retval TH_EINVAL \a buf_sz is not sizeof(int), or the + * \retval OC_FAULT \a theora_state or \a buf is NULL. + * \retval OC_EINVAL \a buf_sz is not sizeof(int), or the * encoding speed level is out of bounds. * The maximum encoding speed level may be * implementation- and encoding mode-specific, and can be * obtained via #TH_ENCCTL_GET_SPLEVEL_MAX. - * \retval TH_IMPL Not supported by this implementation in the current + * \retval OC_IMPL Not supported by this implementation in the current * encoding mode.*/ #define TH_ENCCTL_SET_SPLEVEL (14) + /*@}*/ #define OC_FAULT -1 /**< General failure */ @@ -779,8 +769,8 @@ extern void theora_comment_clear(theora_comment *tc); * This is used to provide advanced control the encoding process. * \param th A #theora_state handle. * \param req The control code to process. - * See \ref encctlcodes "the list of available control codes" - * for details. + * See \ref encctlcodes_old "the list of available + * control codes" for details. * \param buf The parameters for this control code. * \param buf_sz The size of the parameter buffer.*/ extern int theora_control(theora_state *th,int req,void *buf,size_t buf_sz); diff --git a/Engine/lib/libtheora/include/theora/theoradec.h b/Engine/lib/libtheora/include/theora/theoradec.h index 7c08caadf..b20f0e3a6 100644 --- a/Engine/lib/libtheora/include/theora/theoradec.h +++ b/Engine/lib/libtheora/include/theora/theoradec.h @@ -5,7 +5,7 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation http://www.xiph.org/ * * * ******************************************************************** @@ -38,6 +38,10 @@ extern "C" { * Keep any experimental or vendor-specific values above \c 0x8000.*/ /*@{*/ /**Gets the maximum post-processing level. + * The decoder supports a post-processing filter that can improve + * the appearance of the decoded images. This returns the highest + * level setting for this post-processor, corresponding to maximum + * improvement and computational expense. * * \param[out] _buf int: The maximum post-processing level. * \retval TH_EFAULT \a _dec_ctx or \a _buf is NULL. @@ -47,6 +51,10 @@ extern "C" { /**Sets the post-processing level. * By default, post-processing is disabled. * + * Sets the level of post-processing to use when decoding the + * compressed stream. This must be a value between zero (off) + * and the maximum returned by TH_DECCTL_GET_PPLEVEL_MAX. + * * \param[in] _buf int: The new post-processing level. * 0 to disable; larger values use more CPU. * \retval TH_EFAULT \a _dec_ctx or \a _buf is NULL. @@ -83,6 +91,15 @@ extern "C" { * \retval TH_EINVAL \a _buf_sz is not * sizeof(th_stripe_callback).*/ #define TH_DECCTL_SET_STRIPE_CB (7) + +/**Enables telemetry and sets the macroblock display mode */ +#define TH_DECCTL_SET_TELEMETRY_MBMODE (9) +/**Enables telemetry and sets the motion vector display mode */ +#define TH_DECCTL_SET_TELEMETRY_MV (11) +/**Enables telemetry and sets the adaptive quantization display mode */ +#define TH_DECCTL_SET_TELEMETRY_QI (13) +/**Enables telemetry and sets the bitstream breakdown visualization mode */ +#define TH_DECCTL_SET_TELEMETRY_BITS (15) /*@}*/ @@ -289,6 +306,7 @@ extern int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op, * It may be freed or overwritten without notification when * subsequent frames are decoded. * \retval 0 Success + * \retval TH_EFAULT \a _dec or \a _ycbcr was NULL. */ extern int th_decode_ycbcr_out(th_dec_ctx *_dec, th_ycbcr_buffer _ycbcr); diff --git a/Engine/lib/libtheora/include/theora/theoraenc.h b/Engine/lib/libtheora/include/theora/theoraenc.h index b98285862..fdf2ab21e 100644 --- a/Engine/lib/libtheora/include/theora/theoraenc.h +++ b/Engine/lib/libtheora/include/theora/theoraenc.h @@ -5,7 +5,7 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation http://www.xiph.org/ * * * ******************************************************************** @@ -49,26 +49,20 @@ extern "C" { * NULL and \a _buf_sz is not zero, or \a _buf is * non-NULL and \a _buf_sz is not * sizeof(#th_huff_code)*#TH_NHUFFMAN_TABLES*#TH_NDCT_TOKENS. - * \retval TH_IMPL Not supported by this implementation.*/ + * \retval TH_EIMPL Not supported by this implementation.*/ #define TH_ENCCTL_SET_HUFFMAN_CODES (0) /**Sets the quantization parameters to use. * The parameters are copied, not stored by reference, so they can be freed * after this call. * NULL may be specified to revert to the default parameters. - * For the current encoder, scale[ci!=0][qi] must be no greater than - * scale[ci!=0][qi-1] and base[qti][pli][qi][ci] must be no - * greater than base[qti][pli][qi-1][ci]. - * These two conditions ensure that the actual quantizer for a given \a qti, - * \a pli, and \a ci does not increase as \a qi increases. * * \param[in] _buf #th_quant_info * \retval TH_EFAULT \a _enc_ctx is NULL. - * \retval TH_EINVAL Encoding has already begun, the quantization parameters - * do not meet one of the above stated conditions, \a _buf - * is NULL and \a _buf_sz is not zero, or \a _buf - * is non-NULL and \a _buf_sz is not - * sizeof(#th_quant_info). - * \retval TH_IMPL Not supported by this implementation.*/ + * \retval TH_EINVAL Encoding has already begun, \a _buf is + * NULL and \a _buf_sz is not zero, + * or \a _buf is non-NULL and + * \a _buf_sz is not sizeof(#th_quant_info). + * \retval TH_EIMPL Not supported by this implementation.*/ #define TH_ENCCTL_SET_QUANT_PARAMS (2) /**Sets the maximum distance between key frames. * This can be changed during an encode, but will be bounded by @@ -81,12 +75,12 @@ extern "C" { * \param[out] _buf ogg_uint32_t: The actual maximum distance set. * \retval TH_EFAULT \a _enc_ctx or \a _buf is NULL. * \retval TH_EINVAL \a _buf_sz is not sizeof(ogg_uint32_t). - * \retval TH_IMPL Not supported by this implementation.*/ + * \retval TH_EIMPL Not supported by this implementation.*/ #define TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE (4) /**Disables any encoder features that would prevent lossless transcoding back * to VP3. - * This primarily means disabling block-level QI values and not using 4MV mode - * when any of the luma blocks in a macro block are not coded. + * This primarily means disabling block-adaptive quantization and always coding + * all four luma blocks in a macro block when 4MV is used. * It also includes using the VP3 quantization tables and Huffman codes; if you * set them explicitly after calling this function, the resulting stream will * not be VP3-compatible. @@ -109,7 +103,7 @@ extern "C" { * tables and codebooks from being set. * \retval TH_EFAULT \a _enc_ctx or \a _buf is NULL. * \retval TH_EINVAL \a _buf_sz is not sizeof(int). - * \retval TH_IMPL Not supported by this implementation.*/ + * \retval TH_EIMPL Not supported by this implementation.*/ #define TH_ENCCTL_SET_VP3_COMPATIBLE (10) /**Gets the maximum speed level. * Higher speed levels favor quicker encoding over better quality per bit. @@ -117,28 +111,254 @@ extern "C" { * may actually improve, but in this case bitrate will also likely increase. * In any case, overall rate/distortion performance will probably decrease. * The maximum value, and the meaning of each value, may change depending on - * the current encoding mode (VBR vs. CQI, etc.). + * the current encoding mode (VBR vs. constant quality, etc.). * - * \param[out] _buf int: The maximum encoding speed level. + * \param[out] _buf int: The maximum encoding speed level. * \retval TH_EFAULT \a _enc_ctx or \a _buf is NULL. * \retval TH_EINVAL \a _buf_sz is not sizeof(int). - * \retval TH_IMPL Not supported by this implementation in the current + * \retval TH_EIMPL Not supported by this implementation in the current * encoding mode.*/ #define TH_ENCCTL_GET_SPLEVEL_MAX (12) /**Sets the speed level. - * By default, the slowest speed (0) is used. + * The current speed level may be retrieved using #TH_ENCCTL_GET_SPLEVEL. * - * \param[in] _buf int: The new encoding speed level. - * 0 is slowest, larger values use less CPU. + * \param[in] _buf int: The new encoding speed level. + * 0 is slowest, larger values use less CPU. * \retval TH_EFAULT \a _enc_ctx or \a _buf is NULL. * \retval TH_EINVAL \a _buf_sz is not sizeof(int), or the * encoding speed level is out of bounds. * The maximum encoding speed level may be * implementation- and encoding mode-specific, and can be * obtained via #TH_ENCCTL_GET_SPLEVEL_MAX. - * \retval TH_IMPL Not supported by this implementation in the current + * \retval TH_EIMPL Not supported by this implementation in the current * encoding mode.*/ #define TH_ENCCTL_SET_SPLEVEL (14) +/**Gets the current speed level. + * The default speed level may vary according to encoder implementation, but if + * this control code is not supported (it returns #TH_EIMPL), the default may + * be assumed to be the slowest available speed (0). + * The maximum encoding speed level may be implementation- and encoding + * mode-specific, and can be obtained via #TH_ENCCTL_GET_SPLEVEL_MAX. + * + * \param[out] _buf int: The current encoding speed level. + * 0 is slowest, larger values use less CPU. + * \retval TH_EFAULT \a _enc_ctx or \a _buf is NULL. + * \retval TH_EINVAL \a _buf_sz is not sizeof(int). + * \retval TH_EIMPL Not supported by this implementation in the current + * encoding mode.*/ +#define TH_ENCCTL_GET_SPLEVEL (16) +/**Sets the number of duplicates of the next frame to produce. + * Although libtheora can encode duplicate frames very cheaply, it costs some + * amount of CPU to detect them, and a run of duplicates cannot span a + * keyframe boundary. + * This control code tells the encoder to produce the specified number of extra + * duplicates of the next frame. + * This allows the encoder to make smarter keyframe placement decisions and + * rate control decisions, and reduces CPU usage as well, when compared to + * just submitting the same frame for encoding multiple times. + * This setting only applies to the next frame submitted for encoding. + * You MUST call th_encode_packetout() repeatedly until it returns 0, or the + * extra duplicate frames will be lost. + * + * \param[in] _buf int: The number of duplicates to produce. + * If this is negative or zero, no duplicates will be produced. + * \retval TH_EFAULT \a _enc_ctx or \a _buf is NULL. + * \retval TH_EINVAL \a _buf_sz is not sizeof(int), or the + * number of duplicates is greater than or equal to the + * maximum keyframe interval. + * In the latter case, NO duplicate frames will be produced. + * You must ensure that the maximum keyframe interval is set + * larger than the maximum number of duplicates you will + * ever wish to insert prior to encoding. + * \retval TH_EIMPL Not supported by this implementation in the current + * encoding mode.*/ +#define TH_ENCCTL_SET_DUP_COUNT (18) +/**Modifies the default bitrate management behavior. + * Use to allow or disallow frame dropping, and to enable or disable capping + * bit reservoir overflows and underflows. + * See \ref encctlcodes "the list of available flags". + * The flags are set by default to + * #TH_RATECTL_DROP_FRAMES|#TH_RATECTL_CAP_OVERFLOW. + * + * \param[in] _buf int: Any combination of + * \ref ratectlflags "the available flags": + * - #TH_RATECTL_DROP_FRAMES: Enable frame dropping. + * - #TH_RATECTL_CAP_OVERFLOW: Don't bank excess bits for later + * use. + * - #TH_RATECTL_CAP_UNDERFLOW: Don't try to make up shortfalls + * later. + * \retval TH_EFAULT \a _enc_ctx or \a _buf is NULL. + * \retval TH_EINVAL \a _buf_sz is not sizeof(int) or rate control + * is not enabled. + * \retval TH_EIMPL Not supported by this implementation in the current + * encoding mode.*/ +#define TH_ENCCTL_SET_RATE_FLAGS (20) +/**Sets the size of the bitrate management bit reservoir as a function + * of number of frames. + * The reservoir size affects how quickly bitrate management reacts to + * instantaneous changes in the video complexity. + * Larger reservoirs react more slowly, and provide better overall quality, but + * require more buffering by a client, adding more latency to live streams. + * By default, libtheora sets the reservoir to the maximum distance between + * keyframes, subject to a minimum and maximum limit. + * This call may be used to increase or decrease the reservoir, increasing or + * decreasing the allowed temporary variance in bitrate. + * An implementation may impose some limits on the size of a reservoir it can + * handle, in which case the actual reservoir size may not be exactly what was + * requested. + * The actual value set will be returned. + * + * \param[in] _buf int: Requested size of the reservoir measured in + * frames. + * \param[out] _buf int: The actual size of the reservoir set. + * \retval TH_EFAULT \a _enc_ctx or \a _buf is NULL. + * \retval TH_EINVAL \a _buf_sz is not sizeof(int), or rate control + * is not enabled. The buffer has an implementation + * defined minimum and maximum size and the value in _buf + * will be adjusted to match the actual value set. + * \retval TH_EIMPL Not supported by this implementation in the current + * encoding mode.*/ +#define TH_ENCCTL_SET_RATE_BUFFER (22) +/**Enable pass 1 of two-pass encoding mode and retrieve the first pass metrics. + * Pass 1 mode must be enabled before the first frame is encoded, and a target + * bitrate must have already been specified to the encoder. + * Although this does not have to be the exact rate that will be used in the + * second pass, closer values may produce better results. + * The first call returns the size of the two-pass header data, along with some + * placeholder content, and sets the encoder into pass 1 mode implicitly. + * This call sets the encoder to pass 1 mode implicitly. + * Then, a subsequent call must be made after each call to + * th_encode_ycbcr_in() to retrieve the metrics for that frame. + * An additional, final call must be made to retrieve the summary data, + * containing such information as the total number of frames, etc. + * This must be stored in place of the placeholder data that was returned + * in the first call, before the frame metrics data. + * All of this data must be presented back to the encoder during pass 2 using + * #TH_ENCCTL_2PASS_IN. + * + * \param[out] char *_buf: Returns a pointer to internal storage + * containing the two pass metrics data. + * This storage is only valid until the next call, or until the + * encoder context is freed, and must be copied by the + * application. + * \retval >=0 The number of bytes of metric data available in the + * returned buffer. + * \retval TH_EFAULT \a _enc_ctx or \a _buf is NULL. + * \retval TH_EINVAL \a _buf_sz is not sizeof(char *), no target + * bitrate has been set, or the first call was made after + * the first frame was submitted for encoding. + * \retval TH_EIMPL Not supported by this implementation.*/ +#define TH_ENCCTL_2PASS_OUT (24) +/**Submits two-pass encoding metric data collected the first encoding pass to + * the second pass. + * The first call must be made before the first frame is encoded, and a target + * bitrate must have already been specified to the encoder. + * It sets the encoder to pass 2 mode implicitly; this cannot be disabled. + * The encoder may require reading data from some or all of the frames in + * advance, depending on, e.g., the reservoir size used in the second pass. + * You must call this function repeatedly before each frame to provide data + * until either a) it fails to consume all of the data presented or b) all of + * the pass 1 data has been consumed. + * In the first case, you must save the remaining data to be presented after + * the next frame. + * You can call this function with a NULL argument to get an upper bound on + * the number of bytes that will be required before the next frame. + * + * When pass 2 is first enabled, the default bit reservoir is set to the entire + * file; this gives maximum flexibility but can lead to very high peak rates. + * You can subsequently set it to another value with #TH_ENCCTL_SET_RATE_BUFFER + * (e.g., to set it to the keyframe interval for non-live streaming), however, + * you may then need to provide more data before the next frame. + * + * \param[in] _buf char[]: A buffer containing the data returned by + * #TH_ENCCTL_2PASS_OUT in pass 1. + * You may pass NULL for \a _buf to return an upper + * bound on the number of additional bytes needed before the + * next frame. + * The summary data returned at the end of pass 1 must be at + * the head of the buffer on the first call with a + * non-NULL \a _buf, and the placeholder data + * returned at the start of pass 1 should be omitted. + * After each call you should advance this buffer by the number + * of bytes consumed. + * \retval >0 The number of bytes of metric data required/consumed. + * \retval 0 No more data is required before the next frame. + * \retval TH_EFAULT \a _enc_ctx is NULL. + * \retval TH_EINVAL No target bitrate has been set, or the first call was + * made after the first frame was submitted for + * encoding. + * \retval TH_ENOTFORMAT The data did not appear to be pass 1 from a compatible + * implementation of this library. + * \retval TH_EBADHEADER The data was invalid; this may be returned when + * attempting to read an aborted pass 1 file that still + * has the placeholder data in place of the summary + * data. + * \retval TH_EIMPL Not supported by this implementation.*/ +#define TH_ENCCTL_2PASS_IN (26) +/**Sets the current encoding quality. + * This is only valid so long as no bitrate has been specified, either through + * the #th_info struct used to initialize the encoder or through + * #TH_ENCCTL_SET_BITRATE (this restriction may be relaxed in a future + * version). + * If it is set before the headers are emitted, the target quality encoded in + * them will be updated. + * + * \param[in] _buf int: The new target quality, in the range 0...63, + * inclusive. + * \retval 0 Success. + * \retval TH_EFAULT \a _enc_ctx or \a _buf is NULL. + * \retval TH_EINVAL A target bitrate has already been specified, or the + * quality index was not in the range 0...63. + * \retval TH_EIMPL Not supported by this implementation.*/ +#define TH_ENCCTL_SET_QUALITY (28) +/**Sets the current encoding bitrate. + * Once a bitrate is set, the encoder must use a rate-controlled mode for all + * future frames (this restriction may be relaxed in a future version). + * If it is set before the headers are emitted, the target bitrate encoded in + * them will be updated. + * Due to the buffer delay, the exact bitrate of each section of the encode is + * not guaranteed. + * The encoder may have already used more bits than allowed for the frames it + * has encoded, expecting to make them up in future frames, or it may have + * used fewer, holding the excess in reserve. + * The exact transition between the two bitrates is not well-defined by this + * API, but may be affected by flags set with #TH_ENCCTL_SET_RATE_FLAGS. + * After a number of frames equal to the buffer delay, one may expect further + * output to average at the target bitrate. + * + * \param[in] _buf long: The new target bitrate, in bits per second. + * \retval 0 Success. + * \retval TH_EFAULT \a _enc_ctx or \a _buf is NULL. + * \retval TH_EINVAL The target bitrate was not positive. + * \retval TH_EIMPL Not supported by this implementation.*/ +#define TH_ENCCTL_SET_BITRATE (30) + +/*@}*/ + + +/**\name TH_ENCCTL_SET_RATE_FLAGS flags + * \anchor ratectlflags + * These are the flags available for use with #TH_ENCCTL_SET_RATE_FLAGS.*/ +/*@{*/ +/**Drop frames to keep within bitrate buffer constraints. + * This can have a severe impact on quality, but is the only way to ensure that + * bitrate targets are met at low rates during sudden bursts of activity.*/ +#define TH_RATECTL_DROP_FRAMES (0x1) +/**Ignore bitrate buffer overflows. + * If the encoder uses so few bits that the reservoir of available bits + * overflows, ignore the excess. + * The encoder will not try to use these extra bits in future frames. + * At high rates this may cause the result to be undersized, but allows a + * client to play the stream using a finite buffer; it should normally be + * enabled.*/ +#define TH_RATECTL_CAP_OVERFLOW (0x2) +/**Ignore bitrate buffer underflows. + * If the encoder uses so many bits that the reservoir of available bits + * underflows, ignore the deficit. + * The encoder will not try to make up these extra bits in future frames. + * At low rates this may cause the result to be oversized; it should normally + * be disabled.*/ +#define TH_RATECTL_CAP_UNDERFLOW (0x4) /*@}*/ diff --git a/Engine/lib/libtheora/lib/Makefile.am b/Engine/lib/libtheora/lib/Makefile.am new file mode 100644 index 000000000..89ce26120 --- /dev/null +++ b/Engine/lib/libtheora/lib/Makefile.am @@ -0,0 +1,173 @@ +INCLUDES = -I$(top_srcdir)/include +AM_CFLAGS = $(OGG_CFLAGS) $(CAIRO_CFLAGS) + +EXTRA_DIST = \ + cpu.c \ + encoder_disabled.c \ + x86/mmxencfrag.c \ + x86/mmxfdct.c \ + x86/sse2fdct.c \ + x86/x86enc.c \ + x86/x86enc.h \ + x86/mmxfrag.c \ + x86/mmxfrag.h \ + x86/mmxidct.c \ + x86/mmxloop.h \ + x86/mmxstate.c \ + x86/x86int.h \ + x86/x86state.c \ + x86_vc + +lib_LTLIBRARIES = libtheoradec.la libtheoraenc.la libtheora.la + +if THEORA_DISABLE_ENCODE +encoder_uniq_sources = \ + encoder_disabled.c + +encoder_sources = \ + $(encoder_uniq_sources) +else +encoder_uniq_x86_sources = \ + x86/mmxencfrag.c \ + x86/mmxfdct.c \ + x86/x86enc.c + +encoder_uniq_x86_64_sources = \ + x86/sse2fdct.c + +encoder_shared_x86_sources = \ + x86/mmxfrag.c \ + x86/mmxidct.c \ + x86/mmxstate.c \ + x86/x86state.c + +encoder_shared_x86_64_sources = + +if CPU_x86_64 +encoder_uniq_arch_sources = \ + $(encoder_uniq_x86_sources) \ + $(encoder_uniq_x86_64_sources) +encoder_shared_arch_sources = \ + $(encoder_shared_x86_sources) \ + $(encoder_shared_x86_64_sources) +else +if CPU_x86_32 +encoder_uniq_arch_sources = $(encoder_uniq_x86_sources) +encoder_shared_arch_sources = $(encoder_shared_x86_sources) +else +encoder_uniq_arch_sources = +encoder_shared_arch_sources = +endif +endif + +encoder_uniq_sources = \ + analyze.c \ + fdct.c \ + encfrag.c \ + encapiwrapper.c \ + encinfo.c \ + encode.c \ + enquant.c \ + huffenc.c \ + mathops.c \ + mcenc.c \ + rate.c \ + tokenize.c \ + $(encoder_uniq_arch_sources) + +encoder_sources = \ + apiwrapper.c \ + fragment.c \ + idct.c \ + internal.c \ + state.c \ + quant.c \ + $(encoder_shared_arch_sources) \ + $(encoder_uniq_sources) + +endif + +decoder_x86_sources = \ + x86/mmxidct.c \ + x86/mmxfrag.c \ + x86/mmxstate.c \ + x86/x86state.c +if CPU_x86_64 +decoder_arch_sources = $(decoder_x86_sources) +else +if CPU_x86_32 +decoder_arch_sources = $(decoder_x86_sources) +else +decoder_arch_sources = +endif +endif + +decoder_sources = \ + apiwrapper.c \ + bitpack.c \ + decapiwrapper.c \ + decinfo.c \ + decode.c \ + dequant.c \ + fragment.c \ + huffdec.c \ + idct.c \ + info.c \ + internal.c \ + quant.c \ + state.c \ + $(decoder_arch_sources) + +noinst_HEADERS = \ + cpu.h \ + internal.h \ + encint.h \ + enquant.h \ + huffenc.h \ + mathops.h \ + modedec.h \ + x86/x86enc.h \ + apiwrapper.h \ + bitpack.h \ + dct.h \ + decint.h \ + dequant.h \ + huffdec.h \ + huffman.h \ + ocintrin.h \ + quant.h \ + x86/mmxfrag.h \ + x86/mmxloop.h \ + x86/x86int.h + +libtheoradec_la_SOURCES = \ + $(decoder_sources) \ + Version_script-dec theoradec.exp +libtheoradec_la_LDFLAGS = \ + -version-info @THDEC_LIB_CURRENT@:@THDEC_LIB_REVISION@:@THDEC_LIB_AGE@ \ + @THEORADEC_LDFLAGS@ @CAIRO_LIBS@ + +libtheoraenc_la_SOURCES = \ + $(encoder_sources) \ + Version_script-enc theoraenc.exp +libtheoraenc_la_LDFLAGS = \ + -version-info @THENC_LIB_CURRENT@:@THENC_LIB_REVISION@:@THENC_LIB_AGE@ \ + @THEORAENC_LDFLAGS@ $(OGG_LIBS) + +libtheora_la_SOURCES = \ + $(decoder_sources) \ + $(encoder_uniq_sources) \ + Version_script theora.exp +libtheora_la_LDFLAGS = \ + -version-info @TH_LIB_CURRENT@:@TH_LIB_REVISION@:@TH_LIB_AGE@ \ + @THEORA_LDFLAGS@ @CAIRO_LIBS@ $(OGG_LIBS) + +debug: + $(MAKE) all CFLAGS="@DEBUG@" + +profile: + $(MAKE) all CFLAGS="@PROFILE@" + +# contstruct various symbol export list files +.def.exp : defexp.awk + awk -f defexp.awk $< > $@ diff --git a/Engine/lib/libtheora/lib/Makefile.in b/Engine/lib/libtheora/lib/Makefile.in new file mode 100644 index 000000000..f26ccdc0e --- /dev/null +++ b/Engine/lib/libtheora/lib/Makefile.in @@ -0,0 +1,845 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AR = @AR@ +ARGZ_H = @ARGZ_H@ +AS = @AS@ +AWK = @AWK@ +BUILDABLE_EXAMPLES = @BUILDABLE_EXAMPLES@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +DEBUG = @DEBUG@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +F77 = @F77@ +GCJ = @GCJ@ +GCJFLAGS = @GCJFLAGS@ +GETOPT_OBJS = @GETOPT_OBJS@ +GREP = @GREP@ +HAVE_BIBTEX = @HAVE_BIBTEX@ +HAVE_DOXYGEN = @HAVE_DOXYGEN@ +HAVE_PDFLATEX = @HAVE_PDFLATEX@ +HAVE_PKG_CONFIG = @HAVE_PKG_CONFIG@ +HAVE_TRANSFIG = @HAVE_TRANSFIG@ +HAVE_VALGRIND = @HAVE_VALGRIND@ +INCLTDL = @INCLTDL@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBLTDL = @LIBLTDL@ +LIBM = @LIBM@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTDLDEPS = @LTDLDEPS@ +LTDLINCL = @LTDLINCL@ +LTDLOPEN = @LTDLOPEN@ +LT_CONFIG_H = @LT_CONFIG_H@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OGG_CFLAGS = @OGG_CFLAGS@ +OGG_LIBS = @OGG_LIBS@ +OSS_LIBS = @OSS_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PKG_CONFIG = @PKG_CONFIG@ +PNG_CFLAGS = @PNG_CFLAGS@ +PNG_LIBS = @PNG_LIBS@ +PROFILE = @PROFILE@ +RANLIB = @RANLIB@ +RC = @RC@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +STRIP = @STRIP@ +THDEC_LIB_AGE = @THDEC_LIB_AGE@ +THDEC_LIB_CURRENT = @THDEC_LIB_CURRENT@ +THDEC_LIB_REVISION = @THDEC_LIB_REVISION@ +THENC_LIB_AGE = @THENC_LIB_AGE@ +THENC_LIB_CURRENT = @THENC_LIB_CURRENT@ +THENC_LIB_REVISION = @THENC_LIB_REVISION@ +THEORADEC_LDFLAGS = @THEORADEC_LDFLAGS@ +THEORAENC_LDFLAGS = @THEORAENC_LDFLAGS@ +THEORA_LDFLAGS = @THEORA_LDFLAGS@ +TH_LIB_AGE = @TH_LIB_AGE@ +TH_LIB_CURRENT = @TH_LIB_CURRENT@ +TH_LIB_REVISION = @TH_LIB_REVISION@ +VALGRIND_ENVIRONMENT = @VALGRIND_ENVIRONMENT@ +VERSION = @VERSION@ +VORBISENC_LIBS = @VORBISENC_LIBS@ +VORBISFILE_LIBS = @VORBISFILE_LIBS@ +VORBIS_CFLAGS = @VORBIS_CFLAGS@ +VORBIS_LIBS = @VORBIS_LIBS@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +lt_ECHO = @lt_ECHO@ +ltdl_LIBOBJS = @ltdl_LIBOBJS@ +ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@ +sys_symbol_underscore = @sys_symbol_underscore@ +INCLUDES = -I$(top_srcdir)/include +AM_CFLAGS = $(OGG_CFLAGS) $(CAIRO_CFLAGS) + +EXTRA_DIST = \ + cpu.c \ + encoder_disabled.c \ + x86/mmxencfrag.c \ + x86/mmxfdct.c \ + x86/sse2fdct.c \ + x86/x86enc.c \ + x86/x86enc.h \ + x86/mmxfrag.c \ + x86/mmxfrag.h \ + x86/mmxidct.c \ + x86/mmxloop.h \ + x86/mmxstate.c \ + x86/x86int.h \ + x86/x86state.c \ + x86_vc + + +lib_LTLIBRARIES = libtheoradec.la libtheoraenc.la libtheora.la + +@THEORA_DISABLE_ENCODE_TRUE@encoder_uniq_sources = \ +@THEORA_DISABLE_ENCODE_TRUE@ encoder_disabled.c + +@THEORA_DISABLE_ENCODE_FALSE@encoder_uniq_sources = \ +@THEORA_DISABLE_ENCODE_FALSE@ analyze.c \ +@THEORA_DISABLE_ENCODE_FALSE@ fdct.c \ +@THEORA_DISABLE_ENCODE_FALSE@ encfrag.c \ +@THEORA_DISABLE_ENCODE_FALSE@ encapiwrapper.c \ +@THEORA_DISABLE_ENCODE_FALSE@ encinfo.c \ +@THEORA_DISABLE_ENCODE_FALSE@ encode.c \ +@THEORA_DISABLE_ENCODE_FALSE@ enquant.c \ +@THEORA_DISABLE_ENCODE_FALSE@ huffenc.c \ +@THEORA_DISABLE_ENCODE_FALSE@ mathops.c \ +@THEORA_DISABLE_ENCODE_FALSE@ mcenc.c \ +@THEORA_DISABLE_ENCODE_FALSE@ rate.c \ +@THEORA_DISABLE_ENCODE_FALSE@ tokenize.c \ +@THEORA_DISABLE_ENCODE_FALSE@ $(encoder_uniq_arch_sources) + + +@THEORA_DISABLE_ENCODE_TRUE@encoder_sources = \ +@THEORA_DISABLE_ENCODE_TRUE@ $(encoder_uniq_sources) + +@THEORA_DISABLE_ENCODE_FALSE@encoder_sources = \ +@THEORA_DISABLE_ENCODE_FALSE@ apiwrapper.c \ +@THEORA_DISABLE_ENCODE_FALSE@ fragment.c \ +@THEORA_DISABLE_ENCODE_FALSE@ idct.c \ +@THEORA_DISABLE_ENCODE_FALSE@ internal.c \ +@THEORA_DISABLE_ENCODE_FALSE@ state.c \ +@THEORA_DISABLE_ENCODE_FALSE@ quant.c \ +@THEORA_DISABLE_ENCODE_FALSE@ $(encoder_shared_arch_sources) \ +@THEORA_DISABLE_ENCODE_FALSE@ $(encoder_uniq_sources) + +@THEORA_DISABLE_ENCODE_FALSE@encoder_uniq_x86_sources = \ +@THEORA_DISABLE_ENCODE_FALSE@ x86/mmxencfrag.c \ +@THEORA_DISABLE_ENCODE_FALSE@ x86/mmxfdct.c \ +@THEORA_DISABLE_ENCODE_FALSE@ x86/x86enc.c + + +@THEORA_DISABLE_ENCODE_FALSE@encoder_uniq_x86_64_sources = \ +@THEORA_DISABLE_ENCODE_FALSE@ x86/sse2fdct.c + + +@THEORA_DISABLE_ENCODE_FALSE@encoder_shared_x86_sources = \ +@THEORA_DISABLE_ENCODE_FALSE@ x86/mmxfrag.c \ +@THEORA_DISABLE_ENCODE_FALSE@ x86/mmxidct.c \ +@THEORA_DISABLE_ENCODE_FALSE@ x86/mmxstate.c \ +@THEORA_DISABLE_ENCODE_FALSE@ x86/x86state.c + + +@THEORA_DISABLE_ENCODE_FALSE@encoder_shared_x86_64_sources = + +@CPU_x86_32_FALSE@@CPU_x86_64_FALSE@@THEORA_DISABLE_ENCODE_FALSE@encoder_uniq_arch_sources = +@CPU_x86_32_TRUE@@CPU_x86_64_FALSE@@THEORA_DISABLE_ENCODE_FALSE@encoder_uniq_arch_sources = $(encoder_uniq_x86_sources) +@CPU_x86_64_TRUE@@THEORA_DISABLE_ENCODE_FALSE@encoder_uniq_arch_sources = \ +@CPU_x86_64_TRUE@@THEORA_DISABLE_ENCODE_FALSE@ $(encoder_uniq_x86_sources) \ +@CPU_x86_64_TRUE@@THEORA_DISABLE_ENCODE_FALSE@ $(encoder_uniq_x86_64_sources) + +@CPU_x86_32_FALSE@@CPU_x86_64_FALSE@@THEORA_DISABLE_ENCODE_FALSE@encoder_shared_arch_sources = +@CPU_x86_32_TRUE@@CPU_x86_64_FALSE@@THEORA_DISABLE_ENCODE_FALSE@encoder_shared_arch_sources = $(encoder_shared_x86_sources) +@CPU_x86_64_TRUE@@THEORA_DISABLE_ENCODE_FALSE@encoder_shared_arch_sources = \ +@CPU_x86_64_TRUE@@THEORA_DISABLE_ENCODE_FALSE@ $(encoder_shared_x86_sources) \ +@CPU_x86_64_TRUE@@THEORA_DISABLE_ENCODE_FALSE@ $(encoder_shared_x86_64_sources) + + +decoder_x86_sources = \ + x86/mmxidct.c \ + x86/mmxfrag.c \ + x86/mmxstate.c \ + x86/x86state.c + +@CPU_x86_32_FALSE@@CPU_x86_64_FALSE@decoder_arch_sources = +@CPU_x86_32_TRUE@@CPU_x86_64_FALSE@decoder_arch_sources = $(decoder_x86_sources) +@CPU_x86_64_TRUE@decoder_arch_sources = $(decoder_x86_sources) + +decoder_sources = \ + apiwrapper.c \ + bitpack.c \ + decapiwrapper.c \ + decinfo.c \ + decode.c \ + dequant.c \ + fragment.c \ + huffdec.c \ + idct.c \ + info.c \ + internal.c \ + quant.c \ + state.c \ + $(decoder_arch_sources) + + +noinst_HEADERS = \ + cpu.h \ + internal.h \ + encint.h \ + enquant.h \ + huffenc.h \ + mathops.h \ + modedec.h \ + x86/x86enc.h \ + apiwrapper.h \ + bitpack.h \ + dct.h \ + decint.h \ + dequant.h \ + huffdec.h \ + huffman.h \ + ocintrin.h \ + quant.h \ + x86/mmxfrag.h \ + x86/mmxloop.h \ + x86/x86int.h + + +libtheoradec_la_SOURCES = \ + $(decoder_sources) \ + Version_script-dec theoradec.exp + +libtheoradec_la_LDFLAGS = \ + -version-info @THDEC_LIB_CURRENT@:@THDEC_LIB_REVISION@:@THDEC_LIB_AGE@ \ + @THEORADEC_LDFLAGS@ @CAIRO_LIBS@ + + +libtheoraenc_la_SOURCES = \ + $(encoder_sources) \ + Version_script-enc theoraenc.exp + +libtheoraenc_la_LDFLAGS = \ + -version-info @THENC_LIB_CURRENT@:@THENC_LIB_REVISION@:@THENC_LIB_AGE@ \ + @THEORAENC_LDFLAGS@ $(OGG_LIBS) + + +libtheora_la_SOURCES = \ + $(decoder_sources) \ + $(encoder_uniq_sources) \ + Version_script theora.exp + +libtheora_la_LDFLAGS = \ + -version-info @TH_LIB_CURRENT@:@TH_LIB_REVISION@:@TH_LIB_AGE@ \ + @THEORA_LDFLAGS@ @CAIRO_LIBS@ $(OGG_LIBS) + +subdir = lib +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(lib_LTLIBRARIES) + +libtheora_la_LIBADD = +am__objects_1 = mmxidct.lo mmxfrag.lo mmxstate.lo x86state.lo +@CPU_x86_32_FALSE@@CPU_x86_64_FALSE@am__objects_2 = +@CPU_x86_32_TRUE@@CPU_x86_64_FALSE@am__objects_2 = $(am__objects_1) +@CPU_x86_64_TRUE@am__objects_2 = $(am__objects_1) +am__objects_3 = apiwrapper.lo bitpack.lo decapiwrapper.lo decinfo.lo \ + decode.lo dequant.lo fragment.lo huffdec.lo idct.lo info.lo \ + internal.lo quant.lo state.lo $(am__objects_2) +@THEORA_DISABLE_ENCODE_FALSE@am__objects_4 = mmxencfrag.lo mmxfdct.lo \ +@THEORA_DISABLE_ENCODE_FALSE@ x86enc.lo +@THEORA_DISABLE_ENCODE_FALSE@am__objects_5 = sse2fdct.lo +@CPU_x86_32_FALSE@@CPU_x86_64_FALSE@@THEORA_DISABLE_ENCODE_FALSE@am__objects_6 = +@CPU_x86_32_TRUE@@CPU_x86_64_FALSE@@THEORA_DISABLE_ENCODE_FALSE@am__objects_6 = \ +@CPU_x86_32_TRUE@@CPU_x86_64_FALSE@@THEORA_DISABLE_ENCODE_FALSE@ $(am__objects_4) +@CPU_x86_64_TRUE@@THEORA_DISABLE_ENCODE_FALSE@am__objects_6 = \ +@CPU_x86_64_TRUE@@THEORA_DISABLE_ENCODE_FALSE@ $(am__objects_4) \ +@CPU_x86_64_TRUE@@THEORA_DISABLE_ENCODE_FALSE@ $(am__objects_5) +@THEORA_DISABLE_ENCODE_TRUE@am__objects_7 = encoder_disabled.lo +@THEORA_DISABLE_ENCODE_FALSE@am__objects_7 = analyze.lo fdct.lo \ +@THEORA_DISABLE_ENCODE_FALSE@ encfrag.lo encapiwrapper.lo \ +@THEORA_DISABLE_ENCODE_FALSE@ encinfo.lo encode.lo enquant.lo \ +@THEORA_DISABLE_ENCODE_FALSE@ huffenc.lo mathops.lo mcenc.lo \ +@THEORA_DISABLE_ENCODE_FALSE@ rate.lo tokenize.lo \ +@THEORA_DISABLE_ENCODE_FALSE@ $(am__objects_6) +am_libtheora_la_OBJECTS = $(am__objects_3) $(am__objects_7) +libtheora_la_OBJECTS = $(am_libtheora_la_OBJECTS) +libtheoradec_la_LIBADD = +am_libtheoradec_la_OBJECTS = $(am__objects_3) +libtheoradec_la_OBJECTS = $(am_libtheoradec_la_OBJECTS) +libtheoraenc_la_LIBADD = +@THEORA_DISABLE_ENCODE_FALSE@am__objects_8 = mmxfrag.lo mmxidct.lo \ +@THEORA_DISABLE_ENCODE_FALSE@ mmxstate.lo x86state.lo +@THEORA_DISABLE_ENCODE_FALSE@am__objects_9 = +@CPU_x86_32_FALSE@@CPU_x86_64_FALSE@@THEORA_DISABLE_ENCODE_FALSE@am__objects_10 = +@CPU_x86_32_TRUE@@CPU_x86_64_FALSE@@THEORA_DISABLE_ENCODE_FALSE@am__objects_10 = \ +@CPU_x86_32_TRUE@@CPU_x86_64_FALSE@@THEORA_DISABLE_ENCODE_FALSE@ $(am__objects_8) +@CPU_x86_64_TRUE@@THEORA_DISABLE_ENCODE_FALSE@am__objects_10 = \ +@CPU_x86_64_TRUE@@THEORA_DISABLE_ENCODE_FALSE@ $(am__objects_8) \ +@CPU_x86_64_TRUE@@THEORA_DISABLE_ENCODE_FALSE@ $(am__objects_9) +@THEORA_DISABLE_ENCODE_TRUE@am__objects_11 = $(am__objects_7) +@THEORA_DISABLE_ENCODE_FALSE@am__objects_11 = apiwrapper.lo fragment.lo \ +@THEORA_DISABLE_ENCODE_FALSE@ idct.lo internal.lo state.lo \ +@THEORA_DISABLE_ENCODE_FALSE@ quant.lo $(am__objects_10) \ +@THEORA_DISABLE_ENCODE_FALSE@ $(am__objects_7) +am_libtheoraenc_la_OBJECTS = $(am__objects_11) +libtheoraenc_la_OBJECTS = $(am_libtheoraenc_la_OBJECTS) + +DEFS = @DEFS@ +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/analyze.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/apiwrapper.Plo ./$(DEPDIR)/bitpack.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/decapiwrapper.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/decinfo.Plo ./$(DEPDIR)/decode.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/dequant.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/encapiwrapper.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/encfrag.Plo ./$(DEPDIR)/encinfo.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/encode.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/encoder_disabled.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/enquant.Plo ./$(DEPDIR)/fdct.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/fragment.Plo ./$(DEPDIR)/huffdec.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/huffenc.Plo ./$(DEPDIR)/idct.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/info.Plo ./$(DEPDIR)/internal.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/mathops.Plo ./$(DEPDIR)/mcenc.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/mmxencfrag.Plo ./$(DEPDIR)/mmxfdct.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/mmxfrag.Plo ./$(DEPDIR)/mmxidct.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/mmxstate.Plo ./$(DEPDIR)/quant.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/rate.Plo ./$(DEPDIR)/sse2fdct.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/state.Plo ./$(DEPDIR)/tokenize.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/x86enc.Plo ./$(DEPDIR)/x86state.Plo +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ + $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +CFLAGS = @CFLAGS@ +DIST_SOURCES = $(libtheora_la_SOURCES) $(libtheoradec_la_SOURCES) \ + $(libtheoraenc_la_SOURCES) +HEADERS = $(noinst_HEADERS) + +DIST_COMMON = $(noinst_HEADERS) Makefile.am Makefile.in +SOURCES = $(libtheora_la_SOURCES) $(libtheoradec_la_SOURCES) $(libtheoraenc_la_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .def .exp .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu lib/Makefile +Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +libLTLIBRARIES_INSTALL = $(INSTALL) +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(libdir) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$f"; \ + $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$f; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p"; \ + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test -z "$dir" && dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +mmxidct.lo: x86/mmxidct.c +mmxfrag.lo: x86/mmxfrag.c +mmxstate.lo: x86/mmxstate.c +x86state.lo: x86/x86state.c +mmxencfrag.lo: x86/mmxencfrag.c +mmxfdct.lo: x86/mmxfdct.c +x86enc.lo: x86/x86enc.c +sse2fdct.lo: x86/sse2fdct.c +libtheora.la: $(libtheora_la_OBJECTS) $(libtheora_la_DEPENDENCIES) + $(LINK) -rpath $(libdir) $(libtheora_la_LDFLAGS) $(libtheora_la_OBJECTS) $(libtheora_la_LIBADD) $(LIBS) +libtheoradec.la: $(libtheoradec_la_OBJECTS) $(libtheoradec_la_DEPENDENCIES) + $(LINK) -rpath $(libdir) $(libtheoradec_la_LDFLAGS) $(libtheoradec_la_OBJECTS) $(libtheoradec_la_LIBADD) $(LIBS) +libtheoraenc.la: $(libtheoraenc_la_OBJECTS) $(libtheoraenc_la_DEPENDENCIES) + $(LINK) -rpath $(libdir) $(libtheoraenc_la_LDFLAGS) $(libtheoraenc_la_OBJECTS) $(libtheoraenc_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/analyze.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/apiwrapper.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bitpack.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decapiwrapper.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decinfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decode.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dequant.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encapiwrapper.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encfrag.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encinfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encode.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoder_disabled.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enquant.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdct.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fragment.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/huffdec.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/huffenc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idct.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/internal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mathops.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcenc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmxencfrag.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmxfdct.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmxfrag.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmxidct.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmxstate.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quant.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rate.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sse2fdct.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/state.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tokenize.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x86enc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x86state.Plo@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.c.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< + +.c.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(COMPILE) -c `cygpath -w $<` + +.c.lo: +@AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(LTCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +mmxidct.o: x86/mmxidct.c +@AMDEP_TRUE@ source='x86/mmxidct.c' object='mmxidct.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/mmxidct.Po' tmpdepfile='$(DEPDIR)/mmxidct.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmxidct.o `test -f 'x86/mmxidct.c' || echo '$(srcdir)/'`x86/mmxidct.c + +mmxidct.obj: x86/mmxidct.c +@AMDEP_TRUE@ source='x86/mmxidct.c' object='mmxidct.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/mmxidct.Po' tmpdepfile='$(DEPDIR)/mmxidct.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmxidct.obj `cygpath -w x86/mmxidct.c` + +mmxidct.lo: x86/mmxidct.c +@AMDEP_TRUE@ source='x86/mmxidct.c' object='mmxidct.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/mmxidct.Plo' tmpdepfile='$(DEPDIR)/mmxidct.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmxidct.lo `test -f 'x86/mmxidct.c' || echo '$(srcdir)/'`x86/mmxidct.c + +mmxfrag.o: x86/mmxfrag.c +@AMDEP_TRUE@ source='x86/mmxfrag.c' object='mmxfrag.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/mmxfrag.Po' tmpdepfile='$(DEPDIR)/mmxfrag.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmxfrag.o `test -f 'x86/mmxfrag.c' || echo '$(srcdir)/'`x86/mmxfrag.c + +mmxfrag.obj: x86/mmxfrag.c +@AMDEP_TRUE@ source='x86/mmxfrag.c' object='mmxfrag.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/mmxfrag.Po' tmpdepfile='$(DEPDIR)/mmxfrag.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmxfrag.obj `cygpath -w x86/mmxfrag.c` + +mmxfrag.lo: x86/mmxfrag.c +@AMDEP_TRUE@ source='x86/mmxfrag.c' object='mmxfrag.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/mmxfrag.Plo' tmpdepfile='$(DEPDIR)/mmxfrag.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmxfrag.lo `test -f 'x86/mmxfrag.c' || echo '$(srcdir)/'`x86/mmxfrag.c + +mmxstate.o: x86/mmxstate.c +@AMDEP_TRUE@ source='x86/mmxstate.c' object='mmxstate.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/mmxstate.Po' tmpdepfile='$(DEPDIR)/mmxstate.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmxstate.o `test -f 'x86/mmxstate.c' || echo '$(srcdir)/'`x86/mmxstate.c + +mmxstate.obj: x86/mmxstate.c +@AMDEP_TRUE@ source='x86/mmxstate.c' object='mmxstate.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/mmxstate.Po' tmpdepfile='$(DEPDIR)/mmxstate.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmxstate.obj `cygpath -w x86/mmxstate.c` + +mmxstate.lo: x86/mmxstate.c +@AMDEP_TRUE@ source='x86/mmxstate.c' object='mmxstate.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/mmxstate.Plo' tmpdepfile='$(DEPDIR)/mmxstate.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmxstate.lo `test -f 'x86/mmxstate.c' || echo '$(srcdir)/'`x86/mmxstate.c + +x86state.o: x86/x86state.c +@AMDEP_TRUE@ source='x86/x86state.c' object='x86state.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/x86state.Po' tmpdepfile='$(DEPDIR)/x86state.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o x86state.o `test -f 'x86/x86state.c' || echo '$(srcdir)/'`x86/x86state.c + +x86state.obj: x86/x86state.c +@AMDEP_TRUE@ source='x86/x86state.c' object='x86state.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/x86state.Po' tmpdepfile='$(DEPDIR)/x86state.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o x86state.obj `cygpath -w x86/x86state.c` + +x86state.lo: x86/x86state.c +@AMDEP_TRUE@ source='x86/x86state.c' object='x86state.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/x86state.Plo' tmpdepfile='$(DEPDIR)/x86state.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o x86state.lo `test -f 'x86/x86state.c' || echo '$(srcdir)/'`x86/x86state.c + +mmxencfrag.o: x86/mmxencfrag.c +@AMDEP_TRUE@ source='x86/mmxencfrag.c' object='mmxencfrag.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/mmxencfrag.Po' tmpdepfile='$(DEPDIR)/mmxencfrag.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmxencfrag.o `test -f 'x86/mmxencfrag.c' || echo '$(srcdir)/'`x86/mmxencfrag.c + +mmxencfrag.obj: x86/mmxencfrag.c +@AMDEP_TRUE@ source='x86/mmxencfrag.c' object='mmxencfrag.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/mmxencfrag.Po' tmpdepfile='$(DEPDIR)/mmxencfrag.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmxencfrag.obj `cygpath -w x86/mmxencfrag.c` + +mmxencfrag.lo: x86/mmxencfrag.c +@AMDEP_TRUE@ source='x86/mmxencfrag.c' object='mmxencfrag.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/mmxencfrag.Plo' tmpdepfile='$(DEPDIR)/mmxencfrag.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmxencfrag.lo `test -f 'x86/mmxencfrag.c' || echo '$(srcdir)/'`x86/mmxencfrag.c + +mmxfdct.o: x86/mmxfdct.c +@AMDEP_TRUE@ source='x86/mmxfdct.c' object='mmxfdct.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/mmxfdct.Po' tmpdepfile='$(DEPDIR)/mmxfdct.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmxfdct.o `test -f 'x86/mmxfdct.c' || echo '$(srcdir)/'`x86/mmxfdct.c + +mmxfdct.obj: x86/mmxfdct.c +@AMDEP_TRUE@ source='x86/mmxfdct.c' object='mmxfdct.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/mmxfdct.Po' tmpdepfile='$(DEPDIR)/mmxfdct.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmxfdct.obj `cygpath -w x86/mmxfdct.c` + +mmxfdct.lo: x86/mmxfdct.c +@AMDEP_TRUE@ source='x86/mmxfdct.c' object='mmxfdct.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/mmxfdct.Plo' tmpdepfile='$(DEPDIR)/mmxfdct.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmxfdct.lo `test -f 'x86/mmxfdct.c' || echo '$(srcdir)/'`x86/mmxfdct.c + +x86enc.o: x86/x86enc.c +@AMDEP_TRUE@ source='x86/x86enc.c' object='x86enc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/x86enc.Po' tmpdepfile='$(DEPDIR)/x86enc.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o x86enc.o `test -f 'x86/x86enc.c' || echo '$(srcdir)/'`x86/x86enc.c + +x86enc.obj: x86/x86enc.c +@AMDEP_TRUE@ source='x86/x86enc.c' object='x86enc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/x86enc.Po' tmpdepfile='$(DEPDIR)/x86enc.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o x86enc.obj `cygpath -w x86/x86enc.c` + +x86enc.lo: x86/x86enc.c +@AMDEP_TRUE@ source='x86/x86enc.c' object='x86enc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/x86enc.Plo' tmpdepfile='$(DEPDIR)/x86enc.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o x86enc.lo `test -f 'x86/x86enc.c' || echo '$(srcdir)/'`x86/x86enc.c + +sse2fdct.o: x86/sse2fdct.c +@AMDEP_TRUE@ source='x86/sse2fdct.c' object='sse2fdct.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/sse2fdct.Po' tmpdepfile='$(DEPDIR)/sse2fdct.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sse2fdct.o `test -f 'x86/sse2fdct.c' || echo '$(srcdir)/'`x86/sse2fdct.c + +sse2fdct.obj: x86/sse2fdct.c +@AMDEP_TRUE@ source='x86/sse2fdct.c' object='sse2fdct.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/sse2fdct.Po' tmpdepfile='$(DEPDIR)/sse2fdct.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sse2fdct.obj `cygpath -w x86/sse2fdct.c` + +sse2fdct.lo: x86/sse2fdct.c +@AMDEP_TRUE@ source='x86/sse2fdct.c' object='sse2fdct.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/sse2fdct.Plo' tmpdepfile='$(DEPDIR)/sse2fdct.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sse2fdct.lo `test -f 'x86/sse2fdct.c' || echo '$(srcdir)/'`x86/sse2fdct.c +CCDEPMODE = @CCDEPMODE@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + $(mkinstalldirs) $(distdir)/x86 + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) + +installdirs: + $(mkinstalldirs) $(DESTDIR)$(libdir) + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-libLTLIBRARIES + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES + +.PHONY: GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool distclean distclean-compile \ + distclean-depend distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool tags uninstall \ + uninstall-am uninstall-info-am uninstall-libLTLIBRARIES + + +debug: + $(MAKE) all CFLAGS="@DEBUG@" + +profile: + $(MAKE) all CFLAGS="@PROFILE@" + +# contstruct various symbol export list files +.def.exp : defexp.awk + awk -f defexp.awk $< > $@ +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Engine/lib/libtheora/lib/Version_script b/Engine/lib/libtheora/lib/Version_script new file mode 100644 index 000000000..2ecb5e43a --- /dev/null +++ b/Engine/lib/libtheora/lib/Version_script @@ -0,0 +1,53 @@ +# +# Export file for libtheora +# +# Only the symbols listed in the global section will be callable from +# applications linking to the libraries. +# + +# We use something that looks like a versioned so filename here +# to define the old API because of a historical confusion. This +# label must be kept to maintain ABI compatibility. + +libtheora.so.1.0 +{ + global: + theora_version_string; + theora_version_number; + + theora_encode_init; + theora_encode_YUVin; + theora_encode_packetout; + theora_encode_header; + theora_encode_comment; + theora_encode_tables; + + theora_decode_header; + theora_decode_init; + theora_decode_packetin; + theora_decode_YUVout; + + theora_control; + + theora_packet_isheader; + theora_packet_iskeyframe; + + theora_granule_shift; + theora_granule_frame; + theora_granule_time; + + theora_info_init; + theora_info_clear; + + theora_clear; + + theora_comment_init; + theora_comment_add; + theora_comment_add_tag; + theora_comment_query; + theora_comment_query_count; + theora_comment_clear; + + local: + *; +}; diff --git a/Engine/lib/libtheora/lib/Version_script-dec b/Engine/lib/libtheora/lib/Version_script-dec new file mode 100644 index 000000000..cab368397 --- /dev/null +++ b/Engine/lib/libtheora/lib/Version_script-dec @@ -0,0 +1,82 @@ +# +# Export file for libtheoradec +# +# Only the symbols listed in the global section will be callable from +# applications linking to the libraries. +# + +# The 1.x API +libtheoradec_1.0 +{ + global: + th_version_string; + th_version_number; + + th_decode_headerin; + th_decode_alloc; + th_setup_free; + th_decode_ctl; + th_decode_packetin; + th_decode_ycbcr_out; + th_decode_free; + + th_packet_isheader; + th_packet_iskeyframe; + + th_granule_frame; + th_granule_time; + + th_info_init; + th_info_clear; + + th_comment_init; + th_comment_add; + th_comment_add_tag; + th_comment_query; + th_comment_query_count; + th_comment_clear; + + local: + *; +}; + +# The deprecated legacy api from the libtheora alpha releases. +# We use something that looks like a versioned so filename here +# to define the old API because of a historical confusion. This +# label must be kept to maintain ABI compatibility. + +libtheora.so.1.0 +{ + global: + theora_version_string; + theora_version_number; + + theora_decode_header; + theora_decode_init; + theora_decode_packetin; + theora_decode_YUVout; + + theora_control; + + theora_packet_isheader; + theora_packet_iskeyframe; + + theora_granule_shift; + theora_granule_frame; + theora_granule_time; + + theora_info_init; + theora_info_clear; + + theora_clear; + + theora_comment_init; + theora_comment_add; + theora_comment_add_tag; + theora_comment_query; + theora_comment_query_count; + theora_comment_clear; + + local: + *; +}; diff --git a/Engine/lib/libtheora/lib/Version_script-enc b/Engine/lib/libtheora/lib/Version_script-enc new file mode 100644 index 000000000..37699edd6 --- /dev/null +++ b/Engine/lib/libtheora/lib/Version_script-enc @@ -0,0 +1,43 @@ +# +# Export file for libtheora +# +# Only the symbols listed in the global section will be callable from +# applications linking to the libraries. +# + +# The 1.x encoder API +libtheoraenc_1.0 +{ + global: + th_encode_alloc; + th_encode_ctl; + th_encode_flushheader; + th_encode_ycbcr_in; + th_encode_packetout; + th_encode_free; + + TH_VP31_QUANT_INFO; + TH_VP31_HUFF_CODES; + + local: + *; +}; + +# The encoder portion of the deprecated alpha release api. +# We use something that looks like a versioned so filename here +# to define the old API because of a historical confusion. This +# label must be kept to maintain ABI compatibility. + +libtheora.so.1.0 +{ + global: + theora_encode_init; + theora_encode_YUVin; + theora_encode_packetout; + theora_encode_header; + theora_encode_comment; + theora_encode_tables; + + local: + *; +}; diff --git a/Engine/lib/libtheora/lib/analyze.c b/Engine/lib/libtheora/lib/analyze.c new file mode 100644 index 000000000..af01b60df --- /dev/null +++ b/Engine/lib/libtheora/lib/analyze.c @@ -0,0 +1,2709 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: mode selection code + last mod: $Id$ + + ********************************************************************/ +#include +#include +#include "encint.h" +#include "modedec.h" + + + +typedef struct oc_fr_state oc_fr_state; +typedef struct oc_qii_state oc_qii_state; +typedef struct oc_enc_pipeline_state oc_enc_pipeline_state; +typedef struct oc_rd_metric oc_rd_metric; +typedef struct oc_mode_choice oc_mode_choice; + + + +/*There are 8 possible schemes used to encode macro block modes. + Schemes 0-6 use a maximally-skewed Huffman code to code each of the modes. + The same set of Huffman codes is used for each of these 7 schemes, but the + mode assigned to each codeword varies. + Scheme 0 writes a custom mapping from codeword to MB mode to the bitstream, + while schemes 1-6 have a fixed mapping. + Scheme 7 just encodes each mode directly in 3 bits.*/ + +/*The mode orderings for the various mode coding schemes. + Scheme 0 uses a custom alphabet, which is not stored in this table. + This is the inverse of the equivalent table OC_MODE_ALPHABETS in the + decoder.*/ +static const unsigned char OC_MODE_RANKS[7][OC_NMODES]={ + /*Last MV dominates.*/ + /*L P M N I G GM 4*/ + {3,4,2,0,1,5,6,7}, + /*L P N M I G GM 4*/ + {2,4,3,0,1,5,6,7}, + /*L M P N I G GM 4*/ + {3,4,1,0,2,5,6,7}, + /*L M N P I G GM 4*/ + {2,4,1,0,3,5,6,7}, + /*No MV dominates.*/ + /*N L P M I G GM 4*/ + {0,4,3,1,2,5,6,7}, + /*N G L P M I GM 4*/ + {0,5,4,2,3,1,6,7}, + /*Default ordering.*/ + /*N I M L P G GM 4*/ + {0,1,2,3,4,5,6,7} +}; + + + +/*Initialize the mode scheme chooser. + This need only be called once per encoder.*/ +void oc_mode_scheme_chooser_init(oc_mode_scheme_chooser *_chooser){ + int si; + _chooser->mode_ranks[0]=_chooser->scheme0_ranks; + for(si=1;si<8;si++)_chooser->mode_ranks[si]=OC_MODE_RANKS[si-1]; +} + +/*Reset the mode scheme chooser. + This needs to be called once for each frame, including the first.*/ +static void oc_mode_scheme_chooser_reset(oc_mode_scheme_chooser *_chooser){ + int si; + memset(_chooser->mode_counts,0,OC_NMODES*sizeof(*_chooser->mode_counts)); + /*Scheme 0 starts with 24 bits to store the mode list in.*/ + _chooser->scheme_bits[0]=24; + memset(_chooser->scheme_bits+1,0,7*sizeof(*_chooser->scheme_bits)); + for(si=0;si<8;si++){ + /*Scheme 7 should always start first, and scheme 0 should always start + last.*/ + _chooser->scheme_list[si]=7-si; + _chooser->scheme0_list[si]=_chooser->scheme0_ranks[si]=si; + } +} + + +/*This is the real purpose of this data structure: not actually selecting a + mode scheme, but estimating the cost of coding a given mode given all the + modes selected so far. + This is done via opportunity cost: the cost is defined as the number of bits + required to encode all the modes selected so far including the current one + using the best possible scheme, minus the number of bits required to encode + all the modes selected so far not including the current one using the best + possible scheme. + The computational expense of doing this probably makes it overkill. + Just be happy we take a greedy approach instead of trying to solve the + global mode-selection problem (which is NP-hard). + _mb_mode: The mode to determine the cost of. + Return: The number of bits required to code this mode.*/ +static int oc_mode_scheme_chooser_cost(oc_mode_scheme_chooser *_chooser, + int _mb_mode){ + int scheme0; + int scheme1; + int best_bits; + int mode_bits; + int si; + int scheme_bits; + scheme0=_chooser->scheme_list[0]; + scheme1=_chooser->scheme_list[1]; + best_bits=_chooser->scheme_bits[scheme0]; + mode_bits=OC_MODE_BITS[scheme0+1>>3][_chooser->mode_ranks[scheme0][_mb_mode]]; + /*Typical case: If the difference between the best scheme and the next best + is greater than 6 bits, then adding just one mode cannot change which + scheme we use.*/ + if(_chooser->scheme_bits[scheme1]-best_bits>6)return mode_bits; + /*Otherwise, check to see if adding this mode selects a different scheme as + the best.*/ + si=1; + best_bits+=mode_bits; + do{ + /*For any scheme except 0, we can just use the bit cost of the mode's rank + in that scheme.*/ + if(scheme1!=0){ + scheme_bits=_chooser->scheme_bits[scheme1]+ + OC_MODE_BITS[scheme1+1>>3][_chooser->mode_ranks[scheme1][_mb_mode]]; + } + else{ + int ri; + /*For scheme 0, incrementing the mode count could potentially change the + mode's rank. + Find the index where the mode would be moved to in the optimal list, + and use its bit cost instead of the one for the mode's current + position in the list.*/ + /*We don't recompute scheme bits; this is computing opportunity cost, not + an update.*/ + for(ri=_chooser->scheme0_ranks[_mb_mode];ri>0&& + _chooser->mode_counts[_mb_mode]>= + _chooser->mode_counts[_chooser->scheme0_list[ri-1]];ri--); + scheme_bits=_chooser->scheme_bits[0]+OC_MODE_BITS[0][ri]; + } + if(scheme_bits=8)break; + scheme1=_chooser->scheme_list[si]; + } + while(_chooser->scheme_bits[scheme1]-_chooser->scheme_bits[scheme0]<=6); + return best_bits-_chooser->scheme_bits[scheme0]; +} + +/*Incrementally update the mode counts and per-scheme bit counts and re-order + the scheme lists once a mode has been selected. + _mb_mode: The mode that was chosen.*/ +static void oc_mode_scheme_chooser_update(oc_mode_scheme_chooser *_chooser, + int _mb_mode){ + int ri; + int si; + _chooser->mode_counts[_mb_mode]++; + /*Re-order the scheme0 mode list if necessary.*/ + for(ri=_chooser->scheme0_ranks[_mb_mode];ri>0;ri--){ + int pmode; + pmode=_chooser->scheme0_list[ri-1]; + if(_chooser->mode_counts[pmode]>=_chooser->mode_counts[_mb_mode])break; + /*Reorder the mode ranking.*/ + _chooser->scheme0_ranks[pmode]++; + _chooser->scheme0_list[ri]=pmode; + } + _chooser->scheme0_ranks[_mb_mode]=ri; + _chooser->scheme0_list[ri]=_mb_mode; + /*Now add the bit cost for the mode to each scheme.*/ + for(si=0;si<8;si++){ + _chooser->scheme_bits[si]+= + OC_MODE_BITS[si+1>>3][_chooser->mode_ranks[si][_mb_mode]]; + } + /*Finally, re-order the list of schemes.*/ + for(si=1;si<8;si++){ + int sj; + int scheme0; + int bits0; + sj=si; + scheme0=_chooser->scheme_list[si]; + bits0=_chooser->scheme_bits[scheme0]; + do{ + int scheme1; + scheme1=_chooser->scheme_list[sj-1]; + if(bits0>=_chooser->scheme_bits[scheme1])break; + _chooser->scheme_list[sj]=scheme1; + } + while(--sj>0); + _chooser->scheme_list[sj]=scheme0; + } +} + + + +/*The number of bits required to encode a super block run. + _run_count: The desired run count; must be positive and less than 4130.*/ +static int oc_sb_run_bits(int _run_count){ + int i; + for(i=0;_run_count>=OC_SB_RUN_VAL_MIN[i+1];i++); + return OC_SB_RUN_CODE_NBITS[i]; +} + +/*The number of bits required to encode a block run. + _run_count: The desired run count; must be positive and less than 30.*/ +static int oc_block_run_bits(int _run_count){ + return OC_BLOCK_RUN_CODE_NBITS[_run_count-1]; +} + + + +/*State to track coded block flags and their bit cost.*/ +struct oc_fr_state{ + ptrdiff_t bits; + unsigned sb_partial_count:16; + unsigned sb_full_count:16; + unsigned b_coded_count_prev:8; + unsigned b_coded_count:8; + unsigned b_count:8; + signed int sb_partial:2; + signed int sb_full:2; + signed int b_coded_prev:2; + signed int b_coded:2; +}; + + + +static void oc_fr_state_init(oc_fr_state *_fr){ + _fr->bits=0; + _fr->sb_partial_count=0; + _fr->sb_full_count=0; + _fr->b_coded_count_prev=0; + _fr->b_coded_count=0; + _fr->b_count=0; + _fr->sb_partial=-1; + _fr->sb_full=-1; + _fr->b_coded_prev=-1; + _fr->b_coded=-1; +} + + +static void oc_fr_state_advance_sb(oc_fr_state *_fr, + int _sb_partial,int _sb_full){ + ptrdiff_t bits; + int sb_partial_count; + int sb_full_count; + bits=_fr->bits; + /*Extend the sb_partial run, or start a new one.*/ + sb_partial_count=_fr->sb_partial; + if(_fr->sb_partial==_sb_partial){ + if(sb_partial_count>=4129){ + bits++; + sb_partial_count=0; + } + else bits-=oc_sb_run_bits(sb_partial_count); + } + else sb_partial_count=0; + sb_partial_count++; + bits+=oc_sb_run_bits(sb_partial_count); + if(!_sb_partial){ + /*Extend the sb_full run, or start a new one.*/ + sb_full_count=_fr->sb_full_count; + if(_fr->sb_full==_sb_full){ + if(sb_full_count>=4129){ + bits++; + sb_full_count=0; + } + else bits-=oc_sb_run_bits(sb_full_count); + } + else sb_full_count=0; + sb_full_count++; + bits+=oc_sb_run_bits(sb_full_count); + _fr->sb_full=_sb_full; + _fr->sb_full_count=sb_full_count; + } + _fr->bits=bits; + _fr->sb_partial=_sb_partial; + _fr->sb_partial_count=sb_partial_count; +} + +/*Flush any outstanding block flags for a SB (e.g., one with fewer than 16 + blocks).*/ +static void oc_fr_state_flush_sb(oc_fr_state *_fr){ + ptrdiff_t bits; + int sb_partial; + int sb_full=sb_full; + int b_coded_count; + int b_coded; + int b_count; + b_count=_fr->b_count; + if(b_count>0){ + bits=_fr->bits; + b_coded=_fr->b_coded; + b_coded_count=_fr->b_coded_count; + if(b_coded_count>=b_count){ + /*This SB was fully coded/uncoded; roll back the partial block flags.*/ + bits-=oc_block_run_bits(b_coded_count); + if(b_coded_count>b_count)bits+=oc_block_run_bits(b_coded_count-b_count); + sb_partial=0; + sb_full=b_coded; + b_coded=_fr->b_coded_prev; + b_coded_count=_fr->b_coded_count_prev; + } + else{ + /*It was partially coded.*/ + sb_partial=1; + /*sb_full is unused.*/ + } + _fr->bits=bits; + _fr->b_coded_count=b_coded_count; + _fr->b_coded_count_prev=b_coded_count; + _fr->b_count=0; + _fr->b_coded=b_coded; + _fr->b_coded_prev=b_coded; + oc_fr_state_advance_sb(_fr,sb_partial,sb_full); + } +} + +static void oc_fr_state_advance_block(oc_fr_state *_fr,int _b_coded){ + ptrdiff_t bits; + int b_coded_count; + int b_count; + int sb_partial; + int sb_full=sb_full; + bits=_fr->bits; + /*Extend the b_coded run, or start a new one.*/ + b_coded_count=_fr->b_coded_count; + if(_fr->b_coded==_b_coded)bits-=oc_block_run_bits(b_coded_count); + else b_coded_count=0; + b_coded_count++; + b_count=_fr->b_count+1; + if(b_count>=16){ + /*We finished a superblock.*/ + if(b_coded_count>=16){ + /*It was fully coded/uncoded; roll back the partial block flags.*/ + if(b_coded_count>16)bits+=oc_block_run_bits(b_coded_count-16); + sb_partial=0; + sb_full=_b_coded; + _b_coded=_fr->b_coded_prev; + b_coded_count=_fr->b_coded_count_prev; + } + else{ + bits+=oc_block_run_bits(b_coded_count); + /*It was partially coded.*/ + sb_partial=1; + /*sb_full is unused.*/ + } + _fr->bits=bits; + _fr->b_coded_count=b_coded_count; + _fr->b_coded_count_prev=b_coded_count; + _fr->b_count=0; + _fr->b_coded=_b_coded; + _fr->b_coded_prev=_b_coded; + oc_fr_state_advance_sb(_fr,sb_partial,sb_full); + } + else{ + bits+=oc_block_run_bits(b_coded_count); + _fr->bits=bits; + _fr->b_coded_count=b_coded_count; + _fr->b_count=b_count; + _fr->b_coded=_b_coded; + } +} + +static void oc_fr_skip_block(oc_fr_state *_fr){ + oc_fr_state_advance_block(_fr,0); +} + +static void oc_fr_code_block(oc_fr_state *_fr){ + oc_fr_state_advance_block(_fr,1); +} + +static int oc_fr_cost1(const oc_fr_state *_fr){ + oc_fr_state tmp; + ptrdiff_t bits; + *&tmp=*_fr; + oc_fr_skip_block(&tmp); + bits=tmp.bits; + *&tmp=*_fr; + oc_fr_code_block(&tmp); + return (int)(tmp.bits-bits); +} + +static int oc_fr_cost4(const oc_fr_state *_pre,const oc_fr_state *_post){ + oc_fr_state tmp; + *&tmp=*_pre; + oc_fr_skip_block(&tmp); + oc_fr_skip_block(&tmp); + oc_fr_skip_block(&tmp); + oc_fr_skip_block(&tmp); + return (int)(_post->bits-tmp.bits); +} + + + +struct oc_qii_state{ + ptrdiff_t bits; + unsigned qi01_count:14; + signed int qi01:2; + unsigned qi12_count:14; + signed int qi12:2; +}; + + + +static void oc_qii_state_init(oc_qii_state *_qs){ + _qs->bits=0; + _qs->qi01_count=0; + _qs->qi01=-1; + _qs->qi12_count=0; + _qs->qi12=-1; +} + + +static void oc_qii_state_advance(oc_qii_state *_qd, + const oc_qii_state *_qs,int _qii){ + ptrdiff_t bits; + int qi01; + int qi01_count; + int qi12; + int qi12_count; + bits=_qs->bits; + qi01=_qii+1>>1; + qi01_count=_qs->qi01_count; + if(qi01==_qs->qi01){ + if(qi01_count>=4129){ + bits++; + qi01_count=0; + } + else bits-=oc_sb_run_bits(qi01_count); + } + else qi01_count=0; + qi01_count++; + bits+=oc_sb_run_bits(qi01_count); + qi12_count=_qs->qi12_count; + if(_qii){ + qi12=_qii>>1; + if(qi12==_qs->qi12){ + if(qi12_count>=4129){ + bits++; + qi12_count=0; + } + else bits-=oc_sb_run_bits(qi12_count); + } + else qi12_count=0; + qi12_count++; + bits+=oc_sb_run_bits(qi12_count); + } + else qi12=_qs->qi12; + _qd->bits=bits; + _qd->qi01=qi01; + _qd->qi01_count=qi01_count; + _qd->qi12=qi12; + _qd->qi12_count=qi12_count; +} + + + +/*Temporary encoder state for the analysis pipeline.*/ +struct oc_enc_pipeline_state{ + int bounding_values[256]; + oc_fr_state fr[3]; + oc_qii_state qs[3]; + /*Condensed dequantization tables.*/ + const ogg_uint16_t *dequant[3][3][2]; + /*Condensed quantization tables.*/ + const oc_iquant *enquant[3][3][2]; + /*Skip SSD storage for the current MCU in each plane.*/ + unsigned *skip_ssd[3]; + /*Coded/uncoded fragment lists for each plane for the current MCU.*/ + ptrdiff_t *coded_fragis[3]; + ptrdiff_t *uncoded_fragis[3]; + ptrdiff_t ncoded_fragis[3]; + ptrdiff_t nuncoded_fragis[3]; + /*The starting fragment for the current MCU in each plane.*/ + ptrdiff_t froffset[3]; + /*The starting row for the current MCU in each plane.*/ + int fragy0[3]; + /*The ending row for the current MCU in each plane.*/ + int fragy_end[3]; + /*The starting superblock for the current MCU in each plane.*/ + unsigned sbi0[3]; + /*The ending superblock for the current MCU in each plane.*/ + unsigned sbi_end[3]; + /*The number of tokens for zzi=1 for each color plane.*/ + int ndct_tokens1[3]; + /*The outstanding eob_run count for zzi=1 for each color plane.*/ + int eob_run1[3]; + /*Whether or not the loop filter is enabled.*/ + int loop_filter; +}; + + +static void oc_enc_pipeline_init(oc_enc_ctx *_enc,oc_enc_pipeline_state *_pipe){ + ptrdiff_t *coded_fragis; + unsigned mcu_nvsbs; + ptrdiff_t mcu_nfrags; + int hdec; + int vdec; + int pli; + int qii; + int qti; + /*Initialize the per-plane coded block flag trackers. + These are used for bit-estimation purposes only; the real flag bits span + all three planes, so we can't compute them in parallel.*/ + for(pli=0;pli<3;pli++)oc_fr_state_init(_pipe->fr+pli); + for(pli=0;pli<3;pli++)oc_qii_state_init(_pipe->qs+pli); + /*Set up the per-plane skip SSD storage pointers.*/ + mcu_nvsbs=_enc->mcu_nvsbs; + mcu_nfrags=mcu_nvsbs*_enc->state.fplanes[0].nhsbs*16; + hdec=!(_enc->state.info.pixel_fmt&1); + vdec=!(_enc->state.info.pixel_fmt&2); + _pipe->skip_ssd[0]=_enc->mcu_skip_ssd; + _pipe->skip_ssd[1]=_pipe->skip_ssd[0]+mcu_nfrags; + _pipe->skip_ssd[2]=_pipe->skip_ssd[1]+(mcu_nfrags>>hdec+vdec); + /*Set up per-plane pointers to the coded and uncoded fragments lists. + Unlike the decoder, each planes' coded and uncoded fragment list is kept + separate during the analysis stage; we only make the coded list for all + three planes contiguous right before the final packet is output + (destroying the uncoded lists, which are no longer needed).*/ + coded_fragis=_enc->state.coded_fragis; + for(pli=0;pli<3;pli++){ + _pipe->coded_fragis[pli]=coded_fragis; + coded_fragis+=_enc->state.fplanes[pli].nfrags; + _pipe->uncoded_fragis[pli]=coded_fragis; + } + memset(_pipe->ncoded_fragis,0,sizeof(_pipe->ncoded_fragis)); + memset(_pipe->nuncoded_fragis,0,sizeof(_pipe->nuncoded_fragis)); + /*Set up condensed quantizer tables.*/ + for(pli=0;pli<3;pli++){ + for(qii=0;qii<_enc->state.nqis;qii++){ + int qi; + qi=_enc->state.qis[qii]; + for(qti=0;qti<2;qti++){ + _pipe->dequant[pli][qii][qti]=_enc->state.dequant_tables[qi][pli][qti]; + _pipe->enquant[pli][qii][qti]=_enc->enquant_tables[qi][pli][qti]; + } + } + } + /*Initialize the tokenization state.*/ + for(pli=0;pli<3;pli++){ + _pipe->ndct_tokens1[pli]=0; + _pipe->eob_run1[pli]=0; + } + /*Initialize the bounding value array for the loop filter.*/ + _pipe->loop_filter=!oc_state_loop_filter_init(&_enc->state, + _pipe->bounding_values); +} + +/*Sets the current MCU stripe to super block row _sby. + Return: A non-zero value if this was the last MCU.*/ +static int oc_enc_pipeline_set_stripe(oc_enc_ctx *_enc, + oc_enc_pipeline_state *_pipe,int _sby){ + const oc_fragment_plane *fplane; + unsigned mcu_nvsbs; + int sby_end; + int notdone; + int vdec; + int pli; + mcu_nvsbs=_enc->mcu_nvsbs; + sby_end=_enc->state.fplanes[0].nvsbs; + notdone=_sby+mcu_nvsbsstate.fplanes+pli; + _pipe->sbi0[pli]=fplane->sboffset+(_sby>>vdec)*fplane->nhsbs; + _pipe->fragy0[pli]=_sby<<2-vdec; + _pipe->froffset[pli]=fplane->froffset + +_pipe->fragy0[pli]*(ptrdiff_t)fplane->nhfrags; + if(notdone){ + _pipe->sbi_end[pli]=fplane->sboffset+(sby_end>>vdec)*fplane->nhsbs; + _pipe->fragy_end[pli]=sby_end<<2-vdec; + } + else{ + _pipe->sbi_end[pli]=fplane->sboffset+fplane->nsbs; + _pipe->fragy_end[pli]=fplane->nvfrags; + } + vdec=!(_enc->state.info.pixel_fmt&2); + } + return notdone; +} + +static void oc_enc_pipeline_finish_mcu_plane(oc_enc_ctx *_enc, + oc_enc_pipeline_state *_pipe,int _pli,int _sdelay,int _edelay){ + int refi; + /*Copy over all the uncoded fragments from this plane and advance the uncoded + fragment list.*/ + _pipe->uncoded_fragis[_pli]-=_pipe->nuncoded_fragis[_pli]; + oc_state_frag_copy_list(&_enc->state,_pipe->uncoded_fragis[_pli], + _pipe->nuncoded_fragis[_pli],OC_FRAME_SELF,OC_FRAME_PREV,_pli); + _pipe->nuncoded_fragis[_pli]=0; + /*Perform DC prediction.*/ + oc_enc_pred_dc_frag_rows(_enc,_pli, + _pipe->fragy0[_pli],_pipe->fragy_end[_pli]); + /*Finish DC tokenization.*/ + oc_enc_tokenize_dc_frag_list(_enc,_pli, + _pipe->coded_fragis[_pli],_pipe->ncoded_fragis[_pli], + _pipe->ndct_tokens1[_pli],_pipe->eob_run1[_pli]); + _pipe->ndct_tokens1[_pli]=_enc->ndct_tokens[_pli][1]; + _pipe->eob_run1[_pli]=_enc->eob_run[_pli][1]; + /*And advance the coded fragment list.*/ + _enc->state.ncoded_fragis[_pli]+=_pipe->ncoded_fragis[_pli]; + _pipe->coded_fragis[_pli]+=_pipe->ncoded_fragis[_pli]; + _pipe->ncoded_fragis[_pli]=0; + /*Apply the loop filter if necessary.*/ + refi=_enc->state.ref_frame_idx[OC_FRAME_SELF]; + if(_pipe->loop_filter){ + oc_state_loop_filter_frag_rows(&_enc->state,_pipe->bounding_values, + refi,_pli,_pipe->fragy0[_pli]-_sdelay,_pipe->fragy_end[_pli]-_edelay); + } + else _sdelay=_edelay=0; + /*To fill borders, we have an additional two pixel delay, since a fragment + in the next row could filter its top edge, using two pixels from a + fragment in this row. + But there's no reason to delay a full fragment between the two.*/ + oc_state_borders_fill_rows(&_enc->state,refi,_pli, + (_pipe->fragy0[_pli]-_sdelay<<3)-(_sdelay<<1), + (_pipe->fragy_end[_pli]-_edelay<<3)-(_edelay<<1)); +} + + + +/*Cost information about the coded blocks in a MB.*/ +struct oc_rd_metric{ + int uncoded_ac_ssd; + int coded_ac_ssd; + int ac_bits; + int dc_flag; +}; + + + +static int oc_enc_block_transform_quantize(oc_enc_ctx *_enc, + oc_enc_pipeline_state *_pipe,int _pli,ptrdiff_t _fragi,int _overhead_bits, + oc_rd_metric *_mo,oc_token_checkpoint **_stack){ + OC_ALIGN16(ogg_int16_t dct[64]); + OC_ALIGN16(ogg_int16_t data[64]); + ogg_uint16_t dc_dequant; + const ogg_uint16_t *dequant; + const oc_iquant *enquant; + ptrdiff_t frag_offs; + int ystride; + const unsigned char *src; + const unsigned char *ref; + unsigned char *dst; + int frame_type; + int nonzero; + unsigned uncoded_ssd; + unsigned coded_ssd; + int coded_dc; + oc_token_checkpoint *checkpoint; + oc_fragment *frags; + int mb_mode; + int mv_offs[2]; + int nmv_offs; + int ac_bits; + int borderi; + int qti; + int qii; + int pi; + int zzi; + int v; + int val; + int d; + int s; + int dc; + frags=_enc->state.frags; + frag_offs=_enc->state.frag_buf_offs[_fragi]; + ystride=_enc->state.ref_ystride[_pli]; + src=_enc->state.ref_frame_data[OC_FRAME_IO]+frag_offs; + borderi=frags[_fragi].borderi; + qii=frags[_fragi].qii; + if(qii&~3){ +#if !defined(OC_COLLECT_METRICS) + if(_enc->sp_level>=OC_SP_LEVEL_EARLY_SKIP){ + /*Enable early skip detection.*/ + frags[_fragi].coded=0; + return 0; + } +#endif + /*Try and code this block anyway.*/ + qii&=3; + frags[_fragi].qii=qii; + } + mb_mode=frags[_fragi].mb_mode; + ref=_enc->state.ref_frame_data[ + _enc->state.ref_frame_idx[OC_FRAME_FOR_MODE(mb_mode)]]+frag_offs; + dst=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_SELF]] + +frag_offs; + /*Motion compensation:*/ + switch(mb_mode){ + case OC_MODE_INTRA:{ + nmv_offs=0; + oc_enc_frag_sub_128(_enc,data,src,ystride); + }break; + case OC_MODE_GOLDEN_NOMV: + case OC_MODE_INTER_NOMV:{ + nmv_offs=1; + mv_offs[0]=0; + oc_enc_frag_sub(_enc,data,src,ref,ystride); + }break; + default:{ + const oc_mv *frag_mvs; + frag_mvs=(const oc_mv *)_enc->state.frag_mvs; + nmv_offs=oc_state_get_mv_offsets(&_enc->state,mv_offs,_pli, + frag_mvs[_fragi][0],frag_mvs[_fragi][1]); + if(nmv_offs>1){ + oc_enc_frag_copy2(_enc,dst, + ref+mv_offs[0],ref+mv_offs[1],ystride); + oc_enc_frag_sub(_enc,data,src,dst,ystride); + } + else oc_enc_frag_sub(_enc,data,src,ref+mv_offs[0],ystride); + }break; + } +#if defined(OC_COLLECT_METRICS) + { + unsigned satd; + switch(nmv_offs){ + case 0:satd=oc_enc_frag_intra_satd(_enc,src,ystride);break; + case 1:{ + satd=oc_enc_frag_satd_thresh(_enc,src,ref+mv_offs[0],ystride,UINT_MAX); + }break; + default:{ + satd=oc_enc_frag_satd_thresh(_enc,src,dst,ystride,UINT_MAX); + } + } + _enc->frag_satd[_fragi]=satd; + } +#endif + /*Transform:*/ + oc_enc_fdct8x8(_enc,dct,data); + /*Quantize the DC coefficient:*/ + qti=mb_mode!=OC_MODE_INTRA; + enquant=_pipe->enquant[_pli][0][qti]; + dc_dequant=_pipe->dequant[_pli][0][qti][0]; + v=dct[0]; + val=v<<1; + s=OC_SIGNMASK(val); + val+=dc_dequant+s^s; + val=((enquant[0].m*(ogg_int32_t)val>>16)+val>>enquant[0].l)-s; + dc=OC_CLAMPI(-580,val,580); + nonzero=0; + /*Quantize the AC coefficients:*/ + dequant=_pipe->dequant[_pli][qii][qti]; + enquant=_pipe->enquant[_pli][qii][qti]; + for(zzi=1;zzi<64;zzi++){ + v=dct[OC_FZIG_ZAG[zzi]]; + d=dequant[zzi]; + val=v<<1; + v=abs(val); + if(v>=d){ + s=OC_SIGNMASK(val); + /*The bias added here rounds ties away from zero, since token + optimization can only decrease the magnitude of the quantized + value.*/ + val+=d+s^s; + /*Note the arithmetic right shift is not guaranteed by ANSI C. + Hopefully no one still uses ones-complement architectures.*/ + val=((enquant[zzi].m*(ogg_int32_t)val>>16)+val>>enquant[zzi].l)-s; + data[zzi]=OC_CLAMPI(-580,val,580); + nonzero=zzi; + } + else data[zzi]=0; + } + /*Tokenize.*/ + checkpoint=*_stack; + ac_bits=oc_enc_tokenize_ac(_enc,_pli,_fragi,data,dequant,dct,nonzero+1, + _stack,qti?0:3); + /*Reconstruct. + TODO: nonzero may need to be adjusted after tokenization.*/ + if(nonzero==0){ + ogg_int16_t p; + int ci; + /*We round this dequant product (and not any of the others) because there's + no iDCT rounding.*/ + p=(ogg_int16_t)(dc*(ogg_int32_t)dc_dequant+15>>5); + /*LOOP VECTORIZES.*/ + for(ci=0;ci<64;ci++)data[ci]=p; + } + else{ + data[0]=dc*dc_dequant; + oc_idct8x8(&_enc->state,data,nonzero+1); + } + if(!qti)oc_enc_frag_recon_intra(_enc,dst,ystride,data); + else{ + oc_enc_frag_recon_inter(_enc,dst, + nmv_offs==1?ref+mv_offs[0]:dst,ystride,data); + } + frame_type=_enc->state.frame_type; +#if !defined(OC_COLLECT_METRICS) + if(frame_type!=OC_INTRA_FRAME) +#endif + { + /*In retrospect, should we have skipped this block?*/ + oc_enc_frag_sub(_enc,data,src,dst,ystride); + coded_ssd=coded_dc=0; + if(borderi<0){ + for(pi=0;pi<64;pi++){ + coded_ssd+=data[pi]*data[pi]; + coded_dc+=data[pi]; + } + } + else{ + ogg_int64_t mask; + mask=_enc->state.borders[borderi].mask; + for(pi=0;pi<64;pi++,mask>>=1)if(mask&1){ + coded_ssd+=data[pi]*data[pi]; + coded_dc+=data[pi]; + } + } + /*Scale to match DCT domain.*/ + coded_ssd<<=4; + /*We actually only want the AC contribution to the SSD.*/ + coded_ssd-=coded_dc*coded_dc>>2; +#if defined(OC_COLLECT_METRICS) + _enc->frag_ssd[_fragi]=coded_ssd; + } + if(frame_type!=OC_INTRA_FRAME){ +#endif + uncoded_ssd=_pipe->skip_ssd[_pli][_fragi-_pipe->froffset[_pli]]; + if(uncoded_ssdlambda&& + /*Don't allow luma blocks to be skipped in 4MV mode when VP3 + compatibility is enabled.*/ + (!_enc->vp3_compatible||mb_mode!=OC_MODE_INTER_MV_FOUR||_pli)){ + /*Hm, not worth it; roll back.*/ + oc_enc_tokenlog_rollback(_enc,checkpoint,(*_stack)-checkpoint); + *_stack=checkpoint; + frags[_fragi].coded=0; + return 0; + } + } + else _mo->dc_flag=1; + _mo->uncoded_ac_ssd+=uncoded_ssd; + _mo->coded_ac_ssd+=coded_ssd; + _mo->ac_bits+=ac_bits; + } + oc_qii_state_advance(_pipe->qs+_pli,_pipe->qs+_pli,qii); + frags[_fragi].dc=dc; + frags[_fragi].coded=1; + return 1; +} + +static int oc_enc_mb_transform_quantize_luma(oc_enc_ctx *_enc, + oc_enc_pipeline_state *_pipe,unsigned _mbi,int _mode_overhead){ + /*Worst case token stack usage for 4 fragments.*/ + oc_token_checkpoint stack[64*4]; + oc_token_checkpoint *stackptr; + const oc_sb_map *sb_maps; + signed char *mb_modes; + oc_fragment *frags; + ptrdiff_t *coded_fragis; + ptrdiff_t ncoded_fragis; + ptrdiff_t *uncoded_fragis; + ptrdiff_t nuncoded_fragis; + oc_rd_metric mo; + oc_fr_state fr_checkpoint; + oc_qii_state qs_checkpoint; + int mb_mode; + int ncoded; + ptrdiff_t fragi; + int bi; + *&fr_checkpoint=*(_pipe->fr+0); + *&qs_checkpoint=*(_pipe->qs+0); + sb_maps=(const oc_sb_map *)_enc->state.sb_maps; + mb_modes=_enc->state.mb_modes; + frags=_enc->state.frags; + coded_fragis=_pipe->coded_fragis[0]; + ncoded_fragis=_pipe->ncoded_fragis[0]; + uncoded_fragis=_pipe->uncoded_fragis[0]; + nuncoded_fragis=_pipe->nuncoded_fragis[0]; + mb_mode=mb_modes[_mbi]; + ncoded=0; + stackptr=stack; + memset(&mo,0,sizeof(mo)); + for(bi=0;bi<4;bi++){ + fragi=sb_maps[_mbi>>2][_mbi&3][bi]; + frags[fragi].mb_mode=mb_mode; + if(oc_enc_block_transform_quantize(_enc, + _pipe,0,fragi,oc_fr_cost1(_pipe->fr+0),&mo,&stackptr)){ + oc_fr_code_block(_pipe->fr+0); + coded_fragis[ncoded_fragis++]=fragi; + ncoded++; + } + else{ + *(uncoded_fragis-++nuncoded_fragis)=fragi; + oc_fr_skip_block(_pipe->fr+0); + } + } + if(_enc->state.frame_type!=OC_INTRA_FRAME){ + if(ncoded>0&&!mo.dc_flag){ + int cost; + /*Some individual blocks were worth coding. + See if that's still true when accounting for mode and MV overhead.*/ + cost=mo.coded_ac_ssd+_enc->lambda*(mo.ac_bits + +oc_fr_cost4(&fr_checkpoint,_pipe->fr+0)+_mode_overhead); + if(mo.uncoded_ac_ssd<=cost){ + /*Taking macroblock overhead into account, it is not worth coding this + MB.*/ + oc_enc_tokenlog_rollback(_enc,stack,stackptr-stack); + *(_pipe->fr+0)=*&fr_checkpoint; + *(_pipe->qs+0)=*&qs_checkpoint; + for(bi=0;bi<4;bi++){ + fragi=sb_maps[_mbi>>2][_mbi&3][bi]; + if(frags[fragi].coded){ + *(uncoded_fragis-++nuncoded_fragis)=fragi; + frags[fragi].coded=0; + } + oc_fr_skip_block(_pipe->fr+0); + } + ncoded_fragis-=ncoded; + ncoded=0; + } + } + /*If no luma blocks coded, the mode is forced.*/ + if(ncoded==0)mb_modes[_mbi]=OC_MODE_INTER_NOMV; + /*Assume that a 1MV with a single coded block is always cheaper than a 4MV + with a single coded block. + This may not be strictly true: a 4MV computes chroma MVs using (0,0) for + skipped blocks, while a 1MV does not.*/ + else if(ncoded==1&&mb_mode==OC_MODE_INTER_MV_FOUR){ + mb_modes[_mbi]=OC_MODE_INTER_MV; + } + } + _pipe->ncoded_fragis[0]=ncoded_fragis; + _pipe->nuncoded_fragis[0]=nuncoded_fragis; + return ncoded; +} + +static void oc_enc_sb_transform_quantize_chroma(oc_enc_ctx *_enc, + oc_enc_pipeline_state *_pipe,int _pli,int _sbi_start,int _sbi_end){ + const oc_sb_map *sb_maps; + oc_sb_flags *sb_flags; + ptrdiff_t *coded_fragis; + ptrdiff_t ncoded_fragis; + ptrdiff_t *uncoded_fragis; + ptrdiff_t nuncoded_fragis; + int sbi; + sb_maps=(const oc_sb_map *)_enc->state.sb_maps; + sb_flags=_enc->state.sb_flags; + coded_fragis=_pipe->coded_fragis[_pli]; + ncoded_fragis=_pipe->ncoded_fragis[_pli]; + uncoded_fragis=_pipe->uncoded_fragis[_pli]; + nuncoded_fragis=_pipe->nuncoded_fragis[_pli]; + for(sbi=_sbi_start;sbi<_sbi_end;sbi++){ + /*Worst case token stack usage for 1 fragment.*/ + oc_token_checkpoint stack[64]; + oc_rd_metric mo; + int quadi; + int bi; + memset(&mo,0,sizeof(mo)); + for(quadi=0;quadi<4;quadi++)for(bi=0;bi<4;bi++){ + ptrdiff_t fragi; + fragi=sb_maps[sbi][quadi][bi]; + if(fragi>=0){ + oc_token_checkpoint *stackptr; + stackptr=stack; + if(oc_enc_block_transform_quantize(_enc, + _pipe,_pli,fragi,oc_fr_cost1(_pipe->fr+_pli),&mo,&stackptr)){ + coded_fragis[ncoded_fragis++]=fragi; + oc_fr_code_block(_pipe->fr+_pli); + } + else{ + *(uncoded_fragis-++nuncoded_fragis)=fragi; + oc_fr_skip_block(_pipe->fr+_pli); + } + } + } + oc_fr_state_flush_sb(_pipe->fr+_pli); + sb_flags[sbi].coded_fully=_pipe->fr[_pli].sb_full; + sb_flags[sbi].coded_partially=_pipe->fr[_pli].sb_partial; + } + _pipe->ncoded_fragis[_pli]=ncoded_fragis; + _pipe->nuncoded_fragis[_pli]=nuncoded_fragis; +} + +/*Mode decision is done by exhaustively examining all potential choices. + Obviously, doing the motion compensation, fDCT, tokenization, and then + counting the bits each token uses is computationally expensive. + Theora's EOB runs can also split the cost of these tokens across multiple + fragments, and naturally we don't know what the optimal choice of Huffman + codes will be until we know all the tokens we're going to encode in all the + fragments. + So we use a simple approach to estimating the bit cost and distortion of each + mode based upon the SATD value of the residual before coding. + The mathematics behind the technique are outlined by Kim \cite{Kim03}, but + the process (modified somewhat from that of the paper) is very simple. + We build a non-linear regression of the mappings from + (pre-transform+quantization) SATD to (post-transform+quantization) bits and + SSD for each qi. + A separate set of mappings is kept for each quantization type and color + plane. + The mappings are constructed by partitioning the SATD values into a small + number of bins (currently 24) and using a linear regression in each bin + (as opposed to the 0th-order regression used by Kim). + The bit counts and SSD measurements are obtained by examining actual encoded + frames, with appropriate lambda values and optimal Huffman codes selected. + EOB bits are assigned to the fragment that started the EOB run (as opposed to + dividing them among all the blocks in the run; though the latter approach + seems more theoretically correct, Monty's testing showed a small improvement + with the former, though that may have been merely statistical noise). + + @ARTICLE{Kim03, + author="Hyun Mun Kim", + title="Adaptive Rate Control Using Nonlinear Regression", + journal="IEEE Transactions on Circuits and Systems for Video Technology", + volume=13, + number=5, + pages="432--439", + month=May, + year=2003 + }*/ + +/*Computes (_ssd+_lambda*_rate)/(1<>OC_BIT_SCALE)+((_rate)>>OC_BIT_SCALE)*(_lambda) \ + +(((_ssd)&(1<>1)>>OC_BIT_SCALE) + +/*Estimate the R-D cost of the DCT coefficients given the SATD of a block after + prediction.*/ +static unsigned oc_dct_cost2(unsigned *_ssd, + int _qi,int _pli,int _qti,int _satd){ + unsigned rmse; + int bin; + int dx; + int y0; + int z0; + int dy; + int dz; + /*SATD metrics for chroma planes vary much less than luma, so we scale them + by 4 to distribute them into the mode decision bins more evenly.*/ + _satd<<=_pli+1&2; + bin=OC_MINI(_satd>>OC_SAD_SHIFT,OC_SAD_BINS-2); + dx=_satd-(bin<>OC_SAD_SHIFT),0); + *_ssd=rmse*rmse>>2*OC_RMSE_SCALE-OC_BIT_SCALE; + return OC_MAXI(y0+(dy*dx>>OC_SAD_SHIFT),0); +} + +/*Select luma block-level quantizers for a MB in an INTRA frame.*/ +static unsigned oc_analyze_intra_mb_luma(oc_enc_ctx *_enc, + const oc_qii_state *_qs,unsigned _mbi){ + const unsigned char *src; + const ptrdiff_t *frag_buf_offs; + const oc_sb_map *sb_maps; + oc_fragment *frags; + ptrdiff_t frag_offs; + ptrdiff_t fragi; + oc_qii_state qs[4][3]; + unsigned cost[4][3]; + unsigned ssd[4][3]; + unsigned rate[4][3]; + int prev[3][3]; + unsigned satd; + unsigned best_cost; + unsigned best_ssd; + unsigned best_rate; + int best_qii; + int qii; + int lambda; + int ystride; + int nqis; + int bi; + frag_buf_offs=_enc->state.frag_buf_offs; + sb_maps=(const oc_sb_map *)_enc->state.sb_maps; + src=_enc->state.ref_frame_data[OC_FRAME_IO]; + ystride=_enc->state.ref_ystride[0]; + fragi=sb_maps[_mbi>>2][_mbi&3][0]; + frag_offs=frag_buf_offs[fragi]; + satd=oc_enc_frag_intra_satd(_enc,src+frag_offs,ystride); + nqis=_enc->state.nqis; + lambda=_enc->lambda; + for(qii=0;qiistate.qis[qii],0,0,satd) + +(qs[0][qii].bits-_qs->bits<>2][_mbi&3][bi]; + frag_offs=frag_buf_offs[fragi]; + satd=oc_enc_frag_intra_satd(_enc,src+frag_offs,ystride); + for(qii=0;qiistate.qis[qii],0,0,satd); + best_ssd=ssd[bi-1][0]+cur_ssd; + best_rate=rate[bi-1][0]+cur_rate + +(qt[0].bits-qs[bi-1][0].bits<state.frags; + for(bi=3;;){ + fragi=sb_maps[_mbi>>2][_mbi&3][bi]; + frags[fragi].qii=best_qii; + if(bi--<=0)break; + best_qii=prev[bi][best_qii]; + } + return best_cost; +} + +/*Select a block-level quantizer for a single chroma block in an INTRA frame.*/ +static unsigned oc_analyze_intra_chroma_block(oc_enc_ctx *_enc, + const oc_qii_state *_qs,int _pli,ptrdiff_t _fragi){ + const unsigned char *src; + oc_fragment *frags; + ptrdiff_t frag_offs; + oc_qii_state qt[3]; + unsigned cost[3]; + unsigned satd; + unsigned best_cost; + int best_qii; + int qii; + int lambda; + int ystride; + int nqis; + src=_enc->state.ref_frame_data[OC_FRAME_IO]; + ystride=_enc->state.ref_ystride[_pli]; + frag_offs=_enc->state.frag_buf_offs[_fragi]; + satd=oc_enc_frag_intra_satd(_enc,src+frag_offs,ystride); + nqis=_enc->state.nqis; + lambda=_enc->lambda; + best_qii=0; + for(qii=0;qiistate.qis[qii],_pli,0,satd) + +(qt[qii].bits-_qs->bits<state.frags; + frags[_fragi].qii=best_qii; + return best_cost; +} + +static void oc_enc_sb_transform_quantize_intra_chroma(oc_enc_ctx *_enc, + oc_enc_pipeline_state *_pipe,int _pli,int _sbi_start,int _sbi_end){ + const oc_sb_map *sb_maps; + oc_sb_flags *sb_flags; + ptrdiff_t *coded_fragis; + ptrdiff_t ncoded_fragis; + int sbi; + sb_maps=(const oc_sb_map *)_enc->state.sb_maps; + sb_flags=_enc->state.sb_flags; + coded_fragis=_pipe->coded_fragis[_pli]; + ncoded_fragis=_pipe->ncoded_fragis[_pli]; + for(sbi=_sbi_start;sbi<_sbi_end;sbi++){ + /*Worst case token stack usage for 1 fragment.*/ + oc_token_checkpoint stack[64]; + int quadi; + int bi; + for(quadi=0;quadi<4;quadi++)for(bi=0;bi<4;bi++){ + ptrdiff_t fragi; + fragi=sb_maps[sbi][quadi][bi]; + if(fragi>=0){ + oc_token_checkpoint *stackptr; + oc_analyze_intra_chroma_block(_enc,_pipe->qs+_pli,_pli,fragi); + stackptr=stack; + oc_enc_block_transform_quantize(_enc, + _pipe,_pli,fragi,0,NULL,&stackptr); + coded_fragis[ncoded_fragis++]=fragi; + } + } + } + _pipe->ncoded_fragis[_pli]=ncoded_fragis; +} + +/*Analysis stage for an INTRA frame.*/ +void oc_enc_analyze_intra(oc_enc_ctx *_enc,int _recode){ + oc_enc_pipeline_state pipe; + const unsigned char *map_idxs; + int nmap_idxs; + oc_sb_flags *sb_flags; + signed char *mb_modes; + const oc_mb_map *mb_maps; + oc_mb_enc_info *embs; + oc_fragment *frags; + unsigned stripe_sby; + unsigned mcu_nvsbs; + int notstart; + int notdone; + int refi; + int pli; + _enc->state.frame_type=OC_INTRA_FRAME; + oc_enc_tokenize_start(_enc); + oc_enc_pipeline_init(_enc,&pipe); + /*Choose MVs and MB modes and quantize and code luma. + Must be done in Hilbert order.*/ + map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt]; + nmap_idxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt]; + _enc->state.ncoded_fragis[0]=0; + _enc->state.ncoded_fragis[1]=0; + _enc->state.ncoded_fragis[2]=0; + sb_flags=_enc->state.sb_flags; + mb_modes=_enc->state.mb_modes; + mb_maps=(const oc_mb_map *)_enc->state.mb_maps; + embs=_enc->mb_info; + frags=_enc->state.frags; + notstart=0; + notdone=1; + mcu_nvsbs=_enc->mcu_nvsbs; + for(stripe_sby=0;notdone;stripe_sby+=mcu_nvsbs){ + unsigned sbi; + unsigned sbi_end; + notdone=oc_enc_pipeline_set_stripe(_enc,&pipe,stripe_sby); + sbi_end=pipe.sbi_end[0]; + for(sbi=pipe.sbi0[0];sbistate.curframe_num>0)oc_mcenc_search(_enc,mbi); + oc_analyze_intra_mb_luma(_enc,pipe.qs+0,mbi); + mb_modes[mbi]=OC_MODE_INTRA; + oc_enc_mb_transform_quantize_luma(_enc,&pipe,mbi,0); + /*Propagate final MB mode and MVs to the chroma blocks.*/ + for(mapii=4;mapii>2; + bi=mapi&3; + fragi=mb_maps[mbi][pli][bi]; + frags[fragi].mb_mode=OC_MODE_INTRA; + } + } + } + oc_enc_pipeline_finish_mcu_plane(_enc,&pipe,0,notstart,notdone); + /*Code chroma planes.*/ + for(pli=1;pli<3;pli++){ + oc_enc_sb_transform_quantize_intra_chroma(_enc,&pipe, + pli,pipe.sbi0[pli],pipe.sbi_end[pli]); + oc_enc_pipeline_finish_mcu_plane(_enc,&pipe,pli,notstart,notdone); + } + notstart=1; + } + /*Finish filling in the reference frame borders.*/ + refi=_enc->state.ref_frame_idx[OC_FRAME_SELF]; + for(pli=0;pli<3;pli++)oc_state_borders_fill_caps(&_enc->state,refi,pli); + _enc->state.ntotal_coded_fragis=_enc->state.nfrags; +} + + + +/*Cost information about a MB mode.*/ +struct oc_mode_choice{ + unsigned cost; + unsigned ssd; + unsigned rate; + unsigned overhead; + unsigned char qii[12]; +}; + + + +static void oc_mode_set_cost(oc_mode_choice *_modec,int _lambda){ + _modec->cost=OC_MODE_RD_COST(_modec->ssd, + _modec->rate+_modec->overhead,_lambda); +} + +/*A set of skip SSD's to use to disable early skipping.*/ +static const unsigned OC_NOSKIP[12]={ + UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX, + UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX, + UINT_MAX,UINT_MAX,UINT_MAX,UINT_MAX +}; + +/*The estimated number of bits used by a coded chroma block to specify the AC + quantizer. + TODO: Currently this is just 0.5*log2(3) (estimating about 50% compression); + measurements suggest this is in the right ballpark, but it varies somewhat + with lambda.*/ +#define OC_CHROMA_QII_RATE ((0xCAE00D1DU>>31-OC_BIT_SCALE)+1>>1) + +static void oc_analyze_mb_mode_luma(oc_enc_ctx *_enc, + oc_mode_choice *_modec,const oc_fr_state *_fr,const oc_qii_state *_qs, + const unsigned _frag_satd[12],const unsigned _skip_ssd[12],int _qti){ + oc_fr_state fr; + oc_qii_state qs; + unsigned ssd; + unsigned rate; + int overhead; + unsigned satd; + unsigned best_ssd; + unsigned best_rate; + int best_overhead; + int best_fri; + int best_qii; + unsigned cur_cost; + unsigned cur_ssd; + unsigned cur_rate; + int cur_overhead; + int lambda; + int nqis; + int nskipped; + int bi; + int qii; + lambda=_enc->lambda; + nqis=_enc->state.nqis; + /*We could do a trellis optimization here, but we don't make final skip + decisions until after transform+quantization, so the result wouldn't be + optimal anyway. + Instead we just use a greedy approach; for most SATD values, the + differences between the qiis are large enough to drown out the cost to + code the flags, anyway.*/ + *&fr=*_fr; + *&qs=*_qs; + ssd=rate=overhead=nskipped=0; + for(bi=0;bi<4;bi++){ + oc_fr_state ft[2]; + oc_qii_state qt[3]; + unsigned best_cost; + satd=_frag_satd[bi]; + *(ft+0)=*&fr; + oc_fr_code_block(ft+0); + oc_qii_state_advance(qt+0,&qs,0); + best_overhead=(ft[0].bits-fr.bits<state.qis[0],0,_qti,satd) + +(qt[0].bits-qs.bits<state.qis[qii],0,_qti,satd) + +(qt[qii].bits-qs.bits<qii[bi]=best_qii; + } + _modec->ssd=ssd; + _modec->rate=rate; + _modec->overhead=OC_MAXI(overhead,0); +} + +static void oc_analyze_mb_mode_chroma(oc_enc_ctx *_enc, + oc_mode_choice *_modec,const oc_fr_state *_fr,const oc_qii_state *_qs, + const unsigned _frag_satd[12],const unsigned _skip_ssd[12],int _qti){ + unsigned ssd; + unsigned rate; + unsigned satd; + unsigned best_ssd; + unsigned best_rate; + int best_qii; + unsigned cur_cost; + unsigned cur_ssd; + unsigned cur_rate; + int lambda; + int nblocks; + int nqis; + int pli; + int bi; + int qii; + lambda=_enc->lambda; + nqis=_enc->state.nqis; + ssd=_modec->ssd; + rate=_modec->rate; + /*Because (except in 4:4:4 mode) we aren't considering chroma blocks in coded + order, we assume a constant overhead for coded block and qii flags.*/ + nblocks=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt]; + nblocks=(nblocks-4>>1)+4; + bi=4; + for(pli=1;pli<3;pli++){ + for(;bistate.qis[0],pli,_qti,satd) + +OC_CHROMA_QII_RATE; + best_cost=OC_MODE_RD_COST(ssd+best_ssd,rate+best_rate,lambda); + best_qii=0; + for(qii=1;qiistate.qis[qii],0,_qti,satd) + +OC_CHROMA_QII_RATE; + cur_cost=OC_MODE_RD_COST(ssd+cur_ssd,rate+cur_rate,lambda); + if(cur_costqii[bi]=best_qii; + } + nblocks=(nblocks-4<<1)+4; + } + _modec->ssd=ssd; + _modec->rate=rate; +} + +static void oc_skip_cost(oc_enc_ctx *_enc,oc_enc_pipeline_state *_pipe, + unsigned _mbi,unsigned _ssd[12]){ + OC_ALIGN16(ogg_int16_t buffer[64]); + const unsigned char *src; + const unsigned char *ref; + int ystride; + const oc_fragment *frags; + const ptrdiff_t *frag_buf_offs; + const ptrdiff_t *sb_map; + const oc_mb_map_plane *mb_map; + const unsigned char *map_idxs; + int map_nidxs; + ogg_int64_t mask; + unsigned uncoded_ssd; + int uncoded_dc; + unsigned dc_dequant; + int dc_flag; + int mapii; + int mapi; + int pli; + int bi; + ptrdiff_t fragi; + ptrdiff_t frag_offs; + int borderi; + int pi; + src=_enc->state.ref_frame_data[OC_FRAME_IO]; + ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_PREV]]; + ystride=_enc->state.ref_ystride[0]; + frags=_enc->state.frags; + frag_buf_offs=_enc->state.frag_buf_offs; + sb_map=_enc->state.sb_maps[_mbi>>2][_mbi&3]; + dc_dequant=_enc->state.dequant_tables[_enc->state.qis[0]][0][1][0]; + for(bi=0;bi<4;bi++){ + fragi=sb_map[bi]; + frag_offs=frag_buf_offs[fragi]; + oc_enc_frag_sub(_enc,buffer,src+frag_offs,ref+frag_offs,ystride); + borderi=frags[fragi].borderi; + uncoded_ssd=uncoded_dc=0; + if(borderi<0){ + for(pi=0;pi<64;pi++){ + uncoded_ssd+=buffer[pi]*buffer[pi]; + uncoded_dc+=buffer[pi]; + } + } + else{ + ogg_int64_t mask; + mask=_enc->state.borders[borderi].mask; + for(pi=0;pi<64;pi++,mask>>=1)if(mask&1){ + uncoded_ssd+=buffer[pi]*buffer[pi]; + uncoded_dc+=buffer[pi]; + } + } + /*Scale to match DCT domain.*/ + uncoded_ssd<<=4; + /*We actually only want the AC contribution to the SSD.*/ + uncoded_ssd-=uncoded_dc*uncoded_dc>>2; + /*DC is a special case; if there's more than a full-quantizer improvement + in the effective DC component, always force-code the block.*/ + dc_flag=abs(uncoded_dc)>dc_dequant<<1; + uncoded_ssd|=-dc_flag; + _pipe->skip_ssd[0][fragi-_pipe->froffset[0]]=_ssd[bi]=uncoded_ssd; + } + mb_map=(const oc_mb_map_plane *)_enc->state.mb_maps[_mbi]; + map_nidxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt]; + map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt]; + map_nidxs=(map_nidxs-4>>1)+4; + mapii=4; + for(pli=1;pli<3;pli++){ + ystride=_enc->state.ref_ystride[pli]; + dc_dequant=_enc->state.dequant_tables[_enc->state.qis[0]][pli][1][0]; + for(;mapiistate.borders[borderi].mask; + for(pi=0;pi<64;pi++,mask>>=1)if(mask&1){ + uncoded_ssd+=buffer[pi]*buffer[pi]; + uncoded_dc+=buffer[pi]; + } + } + /*Scale to match DCT domain.*/ + uncoded_ssd<<=4; + /*We actually only want the AC contribution to the SSD.*/ + uncoded_ssd-=uncoded_dc*uncoded_dc>>2; + /*DC is a special case; if there's more than a full-quantizer improvement + in the effective DC component, always force-code the block.*/ + dc_flag=abs(uncoded_dc)>dc_dequant<<1; + uncoded_ssd|=-dc_flag; + _pipe->skip_ssd[pli][fragi-_pipe->froffset[pli]]=_ssd[mapii]=uncoded_ssd; + } + map_nidxs=(map_nidxs-4<<1)+4; + } +} + +static void oc_mb_intra_satd(oc_enc_ctx *_enc,unsigned _mbi, + unsigned _frag_satd[12]){ + const unsigned char *src; + const ptrdiff_t *frag_buf_offs; + const ptrdiff_t *sb_map; + const oc_mb_map_plane *mb_map; + const unsigned char *map_idxs; + int map_nidxs; + int mapii; + int mapi; + int ystride; + int pli; + int bi; + ptrdiff_t fragi; + ptrdiff_t frag_offs; + frag_buf_offs=_enc->state.frag_buf_offs; + sb_map=_enc->state.sb_maps[_mbi>>2][_mbi&3]; + src=_enc->state.ref_frame_data[OC_FRAME_IO]; + ystride=_enc->state.ref_ystride[0]; + for(bi=0;bi<4;bi++){ + fragi=sb_map[bi]; + frag_offs=frag_buf_offs[fragi]; + _frag_satd[bi]=oc_enc_frag_intra_satd(_enc,src+frag_offs,ystride); + } + mb_map=(const oc_mb_map_plane *)_enc->state.mb_maps[_mbi]; + map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt]; + map_nidxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt]; + /*Note: This assumes ref_ystride[1]==ref_ystride[2].*/ + ystride=_enc->state.ref_ystride[1]; + for(mapii=4;mapii>2; + bi=mapi&3; + fragi=mb_map[pli][bi]; + frag_offs=frag_buf_offs[fragi]; + _frag_satd[mapii]=oc_enc_frag_intra_satd(_enc,src+frag_offs,ystride); + } +} + +static void oc_cost_intra(oc_enc_ctx *_enc,oc_mode_choice *_modec, + unsigned _mbi,const oc_fr_state *_fr,const oc_qii_state *_qs, + const unsigned _frag_satd[12],const unsigned _skip_ssd[12]){ + oc_analyze_mb_mode_luma(_enc,_modec,_fr,_qs,_frag_satd,_skip_ssd,0); + oc_analyze_mb_mode_chroma(_enc,_modec,_fr,_qs,_frag_satd,_skip_ssd,0); + _modec->overhead+= + oc_mode_scheme_chooser_cost(&_enc->chooser,OC_MODE_INTRA)<lambda); +} + +static void oc_cost_inter(oc_enc_ctx *_enc,oc_mode_choice *_modec, + unsigned _mbi,int _mb_mode,const signed char *_mv, + const oc_fr_state *_fr,const oc_qii_state *_qs,const unsigned _skip_ssd[12]){ + unsigned frag_satd[12]; + const unsigned char *src; + const unsigned char *ref; + int ystride; + const ptrdiff_t *frag_buf_offs; + const ptrdiff_t *sb_map; + const oc_mb_map_plane *mb_map; + const unsigned char *map_idxs; + int map_nidxs; + int mapii; + int mapi; + int mv_offs[2]; + int dx; + int dy; + int pli; + int bi; + ptrdiff_t fragi; + ptrdiff_t frag_offs; + src=_enc->state.ref_frame_data[OC_FRAME_IO]; + ref=_enc->state.ref_frame_data[ + _enc->state.ref_frame_idx[OC_FRAME_FOR_MODE(_mb_mode)]]; + ystride=_enc->state.ref_ystride[0]; + frag_buf_offs=_enc->state.frag_buf_offs; + sb_map=_enc->state.sb_maps[_mbi>>2][_mbi&3]; + dx=_mv[0]; + dy=_mv[1]; + _modec->rate=_modec->ssd=0; + if(oc_state_get_mv_offsets(&_enc->state,mv_offs,0,dx,dy)>1){ + for(bi=0;bi<4;bi++){ + fragi=sb_map[bi]; + frag_offs=frag_buf_offs[fragi]; + frag_satd[bi]=oc_enc_frag_satd2_thresh(_enc,src+frag_offs, + ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX); + } + } + else{ + for(bi=0;bi<4;bi++){ + fragi=sb_map[bi]; + frag_offs=frag_buf_offs[fragi]; + frag_satd[bi]=oc_enc_frag_satd_thresh(_enc,src+frag_offs, + ref+frag_offs+mv_offs[0],ystride,UINT_MAX); + } + } + mb_map=(const oc_mb_map_plane *)_enc->state.mb_maps[_mbi]; + map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt]; + map_nidxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt]; + /*Note: This assumes ref_ystride[1]==ref_ystride[2].*/ + ystride=_enc->state.ref_ystride[1]; + if(oc_state_get_mv_offsets(&_enc->state,mv_offs,1,dx,dy)>1){ + for(mapii=4;mapii>2; + bi=mapi&3; + fragi=mb_map[pli][bi]; + frag_offs=frag_buf_offs[fragi]; + frag_satd[mapii]=oc_enc_frag_satd2_thresh(_enc,src+frag_offs, + ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX); + } + } + else{ + for(mapii=4;mapii>2; + bi=mapi&3; + fragi=mb_map[pli][bi]; + frag_offs=frag_buf_offs[fragi]; + frag_satd[mapii]=oc_enc_frag_satd_thresh(_enc,src+frag_offs, + ref+frag_offs+mv_offs[0],ystride,UINT_MAX); + } + } + oc_analyze_mb_mode_luma(_enc,_modec,_fr,_qs,frag_satd,_skip_ssd,1); + oc_analyze_mb_mode_chroma(_enc,_modec,_fr,_qs,frag_satd,_skip_ssd,1); + _modec->overhead+= + oc_mode_scheme_chooser_cost(&_enc->chooser,_mb_mode)<lambda); +} + +static void oc_cost_inter_nomv(oc_enc_ctx *_enc,oc_mode_choice *_modec, + unsigned _mbi,int _mb_mode,const oc_fr_state *_fr,const oc_qii_state *_qs, + const unsigned _skip_ssd[12]){ + static const oc_mv OC_MV_ZERO; + oc_cost_inter(_enc,_modec,_mbi,_mb_mode,OC_MV_ZERO,_fr,_qs,_skip_ssd); +} + +static int oc_cost_inter1mv(oc_enc_ctx *_enc,oc_mode_choice *_modec, + unsigned _mbi,int _mb_mode,const signed char *_mv, + const oc_fr_state *_fr,const oc_qii_state *_qs,const unsigned _skip_ssd[12]){ + int bits0; + oc_cost_inter(_enc,_modec,_mbi,_mb_mode,_mv,_fr,_qs,_skip_ssd); + bits0=OC_MV_BITS[0][_mv[0]+31]+OC_MV_BITS[0][_mv[1]+31]; + _modec->overhead+=OC_MINI(_enc->mv_bits[0]+bits0,_enc->mv_bits[1]+12) + -OC_MINI(_enc->mv_bits[0],_enc->mv_bits[1])<lambda); + return bits0; +} + +/*A mapping from oc_mb_map (raster) ordering to oc_sb_map (Hilbert) ordering.*/ +static const unsigned char OC_MB_PHASE[4][4]={ + {0,1,3,2},{0,3,1,2},{0,3,1,2},{2,3,1,0} +}; + +static void oc_cost_inter4mv(oc_enc_ctx *_enc,oc_mode_choice *_modec, + unsigned _mbi,oc_mv _mv[4],const oc_fr_state *_fr,const oc_qii_state *_qs, + const unsigned _skip_ssd[12]){ + unsigned frag_satd[12]; + oc_mv lbmvs[4]; + oc_mv cbmvs[4]; + const unsigned char *src; + const unsigned char *ref; + int ystride; + const ptrdiff_t *frag_buf_offs; + oc_mv *frag_mvs; + const oc_mb_map_plane *mb_map; + const unsigned char *map_idxs; + int map_nidxs; + int nqis; + int mapii; + int mapi; + int mv_offs[2]; + int dx; + int dy; + int pli; + int bi; + ptrdiff_t fragi; + ptrdiff_t frag_offs; + int bits0; + int bits1; + unsigned satd; + src=_enc->state.ref_frame_data[OC_FRAME_IO]; + ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_PREV]]; + ystride=_enc->state.ref_ystride[0]; + frag_buf_offs=_enc->state.frag_buf_offs; + frag_mvs=_enc->state.frag_mvs; + mb_map=(const oc_mb_map_plane *)_enc->state.mb_maps[_mbi]; + _modec->rate=_modec->ssd=0; + for(bi=0;bi<4;bi++){ + fragi=mb_map[0][bi]; + dx=_mv[bi][0]; + dy=_mv[bi][1]; + /*Save the block MVs as the current ones while we're here; we'll replace + them if we don't ultimately choose 4MV mode.*/ + frag_mvs[fragi][0]=(signed char)dx; + frag_mvs[fragi][1]=(signed char)dy; + frag_offs=frag_buf_offs[fragi]; + if(oc_state_get_mv_offsets(&_enc->state,mv_offs,0,dx,dy)>1){ + satd=oc_enc_frag_satd2_thresh(_enc,src+frag_offs, + ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX); + } + else{ + satd=oc_enc_frag_satd_thresh(_enc,src+frag_offs, + ref+frag_offs+mv_offs[0],ystride,UINT_MAX); + } + frag_satd[OC_MB_PHASE[_mbi&3][bi]]=satd; + } + oc_analyze_mb_mode_luma(_enc,_modec,_fr,_qs,frag_satd, + _enc->vp3_compatible?OC_NOSKIP:_skip_ssd,1); + /*Figure out which blocks are being skipped and give them (0,0) MVs.*/ + bits0=0; + bits1=0; + nqis=_enc->state.nqis; + for(bi=0;bi<4;bi++){ + if(_modec->qii[OC_MB_PHASE[_mbi&3][bi]]>=nqis){ + memset(lbmvs+bi,0,sizeof(*lbmvs)); + } + else{ + memcpy(lbmvs+bi,_mv+bi,sizeof(*lbmvs)); + bits0+=OC_MV_BITS[0][_mv[bi][0]+31]+OC_MV_BITS[0][_mv[bi][1]+31]; + bits1+=12; + } + } + (*OC_SET_CHROMA_MVS_TABLE[_enc->state.info.pixel_fmt])(cbmvs, + (const oc_mv *)lbmvs); + map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt]; + map_nidxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt]; + /*Note: This assumes ref_ystride[1]==ref_ystride[2].*/ + ystride=_enc->state.ref_ystride[1]; + for(mapii=4;mapii>2; + bi=mapi&3; + fragi=mb_map[pli][bi]; + dx=cbmvs[bi][0]; + dy=cbmvs[bi][1]; + frag_offs=frag_buf_offs[fragi]; + /*TODO: We could save half these calls by re-using the results for the Cb + and Cr planes; is it worth it?*/ + if(oc_state_get_mv_offsets(&_enc->state,mv_offs,pli,dx,dy)>1){ + satd=oc_enc_frag_satd2_thresh(_enc,src+frag_offs, + ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX); + } + else{ + satd=oc_enc_frag_satd_thresh(_enc,src+frag_offs, + ref+frag_offs+mv_offs[0],ystride,UINT_MAX); + } + frag_satd[mapii]=satd; + } + oc_analyze_mb_mode_chroma(_enc,_modec,_fr,_qs,frag_satd,_skip_ssd,1); + _modec->overhead+= + oc_mode_scheme_chooser_cost(&_enc->chooser,OC_MODE_INTER_MV_FOUR) + +OC_MINI(_enc->mv_bits[0]+bits0,_enc->mv_bits[1]+bits1) + -OC_MINI(_enc->mv_bits[0],_enc->mv_bits[1])<lambda); +} + +int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){ + oc_set_chroma_mvs_func set_chroma_mvs; + oc_enc_pipeline_state pipe; + oc_qii_state intra_luma_qs; + oc_mv last_mv; + oc_mv prior_mv; + ogg_int64_t interbits; + ogg_int64_t intrabits; + const unsigned char *map_idxs; + int nmap_idxs; + unsigned *coded_mbis; + unsigned *uncoded_mbis; + size_t ncoded_mbis; + size_t nuncoded_mbis; + oc_sb_flags *sb_flags; + signed char *mb_modes; + const oc_sb_map *sb_maps; + const oc_mb_map *mb_maps; + oc_mb_enc_info *embs; + oc_fragment *frags; + oc_mv *frag_mvs; + int qi; + unsigned stripe_sby; + unsigned mcu_nvsbs; + int notstart; + int notdone; + int vdec; + unsigned sbi; + unsigned sbi_end; + int refi; + int pli; + set_chroma_mvs=OC_SET_CHROMA_MVS_TABLE[_enc->state.info.pixel_fmt]; + _enc->state.frame_type=OC_INTER_FRAME; + oc_mode_scheme_chooser_reset(&_enc->chooser); + oc_enc_tokenize_start(_enc); + oc_enc_pipeline_init(_enc,&pipe); + if(_allow_keyframe)oc_qii_state_init(&intra_luma_qs); + _enc->mv_bits[0]=_enc->mv_bits[1]=0; + interbits=intrabits=0; + last_mv[0]=last_mv[1]=prior_mv[0]=prior_mv[1]=0; + /*Choose MVs and MB modes and quantize and code luma. + Must be done in Hilbert order.*/ + map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt]; + nmap_idxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt]; + qi=_enc->state.qis[0]; + coded_mbis=_enc->coded_mbis; + uncoded_mbis=coded_mbis+_enc->state.nmbs; + ncoded_mbis=0; + nuncoded_mbis=0; + _enc->state.ncoded_fragis[0]=0; + _enc->state.ncoded_fragis[1]=0; + _enc->state.ncoded_fragis[2]=0; + sb_flags=_enc->state.sb_flags; + mb_modes=_enc->state.mb_modes; + sb_maps=(const oc_sb_map *)_enc->state.sb_maps; + mb_maps=(const oc_mb_map *)_enc->state.mb_maps; + embs=_enc->mb_info; + frags=_enc->state.frags; + frag_mvs=_enc->state.frag_mvs; + vdec=!(_enc->state.info.pixel_fmt&2); + notstart=0; + notdone=1; + mcu_nvsbs=_enc->mcu_nvsbs; + for(stripe_sby=0;notdone;stripe_sby+=mcu_nvsbs){ + notdone=oc_enc_pipeline_set_stripe(_enc,&pipe,stripe_sby); + sbi_end=pipe.sbi_end[0]; + for(sbi=pipe.sbi0[0];sbisp_levelsp_levellambda*3; + if(modes[OC_MODE_INTER_MV_FOUR].cost>2][mbi&3][bi]; + frags[fragi].qii=modes[mb_mode].qii[bi]; + } + if(oc_enc_mb_transform_quantize_luma(_enc,&pipe,mbi, + modes[mb_mode].overhead>>OC_BIT_SCALE)>0){ + int orig_mb_mode; + orig_mb_mode=mb_mode; + mb_mode=mb_modes[mbi]; + switch(mb_mode){ + case OC_MODE_INTER_MV:{ + memcpy(prior_mv,last_mv,sizeof(prior_mv)); + /*If we're backing out from 4MV, find the MV we're actually + using.*/ + if(orig_mb_mode==OC_MODE_INTER_MV_FOUR){ + for(bi=0;;bi++){ + fragi=mb_maps[mbi][0][bi]; + if(frags[fragi].coded){ + memcpy(last_mv,frag_mvs[fragi],sizeof(last_mv)); + dx=frag_mvs[fragi][0]; + dy=frag_mvs[fragi][1]; + break; + } + } + mb_mv_bits_0=OC_MV_BITS[0][dx+31]+OC_MV_BITS[0][dy+31]; + } + /*Otherwise we used the original analysis MV.*/ + else{ + memcpy(last_mv, + embs[mbi].analysis_mv[0][OC_FRAME_PREV],sizeof(last_mv)); + } + _enc->mv_bits[0]+=mb_mv_bits_0; + _enc->mv_bits[1]+=12; + }break; + case OC_MODE_INTER_MV_LAST2:{ + oc_mv tmp_mv; + memcpy(tmp_mv,prior_mv,sizeof(tmp_mv)); + memcpy(prior_mv,last_mv,sizeof(prior_mv)); + memcpy(last_mv,tmp_mv,sizeof(last_mv)); + }break; + case OC_MODE_GOLDEN_MV:{ + _enc->mv_bits[0]+=mb_gmv_bits_0; + _enc->mv_bits[1]+=12; + }break; + case OC_MODE_INTER_MV_FOUR:{ + oc_mv lbmvs[4]; + oc_mv cbmvs[4]; + memcpy(prior_mv,last_mv,sizeof(prior_mv)); + for(bi=0;bi<4;bi++){ + fragi=mb_maps[mbi][0][bi]; + if(frags[fragi].coded){ + memcpy(last_mv,frag_mvs[fragi],sizeof(last_mv)); + memcpy(lbmvs[bi],frag_mvs[fragi],sizeof(lbmvs[bi])); + _enc->mv_bits[0]+=OC_MV_BITS[0][frag_mvs[fragi][0]+31] + +OC_MV_BITS[0][frag_mvs[fragi][1]+31]; + _enc->mv_bits[1]+=12; + } + /*Replace the block MVs for not-coded blocks with (0,0).*/ + else memset(lbmvs[bi],0,sizeof(lbmvs[bi])); + } + (*set_chroma_mvs)(cbmvs,(const oc_mv *)lbmvs); + for(mapii=4;mapii>2; + bi=mapi&3; + fragi=mb_maps[mbi][pli][bi]; + frags[fragi].mb_mode=mb_mode; + frags[fragi].qii=modes[OC_MODE_INTER_MV_FOUR].qii[mapii]; + memcpy(frag_mvs[fragi],cbmvs[bi],sizeof(frag_mvs[fragi])); + } + }break; + } + coded_mbis[ncoded_mbis++]=mbi; + oc_mode_scheme_chooser_update(&_enc->chooser,mb_mode); + interbits+=modes[mb_mode].rate+modes[mb_mode].overhead; + } + else{ + *(uncoded_mbis-++nuncoded_mbis)=mbi; + mb_mode=OC_MODE_INTER_NOMV; + dx=dy=0; + } + /*Propagate final MB mode and MVs to the chroma blocks. + This has already been done for 4MV mode, since it requires individual + block motion vectors.*/ + if(mb_mode!=OC_MODE_INTER_MV_FOUR){ + for(mapii=4;mapii>2; + bi=mapi&3; + fragi=mb_maps[mbi][pli][bi]; + frags[fragi].mb_mode=mb_mode; + /*If we switched from 4MV mode to INTER_MV mode, then the qii + values won't have been chosen with the right MV, but it's + probaby not worth re-estimating them.*/ + frags[fragi].qii=modes[mb_mode].qii[mapii]; + frag_mvs[fragi][0]=(signed char)dx; + frag_mvs[fragi][1]=(signed char)dy; + } + } + } + oc_fr_state_flush_sb(pipe.fr+0); + sb_flags[sbi].coded_fully=pipe.fr[0].sb_full; + sb_flags[sbi].coded_partially=pipe.fr[0].sb_partial; + } + oc_enc_pipeline_finish_mcu_plane(_enc,&pipe,0,notstart,notdone); + /*Code chroma planes.*/ + for(pli=1;pli<3;pli++){ + oc_enc_sb_transform_quantize_chroma(_enc,&pipe, + pli,pipe.sbi0[pli],pipe.sbi_end[pli]); + oc_enc_pipeline_finish_mcu_plane(_enc,&pipe,pli,notstart,notdone); + } + notstart=1; + } + /*Finish filling in the reference frame borders.*/ + refi=_enc->state.ref_frame_idx[OC_FRAME_SELF]; + for(pli=0;pli<3;pli++)oc_state_borders_fill_caps(&_enc->state,refi,pli); + /*Finish adding flagging overhead costs to inter bit counts to determine if + we should have coded a key frame instead.*/ + if(_allow_keyframe){ + if(interbits>intrabits)return 1; + /*Technically the chroma plane counts are over-estimations, because they + don't account for continuing runs from the luma planes, but the + inaccuracy is small.*/ + for(pli=0;pli<3;pli++)interbits+=pipe.fr[pli].bits<mv_bits[0],_enc->mv_bits[1])<chooser.scheme_bits[_enc->chooser.scheme_list[0]]<intrabits)return 1; + } + _enc->ncoded_mbis=ncoded_mbis; + /*Compact the coded fragment list.*/ + { + ptrdiff_t ncoded_fragis; + ncoded_fragis=_enc->state.ncoded_fragis[0]; + for(pli=1;pli<3;pli++){ + memmove(_enc->state.coded_fragis+ncoded_fragis, + _enc->state.coded_fragis+_enc->state.fplanes[pli].froffset, + _enc->state.ncoded_fragis[pli]*sizeof(*_enc->state.coded_fragis)); + ncoded_fragis+=_enc->state.ncoded_fragis[pli]; + } + _enc->state.ntotal_coded_fragis=ncoded_fragis; + } + return 0; +} + +#if defined(OC_COLLECT_METRICS) +# include +# include + +/*TODO: It may be helpful (for block-level quantizers especially) to separate + out the contributions from AC and DC into separate tables.*/ + +# define OC_ZWEIGHT (0.25) + +static void oc_mode_metrics_add(oc_mode_metrics *_metrics, + double _w,int _satd,int _rate,double _rmse){ + double rate; + /*Accumulate statistics without the scaling; this lets us change the scale + factor yet still use old data.*/ + rate=ldexp(_rate,-OC_BIT_SCALE); + if(_metrics->fragw>0){ + double dsatd; + double drate; + double drmse; + double w; + dsatd=_satd-_metrics->satd/_metrics->fragw; + drate=rate-_metrics->rate/_metrics->fragw; + drmse=_rmse-_metrics->rmse/_metrics->fragw; + w=_metrics->fragw*_w/(_metrics->fragw+_w); + _metrics->satd2+=dsatd*dsatd*w; + _metrics->satdrate+=dsatd*drate*w; + _metrics->rate2+=drate*drate*w; + _metrics->satdrmse+=dsatd*drmse*w; + _metrics->rmse2+=drmse*drmse*w; + } + _metrics->fragw+=_w; + _metrics->satd+=_satd*_w; + _metrics->rate+=rate*_w; + _metrics->rmse+=_rmse*_w; +} + +static void oc_mode_metrics_merge(oc_mode_metrics *_dst, + const oc_mode_metrics *_src,int _n){ + int i; + /*Find a non-empty set of metrics.*/ + for(i=0;i<_n&&_src[i].fragw<=0;i++); + if(i>=_n){ + memset(_dst,0,sizeof(*_dst)); + return; + } + memcpy(_dst,_src+i,sizeof(*_dst)); + /*And iterate over the remaining non-empty sets of metrics.*/ + for(i++;i<_n;i++)if(_src[i].fragw>0){ + double wa; + double wb; + double dsatd; + double drate; + double drmse; + double w; + wa=_dst->fragw; + wb=_src[i].fragw; + dsatd=_src[i].satd/wb-_dst->satd/wa; + drate=_src[i].rate/wb-_dst->rate/wa; + drmse=_src[i].rmse/wb-_dst->rmse/wa; + w=wa*wb/(wa+wb); + _dst->fragw+=_src[i].fragw; + _dst->satd+=_src[i].satd; + _dst->rate+=_src[i].rate; + _dst->rmse+=_src[i].rmse; + _dst->satd2+=_src[i].satd2+dsatd*dsatd*w; + _dst->satdrate+=_src[i].satdrate+dsatd*drate*w; + _dst->rate2+=_src[i].rate2+drate*drate*w; + _dst->satdrmse+=_src[i].satdrmse+dsatd*drmse*w; + _dst->rmse2+=_src[i].rmse2+drmse*drmse*w; + } +} + +/*Compile collected SATD/rate/RMSE metrics into a form that's immediately + useful for mode decision.*/ +static void oc_enc_mode_metrics_update(oc_enc_ctx *_enc,int _qi){ + int pli; + int qti; + oc_restore_fpu(&_enc->state); + /*Convert raw collected data into cleaned up sample points.*/ + for(pli=0;pli<3;pli++){ + for(qti=0;qti<2;qti++){ + double fragw; + int bin0; + int bin1; + int bin; + fragw=0; + bin0=bin1=0; + for(bin=0;bin=OC_ZWEIGHT){ + fragw-=OC_MODE_METRICS[_qi][pli][qti][bin0++].fragw; + } + /*Merge statistics and fit lines.*/ + oc_mode_metrics_merge(&metrics, + OC_MODE_METRICS[_qi][pli][qti]+bin0,bin1-bin0); + if(metrics.fragw>0&&metrics.satd2>0){ + double a; + double b; + double msatd; + double mrate; + double mrmse; + double rate; + double rmse; + msatd=metrics.satd/metrics.fragw; + mrate=metrics.rate/metrics.fragw; + mrmse=metrics.rmse/metrics.fragw; + /*Compute the points on these lines corresponding to the actual bin + value.*/ + b=metrics.satdrate/metrics.satd2; + a=mrate-b*msatd; + rate=ldexp(a+b*(bin<>1); + return -_extra_bits; +} + +/*Handles the pure zero run tokens.*/ +static ptrdiff_t oc_token_skip_zrl(int _token,int _extra_bits){ + return _extra_bits+1; +} + +/*Handles a normal coefficient value token.*/ +static ptrdiff_t oc_token_skip_val(void){ + return 1; +} + +/*Handles a category 1A zero run/coefficient value combo token.*/ +static ptrdiff_t oc_token_skip_run_cat1a(int _token){ + return _token-OC_DCT_RUN_CAT1A+2; +} + +/*Handles category 1b, 1c, 2a, and 2b zero run/coefficient value combo tokens.*/ +static ptrdiff_t oc_token_skip_run(int _token,int _extra_bits){ + int run_cati; + int ncoeffs_mask; + int ncoeffs_adjust; + run_cati=_token-OC_DCT_RUN_CAT1B; + ncoeffs_mask=OC_BYTE_TABLE32(3,7,0,1,run_cati); + ncoeffs_adjust=OC_BYTE_TABLE32(7,11,2,3,run_cati); + return (_extra_bits&ncoeffs_mask)+ncoeffs_adjust; +} + +/*A jump table for computing the number of coefficients or blocks to skip for + a given token value. + This reduces all the conditional branches, etc., needed to parse these token + values down to one indirect jump.*/ +static const oc_token_skip_func OC_TOKEN_SKIP_TABLE[TH_NDCT_TOKENS]={ + oc_token_skip_eob, + oc_token_skip_eob, + oc_token_skip_eob, + oc_token_skip_eob, + oc_token_skip_eob, + oc_token_skip_eob, + oc_token_skip_eob6, + oc_token_skip_zrl, + oc_token_skip_zrl, + (oc_token_skip_func)oc_token_skip_val, + (oc_token_skip_func)oc_token_skip_val, + (oc_token_skip_func)oc_token_skip_val, + (oc_token_skip_func)oc_token_skip_val, + (oc_token_skip_func)oc_token_skip_val, + (oc_token_skip_func)oc_token_skip_val, + (oc_token_skip_func)oc_token_skip_val, + (oc_token_skip_func)oc_token_skip_val, + (oc_token_skip_func)oc_token_skip_val, + (oc_token_skip_func)oc_token_skip_val, + (oc_token_skip_func)oc_token_skip_val, + (oc_token_skip_func)oc_token_skip_val, + (oc_token_skip_func)oc_token_skip_val, + (oc_token_skip_func)oc_token_skip_val, + (oc_token_skip_func)oc_token_skip_run_cat1a, + (oc_token_skip_func)oc_token_skip_run_cat1a, + (oc_token_skip_func)oc_token_skip_run_cat1a, + (oc_token_skip_func)oc_token_skip_run_cat1a, + (oc_token_skip_func)oc_token_skip_run_cat1a, + oc_token_skip_run, + oc_token_skip_run, + oc_token_skip_run, + oc_token_skip_run +}; + +/*Determines the number of blocks or coefficients to be skipped for a given + token value. + _token: The token value to skip. + _extra_bits: The extra bits attached to this token. + Return: A positive value indicates that number of coefficients are to be + skipped in the current block. + Otherwise, the negative of the return value indicates that number of + blocks are to be ended. + 0 will never be returned, so that at least one coefficient in one + block will always be decoded for every token.*/ +static ptrdiff_t oc_dct_token_skip(int _token,int _extra_bits){ + return (*OC_TOKEN_SKIP_TABLE[_token])(_token,_extra_bits); +} + + + +void oc_enc_mode_metrics_collect(oc_enc_ctx *_enc){ + static const unsigned char OC_ZZI_HUFF_OFFSET[64]={ + 0,16,16,16,16,16,32,32, + 32,32,32,32,32,32,32,48, + 48,48,48,48,48,48,48,48, + 48,48,48,48,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64 + }; + const oc_fragment *frags; + const unsigned *frag_satd; + const unsigned *frag_ssd; + const ptrdiff_t *coded_fragis; + ptrdiff_t ncoded_fragis; + ptrdiff_t fragii; + double fragw; + int qti; + int qii; + int qi; + int pli; + int zzi; + int token; + int eb; + oc_restore_fpu(&_enc->state); + /*Load any existing mode metrics if we haven't already.*/ + if(!oc_has_mode_metrics){ + FILE *fmetrics; + memset(OC_MODE_METRICS,0,sizeof(OC_MODE_METRICS)); + fmetrics=fopen("modedec.stats","rb"); + if(fmetrics!=NULL){ + fread(OC_MODE_METRICS,sizeof(OC_MODE_METRICS),1,fmetrics); + fclose(fmetrics); + } + for(qi=0;qi<64;qi++)oc_enc_mode_metrics_update(_enc,qi); + oc_has_mode_metrics=1; + } + qti=_enc->state.frame_type; + frags=_enc->state.frags; + frag_satd=_enc->frag_satd; + frag_ssd=_enc->frag_ssd; + coded_fragis=_enc->state.coded_fragis; + ncoded_fragis=fragii=0; + /*Weight the fragments by the inverse frame size; this prevents HD content + from dominating the statistics.*/ + fragw=1.0/_enc->state.nfrags; + for(pli=0;pli<3;pli++){ + ptrdiff_t ti[64]; + int eob_token[64]; + int eob_run[64]; + /*Set up token indices and eob run counts. + We don't bother trying to figure out the real cost of the runs that span + coefficients; instead we use the costs that were available when R-D + token optimization was done.*/ + for(zzi=0;zzi<64;zzi++){ + ti[zzi]=_enc->dct_token_offs[pli][zzi]; + if(ti[zzi]>0){ + token=_enc->dct_tokens[pli][zzi][0]; + eb=_enc->extra_bits[pli][zzi][0]; + eob_token[zzi]=token; + eob_run[zzi]=-oc_dct_token_skip(token,eb); + } + else{ + eob_token[zzi]=OC_NDCT_EOB_TOKEN_MAX; + eob_run[zzi]=0; + } + } + /*Scan the list of coded fragments for this plane.*/ + ncoded_fragis+=_enc->state.ncoded_fragis[pli]; + for(;fragii0){ + /*We've reached the end of the block.*/ + eob_run[zzi]--; + break; + } + huffi=_enc->huff_idxs[qti][zzi>0][pli+1>>1] + +OC_ZZI_HUFF_OFFSET[zzi]; + if(eob_token[zzi]huff_codes[huffi][eob_token[zzi]].nbits + +OC_DCT_TOKEN_EXTRA_BITS[eob_token[zzi]]; + eob_token[zzi]=OC_NDCT_EOB_TOKEN_MAX; + } + token=_enc->dct_tokens[pli][zzi][ti[zzi]]; + eb=_enc->extra_bits[pli][zzi][ti[zzi]]; + ti[zzi]++; + skip=oc_dct_token_skip(token,eb); + if(skip<0){ + eob_token[zzi]=token; + eob_run[zzi]=-skip; + } + else{ + /*A regular DCT value token; accumulate the bits for it.*/ + frag_bits+=_enc->huff_codes[huffi][token].nbits + +OC_DCT_TOKEN_EXTRA_BITS[token]; + zzi+=skip; + } + } + mb_mode=frags[fragi].mb_mode; + qi=_enc->state.qis[frags[fragi].qii]; + satd=frag_satd[fragi]<<(pli+1&2); + bin=OC_MINI(satd>>OC_SAD_SHIFT,OC_SAD_BINS-1); + oc_mode_metrics_add(OC_MODE_METRICS[qi][pli][mb_mode!=OC_MODE_INTRA]+bin, + fragw,satd,frag_bits<state.nqis;qii++){ + oc_enc_mode_metrics_update(_enc,_enc->state.qis[qii]); + } +} + +void oc_enc_mode_metrics_dump(oc_enc_ctx *_enc){ + FILE *fmetrics; + int qi; + /*Generate sample points for complete list of QI values.*/ + for(qi=0;qi<64;qi++)oc_enc_mode_metrics_update(_enc,qi); + fmetrics=fopen("modedec.stats","wb"); + if(fmetrics!=NULL){ + fwrite(OC_MODE_METRICS,sizeof(OC_MODE_METRICS),1,fmetrics); + fclose(fmetrics); + } + fprintf(stdout, + "/*File generated by libtheora with OC_COLLECT_METRICS" + " defined at compile time.*/\n" + "#if !defined(_modedec_H)\n" + "# define _modedec_H (1)\n" + "\n" + "\n" + "\n" + "# if defined(OC_COLLECT_METRICS)\n" + "typedef struct oc_mode_metrics oc_mode_metrics;\n" + "# endif\n" + "typedef struct oc_mode_rd oc_mode_rd;\n" + "\n" + "\n" + "\n" + "/*The number of extra bits of precision at which to store rate" + " metrics.*/\n" + "# define OC_BIT_SCALE (%i)\n" + "/*The number of extra bits of precision at which to store RMSE metrics.\n" + " This must be at least half OC_BIT_SCALE (rounded up).*/\n" + "# define OC_RMSE_SCALE (%i)\n" + "/*The number of bins to partition statistics into.*/\n" + "# define OC_SAD_BINS (%i)\n" + "/*The number of bits of precision to drop" + " from SAD scores to assign them to a\n" + " bin.*/\n" + "# define OC_SAD_SHIFT (%i)\n" + "\n" + "\n" + "\n" + "# if defined(OC_COLLECT_METRICS)\n" + "struct oc_mode_metrics{\n" + " double fragw;\n" + " double satd;\n" + " double rate;\n" + " double rmse;\n" + " double satd2;\n" + " double satdrate;\n" + " double rate2;\n" + " double satdrmse;\n" + " double rmse2;\n" + "};\n" + "\n" + "\n" + "int oc_has_mode_metrics;\n" + "oc_mode_metrics OC_MODE_METRICS[64][3][2][OC_SAD_BINS];\n" + "# endif\n" + "\n" + "\n" + "\n" + "struct oc_mode_rd{\n" + " ogg_int16_t rate;\n" + " ogg_int16_t rmse;\n" + "};\n" + "\n" + "\n" + "# if !defined(OC_COLLECT_METRICS)\n" + "static const\n" + "# endif\n" + "oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={\n", + OC_BIT_SCALE,OC_RMSE_SCALE,OC_SAD_BINS,OC_SAD_SHIFT); + for(qi=0;qi<64;qi++){ + int pli; + fprintf(stdout," {\n"); + for(pli=0;pli<3;pli++){ + int qti; + fprintf(stdout," {\n"); + for(qti=0;qti<2;qti++){ + int bin; + static const char *pl_names[3]={"Y'","Cb","Cr"}; + static const char *qti_names[2]={"INTRA","INTER"}; + fprintf(stdout," /*%s qi=%i %s*/\n", + pl_names[pli],qi,qti_names[qti]); + fprintf(stdout," {\n"); + fprintf(stdout," "); + for(bin=0;bininternal_decode!=NULL){ - (*((oc_state_dispatch_vtbl *)_th->internal_decode)->clear)(_th); + (*((oc_state_dispatch_vtable *)_th->internal_decode)->clear)(_th); } if(_th->internal_encode!=NULL){ - (*((oc_state_dispatch_vtbl *)_th->internal_encode)->clear)(_th); + (*((oc_state_dispatch_vtable *)_th->internal_encode)->clear)(_th); } if(_th->i!=NULL)theora_info_clear(_th->i); memset(_th,0,sizeof(*_th)); @@ -59,11 +59,11 @@ void theora_clear(theora_state *_th){ int theora_control(theora_state *_th,int _req,void *_buf,size_t _buf_sz){ /*Provide compatibility with mixed encoder and decoder shared lib versions.*/ if(_th->internal_decode!=NULL){ - return (*((oc_state_dispatch_vtbl *)_th->internal_decode)->control)(_th, + return (*((oc_state_dispatch_vtable *)_th->internal_decode)->control)(_th, _req,_buf,_buf_sz); } else if(_th->internal_encode!=NULL){ - return (*((oc_state_dispatch_vtbl *)_th->internal_encode)->control)(_th, + return (*((oc_state_dispatch_vtable *)_th->internal_encode)->control)(_th, _req,_buf,_buf_sz); } else return TH_EINVAL; @@ -72,11 +72,11 @@ int theora_control(theora_state *_th,int _req,void *_buf,size_t _buf_sz){ ogg_int64_t theora_granule_frame(theora_state *_th,ogg_int64_t _gp){ /*Provide compatibility with mixed encoder and decoder shared lib versions.*/ if(_th->internal_decode!=NULL){ - return (*((oc_state_dispatch_vtbl *)_th->internal_decode)->granule_frame)( + return (*((oc_state_dispatch_vtable *)_th->internal_decode)->granule_frame)( _th,_gp); } else if(_th->internal_encode!=NULL){ - return (*((oc_state_dispatch_vtbl *)_th->internal_encode)->granule_frame)( + return (*((oc_state_dispatch_vtable *)_th->internal_encode)->granule_frame)( _th,_gp); } else return -1; @@ -85,11 +85,11 @@ ogg_int64_t theora_granule_frame(theora_state *_th,ogg_int64_t _gp){ double theora_granule_time(theora_state *_th, ogg_int64_t _gp){ /*Provide compatibility with mixed encoder and decoder shared lib versions.*/ if(_th->internal_decode!=NULL){ - return (*((oc_state_dispatch_vtbl *)_th->internal_decode)->granule_time)( + return (*((oc_state_dispatch_vtable *)_th->internal_decode)->granule_time)( _th,_gp); } else if(_th->internal_encode!=NULL){ - return (*((oc_state_dispatch_vtbl *)_th->internal_encode)->granule_time)( + return (*((oc_state_dispatch_vtable *)_th->internal_encode)->granule_time)( _th,_gp); } else return -1; diff --git a/Engine/lib/libtheora/lib/dec/apiwrapper.h b/Engine/lib/libtheora/lib/apiwrapper.h similarity index 92% rename from Engine/lib/libtheora/lib/dec/apiwrapper.h rename to Engine/lib/libtheora/lib/apiwrapper.h index 211021fc0..93454d7bd 100644 --- a/Engine/lib/libtheora/lib/dec/apiwrapper.h +++ b/Engine/lib/libtheora/lib/apiwrapper.h @@ -5,7 +5,7 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** @@ -20,9 +20,8 @@ # include # include # include "theora/theoradec.h" -/*# include "theora/theoraenc.h"*/ -typedef struct th_enc_ctx th_enc_ctx; -# include "../internal.h" +# include "theora/theoraenc.h" +# include "internal.h" typedef struct th_api_wrapper th_api_wrapper; typedef struct th_api_info th_api_info; diff --git a/Engine/lib/libtheora/lib/bitpack.c b/Engine/lib/libtheora/lib/bitpack.c new file mode 100644 index 000000000..8195003ba --- /dev/null +++ b/Engine/lib/libtheora/lib/bitpack.c @@ -0,0 +1,111 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggTheora SOURCE CODE IS (C) COPYRIGHT 1994-2009 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: packing variable sized words into an octet stream + last mod: $Id: bitpack.c 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ +#include +#include +#include "bitpack.h" + +/*We're 'MSb' endian; if we write a word but read individual bits, + then we'll read the MSb first.*/ + +void oc_pack_readinit(oc_pack_buf *_b,unsigned char *_buf,long _bytes){ + memset(_b,0,sizeof(*_b)); + _b->ptr=_buf; + _b->stop=_buf+_bytes; +} + +static oc_pb_window oc_pack_refill(oc_pack_buf *_b,int _bits){ + const unsigned char *ptr; + const unsigned char *stop; + oc_pb_window window; + int available; + window=_b->window; + available=_b->bits; + ptr=_b->ptr; + stop=_b->stop; + while(available<=OC_PB_WINDOW_SIZE-8&&ptrptr=ptr; + if(_bits>available){ + if(ptr>=stop){ + _b->eof=1; + available=OC_LOTS_OF_BITS; + } + else window|=*ptr>>(available&7); + } + _b->bits=available; + return window; +} + +int oc_pack_look1(oc_pack_buf *_b){ + oc_pb_window window; + int available; + window=_b->window; + available=_b->bits; + if(available<1)_b->window=window=oc_pack_refill(_b,1); + return window>>OC_PB_WINDOW_SIZE-1; +} + +void oc_pack_adv1(oc_pack_buf *_b){ + _b->window<<=1; + _b->bits--; +} + +/*Here we assume that 0<=_bits&&_bits<=32.*/ +long oc_pack_read(oc_pack_buf *_b,int _bits){ + oc_pb_window window; + int available; + long result; + window=_b->window; + available=_b->bits; + if(_bits==0)return 0; + if(available<_bits){ + window=oc_pack_refill(_b,_bits); + available=_b->bits; + } + result=window>>OC_PB_WINDOW_SIZE-_bits; + available-=_bits; + window<<=1; + window<<=_bits-1; + _b->bits=available; + _b->window=window; + return result; +} + +int oc_pack_read1(oc_pack_buf *_b){ + oc_pb_window window; + int available; + int result; + window=_b->window; + available=_b->bits; + if(available<1){ + window=oc_pack_refill(_b,1); + available=_b->bits; + } + result=window>>OC_PB_WINDOW_SIZE-1; + available--; + window<<=1; + _b->bits=available; + _b->window=window; + return result; +} + +long oc_pack_bytes_left(oc_pack_buf *_b){ + if(_b->eof)return -1; + return _b->stop-_b->ptr+(_b->bits>>3); +} diff --git a/Engine/lib/libtheora/lib/dec/bitpack.h b/Engine/lib/libtheora/lib/bitpack.h similarity index 51% rename from Engine/lib/libtheora/lib/dec/bitpack.h rename to Engine/lib/libtheora/lib/bitpack.h index 1bff3fa50..a020a292f 100644 --- a/Engine/lib/libtheora/lib/dec/bitpack.h +++ b/Engine/lib/libtheora/lib/bitpack.h @@ -5,7 +5,7 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE OggTheora SOURCE CODE IS (C) COPYRIGHT 1994-2008 * + * THE OggTheora SOURCE CODE IS (C) COPYRIGHT 1994-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** @@ -16,23 +16,44 @@ ********************************************************************/ #if !defined(_bitpack_H) # define _bitpack_H (1) -# include +# include -void theorapackB_readinit(oggpack_buffer *_b,unsigned char *_buf,int _bytes); -int theorapackB_look1(oggpack_buffer *_b,long *_ret); -void theorapackB_adv1(oggpack_buffer *_b); + + +typedef unsigned long oc_pb_window; +typedef struct oc_pack_buf oc_pack_buf; + + + +# define OC_PB_WINDOW_SIZE ((int)sizeof(oc_pb_window)*CHAR_BIT) +/*This is meant to be a large, positive constant that can still be efficiently + loaded as an immediate (on platforms like ARM, for example). + Even relatively modest values like 100 would work fine.*/ +# define OC_LOTS_OF_BITS (0x40000000) + + + +struct oc_pack_buf{ + oc_pb_window window; + const unsigned char *ptr; + const unsigned char *stop; + int bits; + int eof; +}; + +void oc_pack_readinit(oc_pack_buf *_b,unsigned char *_buf,long _bytes); +int oc_pack_look1(oc_pack_buf *_b); +void oc_pack_adv1(oc_pack_buf *_b); /*Here we assume 0<=_bits&&_bits<=32.*/ -int theorapackB_read(oggpack_buffer *_b,int _bits,long *_ret); -int theorapackB_read1(oggpack_buffer *_b,long *_ret); -long theorapackB_bytes(oggpack_buffer *_b); -long theorapackB_bits(oggpack_buffer *_b); -unsigned char *theorapackB_get_buffer(oggpack_buffer *_b); +long oc_pack_read(oc_pack_buf *_b,int _bits); +int oc_pack_read1(oc_pack_buf *_b); +/* returns -1 for read beyond EOF, or the number of whole bytes available */ +long oc_pack_bytes_left(oc_pack_buf *_b); /*These two functions are implemented locally in huffdec.c*/ /*Read in bits without advancing the bitptr. Here we assume 0<=_bits&&_bits<=32.*/ -/*static int theorapackB_look(oggpack_buffer *_b,int _bits,long *_ret);*/ -/*static void theorapackB_adv(oggpack_buffer *_b,int _bits);*/ - +/*static int oc_pack_look(oc_pack_buf *_b,int _bits);*/ +/*static void oc_pack_adv(oc_pack_buf *_b,int _bits);*/ #endif diff --git a/Engine/lib/libtheora/lib/cpu.c b/Engine/lib/libtheora/lib/cpu.c index 8da50d070..a863aad7f 100644 --- a/Engine/lib/libtheora/lib/cpu.c +++ b/Engine/lib/libtheora/lib/cpu.c @@ -5,7 +5,7 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2008 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** @@ -14,13 +14,13 @@ Originally written by Rudolf Marek. function: - last mod: $Id: cpu.c 15427 2008-10-21 02:36:19Z xiphmont $ + last mod: $Id: cpu.c 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ #include "cpu.h" -#if !defined(USE_ASM) +#if !defined(OC_X86_ASM) static ogg_uint32_t oc_cpu_flags_get(void){ return 0; } @@ -166,7 +166,7 @@ static ogg_uint32_t oc_cpu_flags_get(void){ /* D M A c i t n e h t u A*/ else if(ecx==0x444D4163&&edx==0x69746E65&&ebx==0x68747541|| /* C S N y b e d o e G*/ - ecx==0x43534E20&&edx==0x79622065&&ebx==0x646F6547){ + ecx==0x43534e20&&edx==0x79622065&&ebx==0x646f6547){ /*AMD, Geode:*/ cpuid(0x80000000,eax,ebx,ecx,edx); if(eax<0x80000001)flags=0; @@ -192,7 +192,6 @@ static ogg_uint32_t oc_cpu_flags_get(void){ The C3-2 (Nehemiah) cores appear to, as well.*/ cpuid(1,eax,ebx,ecx,edx); flags=oc_parse_intel_flags(edx,ecx); - cpuid(0x80000000,eax,ebx,ecx,edx); if(eax>=0x80000001){ /*The (non-Nehemiah) C3 processors support AMD-like cpuid info. We need to check this even if the Intel test succeeds to pick up 3DNow! diff --git a/Engine/lib/libtheora/lib/cpu.h b/Engine/lib/libtheora/lib/cpu.h index efe5e9f52..a43c957a3 100644 --- a/Engine/lib/libtheora/lib/cpu.h +++ b/Engine/lib/libtheora/lib/cpu.h @@ -5,12 +5,12 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: cpu.h 15430 2008-10-21 05:03:55Z giles $ + last mod: $Id: cpu.h 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ diff --git a/Engine/lib/libtheora/lib/dec/dct.h b/Engine/lib/libtheora/lib/dct.h similarity index 90% rename from Engine/lib/libtheora/lib/dec/dct.h rename to Engine/lib/libtheora/lib/dct.h index 09043dc51..24ba6f111 100644 --- a/Engine/lib/libtheora/lib/dec/dct.h +++ b/Engine/lib/libtheora/lib/dct.h @@ -5,13 +5,13 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: dct.h 15400 2008-10-15 12:10:58Z tterribe $ + last mod: $Id: dct.h 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ diff --git a/Engine/lib/libtheora/lib/dec/bitpack.c b/Engine/lib/libtheora/lib/dec/bitpack.c deleted file mode 100644 index 3836150c2..000000000 --- a/Engine/lib/libtheora/lib/dec/bitpack.c +++ /dev/null @@ -1,121 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE OggTheora SOURCE CODE IS (C) COPYRIGHT 1994-2008 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: packing variable sized words into an octet stream - last mod: $Id: bitpack.c 15400 2008-10-15 12:10:58Z tterribe $ - - ********************************************************************/ - -/*We're 'MSb' endian; if we write a word but read individual bits, - then we'll read the MSb first.*/ - -#include -#include -#include "bitpack.h" - -void theorapackB_readinit(oggpack_buffer *_b,unsigned char *_buf,int _bytes){ - memset(_b,0,sizeof(*_b)); - _b->buffer=_b->ptr=_buf; - _b->storage=_bytes; -} - -int theorapackB_look1(oggpack_buffer *_b,long *_ret){ - if(_b->endbyte>=_b->storage){ - *_ret=0L; - return -1; - } - *_ret=(_b->ptr[0]>>7-_b->endbit)&1; - return 0; -} - -void theorapackB_adv1(oggpack_buffer *_b){ - if(++(_b->endbit)>7){ - _b->endbit=0; - _b->ptr++; - _b->endbyte++; - } -} - -/*Here we assume that 0<=_bits&&_bits<=32.*/ -int theorapackB_read(oggpack_buffer *_b,int _bits,long *_ret){ - long ret; - long m; - long d; - int fail; - m=32-_bits; - _bits+=_b->endbit; - d=_b->storage-_b->endbyte; - if(d<=4){ - /*Not the main path.*/ - if(d*8<_bits){ - *_ret=0L; - fail=-1; - goto overflow; - } - /*Special case to avoid reading _b->ptr[0], which might be past the end of - the buffer; also skips some useless accounting.*/ - else if(!_bits){ - *_ret=0L; - return 0; - } - } - ret=_b->ptr[0]<<24+_b->endbit; - if(_bits>8){ - ret|=_b->ptr[1]<<16+_b->endbit; - if(_bits>16){ - ret|=_b->ptr[2]<<8+_b->endbit; - if(_bits>24){ - ret|=_b->ptr[3]<<_b->endbit; - if(_bits>32)ret|=_b->ptr[4]>>8-_b->endbit; - } - } - } - *_ret=((ret&0xFFFFFFFFUL)>>(m>>1))>>(m+1>>1); - fail=0; -overflow: - _b->ptr+=_bits>>3; - _b->endbyte+=_bits>>3; - _b->endbit=_bits&7; - return fail; -} - -int theorapackB_read1(oggpack_buffer *_b,long *_ret){ - int fail; - if(_b->endbyte>=_b->storage){ - /*Not the main path.*/ - *_ret=0L; - fail=-1; - } - else{ - *_ret=(_b->ptr[0]>>7-_b->endbit)&1; - fail=0; - } - _b->endbit++; - if(_b->endbit>7){ - _b->endbit=0; - _b->ptr++; - _b->endbyte++; - } - return fail; -} - -long theorapackB_bytes(oggpack_buffer *_b){ - return _b->endbyte+(_b->endbit+7>>3); -} - -long theorapackB_bits(oggpack_buffer *_b){ - return _b->endbyte*8+_b->endbit; -} - -unsigned char *theorapackB_get_buffer(oggpack_buffer *_b){ - return _b->buffer; -} diff --git a/Engine/lib/libtheora/lib/dec/decode.c b/Engine/lib/libtheora/lib/dec/decode.c deleted file mode 100644 index 5804cf709..000000000 --- a/Engine/lib/libtheora/lib/dec/decode.c +++ /dev/null @@ -1,2057 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: decode.c 15403 2008-10-16 12:44:05Z tterribe $ - - ********************************************************************/ - -#include -#include -#include -#include "decint.h" -#if defined(OC_DUMP_IMAGES) -# include -# include "png.h" -#endif - -/*No post-processing.*/ -#define OC_PP_LEVEL_DISABLED (0) -/*Keep track of DC qi for each block only.*/ -#define OC_PP_LEVEL_TRACKDCQI (1) -/*Deblock the luma plane.*/ -#define OC_PP_LEVEL_DEBLOCKY (2) -/*Dering the luma plane.*/ -#define OC_PP_LEVEL_DERINGY (3) -/*Stronger luma plane deringing.*/ -#define OC_PP_LEVEL_SDERINGY (4) -/*Deblock the chroma planes.*/ -#define OC_PP_LEVEL_DEBLOCKC (5) -/*Dering the chroma planes.*/ -#define OC_PP_LEVEL_DERINGC (6) -/*Stronger chroma plane deringing.*/ -#define OC_PP_LEVEL_SDERINGC (7) -/*Maximum valid post-processing level.*/ -#define OC_PP_LEVEL_MAX (7) - - - -/*The mode alphabets for the various mode coding schemes. - Scheme 0 uses a custom alphabet, which is not stored in this table.*/ -static const int OC_MODE_ALPHABETS[7][OC_NMODES]={ - /*Last MV dominates */ - { - OC_MODE_INTER_MV_LAST,OC_MODE_INTER_MV_LAST2,OC_MODE_INTER_MV, - OC_MODE_INTER_NOMV,OC_MODE_INTRA,OC_MODE_GOLDEN_NOMV,OC_MODE_GOLDEN_MV, - OC_MODE_INTER_MV_FOUR - }, - { - OC_MODE_INTER_MV_LAST,OC_MODE_INTER_MV_LAST2,OC_MODE_INTER_NOMV, - OC_MODE_INTER_MV,OC_MODE_INTRA,OC_MODE_GOLDEN_NOMV,OC_MODE_GOLDEN_MV, - OC_MODE_INTER_MV_FOUR - }, - { - OC_MODE_INTER_MV_LAST,OC_MODE_INTER_MV,OC_MODE_INTER_MV_LAST2, - OC_MODE_INTER_NOMV,OC_MODE_INTRA,OC_MODE_GOLDEN_NOMV,OC_MODE_GOLDEN_MV, - OC_MODE_INTER_MV_FOUR - }, - { - OC_MODE_INTER_MV_LAST,OC_MODE_INTER_MV,OC_MODE_INTER_NOMV, - OC_MODE_INTER_MV_LAST2,OC_MODE_INTRA,OC_MODE_GOLDEN_NOMV, - OC_MODE_GOLDEN_MV,OC_MODE_INTER_MV_FOUR - }, - /*No MV dominates.*/ - { - OC_MODE_INTER_NOMV,OC_MODE_INTER_MV_LAST,OC_MODE_INTER_MV_LAST2, - OC_MODE_INTER_MV,OC_MODE_INTRA,OC_MODE_GOLDEN_NOMV,OC_MODE_GOLDEN_MV, - OC_MODE_INTER_MV_FOUR - }, - { - OC_MODE_INTER_NOMV,OC_MODE_GOLDEN_NOMV,OC_MODE_INTER_MV_LAST, - OC_MODE_INTER_MV_LAST2,OC_MODE_INTER_MV,OC_MODE_INTRA,OC_MODE_GOLDEN_MV, - OC_MODE_INTER_MV_FOUR - }, - /*Default ordering.*/ - { - OC_MODE_INTER_NOMV,OC_MODE_INTRA,OC_MODE_INTER_MV,OC_MODE_INTER_MV_LAST, - OC_MODE_INTER_MV_LAST2,OC_MODE_GOLDEN_NOMV,OC_MODE_GOLDEN_MV, - OC_MODE_INTER_MV_FOUR - } -}; - - -static int oc_sb_run_unpack(oggpack_buffer *_opb){ - long bits; - int ret; - /*Coding scheme: - Codeword Run Length - 0 1 - 10x 2-3 - 110x 4-5 - 1110xx 6-9 - 11110xxx 10-17 - 111110xxxx 18-33 - 111111xxxxxxxxxxxx 34-4129*/ - theorapackB_read1(_opb,&bits); - if(bits==0)return 1; - theorapackB_read(_opb,2,&bits); - if((bits&2)==0)return 2+(int)bits; - else if((bits&1)==0){ - theorapackB_read1(_opb,&bits); - return 4+(int)bits; - } - theorapackB_read(_opb,3,&bits); - if((bits&4)==0)return 6+(int)bits; - else if((bits&2)==0){ - ret=10+((bits&1)<<2); - theorapackB_read(_opb,2,&bits); - return ret+(int)bits; - } - else if((bits&1)==0){ - theorapackB_read(_opb,4,&bits); - return 18+(int)bits; - } - theorapackB_read(_opb,12,&bits); - return 34+(int)bits; -} - -static int oc_block_run_unpack(oggpack_buffer *_opb){ - long bits; - long bits2; - /*Coding scheme: - Codeword Run Length - 0x 1-2 - 10x 3-4 - 110x 5-6 - 1110xx 7-10 - 11110xx 11-14 - 11111xxxx 15-30*/ - theorapackB_read(_opb,2,&bits); - if((bits&2)==0)return 1+(int)bits; - else if((bits&1)==0){ - theorapackB_read1(_opb,&bits); - return 3+(int)bits; - } - theorapackB_read(_opb,2,&bits); - if((bits&2)==0)return 5+(int)bits; - else if((bits&1)==0){ - theorapackB_read(_opb,2,&bits); - return 7+(int)bits; - } - theorapackB_read(_opb,3,&bits); - if((bits&4)==0)return 11+bits; - theorapackB_read(_opb,2,&bits2); - return 15+((bits&3)<<2)+bits2; -} - - - -static int oc_dec_init(oc_dec_ctx *_dec,const th_info *_info, - const th_setup_info *_setup){ - int qti; - int pli; - int qi; - int ret; - ret=oc_state_init(&_dec->state,_info); - if(ret<0)return ret; - oc_huff_trees_copy(_dec->huff_tables, - (const oc_huff_node *const *)_setup->huff_tables); - for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){ - _dec->state.dequant_tables[qti][pli]= - _dec->state.dequant_table_data[qti][pli]; - } - oc_dequant_tables_init(_dec->state.dequant_tables,_dec->pp_dc_scale, - &_setup->qinfo); - for(qi=0;qi<64;qi++){ - int qsum; - qsum=0; - for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){ - qsum+=_dec->state.dequant_tables[qti][pli][qi][18]+ - _dec->state.dequant_tables[qti][pli][qi][19]+ - _dec->state.dequant_tables[qti][pli][qi][26]+ - _dec->state.dequant_tables[qti][pli][qi][27]<<(pli==0); - } - _dec->pp_sharp_mod[qi]=-(qsum>>11); - } - _dec->dct_tokens=(unsigned char **)oc_calloc_2d(64, - _dec->state.nfrags,sizeof(_dec->dct_tokens[0][0])); - _dec->extra_bits=(ogg_uint16_t **)oc_calloc_2d(64, - _dec->state.nfrags,sizeof(_dec->extra_bits[0][0])); - memcpy(_dec->state.loop_filter_limits,_setup->qinfo.loop_filter_limits, - sizeof(_dec->state.loop_filter_limits)); - _dec->pp_level=OC_PP_LEVEL_DISABLED; - _dec->dc_qis=NULL; - _dec->variances=NULL; - _dec->pp_frame_data=NULL; - _dec->stripe_cb.ctx=NULL; - _dec->stripe_cb.stripe_decoded=NULL; - return 0; -} - -static void oc_dec_clear(oc_dec_ctx *_dec){ - _ogg_free(_dec->pp_frame_data); - _ogg_free(_dec->variances); - _ogg_free(_dec->dc_qis); - oc_free_2d(_dec->extra_bits); - oc_free_2d(_dec->dct_tokens); - oc_huff_trees_clear(_dec->huff_tables); - oc_state_clear(&_dec->state); -} - - -static int oc_dec_frame_header_unpack(oc_dec_ctx *_dec){ - long val; - /*Check to make sure this is a data packet.*/ - theorapackB_read1(&_dec->opb,&val); - if(val!=0)return TH_EBADPACKET; - /*Read in the frame type (I or P).*/ - theorapackB_read1(&_dec->opb,&val); - _dec->state.frame_type=(int)val; - /*Read in the current qi.*/ - theorapackB_read(&_dec->opb,6,&val); - _dec->state.qis[0]=(int)val; - theorapackB_read1(&_dec->opb,&val); - if(!val)_dec->state.nqis=1; - else{ - theorapackB_read(&_dec->opb,6,&val); - _dec->state.qis[1]=(int)val; - theorapackB_read1(&_dec->opb,&val); - if(!val)_dec->state.nqis=2; - else{ - theorapackB_read(&_dec->opb,6,&val); - _dec->state.qis[2]=(int)val; - _dec->state.nqis=3; - } - } - if(_dec->state.frame_type==OC_INTRA_FRAME){ - /*Keyframes have 3 unused configuration bits, holdovers from VP3 days. - Most of the other unused bits in the VP3 headers were eliminated. - I don't know why these remain.*/ - /* I wanted to eliminate wasted bits, but not all config wiggle room --Monty */ - theorapackB_read(&_dec->opb,3,&val); - if(val!=0)return TH_EIMPL; - } - return 0; -} - -/*Mark all fragments as coded and in OC_MODE_INTRA. - This also builds up the coded fragment list (in coded order), and clears the - uncoded fragment list. - It does not update the coded macro block list, as that is not used when - decoding INTRA frames.*/ -static void oc_dec_mark_all_intra(oc_dec_ctx *_dec){ - oc_sb *sb; - oc_sb *sb_end; - int pli; - int ncoded_fragis; - int prev_ncoded_fragis; - prev_ncoded_fragis=ncoded_fragis=0; - sb=sb_end=_dec->state.sbs; - for(pli=0;pli<3;pli++){ - const oc_fragment_plane *fplane; - fplane=_dec->state.fplanes+pli; - sb_end+=fplane->nsbs; - for(;sbquad_valid&1<map[quadi][bi]; - if(fragi>=0){ - oc_fragment *frag; - frag=_dec->state.frags+fragi; - frag->coded=1; - frag->mbmode=OC_MODE_INTRA; - _dec->state.coded_fragis[ncoded_fragis++]=fragi; - } - } - } - } - _dec->state.ncoded_fragis[pli]=ncoded_fragis-prev_ncoded_fragis; - prev_ncoded_fragis=ncoded_fragis; - _dec->state.nuncoded_fragis[pli]=0; - } -} - -/*Decodes the bit flags for whether or not each super block is partially coded - or not. - Return: The number of partially coded super blocks.*/ -static int oc_dec_partial_sb_flags_unpack(oc_dec_ctx *_dec){ - oc_sb *sb; - oc_sb *sb_end; - long val; - int flag; - int npartial; - int run_count; - theorapackB_read1(&_dec->opb,&val); - flag=(int)val; - sb=_dec->state.sbs; - sb_end=sb+_dec->state.nsbs; - run_count=npartial=0; - while(sbopb); - full_run=run_count>=4129; - do{ - sb->coded_partially=flag; - sb->coded_fully=0; - npartial+=flag; - sb++; - } - while(--run_count>0&&sbopb,&val); - flag=(int)val; - } - else flag=!flag; - } - /*TODO: run_count should be 0 here. - If it's not, we should issue a warning of some kind.*/ - return npartial; -} - -/*Decodes the bit flags for whether or not each non-partially-coded super - block is fully coded or not. - This function should only be called if there is at least one - non-partially-coded super block. - Return: The number of partially coded super blocks.*/ -static void oc_dec_coded_sb_flags_unpack(oc_dec_ctx *_dec){ - oc_sb *sb; - oc_sb *sb_end; - long val; - int flag; - int run_count; - sb=_dec->state.sbs; - sb_end=sb+_dec->state.nsbs; - /*Skip partially coded super blocks.*/ - for(;sb->coded_partially;sb++); - theorapackB_read1(&_dec->opb,&val); - flag=(int)val; - while(sbopb); - full_run=run_count>=4129; - for(;sbcoded_partially)continue; - if(run_count--<=0)break; - sb->coded_fully=flag; - } - if(full_run&&sbopb,&val); - flag=(int)val; - } - else flag=!flag; - } - /*TODO: run_count should be 0 here. - If it's not, we should issue a warning of some kind.*/ -} - -static void oc_dec_coded_flags_unpack(oc_dec_ctx *_dec){ - oc_sb *sb; - oc_sb *sb_end; - long val; - int npartial; - int pli; - int flag; - int run_count; - int ncoded_fragis; - int prev_ncoded_fragis; - int nuncoded_fragis; - int prev_nuncoded_fragis; - npartial=oc_dec_partial_sb_flags_unpack(_dec); - if(npartial<_dec->state.nsbs)oc_dec_coded_sb_flags_unpack(_dec); - if(npartial>0){ - theorapackB_read1(&_dec->opb,&val); - flag=!(int)val; - } - else flag=0; - run_count=0; - prev_ncoded_fragis=ncoded_fragis=prev_nuncoded_fragis=nuncoded_fragis=0; - sb=sb_end=_dec->state.sbs; - for(pli=0;pli<3;pli++){ - const oc_fragment_plane *fplane; - fplane=_dec->state.fplanes+pli; - sb_end+=fplane->nsbs; - for(;sbquad_valid&1<map[quadi][bi]; - if(fragi>=0){ - oc_fragment *frag; - frag=_dec->state.frags+fragi; - if(sb->coded_fully)frag->coded=1; - else if(!sb->coded_partially)frag->coded=0; - else{ - if(run_count<=0){ - run_count=oc_block_run_unpack(&_dec->opb); - flag=!flag; - } - run_count--; - frag->coded=flag; - } - if(frag->coded)_dec->state.coded_fragis[ncoded_fragis++]=fragi; - else *(_dec->state.uncoded_fragis-++nuncoded_fragis)=fragi; - } - } - } - } - _dec->state.ncoded_fragis[pli]=ncoded_fragis-prev_ncoded_fragis; - prev_ncoded_fragis=ncoded_fragis; - _dec->state.nuncoded_fragis[pli]=nuncoded_fragis-prev_nuncoded_fragis; - prev_nuncoded_fragis=nuncoded_fragis; - } - /*TODO: run_count should be 0 here. - If it's not, we should issue a warning of some kind.*/ -} - - - -typedef int (*oc_mode_unpack_func)(oggpack_buffer *_opb); - -static int oc_vlc_mode_unpack(oggpack_buffer *_opb){ - long val; - int i; - for(i=0;i<7;i++){ - theorapackB_read1(_opb,&val); - if(!val)break; - } - return i; -} - -static int oc_clc_mode_unpack(oggpack_buffer *_opb){ - long val; - theorapackB_read(_opb,3,&val); - return (int)val; -} - -/*Unpacks the list of macro block modes for INTER frames.*/ -static void oc_dec_mb_modes_unpack(oc_dec_ctx *_dec){ - oc_mode_unpack_func mode_unpack; - oc_mb *mb; - oc_mb *mb_end; - const int *alphabet; - long val; - int scheme0_alphabet[8]; - int mode_scheme; - theorapackB_read(&_dec->opb,3,&val); - mode_scheme=(int)val; - if(mode_scheme==0){ - int mi; - /*Just in case, initialize the modes to something. - If the bitstream doesn't contain each index exactly once, it's likely - corrupt and the rest of the packet is garbage anyway, but this way we - won't crash, and we'll decode SOMETHING.*/ - /*LOOP VECTORIZES.*/ - for(mi=0;miopb,3,&val); - scheme0_alphabet[val]=OC_MODE_ALPHABETS[6][mi]; - } - alphabet=scheme0_alphabet; - } - else alphabet=OC_MODE_ALPHABETS[mode_scheme-1]; - if(mode_scheme==7)mode_unpack=oc_clc_mode_unpack; - else mode_unpack=oc_vlc_mode_unpack; - mb=_dec->state.mbs; - mb_end=mb+_dec->state.nmbs; - for(;mbmode!=OC_MODE_INVALID){ - int bi; - for(bi=0;bi<4;bi++){ - int fragi; - fragi=mb->map[0][bi]; - if(fragi>=0&&_dec->state.frags[fragi].coded)break; - } - if(bi<4)mb->mode=alphabet[(*mode_unpack)(&_dec->opb)]; - else mb->mode=OC_MODE_INTER_NOMV; - } - } -} - - - -typedef int (*oc_mv_comp_unpack_func)(oggpack_buffer *_opb); - -static int oc_vlc_mv_comp_unpack(oggpack_buffer *_opb){ - long bits; - int mvsigned[2]; - theorapackB_read(_opb,3,&bits); - switch(bits){ - case 0:return 0; - case 1:return 1; - case 2:return -1; - case 3: - case 4:{ - mvsigned[0]=(int)(bits-1); - theorapackB_read1(_opb,&bits); - }break; - /*case 5: - case 6: - case 7:*/ - default:{ - mvsigned[0]=1<>1); - bits&=1; - }break; - } - mvsigned[1]=-mvsigned[0]; - return mvsigned[bits]; -} - -static int oc_clc_mv_comp_unpack(oggpack_buffer *_opb){ - long bits; - int mvsigned[2]; - theorapackB_read(_opb,6,&bits); - mvsigned[0]=bits>>1; - mvsigned[1]=-mvsigned[0]; - return mvsigned[bits&1]; -} - -/*Unpacks the list of motion vectors for INTER frames, and propagtes the macro - block modes and motion vectors to the individual fragments.*/ -static void oc_dec_mv_unpack_and_frag_modes_fill(oc_dec_ctx *_dec){ - oc_set_chroma_mvs_func set_chroma_mvs; - oc_mv_comp_unpack_func mv_comp_unpack; - oc_mb *mb; - oc_mb *mb_end; - const int *map_idxs; - long val; - int map_nidxs; - oc_mv last_mv[2]; - oc_mv cbmvs[4]; - set_chroma_mvs=OC_SET_CHROMA_MVS_TABLE[_dec->state.info.pixel_fmt]; - theorapackB_read1(&_dec->opb,&val); - mv_comp_unpack=val?oc_clc_mv_comp_unpack:oc_vlc_mv_comp_unpack; - map_idxs=OC_MB_MAP_IDXS[_dec->state.info.pixel_fmt]; - map_nidxs=OC_MB_MAP_NIDXS[_dec->state.info.pixel_fmt]; - memset(last_mv,0,sizeof(last_mv)); - mb=_dec->state.mbs; - mb_end=mb+_dec->state.nmbs; - for(;mbmode!=OC_MODE_INVALID){ - oc_fragment *frag; - oc_mv mbmv; - int coded[13]; - int codedi; - int ncoded; - int mapi; - int mapii; - int fragi; - int mb_mode; - /*Search for at least one coded fragment.*/ - ncoded=mapii=0; - do{ - mapi=map_idxs[mapii]; - fragi=mb->map[mapi>>2][mapi&3]; - if(fragi>=0&&_dec->state.frags[fragi].coded)coded[ncoded++]=mapi; - } - while(++mapiimode; - switch(mb_mode){ - case OC_MODE_INTER_MV_FOUR:{ - oc_mv lbmvs[4]; - int bi; - /*Mark the tail of the list, so we don't accidentally go past it.*/ - coded[ncoded]=-1; - for(bi=codedi=0;bi<4;bi++){ - if(coded[codedi]==bi){ - codedi++; - frag=_dec->state.frags+mb->map[0][bi]; - frag->mbmode=mb_mode; - frag->mv[0]=lbmvs[bi][0]=(signed char)(*mv_comp_unpack)(&_dec->opb); - frag->mv[1]=lbmvs[bi][1]=(signed char)(*mv_comp_unpack)(&_dec->opb); - } - else lbmvs[bi][0]=lbmvs[bi][1]=0; - } - if(codedi>0){ - last_mv[1][0]=last_mv[0][0]; - last_mv[1][1]=last_mv[0][1]; - last_mv[0][0]=lbmvs[coded[codedi-1]][0]; - last_mv[0][1]=lbmvs[coded[codedi-1]][1]; - } - if(codedistate.frags+mb->map[mapi>>2][bi]; - frag->mbmode=mb_mode; - frag->mv[0]=cbmvs[bi][0]; - frag->mv[1]=cbmvs[bi][1]; - } - } - }break; - case OC_MODE_INTER_MV:{ - last_mv[1][0]=last_mv[0][0]; - last_mv[1][1]=last_mv[0][1]; - mbmv[0]=last_mv[0][0]=(signed char)(*mv_comp_unpack)(&_dec->opb); - mbmv[1]=last_mv[0][1]=(signed char)(*mv_comp_unpack)(&_dec->opb); - }break; - case OC_MODE_INTER_MV_LAST:{ - mbmv[0]=last_mv[0][0]; - mbmv[1]=last_mv[0][1]; - }break; - case OC_MODE_INTER_MV_LAST2:{ - mbmv[0]=last_mv[1][0]; - mbmv[1]=last_mv[1][1]; - last_mv[1][0]=last_mv[0][0]; - last_mv[1][1]=last_mv[0][1]; - last_mv[0][0]=mbmv[0]; - last_mv[0][1]=mbmv[1]; - }break; - case OC_MODE_GOLDEN_MV:{ - mbmv[0]=(signed char)(*mv_comp_unpack)(&_dec->opb); - mbmv[1]=(signed char)(*mv_comp_unpack)(&_dec->opb); - }break; - default:mbmv[0]=mbmv[1]=0;break; - } - /*4MV mode fills in the fragments itself. - For all other modes we can use this common code.*/ - if(mb_mode!=OC_MODE_INTER_MV_FOUR){ - for(codedi=0;codedimap[mapi>>2][mapi&3]; - frag=_dec->state.frags+fragi; - frag->mbmode=mb_mode; - frag->mv[0]=mbmv[0]; - frag->mv[1]=mbmv[1]; - } - } - } -} - -static void oc_dec_block_qis_unpack(oc_dec_ctx *_dec){ - oc_fragment *frag; - int *coded_fragi; - int *coded_fragi_end; - int ncoded_fragis; - ncoded_fragis=_dec->state.ncoded_fragis[0]+ - _dec->state.ncoded_fragis[1]+_dec->state.ncoded_fragis[2]; - if(ncoded_fragis<=0)return; - coded_fragi=_dec->state.coded_fragis; - coded_fragi_end=coded_fragi+ncoded_fragis; - if(_dec->state.nqis==1){ - /*If this frame has only a single qi value, then just set it in all coded - fragments.*/ - while(coded_fragistate.frags[*coded_fragi++].qi=_dec->state.qis[0]; - } - } - else{ - long val; - int flag; - int nqi1; - int run_count; - /*Otherwise, we decode a qi index for each fragment, using two passes of - the same binary RLE scheme used for super-block coded bits. - The first pass marks each fragment as having a qii of 0 or greater than - 0, and the second pass (if necessary), distinguishes between a qii of - 1 and 2. - At first we just store the qii in the fragment. - After all the qii's are decoded, we make a final pass to replace them - with the corresponding qi's for this frame.*/ - theorapackB_read1(&_dec->opb,&val); - flag=(int)val; - run_count=nqi1=0; - while(coded_fragiopb); - full_run=run_count>=4129; - do{ - _dec->state.frags[*coded_fragi++].qi=flag; - nqi1+=flag; - } - while(--run_count>0&&coded_fragiopb,&val); - flag=(int)val; - } - else flag=!flag; - } - /*TODO: run_count should be 0 here. - If it's not, we should issue a warning of some kind.*/ - /*If we have 3 different qi's for this frame, and there was at least one - fragment with a non-zero qi, make the second pass.*/ - if(_dec->state.nqis==3&&nqi1>0){ - /*Skip qii==0 fragments.*/ - for(coded_fragi=_dec->state.coded_fragis; - _dec->state.frags[*coded_fragi].qi==0;coded_fragi++); - theorapackB_read1(&_dec->opb,&val); - flag=(int)val; - while(coded_fragiopb); - full_run=run_count>=4129; - for(;coded_fragistate.frags+*coded_fragi; - if(frag->qi==0)continue; - if(run_count--<=0)break; - frag->qi+=flag; - } - if(full_run&&coded_fragiopb,&val); - flag=(int)val; - } - else flag=!flag; - } - /*TODO: run_count should be 0 here. - If it's not, we should issue a warning of some kind.*/ - } - /*Finally, translate qii's to qi's.*/ - for(coded_fragi=_dec->state.coded_fragis;coded_fragistate.frags+*coded_fragi; - frag->qi=_dec->state.qis[frag->qi]; - } - } -} - - - -/*Returns the decoded value of the given token. - It CANNOT be called for any of the EOB tokens. - _token: The token value to skip. - _extra_bits: The extra bits attached to this token. - Return: The decoded coefficient value.*/ -typedef int (*oc_token_dec1val_func)(int _token,int _extra_bits); - -/*Handles zero run tokens.*/ -static int oc_token_dec1val_zrl(void){ - return 0; -} - -/*Handles 1, -1, 2 and -2 tokens.*/ -static int oc_token_dec1val_const(int _token){ - static const int CONST_VALS[4]={1,-1,2,-2}; - return CONST_VALS[_token-OC_NDCT_ZRL_TOKEN_MAX]; -} - -/*Handles DCT value tokens category 2.*/ -static int oc_token_dec1val_cat2(int _token,int _extra_bits){ - int valsigned[2]; - valsigned[0]=_token-OC_DCT_VAL_CAT2+3; - valsigned[1]=-valsigned[0]; - return valsigned[_extra_bits]; -} - -/*Handles DCT value tokens categories 3 through 8.*/ -static int oc_token_dec1val_cati(int _token,int _extra_bits){ - static const int VAL_CAT_OFFS[6]={ - OC_NDCT_VAL_CAT2_SIZE+3, - OC_NDCT_VAL_CAT2_SIZE+5, - OC_NDCT_VAL_CAT2_SIZE+9, - OC_NDCT_VAL_CAT2_SIZE+17, - OC_NDCT_VAL_CAT2_SIZE+33, - OC_NDCT_VAL_CAT2_SIZE+65 - }; - static const int VAL_CAT_MASKS[6]={ - 0x001,0x003,0x007,0x00F,0x01F,0x1FF - }; - static const int VAL_CAT_SHIFTS[6]={1,2,3,4,5,9}; - int valsigned[2]; - int cati; - cati=_token-OC_NDCT_VAL_CAT2_MAX; - valsigned[0]=VAL_CAT_OFFS[cati]+(_extra_bits&VAL_CAT_MASKS[cati]); - valsigned[1]=-valsigned[0]; - return valsigned[_extra_bits>>VAL_CAT_SHIFTS[cati]&1]; -} - -/*A jump table for compute the first coefficient value the given token value - represents.*/ -static const oc_token_dec1val_func OC_TOKEN_DEC1VAL_TABLE[TH_NDCT_TOKENS- - OC_NDCT_EOB_TOKEN_MAX]={ - (oc_token_dec1val_func)oc_token_dec1val_zrl, - (oc_token_dec1val_func)oc_token_dec1val_zrl, - (oc_token_dec1val_func)oc_token_dec1val_const, - (oc_token_dec1val_func)oc_token_dec1val_const, - (oc_token_dec1val_func)oc_token_dec1val_const, - (oc_token_dec1val_func)oc_token_dec1val_const, - oc_token_dec1val_cat2, - oc_token_dec1val_cat2, - oc_token_dec1val_cat2, - oc_token_dec1val_cat2, - oc_token_dec1val_cati, - oc_token_dec1val_cati, - oc_token_dec1val_cati, - oc_token_dec1val_cati, - oc_token_dec1val_cati, - oc_token_dec1val_cati, - (oc_token_dec1val_func)oc_token_dec1val_zrl, - (oc_token_dec1val_func)oc_token_dec1val_zrl, - (oc_token_dec1val_func)oc_token_dec1val_zrl, - (oc_token_dec1val_func)oc_token_dec1val_zrl, - (oc_token_dec1val_func)oc_token_dec1val_zrl, - (oc_token_dec1val_func)oc_token_dec1val_zrl, - (oc_token_dec1val_func)oc_token_dec1val_zrl, - (oc_token_dec1val_func)oc_token_dec1val_zrl, - (oc_token_dec1val_func)oc_token_dec1val_zrl -}; - -/*Returns the decoded value of the given token. - It CANNOT be called for any of the EOB tokens. - _token: The token value to skip. - _extra_bits: The extra bits attached to this token. - Return: The decoded coefficient value.*/ -static int oc_dct_token_dec1val(int _token,int _extra_bits){ - return (*OC_TOKEN_DEC1VAL_TABLE[_token-OC_NDCT_EOB_TOKEN_MAX])(_token, - _extra_bits); -} - -/*Unpacks the DC coefficient tokens. - Unlike when unpacking the AC coefficient tokens, we actually need to decode - the DC coefficient values now so that we can do DC prediction. - _huff_idx: The index of the Huffman table to use for each color plane. - _ntoks_left: The number of tokens left to be decoded in each color plane for - each coefficient. - This is updated as EOB tokens and zero run tokens are decoded. - Return: The length of any outstanding EOB run.*/ -static int oc_dec_dc_coeff_unpack(oc_dec_ctx *_dec,int _huff_idxs[3], - int _ntoks_left[3][64]){ - long val; - int *coded_fragi; - int *coded_fragi_end; - int run_counts[64]; - int cfi; - int eobi; - int eobs; - int ti; - int ebi; - int pli; - int rli; - eobs=0; - ti=ebi=0; - coded_fragi_end=coded_fragi=_dec->state.coded_fragis; - for(pli=0;pli<3;pli++){ - coded_fragi_end+=_dec->state.ncoded_fragis[pli]; - memset(run_counts,0,sizeof(run_counts)); - _dec->eob_runs[pli][0]=eobs; - /*Continue any previous EOB run, if there was one.*/ - for(eobi=eobs;eobi-->0&&coded_fragistate.frags[*coded_fragi++].dc=0; - } - cfi=0; - while(eobs<_ntoks_left[pli][0]-cfi){ - int token; - int neb; - int eb; - int skip; - cfi+=eobs; - run_counts[63]+=eobs; - token=oc_huff_token_decode(&_dec->opb, - _dec->huff_tables[_huff_idxs[pli]]); - _dec->dct_tokens[0][ti++]=(unsigned char)token; - neb=OC_DCT_TOKEN_EXTRA_BITS[token]; - if(neb){ - theorapackB_read(&_dec->opb,neb,&val); - eb=(int)val; - _dec->extra_bits[0][ebi++]=(ogg_uint16_t)eb; - } - else eb=0; - skip=oc_dct_token_skip(token,eb); - if(skip<0){ - eobs=eobi=-skip; - while(eobi-->0&&coded_fragistate.frags[*coded_fragi++].dc=0; - } - } - else{ - run_counts[skip-1]++; - cfi++; - eobs=0; - _dec->state.frags[*coded_fragi++].dc=oc_dct_token_dec1val(token,eb); - } - } - _dec->ti0[pli][0]=ti; - _dec->ebi0[pli][0]=ebi; - /*Set the EOB count to the portion of the last EOB run which extends past - this coefficient.*/ - eobs=eobs+cfi-_ntoks_left[pli][0]; - /*Add the portion of the last EOB which was included in this coefficient to - to the longest run length.*/ - run_counts[63]+=_ntoks_left[pli][0]-cfi; - /*And convert the run_counts array to a moment table.*/ - for(rli=63;rli-->0;)run_counts[rli]+=run_counts[rli+1]; - /*Finally, subtract off the number of coefficients that have been - accounted for by runs started in this coefficient.*/ - for(rli=64;rli-->0;)_ntoks_left[pli][rli]-=run_counts[rli]; - } - return eobs; -} - -/*Unpacks the AC coefficient tokens. - This can completely discard coefficient values while unpacking, and so is - somewhat simpler than unpacking the DC coefficient tokens. - _huff_idx: The index of the Huffman table to use for each color plane. - _ntoks_left: The number of tokens left to be decoded in each color plane for - each coefficient. - This is updated as EOB tokens and zero run tokens are decoded. - _eobs: The length of any outstanding EOB run from previous - coefficients. - Return: The length of any outstanding EOB run.*/ -static int oc_dec_ac_coeff_unpack(oc_dec_ctx *_dec,int _zzi,int _huff_idxs[3], - int _ntoks_left[3][64],int _eobs){ - long val; - int run_counts[64]; - int cfi; - int ti; - int ebi; - int pli; - int rli; - ti=ebi=0; - for(pli=0;pli<3;pli++){ - memset(run_counts,0,sizeof(run_counts)); - _dec->eob_runs[pli][_zzi]=_eobs; - cfi=0; - while(_eobs<_ntoks_left[pli][_zzi]-cfi){ - int token; - int neb; - int eb; - int skip; - cfi+=_eobs; - run_counts[63]+=_eobs; - token=oc_huff_token_decode(&_dec->opb, - _dec->huff_tables[_huff_idxs[pli]]); - _dec->dct_tokens[_zzi][ti++]=(unsigned char)token; - neb=OC_DCT_TOKEN_EXTRA_BITS[token]; - if(neb){ - theorapackB_read(&_dec->opb,neb,&val); - eb=(int)val; - _dec->extra_bits[_zzi][ebi++]=(ogg_uint16_t)eb; - } - else eb=0; - skip=oc_dct_token_skip(token,eb); - if(skip<0)_eobs=-skip; - else{ - run_counts[skip-1]++; - cfi++; - _eobs=0; - } - } - _dec->ti0[pli][_zzi]=ti; - _dec->ebi0[pli][_zzi]=ebi; - /*Set the EOB count to the portion of the last EOB run which extends past - this coefficient.*/ - _eobs=_eobs+cfi-_ntoks_left[pli][_zzi]; - /*Add the portion of the last EOB which was included in this coefficient to - to the longest run length.*/ - run_counts[63]+=_ntoks_left[pli][_zzi]-cfi; - /*And convert the run_counts array to a moment table.*/ - for(rli=63;rli-->0;)run_counts[rli]+=run_counts[rli+1]; - /*Finally, subtract off the number of coefficients that have been - accounted for by runs started in this coefficient.*/ - for(rli=64-_zzi;rli-->0;)_ntoks_left[pli][_zzi+rli]-=run_counts[rli]; - } - return _eobs; -} - -/*Tokens describing the DCT coefficients that belong to each fragment are - stored in the bitstream grouped by coefficient, not by fragment. - - This means that we either decode all the tokens in order, building up a - separate coefficient list for each fragment as we go, and then go back and - do the iDCT on each fragment, or we have to create separate lists of tokens - for each coefficient, so that we can pull the next token required off the - head of the appropriate list when decoding a specific fragment. - - The former was VP3's choice, and it meant 2*w*h extra storage for all the - decoded coefficient values. - - We take the second option, which lets us store just one or three bytes per - token (generally far fewer than the number of coefficients, due to EOB - tokens and zero runs), and which requires us to only maintain a counter for - each of the 64 coefficients, instead of a counter for every fragment to - determine where the next token goes. - - Actually, we use 3 counters per coefficient, one for each color plane, so we - can decode all color planes simultaneously. - - This lets color conversion, etc., be done as soon as a full MCU (one or - two super block rows) is decoded, while the image data is still in cache.*/ - -static void oc_dec_residual_tokens_unpack(oc_dec_ctx *_dec){ - static const int OC_HUFF_LIST_MAX[5]={1,6,15,28,64}; - long val; - int ntoks_left[3][64]; - int huff_idxs[3]; - int pli; - int zzi; - int hgi; - int huffi_y; - int huffi_c; - int eobs; - for(pli=0;pli<3;pli++)for(zzi=0;zzi<64;zzi++){ - ntoks_left[pli][zzi]=_dec->state.ncoded_fragis[pli]; - } - theorapackB_read(&_dec->opb,4,&val); - huffi_y=(int)val; - theorapackB_read(&_dec->opb,4,&val); - huffi_c=(int)val; - huff_idxs[0]=huffi_y; - huff_idxs[1]=huff_idxs[2]=huffi_c; - _dec->eob_runs[0][0]=0; - eobs=oc_dec_dc_coeff_unpack(_dec,huff_idxs,ntoks_left); - theorapackB_read(&_dec->opb,4,&val); - huffi_y=(int)val; - theorapackB_read(&_dec->opb,4,&val); - huffi_c=(int)val; - zzi=1; - for(hgi=1;hgi<5;hgi++){ - huff_idxs[0]=huffi_y+(hgi<<4); - huff_idxs[1]=huff_idxs[2]=huffi_c+(hgi<<4); - for(;zzi0); - *_zzi=zzi; -} - -/*Expands a constant, single-value token.*/ -static void oc_token_expand_const(int _token,int _extra_bits, - ogg_int16_t _dct_coeffs[128],int *_zzi){ - _dct_coeffs[(*_zzi)++]=(ogg_int16_t)oc_token_dec1val_const(_token); -} - -/*Expands category 2 single-valued tokens.*/ -static void oc_token_expand_cat2(int _token,int _extra_bits, - ogg_int16_t _dct_coeffs[128],int *_zzi){ - _dct_coeffs[(*_zzi)++]= - (ogg_int16_t)oc_token_dec1val_cat2(_token,_extra_bits); -} - -/*Expands category 3 through 8 single-valued tokens.*/ -static void oc_token_expand_cati(int _token,int _extra_bits, - ogg_int16_t _dct_coeffs[128],int *_zzi){ - _dct_coeffs[(*_zzi)++]= - (ogg_int16_t)oc_token_dec1val_cati(_token,_extra_bits); -} - -/*Expands a category 1a zero run/value combo token.*/ -static void oc_token_expand_run_cat1a(int _token,int _extra_bits, - ogg_int16_t _dct_coeffs[128],int *_zzi){ - int zzi; - int rl; - zzi=*_zzi; - /*LOOP VECTORIZES.*/ - for(rl=_token-OC_DCT_RUN_CAT1A+1;rl-->0;)_dct_coeffs[zzi++]=0; - _dct_coeffs[zzi++]=(ogg_int16_t)(1-(_extra_bits<<1)); - *_zzi=zzi; -} - -/*Expands all other zero run/value combo tokens.*/ -static void oc_token_expand_run(int _token,int _extra_bits, - ogg_int16_t _dct_coeffs[128],int *_zzi){ - static const int NZEROS_ADJUST[OC_NDCT_RUN_MAX-OC_DCT_RUN_CAT1B]={ - 6,10,1,2 - }; - static const int NZEROS_MASK[OC_NDCT_RUN_MAX-OC_DCT_RUN_CAT1B]={ - 3,7,0,1 - }; - static const int VALUE_SHIFT[OC_NDCT_RUN_MAX-OC_DCT_RUN_CAT1B]={ - 0,0,0,1 - }; - static const int VALUE_MASK[OC_NDCT_RUN_MAX-OC_DCT_RUN_CAT1B]={ - 0,0,1,1 - }; - static const int VALUE_ADJUST[OC_NDCT_RUN_MAX-OC_DCT_RUN_CAT1B]={ - 1,1,2,2 - }; - static const int SIGN_SHIFT[OC_NDCT_RUN_MAX-OC_DCT_RUN_CAT1B]={ - 2,3,1,2 - }; - int valsigned[2]; - int zzi; - int rl; - _token-=OC_DCT_RUN_CAT1B; - rl=(_extra_bits&NZEROS_MASK[_token])+NZEROS_ADJUST[_token]; - zzi=*_zzi; - /*LOOP VECTORIZES.*/ - while(rl-->0)_dct_coeffs[zzi++]=0; - valsigned[0]=VALUE_ADJUST[_token]+ - (_extra_bits>>VALUE_SHIFT[_token]&VALUE_MASK[_token]); - valsigned[1]=-valsigned[0]; - _dct_coeffs[zzi++]=(ogg_int16_t)valsigned[ - _extra_bits>>SIGN_SHIFT[_token]]; - *_zzi=zzi; -} - -/*A jump table for expanding token values into coefficient values. - This reduces all the conditional branches, etc., needed to parse these token - values down to one indirect jump.*/ -static const oc_token_expand_func OC_TOKEN_EXPAND_TABLE[TH_NDCT_TOKENS- - OC_NDCT_EOB_TOKEN_MAX]={ - oc_token_expand_zrl, - oc_token_expand_zrl, - oc_token_expand_const, - oc_token_expand_const, - oc_token_expand_const, - oc_token_expand_const, - oc_token_expand_cat2, - oc_token_expand_cat2, - oc_token_expand_cat2, - oc_token_expand_cat2, - oc_token_expand_cati, - oc_token_expand_cati, - oc_token_expand_cati, - oc_token_expand_cati, - oc_token_expand_cati, - oc_token_expand_cati, - oc_token_expand_run_cat1a, - oc_token_expand_run_cat1a, - oc_token_expand_run_cat1a, - oc_token_expand_run_cat1a, - oc_token_expand_run_cat1a, - oc_token_expand_run, - oc_token_expand_run, - oc_token_expand_run, - oc_token_expand_run -}; - -/*Expands a single token into the given coefficient list. - This fills in the zeros for zero runs as well as coefficient values, and - updates the index of the current coefficient. - It CANNOT be called for any of the EOB tokens. - _token: The token value to expand. - _extra_bits: The extra bits associated with the token. - _dct_coeffs: The current list of coefficients, in zig-zag order. - _zzi: A pointer to the zig-zag index of the next coefficient to write - to. - This is updated before the function returns.*/ -static void oc_dct_token_expand(int _token,int _extra_bits, - ogg_int16_t *_dct_coeffs,int *_zzi){ - (*OC_TOKEN_EXPAND_TABLE[_token-OC_NDCT_EOB_TOKEN_MAX])(_token, - _extra_bits,_dct_coeffs,_zzi); -} - - - -static int oc_dec_postprocess_init(oc_dec_ctx *_dec){ - /*pp_level 0: disabled; free any memory used and return*/ - if(_dec->pp_level<=OC_PP_LEVEL_DISABLED){ - if(_dec->dc_qis!=NULL){ - _ogg_free(_dec->dc_qis); - _dec->dc_qis=NULL; - _ogg_free(_dec->variances); - _dec->variances=NULL; - _ogg_free(_dec->pp_frame_data); - _dec->pp_frame_data=NULL; - } - return 1; - } - if(_dec->dc_qis==NULL){ - /*If we haven't been tracking DC quantization indices, there's no point in - starting now.*/ - if(_dec->state.frame_type!=OC_INTRA_FRAME)return 1; - _dec->dc_qis=(unsigned char *)_ogg_malloc( - _dec->state.nfrags*sizeof(_dec->dc_qis[0])); - memset(_dec->dc_qis,_dec->state.qis[0],_dec->state.nfrags); - } - else{ - int *coded_fragi; - int *coded_fragi_end; - unsigned char qi0; - /*Update the DC quantization index of each coded block.*/ - qi0=(unsigned char)_dec->state.qis[0]; - coded_fragi_end=_dec->state.coded_fragis+_dec->state.ncoded_fragis[0]+ - _dec->state.ncoded_fragis[1]+_dec->state.ncoded_fragis[2]; - for(coded_fragi=_dec->state.coded_fragis;coded_fragidc_qis[*coded_fragi]=qi0; - } - } - /*pp_level 1: Stop after updating DC quantization indices.*/ - if(_dec->pp_level<=OC_PP_LEVEL_TRACKDCQI){ - if(_dec->variances!=NULL){ - _ogg_free(_dec->variances); - _dec->variances=NULL; - _ogg_free(_dec->pp_frame_data); - _dec->pp_frame_data=NULL; - } - return 1; - } - if(_dec->variances==NULL|| - _dec->pp_frame_has_chroma!=(_dec->pp_level>=OC_PP_LEVEL_DEBLOCKC)){ - size_t frame_sz; - frame_sz=_dec->state.info.frame_width*_dec->state.info.frame_height; - if(_dec->pp_levelvariances=(int *)_ogg_realloc(_dec->variances, - _dec->state.fplanes[0].nfrags*sizeof(_dec->variances[0])); - _dec->pp_frame_data=(unsigned char *)_ogg_realloc( - _dec->pp_frame_data,frame_sz*sizeof(_dec->pp_frame_data[0])); - _dec->pp_frame_buf[0].width=_dec->state.info.frame_width; - _dec->pp_frame_buf[0].height=_dec->state.info.frame_height; - _dec->pp_frame_buf[0].stride=-_dec->pp_frame_buf[0].width; - _dec->pp_frame_buf[0].data=_dec->pp_frame_data+ - (1-_dec->pp_frame_buf[0].height)*_dec->pp_frame_buf[0].stride; - } - else{ - size_t y_sz; - size_t c_sz; - int c_w; - int c_h; - _dec->variances=(int *)_ogg_realloc(_dec->variances, - _dec->state.nfrags*sizeof(_dec->variances[0])); - y_sz=frame_sz; - c_w=_dec->state.info.frame_width>>!(_dec->state.info.pixel_fmt&1); - c_h=_dec->state.info.frame_height>>!(_dec->state.info.pixel_fmt&2); - c_sz=c_w*c_h; - frame_sz+=c_sz<<1; - _dec->pp_frame_data=(unsigned char *)_ogg_realloc( - _dec->pp_frame_data,frame_sz*sizeof(_dec->pp_frame_data[0])); - _dec->pp_frame_buf[0].width=_dec->state.info.frame_width; - _dec->pp_frame_buf[0].height=_dec->state.info.frame_height; - _dec->pp_frame_buf[0].stride=_dec->pp_frame_buf[0].width; - _dec->pp_frame_buf[0].data=_dec->pp_frame_data; - _dec->pp_frame_buf[1].width=c_w; - _dec->pp_frame_buf[1].height=c_h; - _dec->pp_frame_buf[1].stride=_dec->pp_frame_buf[1].width; - _dec->pp_frame_buf[1].data=_dec->pp_frame_buf[0].data+y_sz; - _dec->pp_frame_buf[2].width=c_w; - _dec->pp_frame_buf[2].height=c_h; - _dec->pp_frame_buf[2].stride=_dec->pp_frame_buf[2].width; - _dec->pp_frame_buf[2].data=_dec->pp_frame_buf[1].data+c_sz; - oc_ycbcr_buffer_flip(_dec->pp_frame_buf,_dec->pp_frame_buf); - } - _dec->pp_frame_has_chroma=(_dec->pp_level>=OC_PP_LEVEL_DEBLOCKC); - } - /*If we're not processing chroma, copy the reference frame's chroma planes.*/ - if(_dec->pp_levelpp_frame_buf+1, - _dec->state.ref_frame_bufs[_dec->state.ref_frame_idx[OC_FRAME_SELF]]+1, - sizeof(_dec->pp_frame_buf[1])*2); - } - return 0; -} - - - -typedef struct{ - int ti[3][64]; - int ebi[3][64]; - int eob_runs[3][64]; - int bounding_values[256]; - int *coded_fragis[3]; - int *uncoded_fragis[3]; - int fragy0[3]; - int fragy_end[3]; - int ncoded_fragis[3]; - int nuncoded_fragis[3]; - int pred_last[3][3]; - int mcu_nvfrags; - int loop_filter; - int pp_level; -}oc_dec_pipeline_state; - - - -/*Initialize the main decoding pipeline.*/ -static void oc_dec_pipeline_init(oc_dec_ctx *_dec, - oc_dec_pipeline_state *_pipe){ - int *coded_fragi_end; - int *uncoded_fragi_end; - int pli; - /*If chroma is sub-sampled in the vertical direction, we have to decode two - super block rows of Y' for each super block row of Cb and Cr.*/ - _pipe->mcu_nvfrags=4<state.info.pixel_fmt&2); - /*Initialize the token and extra bits indices for each plane and - coefficient.*/ - memset(_pipe->ti[0],0,sizeof(_pipe->ti[0])); - memset(_pipe->ebi[0],0,sizeof(_pipe->ebi[0])); - for(pli=1;pli<3;pli++){ - memcpy(_pipe->ti[pli],_dec->ti0[pli-1],sizeof(_pipe->ti[0])); - memcpy(_pipe->ebi[pli],_dec->ebi0[pli-1],sizeof(_pipe->ebi[0])); - } - /*Also copy over the initial the EOB run counts.*/ - memcpy(_pipe->eob_runs,_dec->eob_runs,sizeof(_pipe->eob_runs)); - /*Set up per-plane pointers to the coded and uncoded fragments lists.*/ - coded_fragi_end=_dec->state.coded_fragis; - uncoded_fragi_end=_dec->state.uncoded_fragis; - for(pli=0;pli<3;pli++){ - _pipe->coded_fragis[pli]=coded_fragi_end; - _pipe->uncoded_fragis[pli]=uncoded_fragi_end; - coded_fragi_end+=_dec->state.ncoded_fragis[pli]; - uncoded_fragi_end-=_dec->state.nuncoded_fragis[pli]; - } - /*Set the previous DC predictor to 0 for all color planes and frame types.*/ - memset(_pipe->pred_last,0,sizeof(_pipe->pred_last)); - /*Initialize the bounding value array for the loop filter.*/ - _pipe->loop_filter=!oc_state_loop_filter_init(&_dec->state, - _pipe->bounding_values); - /*Initialize any buffers needed for post-processing. - We also save the current post-processing level, to guard against the user - changing it from a callback.*/ - if(!oc_dec_postprocess_init(_dec))_pipe->pp_level=_dec->pp_level; - /*If we don't have enough information to post-process, disable it, regardless - of the user-requested level.*/ - else{ - _pipe->pp_level=OC_PP_LEVEL_DISABLED; - memcpy(_dec->pp_frame_buf, - _dec->state.ref_frame_bufs[_dec->state.ref_frame_idx[OC_FRAME_SELF]], - sizeof(_dec->pp_frame_buf[0])*3); - } -} - -/*Undo the DC prediction in a single plane of an MCU (one or two super block - rows). - As a side effect, the number of coded and uncoded fragments in this plane of - the MCU is also computed.*/ -static void oc_dec_dc_unpredict_mcu_plane(oc_dec_ctx *_dec, - oc_dec_pipeline_state *_pipe,int _pli){ - /*Undo the DC prediction.*/ - oc_fragment_plane *fplane; - oc_fragment *frag; - int *pred_last; - int ncoded_fragis; - int fragx; - int fragy; - int fragy0; - int fragy_end; - /*Compute the first and last fragment row of the current MCU for this - plane.*/ - fplane=_dec->state.fplanes+_pli; - fragy0=_pipe->fragy0[_pli]; - fragy_end=_pipe->fragy_end[_pli]; - frag=_dec->state.frags+fplane->froffset+(fragy0*fplane->nhfrags); - ncoded_fragis=0; - pred_last=_pipe->pred_last[_pli]; - for(fragy=fragy0;fragynhfrags;fragx++,frag++){ - if(!frag->coded)continue; - pred_last[OC_FRAME_FOR_MODE[frag->mbmode]]=frag->dc+= - oc_frag_pred_dc(frag,fplane,fragx,fragy,pred_last); - ncoded_fragis++; - } - } - _pipe->ncoded_fragis[_pli]=ncoded_fragis; - /*Also save the number of uncoded fragments so we know how many to copy.*/ - _pipe->nuncoded_fragis[_pli]= - (fragy_end-fragy0)*fplane->nhfrags-ncoded_fragis; -} - -/*Reconstructs all coded fragments in a single MCU (one or two super block - rows). - This requires that each coded fragment have a proper macro block mode and - motion vector (if not in INTRA mode), and have it's DC value decoded, with - the DC prediction process reversed, and the number of coded and uncoded - fragments in this plane of the MCU be counted. - The token lists for each color plane and coefficient should also be filled - in, along with initial token offsets, extra bits offsets, and EOB run - counts.*/ -static void oc_dec_frags_recon_mcu_plane(oc_dec_ctx *_dec, - oc_dec_pipeline_state *_pipe,int _pli){ - /*Decode the AC coefficients.*/ - int *ti; - int *ebi; - int *eob_runs; - int *coded_fragi; - int *coded_fragi_end; - ti=_pipe->ti[_pli]; - ebi=_pipe->ebi[_pli]; - eob_runs=_pipe->eob_runs[_pli]; - coded_fragi_end=coded_fragi=_pipe->coded_fragis[_pli]; - coded_fragi_end+=_pipe->ncoded_fragis[_pli]; - for(;coded_fragistate.frags+fragi; - for(zzi=0;zzi<64;){ - int token; - int eb; - last_zzi=zzi; - if(eob_runs[zzi]){ - eob_runs[zzi]--; - break; - } - else{ - int ebflag; - token=_dec->dct_tokens[zzi][ti[zzi]++]; - ebflag=OC_DCT_TOKEN_EXTRA_BITS[token]!=0; - eb=_dec->extra_bits[zzi][ebi[zzi]]&-ebflag; - ebi[zzi]+=ebflag; - if(tokendc; - iquants=_dec->state.dequant_tables[frag->mbmode!=OC_MODE_INTRA][_pli]; - /*last_zzi is always initialized. - If your compiler thinks otherwise, it is dumb.*/ - oc_state_frag_recon(&_dec->state,frag,_pli,dct_coeffs,last_zzi,zzi, - iquants[_dec->state.qis[0]][0],iquants[frag->qi]); - } - _pipe->coded_fragis[_pli]=coded_fragi; - /*Right now the reconstructed MCU has only the coded blocks in it.*/ - /*TODO: We make the decision here to always copy the uncoded blocks into it - from the reference frame. - We could also copy the coded blocks back over the reference frame, if we - wait for an additional MCU to be decoded, which might be faster if only a - small number of blocks are coded. - However, this introduces more latency, creating a larger cache footprint. - It's unknown which decision is better, but this one results in simpler - code, and the hard case (high bitrate, high resolution) is handled - correctly.*/ - /*Copy the uncoded blocks from the previous reference frame.*/ - _pipe->uncoded_fragis[_pli]-=_pipe->nuncoded_fragis[_pli]; - oc_state_frag_copy(&_dec->state,_pipe->uncoded_fragis[_pli], - _pipe->nuncoded_fragis[_pli],OC_FRAME_SELF,OC_FRAME_PREV,_pli); -} - -/*Filter a horizontal block edge.*/ -static void oc_filter_hedge(unsigned char *_dst,int _dst_ystride, - const unsigned char *_src,int _src_ystride,int _qstep,int _flimit, - int *_variance0,int *_variance1){ - unsigned char *rdst; - const unsigned char *rsrc; - unsigned char *cdst; - const unsigned char *csrc; - int r[10]; - int sum0; - int sum1; - int bx; - int by; - rdst=_dst; - rsrc=_src; - for(bx=0;bx<8;bx++){ - cdst=rdst; - csrc=rsrc; - for(by=0;by<10;by++){ - r[by]=*csrc; - csrc+=_src_ystride; - } - sum0=sum1=0; - for(by=0;by<4;by++){ - sum0+=abs(r[by+1]-r[by]); - sum1+=abs(r[by+5]-r[by+6]); - } - *_variance0+=OC_MINI(255,sum0); - *_variance1+=OC_MINI(255,sum1); - if(sum0<_flimit&&sum1<_flimit&&r[5]-r[4]<_qstep&&r[4]-r[5]<_qstep){ - *cdst=(unsigned char)(r[0]*3+r[1]*2+r[2]+r[3]+r[4]+4>>3); - cdst+=_dst_ystride; - *cdst=(unsigned char)(r[0]*2+r[1]+r[2]*2+r[3]+r[4]+r[5]+4>>3); - cdst+=_dst_ystride; - for(by=0;by<4;by++){ - *cdst=(unsigned char)(r[by]+r[by+1]+r[by+2]+r[by+3]*2+ - r[by+4]+r[by+5]+r[by+6]+4>>3); - cdst+=_dst_ystride; - } - *cdst=(unsigned char)(r[4]+r[5]+r[6]+r[7]*2+r[8]+r[9]*2+4>>3); - cdst+=_dst_ystride; - *cdst=(unsigned char)(r[5]+r[6]+r[7]+r[8]*2+r[9]*3+4>>3); - } - else{ - for(by=1;by<=8;by++){ - *cdst=(unsigned char)r[by]; - cdst+=_dst_ystride; - } - } - rdst++; - rsrc++; - } -} - -/*Filter a vertical block edge.*/ -static void oc_filter_vedge(unsigned char *_dst,int _dst_ystride, - int _qstep,int _flimit,int *_variances){ - unsigned char *rdst; - const unsigned char *rsrc; - unsigned char *cdst; - int r[10]; - int sum0; - int sum1; - int bx; - int by; - cdst=_dst; - for(by=0;by<8;by++){ - rsrc=cdst-1; - rdst=cdst; - for(bx=0;bx<10;bx++)r[bx]=*rsrc++; - sum0=sum1=0; - for(bx=0;bx<4;bx++){ - sum0+=abs(r[bx+1]-r[bx]); - sum1+=abs(r[bx+5]-r[bx+6]); - } - _variances[0]+=OC_MINI(255,sum0); - _variances[1]+=OC_MINI(255,sum1); - if(sum0<_flimit&&sum1<_flimit&&r[5]-r[4]<_qstep&&r[4]-r[5]<_qstep){ - *rdst++=(unsigned char)(r[0]*3+r[1]*2+r[2]+r[3]+r[4]+4>>3); - *rdst++=(unsigned char)(r[0]*2+r[1]+r[2]*2+r[3]+r[4]+r[5]+4>>3); - for(bx=0;bx<4;bx++){ - *rdst++=(unsigned char)(r[bx]+r[bx+1]+r[bx+2]+r[bx+3]*2+ - r[bx+4]+r[bx+5]+r[bx+6]+4>>3); - } - *rdst++=(unsigned char)(r[4]+r[5]+r[6]+r[7]*2+r[8]+r[9]*2+4>>3); - *rdst=(unsigned char)(r[5]+r[6]+r[7]+r[8]*2+r[9]*3+4>>3); - } - else for(bx=1;bx<=8;bx++)*rdst++=(unsigned char)r[bx]; - cdst+=_dst_ystride; - } -} - -static void oc_dec_deblock_frag_rows(oc_dec_ctx *_dec, - th_img_plane *_dst,th_img_plane *_src,int _pli,int _fragy0, - int _fragy_end){ - oc_fragment_plane *fplane; - int *variance; - unsigned char *dc_qi; - unsigned char *dst; - const unsigned char *src; - int notstart; - int notdone; - int froffset; - int flimit; - int qstep; - int y_end; - int y; - int x; - _dst+=_pli; - _src+=_pli; - fplane=_dec->state.fplanes+_pli; - froffset=fplane->froffset+_fragy0*fplane->nhfrags; - variance=_dec->variances+froffset; - dc_qi=_dec->dc_qis+froffset; - notstart=_fragy0>0; - notdone=_fragy_endnvfrags; - /*We want to clear an extra row of variances, except at the end.*/ - memset(variance+(fplane->nhfrags&-notstart),0, - (_fragy_end+notdone-_fragy0-notstart)*fplane->nhfrags*sizeof(variance[0])); - /*Except for the first time, we want to point to the middle of the row.*/ - y=(_fragy0<<3)+(notstart<<2); - dst=_dst->data+y*_dst->stride; - src=_src->data+y*_src->stride; - for(;y<4;y++){ - memcpy(dst,src,_dst->width*sizeof(dst[0])); - dst+=_dst->stride; - src+=_src->stride; - } - /*We also want to skip the last row in the frame for this loop.*/ - y_end=_fragy_end-!notdone<<3; - for(;ypp_dc_scale[*dc_qi]; - flimit=(qstep*3)>>2; - oc_filter_hedge(dst,_dst->stride,src-_src->stride,_src->stride, - qstep,flimit,variance,variance+fplane->nhfrags); - variance++; - dc_qi++; - for(x=8;x<_dst->width;x+=8){ - qstep=_dec->pp_dc_scale[*dc_qi]; - flimit=(qstep*3)>>2; - oc_filter_hedge(dst+x,_dst->stride,src+x-_src->stride,_src->stride, - qstep,flimit,variance,variance+fplane->nhfrags); - oc_filter_vedge(dst+x-(_dst->stride<<2)-4,_dst->stride, - qstep,flimit,variance-1); - variance++; - dc_qi++; - } - dst+=_dst->stride<<3; - src+=_src->stride<<3; - } - /*And finally, handle the last row in the frame, if it's in the range.*/ - if(!notdone){ - for(;y<_dst->height;y++){ - memcpy(dst,src,_dst->width*sizeof(dst[0])); - dst+=_dst->stride; - src+=_src->stride; - } - /*Filter the last row of vertical block edges.*/ - dc_qi++; - for(x=8;x<_dst->width;x+=8){ - qstep=_dec->pp_dc_scale[*dc_qi++]; - flimit=(qstep*3)>>2; - oc_filter_vedge(dst+x-(_dst->stride<<3)-4,_dst->stride, - qstep,flimit,variance++); - } - } -} - -static void oc_dering_block(unsigned char *_idata,int _ystride,int _b, - int _dc_scale,int _sharp_mod,int _strong){ - static const int MOD_MAX[2]={24,32}; - static const int MOD_SHIFT[2]={1,0}; - const unsigned char *psrc; - const unsigned char *src; - const unsigned char *nsrc; - unsigned char *dst; - int vmod[72]; - int hmod[72]; - int mod_hi; - int by; - int bx; - mod_hi=OC_MINI(3*_dc_scale,MOD_MAX[_strong]); - dst=_idata; - src=dst; - psrc=src-(_ystride&-!(_b&4)); - for(by=0;by<9;by++){ - for(bx=0;bx<8;bx++){ - int mod; - mod=32+_dc_scale-(abs(src[bx]-psrc[bx])<>7); - for(bx=1;bx<7;bx++){ - a=128; - b=64; - w=hmod[(bx<<3)+by]; - a-=w; - b+=w*src[bx-1]; - w=vmod[(by<<3)+bx]; - a-=w; - b+=w*psrc[bx]; - w=vmod[(by+1<<3)+bx]; - a-=w; - b+=w*nsrc[bx]; - w=hmod[(bx+1<<3)+by]; - a-=w; - b+=w*src[bx+1]; - dst[bx]=OC_CLAMP255(a*src[bx]+b>>7); - } - a=128; - b=64; - w=hmod[(7<<3)+by]; - a-=w; - b+=w*src[6]; - w=vmod[(by<<3)+7]; - a-=w; - b+=w*psrc[7]; - w=vmod[(by+1<<3)+7]; - a-=w; - b+=w*nsrc[7]; - w=hmod[(8<<3)+by]; - a-=w; - b+=w*src[7+!(_b&2)]; - dst[7]=OC_CLAMP255(a*src[7]+b>>7); - dst+=_ystride; - psrc=src; - src=nsrc; - nsrc+=_ystride&-(!(_b&8)|by<6); - } -} - -#define OC_DERING_THRESH1 (384) -#define OC_DERING_THRESH2 (4*OC_DERING_THRESH1) -#define OC_DERING_THRESH3 (5*OC_DERING_THRESH1) -#define OC_DERING_THRESH4 (10*OC_DERING_THRESH1) - -static void oc_dec_dering_frag_rows(oc_dec_ctx *_dec,th_img_plane *_img, - int _pli,int _fragy0,int _fragy_end){ - th_img_plane *iplane; - oc_fragment_plane *fplane; - oc_fragment *frag; - int *variance; - unsigned char *idata; - int sthresh; - int strong; - int froffset; - int y_end; - int y; - int x; - iplane=_img+_pli; - fplane=_dec->state.fplanes+_pli; - froffset=fplane->froffset+_fragy0*fplane->nhfrags; - variance=_dec->variances+froffset; - frag=_dec->state.frags+froffset; - strong=_dec->pp_level>=(_pli?OC_PP_LEVEL_SDERINGC:OC_PP_LEVEL_SDERINGY); - sthresh=_pli?OC_DERING_THRESH4:OC_DERING_THRESH3; - y=_fragy0<<3; - idata=iplane->data+y*iplane->stride; - y_end=_fragy_end<<3; - for(;ywidth;x+=8){ - int b; - int qi; - int var; - qi=frag->qi; - var=*variance; - b=(x<=0)|(x+8>=iplane->width)<<1|(y<=0)<<2|(y+8>=iplane->height)<<3; - if(strong&&var>sthresh){ - oc_dering_block(idata+x,iplane->stride,b, - _dec->pp_dc_scale[qi],_dec->pp_sharp_mod[qi],1); - if(_pli||!(b&1)&&*(variance-1)>OC_DERING_THRESH4|| - !(b&2)&&variance[1]>OC_DERING_THRESH4|| - !(b&4)&&*(variance-fplane->nvfrags)>OC_DERING_THRESH4|| - !(b&8)&&variance[fplane->nvfrags]>OC_DERING_THRESH4){ - oc_dering_block(idata+x,iplane->stride,b, - _dec->pp_dc_scale[qi],_dec->pp_sharp_mod[qi],1); - oc_dering_block(idata+x,iplane->stride,b, - _dec->pp_dc_scale[qi],_dec->pp_sharp_mod[qi],1); - } - } - else if(var>OC_DERING_THRESH2){ - oc_dering_block(idata+x,iplane->stride,b, - _dec->pp_dc_scale[qi],_dec->pp_sharp_mod[qi],1); - } - else if(var>OC_DERING_THRESH1){ - oc_dering_block(idata+x,iplane->stride,b, - _dec->pp_dc_scale[qi],_dec->pp_sharp_mod[qi],0); - } - frag++; - variance++; - } - idata+=iplane->stride<<3; - } -} - - - -th_dec_ctx *th_decode_alloc(const th_info *_info, - const th_setup_info *_setup){ - oc_dec_ctx *dec; - if(_info==NULL||_setup==NULL)return NULL; - dec=_ogg_malloc(sizeof(*dec)); - if(oc_dec_init(dec,_info,_setup)<0){ - _ogg_free(dec); - return NULL; - } - dec->state.curframe_num=0; - return dec; -} - -void th_decode_free(th_dec_ctx *_dec){ - if(_dec!=NULL){ - oc_dec_clear(_dec); - _ogg_free(_dec); - } -} - -int th_decode_ctl(th_dec_ctx *_dec,int _req,void *_buf, - size_t _buf_sz){ - switch(_req){ - case TH_DECCTL_GET_PPLEVEL_MAX:{ - if(_dec==NULL||_buf==NULL)return TH_EFAULT; - if(_buf_sz!=sizeof(int))return TH_EINVAL; - (*(int *)_buf)=OC_PP_LEVEL_MAX; - return 0; - }break; - case TH_DECCTL_SET_PPLEVEL:{ - int pp_level; - if(_dec==NULL||_buf==NULL)return TH_EFAULT; - if(_buf_sz!=sizeof(int))return TH_EINVAL; - pp_level=*(int *)_buf; - if(pp_level<0||pp_level>OC_PP_LEVEL_MAX)return TH_EINVAL; - _dec->pp_level=pp_level; - return 0; - }break; - case TH_DECCTL_SET_GRANPOS:{ - ogg_int64_t granpos; - if(_dec==NULL||_buf==NULL)return TH_EFAULT; - if(_buf_sz!=sizeof(ogg_int64_t))return TH_EINVAL; - granpos=*(ogg_int64_t *)_buf; - if(granpos<0)return TH_EINVAL; - _dec->state.granpos=granpos; - _dec->state.keyframe_num= - granpos>>_dec->state.info.keyframe_granule_shift; - _dec->state.curframe_num=_dec->state.keyframe_num+ - (granpos&(1<<_dec->state.info.keyframe_granule_shift)-1); - return 0; - }break; - case TH_DECCTL_SET_STRIPE_CB:{ - th_stripe_callback *cb; - if(_dec==NULL||_buf==NULL)return TH_EFAULT; - if(_buf_sz!=sizeof(th_stripe_callback))return TH_EINVAL; - cb=(th_stripe_callback *)_buf; - _dec->stripe_cb.ctx=cb->ctx; - _dec->stripe_cb.stripe_decoded=cb->stripe_decoded; - return 0; - }break; - default:return TH_EIMPL; - } -} - -int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op, - ogg_int64_t *_granpos){ - int ret; - if(_dec==NULL||_op==NULL)return TH_EFAULT; - /*A completely empty packet indicates a dropped frame and is treated exactly - like an inter frame with no coded blocks. - Only proceed if we have a non-empty packet.*/ - if(_op->bytes!=0){ - oc_dec_pipeline_state pipe; - th_ycbcr_buffer stripe_buf; - int stripe_fragy; - int refi; - int pli; - int notstart; - int notdone; - theorapackB_readinit(&_dec->opb,_op->packet,_op->bytes); - ret=oc_dec_frame_header_unpack(_dec); - if(ret<0)return ret; - /*Select a free buffer to use for the reconstructed version of this - frame.*/ - if(_dec->state.frame_type!=OC_INTRA_FRAME&& - (_dec->state.ref_frame_idx[OC_FRAME_GOLD]<0|| - _dec->state.ref_frame_idx[OC_FRAME_PREV]<0)){ - th_info *info; - size_t yplane_sz; - size_t cplane_sz; - int yhstride; - int yvstride; - int chstride; - int cvstride; - /*We're decoding an INTER frame, but have no initialized reference - buffers (i.e., decoding did not start on a key frame). - We initialize them to a solid gray here.*/ - _dec->state.ref_frame_idx[OC_FRAME_GOLD]=0; - _dec->state.ref_frame_idx[OC_FRAME_PREV]=0; - _dec->state.ref_frame_idx[OC_FRAME_SELF]=refi=1; - info=&_dec->state.info; - yhstride=info->frame_width+2*OC_UMV_PADDING; - yvstride=info->frame_height+2*OC_UMV_PADDING; - chstride=yhstride>>!(info->pixel_fmt&1); - cvstride=yvstride>>!(info->pixel_fmt&2); - yplane_sz=(size_t)yhstride*yvstride; - cplane_sz=(size_t)chstride*cvstride; - memset(_dec->state.ref_frame_data,0x80,yplane_sz+2*cplane_sz); - } - else{ - for(refi=0;refi==_dec->state.ref_frame_idx[OC_FRAME_GOLD]|| - refi==_dec->state.ref_frame_idx[OC_FRAME_PREV];refi++); - _dec->state.ref_frame_idx[OC_FRAME_SELF]=refi; - } - if(_dec->state.frame_type==OC_INTRA_FRAME){ - oc_dec_mark_all_intra(_dec); - _dec->state.keyframe_num=_dec->state.curframe_num; - }else{ - oc_dec_coded_flags_unpack(_dec); - oc_dec_mb_modes_unpack(_dec); - oc_dec_mv_unpack_and_frag_modes_fill(_dec); - } - oc_dec_block_qis_unpack(_dec); - oc_dec_residual_tokens_unpack(_dec); - /*Update granule position. - This must be done before the striped decode callbacks so that the - application knows what to do with the frame data.*/ - _dec->state.granpos= - (_dec->state.keyframe_num<<_dec->state.info.keyframe_granule_shift)+ - (_dec->state.curframe_num-_dec->state.keyframe_num); - _dec->state.curframe_num++; - if(_granpos!=NULL)*_granpos=_dec->state.granpos; - /*All of the rest of the operations -- DC prediction reversal, - reconstructing coded fragments, copying uncoded fragments, loop - filtering, extending borders, and out-of-loop post-processing -- should - be pipelined. - I.e., DC prediction reversal, reconstruction, and uncoded fragment - copying are done for one or two super block rows, then loop filtering is - run as far as it can, then bordering copying, then post-processing. - For 4:2:0 video a Minimum Codable Unit or MCU contains two luma super - block rows, and one chroma. - Otherwise, an MCU consists of one super block row from each plane. - Inside each MCU, we perform all of the steps on one color plane before - moving on to the next. - After reconstruction, the additional filtering stages introduce a delay - since they need some pixels from the next fragment row. - Thus the actual number of decoded rows available is slightly smaller for - the first MCU, and slightly larger for the last. - - This entire process allows us to operate on the data while it is still in - cache, resulting in big performance improvements. - An application callback allows further application processing (blitting - to video memory, color conversion, etc.) to also use the data while it's - in cache.*/ - oc_dec_pipeline_init(_dec,&pipe); - oc_ycbcr_buffer_flip(stripe_buf,_dec->pp_frame_buf); - notstart=0; - notdone=1; - for(stripe_fragy=notstart=0;notdone;stripe_fragy+=pipe.mcu_nvfrags){ - int avail_fragy0; - int avail_fragy_end; - avail_fragy0=avail_fragy_end=_dec->state.fplanes[0].nvfrags; - notdone=stripe_fragy+pipe.mcu_nvfragsstate.fplanes+pli; - /*Compute the first and last fragment row of the current MCU for this - plane.*/ - frag_shift=pli!=0&&!(_dec->state.info.pixel_fmt&2); - pipe.fragy0[pli]=stripe_fragy>>frag_shift; - pipe.fragy_end[pli]=OC_MINI(fplane->nvfrags, - pipe.fragy0[pli]+(pipe.mcu_nvfrags>>frag_shift)); - oc_dec_dc_unpredict_mcu_plane(_dec,&pipe,pli); - oc_dec_frags_recon_mcu_plane(_dec,&pipe,pli); - sdelay=edelay=0; - if(pipe.loop_filter){ - sdelay+=notstart; - edelay+=notdone; - oc_state_loop_filter_frag_rows(&_dec->state,pipe.bounding_values, - refi,pli,pipe.fragy0[pli]-sdelay,pipe.fragy_end[pli]-edelay); - } - /*To fill the borders, we have an additional two pixel delay, since a - fragment in the next row could filter its top edge, using two pixels - from a fragment in this row. - But there's no reason to delay a full fragment between the two.*/ - oc_state_borders_fill_rows(&_dec->state,refi,pli, - (pipe.fragy0[pli]-sdelay<<3)-(sdelay<<1), - (pipe.fragy_end[pli]-edelay<<3)-(edelay<<1)); - /*Out-of-loop post-processing.*/ - pp_offset=3*(pli!=0); - if(pipe.pp_level>=OC_PP_LEVEL_DEBLOCKY+pp_offset){ - /*Perform de-blocking in one plane.*/ - sdelay+=notstart; - edelay+=notdone; - oc_dec_deblock_frag_rows(_dec,_dec->pp_frame_buf, - _dec->state.ref_frame_bufs[refi],pli, - pipe.fragy0[pli]-sdelay,pipe.fragy_end[pli]-edelay); - if(pipe.pp_level>=OC_PP_LEVEL_DERINGY+pp_offset){ - /*Perform de-ringing in one plane.*/ - sdelay+=notstart; - edelay+=notdone; - oc_dec_dering_frag_rows(_dec,_dec->pp_frame_buf,pli, - pipe.fragy0[pli]-sdelay,pipe.fragy_end[pli]-edelay); - } - } - /*If no post-processing is done, we still need to delay a row for the - loop filter, thanks to the strange filtering order VP3 chose.*/ - else if(pipe.loop_filter){ - sdelay+=notstart; - edelay+=notdone; - } - /*Compute the intersection of the available rows in all planes. - If chroma is sub-sampled, the effect of each of its delays is - doubled, but luma might have more post-processing filters enabled - than chroma, so we don't know up front which one is the limiting - factor.*/ - avail_fragy0=OC_MINI(avail_fragy0,pipe.fragy0[pli]-sdelay<stripe_cb.stripe_decoded!=NULL){ - /*Make the callback, ensuring we flip the sense of the "start" and - "end" of the available region upside down.*/ - (*_dec->stripe_cb.stripe_decoded)(_dec->stripe_cb.ctx,stripe_buf, - _dec->state.fplanes[0].nvfrags-avail_fragy_end, - _dec->state.fplanes[0].nvfrags-avail_fragy0); - } - notstart=1; - } - /*Finish filling in the reference frame borders.*/ - for(pli=0;pli<3;pli++)oc_state_borders_fill_caps(&_dec->state,refi,pli); - /*Update the reference frame indices.*/ - if(_dec->state.frame_type==OC_INTRA_FRAME){ - /*The new frame becomes both the previous and gold reference frames.*/ - _dec->state.ref_frame_idx[OC_FRAME_GOLD]= - _dec->state.ref_frame_idx[OC_FRAME_PREV]= - _dec->state.ref_frame_idx[OC_FRAME_SELF]; - } - else{ - /*Otherwise, just replace the previous reference frame.*/ - _dec->state.ref_frame_idx[OC_FRAME_PREV]= - _dec->state.ref_frame_idx[OC_FRAME_SELF]; - } -#if defined(OC_DUMP_IMAGES) - /*Don't dump images for dropped frames.*/ - oc_state_dump_frame(&_dec->state,OC_FRAME_SELF,"dec"); -#endif - return 0; - } - else{ - /*Just update the granule position and return.*/ - _dec->state.granpos= - (_dec->state.keyframe_num<<_dec->state.info.keyframe_granule_shift)+ - (_dec->state.curframe_num-_dec->state.keyframe_num); - _dec->state.curframe_num++; - if(_granpos!=NULL)*_granpos=_dec->state.granpos; - return TH_DUPFRAME; - } -} - -int th_decode_ycbcr_out(th_dec_ctx *_dec,th_ycbcr_buffer _ycbcr){ - oc_ycbcr_buffer_flip(_ycbcr,_dec->pp_frame_buf); - return 0; -} diff --git a/Engine/lib/libtheora/lib/dec/fragment.c b/Engine/lib/libtheora/lib/dec/fragment.c deleted file mode 100644 index 77f1c7f6b..000000000 --- a/Engine/lib/libtheora/lib/dec/fragment.c +++ /dev/null @@ -1,199 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: fragment.c 15469 2008-10-30 12:49:42Z tterribe $ - - ********************************************************************/ - -#include "../internal.h" - -void oc_frag_recon_intra(const oc_theora_state *_state,unsigned char *_dst, - int _dst_ystride,const ogg_int16_t *_residue){ - _state->opt_vtable.frag_recon_intra(_dst,_dst_ystride,_residue); -} - -void oc_frag_recon_intra_c(unsigned char *_dst,int _dst_ystride, - const ogg_int16_t *_residue){ - int i; - for(i=0;i<8;i++){ - int j; - for(j=0;j<8;j++){ - int res; - res=*_residue++; - _dst[j]=OC_CLAMP255(res+128); - } - _dst+=_dst_ystride; - } -} - -void oc_frag_recon_inter(const oc_theora_state *_state,unsigned char *_dst, - int _dst_ystride,const unsigned char *_src,int _src_ystride, - const ogg_int16_t *_residue){ - _state->opt_vtable.frag_recon_inter(_dst,_dst_ystride,_src,_src_ystride, - _residue); -} - -void oc_frag_recon_inter_c(unsigned char *_dst,int _dst_ystride, - const unsigned char *_src,int _src_ystride,const ogg_int16_t *_residue){ - int i; - for(i=0;i<8;i++){ - int j; - for(j=0;j<8;j++){ - int res; - res=*_residue++; - _dst[j]=OC_CLAMP255(res+_src[j]); - } - _dst+=_dst_ystride; - _src+=_src_ystride; - } -} - -void oc_frag_recon_inter2(const oc_theora_state *_state,unsigned char *_dst, - int _dst_ystride,const unsigned char *_src1,int _src1_ystride, - const unsigned char *_src2,int _src2_ystride,const ogg_int16_t *_residue){ - _state->opt_vtable.frag_recon_inter2(_dst,_dst_ystride,_src1,_src1_ystride, - _src2,_src2_ystride,_residue); -} - -void oc_frag_recon_inter2_c(unsigned char *_dst,int _dst_ystride, - const unsigned char *_src1,int _src1_ystride,const unsigned char *_src2, - int _src2_ystride,const ogg_int16_t *_residue){ - int i; - for(i=0;i<8;i++){ - int j; - for(j=0;j<8;j++){ - int res; - res=*_residue++; - _dst[j]=OC_CLAMP255(res+((int)_src1[j]+_src2[j]>>1)); - } - _dst+=_dst_ystride; - _src1+=_src1_ystride; - _src2+=_src2_ystride; - } -} - -/*Computes the predicted DC value for the given fragment. - This requires that the fully decoded DC values be available for the left, - upper-left, upper, and upper-right fragments (if they exist). - _frag: The fragment to predict the DC value for. - _fplane: The fragment plane the fragment belongs to. - _x: The x-coordinate of the fragment. - _y: The y-coordinate of the fragment. - _pred_last: The last fully-decoded DC value for each predictor frame - (OC_FRAME_GOLD, OC_FRAME_PREV and OC_FRAME_SELF). - This should be initialized to 0's for the first fragment in each - color plane. - Return: The predicted DC value for this fragment.*/ -int oc_frag_pred_dc(const oc_fragment *_frag, - const oc_fragment_plane *_fplane,int _x,int _y,int _pred_last[3]){ - static const int PRED_SCALE[16][4]={ - /*0*/ - {0,0,0,0}, - /*OC_PL*/ - {1,0,0,0}, - /*OC_PUL*/ - {1,0,0,0}, - /*OC_PL|OC_PUL*/ - {1,0,0,0}, - /*OC_PU*/ - {1,0,0,0}, - /*OC_PL|OC_PU*/ - {1,1,0,0}, - /*OC_PUL|OC_PU*/ - {0,1,0,0}, - /*OC_PL|OC_PUL|PC_PU*/ - {29,-26,29,0}, - /*OC_PUR*/ - {1,0,0,0}, - /*OC_PL|OC_PUR*/ - {75,53,0,0}, - /*OC_PUL|OC_PUR*/ - {1,1,0,0}, - /*OC_PL|OC_PUL|OC_PUR*/ - {75,0,53,0}, - /*OC_PU|OC_PUR*/ - {1,0,0,0}, - /*OC_PL|OC_PU|OC_PUR*/ - {75,0,53,0}, - /*OC_PUL|OC_PU|OC_PUR*/ - {3,10,3,0}, - /*OC_PL|OC_PUL|OC_PU|OC_PUR*/ - {29,-26,29,0} - }; - static const int PRED_SHIFT[16]={0,0,0,0,0,1,0,5,0,7,1,7,0,7,4,5}; - static const int PRED_RMASK[16]={0,0,0,0,0,1,0,31,0,127,1,127,0,127,15,31}; - static const int BC_MASK[8]={ - /*No boundary condition.*/ - OC_PL|OC_PUL|OC_PU|OC_PUR, - /*Left column.*/ - OC_PU|OC_PUR, - /*Top row.*/ - OC_PL, - /*Top row, left column.*/ - 0, - /*Right column.*/ - OC_PL|OC_PUL|OC_PU, - /*Right and left column.*/ - OC_PU, - /*Top row, right column.*/ - OC_PL, - /*Top row, right and left column.*/ - 0 - }; - /*Predictor fragments, left, up-left, up, up-right.*/ - const oc_fragment *predfr[4]; - /*The frame used for prediction for this fragment.*/ - int pred_frame; - /*The boundary condition flags.*/ - int bc; - /*DC predictor values: left, up-left, up, up-right, missing values - skipped.*/ - int p[4]; - /*Predictor count.*/ - int np; - /*Which predictor constants to use.*/ - int pflags; - /*The predicted DC value.*/ - int ret; - int i; - pred_frame=OC_FRAME_FOR_MODE[_frag->mbmode]; - bc=(_x==0)+((_y==0)<<1)+((_x+1==_fplane->nhfrags)<<2); - predfr[0]=_frag-1; - predfr[1]=_frag-_fplane->nhfrags-1; - predfr[2]=predfr[1]+1; - predfr[3]=predfr[2]+1; - np=0; - pflags=0; - for(i=0;i<4;i++){ - int pflag; - pflag=1<coded&& - OC_FRAME_FOR_MODE[predfr[i]->mbmode]==pred_frame){ - p[np++]=predfr[i]->dc; - pflags|=pflag; - } - } - if(pflags==0)return _pred_last[pred_frame]; - else{ - ret=PRED_SCALE[pflags][0]*p[0]; - /*LOOP VECTORIZES.*/ - for(i=1;i128)ret=p[2]; - else if(abs(ret-p[0])>128)ret=p[0]; - else if(abs(ret-p[1])>128)ret=p[1]; - } - return ret; -} diff --git a/Engine/lib/libtheora/lib/dec/huffdec.c b/Engine/lib/libtheora/lib/dec/huffdec.c deleted file mode 100644 index 86c52b62f..000000000 --- a/Engine/lib/libtheora/lib/dec/huffdec.c +++ /dev/null @@ -1,325 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: huffdec.c 15431 2008-10-21 05:04:02Z giles $ - - ********************************************************************/ - -#include -#include -#include "huffdec.h" -#include "decint.h" - - -/*The ANSI offsetof macro is broken on some platforms (e.g., older DECs).*/ -#define _ogg_offsetof(_type,_field)\ - ((size_t)((char *)&((_type *)0)->_field-(char *)0)) - -/*These two functions are really part of the bitpack.c module, but - they are only used here. Declaring local static versions so they - can be inlined saves considerable function call overhead.*/ - -/*Read in bits without advancing the bitptr. - Here we assume 0<=_bits&&_bits<=32.*/ -static int theorapackB_look(oggpack_buffer *_b,int _bits,long *_ret){ - long ret; - long m; - long d; - m=32-_bits; - _bits+=_b->endbit; - d=_b->storage-_b->endbyte; - if(d<=4){ - /*Not the main path.*/ - if(d<=0){ - *_ret=0L; - return -(_bits>d*8); - } - /*If we have some bits left, but not enough, return the ones we have.*/ - if(d*8<_bits)_bits=d*8; - } - ret=_b->ptr[0]<<24+_b->endbit; - if(_bits>8){ - ret|=_b->ptr[1]<<16+_b->endbit; - if(_bits>16){ - ret|=_b->ptr[2]<<8+_b->endbit; - if(_bits>24){ - ret|=_b->ptr[3]<<_b->endbit; - if(_bits>32)ret|=_b->ptr[4]>>8-_b->endbit; - } - } - } - *_ret=((ret&0xFFFFFFFF)>>(m>>1))>>(m+1>>1); - return 0; -} - -/*advance the bitptr*/ -static void theorapackB_adv(oggpack_buffer *_b,int _bits){ - _bits+=_b->endbit; - _b->ptr+=_bits>>3; - _b->endbyte+=_bits>>3; - _b->endbit=_bits&7; -} - - -/*The log_2 of the size of a lookup table is allowed to grow to relative to - the number of unique nodes it contains. - E.g., if OC_HUFF_SLUSH is 2, then at most 75% of the space in the tree is - wasted (each node will have an amortized cost of at most 20 bytes when using - 4-byte pointers). - Larger numbers can decode tokens with fewer read operations, while smaller - numbers may save more space (requiring as little as 8 bytes amortized per - node, though there will be more nodes). - With a sample file: - 32233473 read calls are required when no tree collapsing is done (100.0%). - 19269269 read calls are required when OC_HUFF_SLUSH is 0 (59.8%). - 11144969 read calls are required when OC_HUFF_SLUSH is 1 (34.6%). - 10538563 read calls are required when OC_HUFF_SLUSH is 2 (32.7%). - 10192578 read calls are required when OC_HUFF_SLUSH is 3 (31.6%). - Since a value of 1 gets us the vast majority of the speed-up with only a - small amount of wasted memory, this is what we use.*/ -#define OC_HUFF_SLUSH (1) - - -/*Allocates a Huffman tree node that represents a subtree of depth _nbits. - _nbits: The depth of the subtree. - If this is 0, the node is a leaf node. - Otherwise 1<<_nbits pointers are allocated for children. - Return: The newly allocated and fully initialized Huffman tree node.*/ -static oc_huff_node *oc_huff_node_alloc(int _nbits){ - oc_huff_node *ret; - size_t size; - size=_ogg_offsetof(oc_huff_node,nodes); - if(_nbits>0)size+=sizeof(oc_huff_node *)*(1<<_nbits); - ret=_ogg_calloc(1,size); - ret->nbits=(unsigned char)_nbits; - return ret; -} - -/*Frees a Huffman tree node allocated with oc_huf_node_alloc. - _node: The node to free. - This may be NULL.*/ -static void oc_huff_node_free(oc_huff_node *_node){ - _ogg_free(_node); -} - -/*Frees the memory used by a Huffman tree. - _node: The Huffman tree to free. - This may be NULL.*/ -static void oc_huff_tree_free(oc_huff_node *_node){ - if(_node==NULL)return; - if(_node->nbits){ - int nchildren; - int i; - int inext; - nchildren=1<<_node->nbits; - for(i=0;inodes[i]!=NULL?1<<_node->nbits-_node->nodes[i]->depth:1); - oc_huff_tree_free(_node->nodes[i]); - } - } - oc_huff_node_free(_node); -} - -/*Unpacks a sub-tree from the given buffer. - _opb: The buffer to unpack from. - _binode: The location to store a pointer to the sub-tree in. - _depth: The current depth of the tree. - This is used to prevent infinite recursion. - Return: 0 on success, or a negative value on error.*/ -static int oc_huff_tree_unpack(oggpack_buffer *_opb, - oc_huff_node **_binode,int _depth){ - oc_huff_node *binode; - long bits; - /*Prevent infinite recursion.*/ - if(++_depth>32)return TH_EBADHEADER; - if(theorapackB_read1(_opb,&bits)<0)return TH_EBADHEADER; - /*Read an internal node:*/ - if(!bits){ - int ret; - binode=oc_huff_node_alloc(1); - binode->depth=(unsigned char)(_depth>1); - ret=oc_huff_tree_unpack(_opb,binode->nodes,_depth); - if(ret>=0)ret=oc_huff_tree_unpack(_opb,binode->nodes+1,_depth); - if(ret<0){ - oc_huff_tree_free(binode); - *_binode=NULL; - return ret; - } - } - /*Read a leaf node:*/ - else{ - if(theorapackB_read(_opb,OC_NDCT_TOKEN_BITS,&bits)<0)return TH_EBADHEADER; - binode=oc_huff_node_alloc(0); - binode->depth=(unsigned char)(_depth>1); - binode->token=(unsigned char)bits; - } - *_binode=binode; - return 0; -} - -/*Finds the depth of shortest branch of the given sub-tree. - The tree must be binary. - _binode: The root of the given sub-tree. - _binode->nbits must be 0 or 1. - Return: The smallest depth of a leaf node in this sub-tree. - 0 indicates this sub-tree is a leaf node.*/ -static int oc_huff_tree_mindepth(oc_huff_node *_binode){ - int depth0; - int depth1; - if(_binode->nbits==0)return 0; - depth0=oc_huff_tree_mindepth(_binode->nodes[0]); - depth1=oc_huff_tree_mindepth(_binode->nodes[1]); - return OC_MINI(depth0,depth1)+1; -} - -/*Finds the number of internal nodes at a given depth, plus the number of - leaves at that depth or shallower. - The tree must be binary. - _binode: The root of the given sub-tree. - _binode->nbits must be 0 or 1. - Return: The number of entries that would be contained in a jump table of the - given depth.*/ -static int oc_huff_tree_occupancy(oc_huff_node *_binode,int _depth){ - if(_binode->nbits==0||_depth<=0)return 1; - else{ - return oc_huff_tree_occupancy(_binode->nodes[0],_depth-1)+ - oc_huff_tree_occupancy(_binode->nodes[1],_depth-1); - } -} - -static oc_huff_node *oc_huff_tree_collapse(oc_huff_node *_binode); - -/*Fills the given nodes table with all the children in the sub-tree at the - given depth. - The nodes in the sub-tree with a depth less than that stored in the table - are freed. - The sub-tree must be binary and complete up until the given depth. - _nodes: The nodes table to fill. - _binode: The root of the sub-tree to fill it with. - _binode->nbits must be 0 or 1. - _level: The current level in the table. - 0 indicates that the current node should be stored, regardless of - whether it is a leaf node or an internal node. - _depth: The depth of the nodes to fill the table with, relative to their - parent.*/ -static void oc_huff_node_fill(oc_huff_node **_nodes, - oc_huff_node *_binode,int _level,int _depth){ - if(_level<=0||_binode->nbits==0){ - int i; - _binode->depth=(unsigned char)(_depth-_level); - _nodes[0]=oc_huff_tree_collapse(_binode); - for(i=1;i<1<<_level;i++)_nodes[i]=_nodes[0]; - } - else{ - _level--; - oc_huff_node_fill(_nodes,_binode->nodes[0],_level,_depth); - oc_huff_node_fill(_nodes+(1<<_level),_binode->nodes[1],_level,_depth); - oc_huff_node_free(_binode); - } -} - -/*Finds the largest complete sub-tree rooted at the current node and collapses - it into a single node. - This procedure is then applied recursively to all the children of that node. - _binode: The root of the sub-tree to collapse. - _binode->nbits must be 0 or 1. - Return: The new root of the collapsed sub-tree.*/ -static oc_huff_node *oc_huff_tree_collapse(oc_huff_node *_binode){ - oc_huff_node *root; - int mindepth; - int depth; - int loccupancy; - int occupancy; - depth=mindepth=oc_huff_tree_mindepth(_binode); - occupancy=1<loccupancy&&occupancy>=1<depth=_binode->depth; - oc_huff_node_fill(root->nodes,_binode,depth,depth); - return root; -} - -/*Makes a copy of the given Huffman tree. - _node: The Huffman tree to copy. - Return: The copy of the Huffman tree.*/ -static oc_huff_node *oc_huff_tree_copy(const oc_huff_node *_node){ - oc_huff_node *ret; - ret=oc_huff_node_alloc(_node->nbits); - ret->depth=_node->depth; - if(_node->nbits){ - int nchildren; - int i; - int inext; - nchildren=1<<_node->nbits; - for(i=0;inodes[i]=oc_huff_tree_copy(_node->nodes[i]); - inext=i+(1<<_node->nbits-ret->nodes[i]->depth); - while(++inodes[i]=ret->nodes[i-1]; - } - } - else ret->token=_node->token; - return ret; -} - -/*Unpacks a set of Huffman trees, and reduces them to a collapsed - representation. - _opb: The buffer to unpack the trees from. - _nodes: The table to fill with the Huffman trees. - Return: 0 on success, or a negative value on error.*/ -int oc_huff_trees_unpack(oggpack_buffer *_opb, - oc_huff_node *_nodes[TH_NHUFFMAN_TABLES]){ - int i; - for(i=0;inbits!=0){ - theorapackB_look(_opb,_node->nbits,&bits); - _node=_node->nodes[bits]; - theorapackB_adv(_opb,_node->depth); - } - return _node->token; -} diff --git a/Engine/lib/libtheora/lib/dec/idct.h b/Engine/lib/libtheora/lib/dec/idct.h deleted file mode 100644 index 3ee53712e..000000000 --- a/Engine/lib/libtheora/lib/dec/idct.h +++ /dev/null @@ -1,26 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: idct.h 15400 2008-10-15 12:10:58Z tterribe $ - - ********************************************************************/ - -/*Inverse DCT transforms.*/ -#include -#if !defined(_idct_H) -# define _idct_H (1) - -void oc_idct8x8_c(ogg_int16_t _y[64],const ogg_int16_t _x[64]); -void oc_idct8x8_10_c(ogg_int16_t _y[64],const ogg_int16_t _x[64]); - -#endif diff --git a/Engine/lib/libtheora/lib/dec/ocintrin.h b/Engine/lib/libtheora/lib/dec/ocintrin.h deleted file mode 100644 index 317f5aeae..000000000 --- a/Engine/lib/libtheora/lib/dec/ocintrin.h +++ /dev/null @@ -1,88 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: ocintrin.h 15400 2008-10-15 12:10:58Z tterribe $ - - ********************************************************************/ - -/*Some common macros for potential platform-specific optimization.*/ -#include -#if !defined(_ocintrin_H) -# define _ocintrin_H (1) - -/*Some specific platforms may have optimized intrinsic or inline assembly - versions of these functions which can substantially improve performance. - We define macros for them to allow easy incorporation of these non-ANSI - features.*/ - -/*Branchless, but not correct for differences larger than INT_MAX. -static int oc_mini(int _a,int _b){ - int ambsign; - ambsign=_a-_b>>sizeof(int)*8-1; - return (_a&~ambsign)+(_b&ambsign); -}*/ - - -#define OC_MAXI(_a,_b) ((_a)<(_b)?(_b):(_a)) -#define OC_MINI(_a,_b) ((_a)>(_b)?(_b):(_a)) -/*Clamps an integer into the given range. - If _a>_c, then the lower bound _a is respected over the upper bound _c (this - behavior is required to meet our documented API behavior). - _a: The lower bound. - _b: The value to clamp. - _c: The upper boud.*/ -#define OC_CLAMPI(_a,_b,_c) (OC_MAXI(_a,OC_MINI(_b,_c))) -#define OC_CLAMP255(_x) ((unsigned char)((((_x)<0)-1)&((_x)|-((_x)>255)))) -/*Divides an integer by a power of two, truncating towards 0. - _dividend: The integer to divide. - _shift: The non-negative power of two to divide by. - _rmask: (1<<_shift)-1*/ -#define OC_DIV_POW2(_dividend,_shift,_rmask)\ - ((_dividend)+(((_dividend)>>sizeof(_dividend)*8-1)&(_rmask))>>(_shift)) -/*Divides _x by 65536, truncating towards 0.*/ -#define OC_DIV2_16(_x) OC_DIV_POW2(_x,16,0xFFFF) -/*Divides _x by 2, truncating towards 0.*/ -#define OC_DIV2(_x) OC_DIV_POW2(_x,1,0x1) -/*Divides _x by 8, truncating towards 0.*/ -#define OC_DIV8(_x) OC_DIV_POW2(_x,3,0x7) -/*Divides _x by 16, truncating towards 0.*/ -#define OC_DIV16(_x) OC_DIV_POW2(_x,4,0xF) -/*Right shifts _dividend by _shift, adding _rval, and subtracting one for - negative dividends first.. - When _rval is (1<<_shift-1), this is equivalent to division with rounding - ties towards positive infinity.*/ -#define OC_DIV_ROUND_POW2(_dividend,_shift,_rval)\ - ((_dividend)+((_dividend)>>sizeof(_dividend)*8-1)+(_rval)>>(_shift)) -/*Swaps two integers _a and _b if _a>_b.*/ -#define OC_SORT2I(_a,_b)\ - if((_a)>(_b)){\ - int t__;\ - t__=(_a);\ - (_a)=(_b);\ - (_b)=t__;\ - } - - - -/*All of these macros should expect floats as arguments.*/ -#define OC_MAXF(_a,_b) ((_a)<(_b)?(_b):(_a)) -#define OC_MINF(_a,_b) ((_a)>(_b)?(_b):(_a)) -#define OC_CLAMPF(_a,_b,_c) (OC_MINF(_a,OC_MAXF(_b,_c))) -#define OC_FABSF(_f) ((float)fabs(_f)) -#define OC_SQRTF(_f) ((float)sqrt(_f)) -#define OC_POWF(_b,_e) ((float)pow(_b,_e)) -#define OC_LOGF(_f) ((float)log(_f)) -#define OC_IFLOORF(_f) ((int)floor(_f)) -#define OC_ICEILF(_f) ((int)ceil(_f)) - -#endif diff --git a/Engine/lib/libtheora/lib/dec/quant.c b/Engine/lib/libtheora/lib/dec/quant.c deleted file mode 100644 index 5cb7784db..000000000 --- a/Engine/lib/libtheora/lib/dec/quant.c +++ /dev/null @@ -1,122 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: quant.c 15400 2008-10-15 12:10:58Z tterribe $ - - ********************************************************************/ - -#include -#include -#include -#include "quant.h" -#include "decint.h" - -static const unsigned OC_DC_QUANT_MIN[2]={4<<2,8<<2}; -static const unsigned OC_AC_QUANT_MIN[2]={2<<2,4<<2}; - -/*Initializes the dequantization tables from a set of quantizer info. - Currently the dequantizer (and elsewhere enquantizer) tables are expected to - be initialized as pointing to the storage reserved for them in the - oc_theora_state (resp. oc_enc_ctx) structure. - If some tables are duplicates of others, the pointers will be adjusted to - point to a single copy of the tables, but the storage for them will not be - freed. - If you're concerned about the memory footprint, the obvious thing to do is - to move the storage out of its fixed place in the structures and allocate - it on demand. - However, a much, much better option is to only store the quantization - matrices being used for the current frame, and to recalculate these as the - qi values change between frames (this is what VP3 did).*/ -void oc_dequant_tables_init(oc_quant_table *_dequant[2][3], - int _pp_dc_scale[64],const th_quant_info *_qinfo){ - /*coding mode: intra or inter.*/ - int qti; - /*Y', C_b, C_r*/ - int pli; - for(qti=0;qti<2;qti++){ - for(pli=0;pli<3;pli++){ - oc_quant_tables stage; - /*Quality index.*/ - int qi; - /*Range iterator.*/ - int qri; - for(qi=0,qri=0; qri<=_qinfo->qi_ranges[qti][pli].nranges; qri++){ - th_quant_base base; - ogg_uint32_t q; - int qi_start; - int qi_end; - int ci; - memcpy(base,_qinfo->qi_ranges[qti][pli].base_matrices[qri], - sizeof(base)); - qi_start=qi; - if(qri==_qinfo->qi_ranges[qti][pli].nranges)qi_end=qi+1; - else qi_end=qi+_qinfo->qi_ranges[qti][pli].sizes[qri]; - /*Iterate over quality indicies in this range.*/ - for(;;){ - ogg_uint32_t qfac; - /*In the original VP3.2 code, the rounding offset and the size of the - dead zone around 0 were controlled by a "sharpness" parameter. - The size of our dead zone is now controlled by the per-coefficient - quality thresholds returned by our HVS module. - We round down from a more accurate value when the quality of the - reconstruction does not fall below our threshold and it saves bits. - Hence, all of that VP3.2 code is gone from here, and the remaining - floating point code has been implemented as equivalent integer code - with exact precision.*/ - qfac=(ogg_uint32_t)_qinfo->dc_scale[qi]*base[0]; - /*For postprocessing, not dequantization.*/ - if(_pp_dc_scale!=NULL)_pp_dc_scale[qi]=(int)(qfac/160); - /*Scale DC the coefficient from the proper table.*/ - q=(qfac/100)<<2; - q=OC_CLAMPI(OC_DC_QUANT_MIN[qti],q,OC_QUANT_MAX); - stage[qi][0]=(ogg_uint16_t)q; - /*Now scale AC coefficients from the proper table.*/ - for(ci=1;ci<64;ci++){ - q=((ogg_uint32_t)_qinfo->ac_scale[qi]*base[ci]/100)<<2; - q=OC_CLAMPI(OC_AC_QUANT_MIN[qti],q,OC_QUANT_MAX); - stage[qi][ci]=(ogg_uint16_t)q; - } - if(++qi>=qi_end)break; - /*Interpolate the next base matrix.*/ - for(ci=0;ci<64;ci++){ - base[ci]=(unsigned char)( - (2*((qi_end-qi)*_qinfo->qi_ranges[qti][pli].base_matrices[qri][ci]+ - (qi-qi_start)*_qinfo->qi_ranges[qti][pli].base_matrices[qri+1][ci]) - +_qinfo->qi_ranges[qti][pli].sizes[qri])/ - (2*_qinfo->qi_ranges[qti][pli].sizes[qri])); - } - } - } - /*Staging matrices complete; commit to memory only if this isn't a - duplicate of a preceeding plane. - This simple check helps us improve cache coherency later.*/ - { - int dupe; - int qtj; - int plj; - dupe=0; - for(qtj=0;qtj<=qti;qtj++){ - for(plj=0;plj<(qtj - -#if defined(USE_ASM) - -static const __attribute__((aligned(8),used)) int OC_FZIG_ZAGMMX[64]={ - 0, 8, 1, 2, 9,16,24,17, - 10, 3,32,11,18,25, 4,12, - 5,26,19,40,33,34,41,48, - 27, 6,13,20,28,21,14, 7, - 56,49,42,35,43,50,57,36, - 15,22,29,30,23,44,37,58, - 51,59,38,45,52,31,60,53, - 46,39,47,54,61,62,55,63 -}; - - - -void oc_state_frag_recon_mmx(oc_theora_state *_state,oc_fragment *_frag, - int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,int _ncoefs, - ogg_uint16_t _dc_iquant,const ogg_uint16_t _ac_iquant[64]){ - ogg_int16_t __attribute__((aligned(8))) res_buf[64]; - int dst_framei; - int dst_ystride; - int zzi; - /*_last_zzi is subtly different from an actual count of the number of - coefficients we decoded for this block. - It contains the value of zzi BEFORE the final token in the block was - decoded. - In most cases this is an EOB token (the continuation of an EOB run from a - previous block counts), and so this is the same as the coefficient count. - However, in the case that the last token was NOT an EOB token, but filled - the block up with exactly 64 coefficients, _last_zzi will be less than 64. - Provided the last token was not a pure zero run, the minimum value it can - be is 46, and so that doesn't affect any of the cases in this routine. - However, if the last token WAS a pure zero run of length 63, then _last_zzi - will be 1 while the number of coefficients decoded is 64. - Thus, we will trigger the following special case, where the real - coefficient count would not. - Note also that a zero run of length 64 will give _last_zzi a value of 0, - but we still process the DC coefficient, which might have a non-zero value - due to DC prediction. - Although convoluted, this is arguably the correct behavior: it allows us to - dequantize fewer coefficients and use a smaller transform when the block - ends with a long zero run instead of a normal EOB token. - It could be smarter... multiple separate zero runs at the end of a block - will fool it, but an encoder that generates these really deserves what it - gets. - Needless to say we inherited this approach from VP3.*/ - /*Special case only having a DC component.*/ - if(_last_zzi<2){ - ogg_uint16_t p; - /*Why is the iquant product rounded in this case and no others? - Who knows.*/ - p=(ogg_int16_t)((ogg_int32_t)_frag->dc*_dc_iquant+15>>5); - /*Fill res_buf with p.*/ - __asm__ __volatile__( - /*mm0=0000 0000 0000 AAAA*/ - "movd %[p],%%mm0\n\t" - /*mm1=0000 0000 0000 AAAA*/ - "movd %[p],%%mm1\n\t" - /*mm0=0000 0000 AAAA 0000*/ - "pslld $16,%%mm0\n\t" - /*mm0=0000 0000 AAAA AAAA*/ - "por %%mm1,%%mm0\n\t" - /*mm0=AAAA AAAA AAAA AAAA*/ - "punpcklwd %%mm0,%%mm0\n\t" - "movq %%mm0,(%[res_buf])\n\t" - "movq %%mm0,8(%[res_buf])\n\t" - "movq %%mm0,16(%[res_buf])\n\t" - "movq %%mm0,24(%[res_buf])\n\t" - "movq %%mm0,32(%[res_buf])\n\t" - "movq %%mm0,40(%[res_buf])\n\t" - "movq %%mm0,48(%[res_buf])\n\t" - "movq %%mm0,56(%[res_buf])\n\t" - "movq %%mm0,64(%[res_buf])\n\t" - "movq %%mm0,72(%[res_buf])\n\t" - "movq %%mm0,80(%[res_buf])\n\t" - "movq %%mm0,88(%[res_buf])\n\t" - "movq %%mm0,96(%[res_buf])\n\t" - "movq %%mm0,104(%[res_buf])\n\t" - "movq %%mm0,112(%[res_buf])\n\t" - "movq %%mm0,120(%[res_buf])\n\t" - : - :[res_buf]"r"(res_buf),[p]"r"((unsigned)p) - :"memory" - ); - } - else{ - /*Then, fill in the remainder of the coefficients with 0's, and perform - the iDCT.*/ - /*First zero the buffer.*/ - /*On K7, etc., this could be replaced with movntq and sfence.*/ - __asm__ __volatile__( - "pxor %%mm0,%%mm0\n\t" - "movq %%mm0,(%[res_buf])\n\t" - "movq %%mm0,8(%[res_buf])\n\t" - "movq %%mm0,16(%[res_buf])\n\t" - "movq %%mm0,24(%[res_buf])\n\t" - "movq %%mm0,32(%[res_buf])\n\t" - "movq %%mm0,40(%[res_buf])\n\t" - "movq %%mm0,48(%[res_buf])\n\t" - "movq %%mm0,56(%[res_buf])\n\t" - "movq %%mm0,64(%[res_buf])\n\t" - "movq %%mm0,72(%[res_buf])\n\t" - "movq %%mm0,80(%[res_buf])\n\t" - "movq %%mm0,88(%[res_buf])\n\t" - "movq %%mm0,96(%[res_buf])\n\t" - "movq %%mm0,104(%[res_buf])\n\t" - "movq %%mm0,112(%[res_buf])\n\t" - "movq %%mm0,120(%[res_buf])\n\t" - : - :[res_buf]"r"(res_buf) - :"memory" - ); - res_buf[0]=(ogg_int16_t)((ogg_int32_t)_frag->dc*_dc_iquant); - /*This is planned to be rewritten in MMX.*/ - for(zzi=1;zzi<_ncoefs;zzi++){ - int ci; - ci=OC_FZIG_ZAG[zzi]; - res_buf[OC_FZIG_ZAGMMX[zzi]]=(ogg_int16_t)((ogg_int32_t)_dct_coeffs[zzi]* - _ac_iquant[ci]); - } - if(_last_zzi<10)oc_idct8x8_10_mmx(res_buf); - else oc_idct8x8_mmx(res_buf); - } - /*Fill in the target buffer.*/ - dst_framei=_state->ref_frame_idx[OC_FRAME_SELF]; - dst_ystride=_state->ref_frame_bufs[dst_framei][_pli].stride; - /*For now ystride values in all ref frames assumed to be equal.*/ - if(_frag->mbmode==OC_MODE_INTRA){ - oc_frag_recon_intra_mmx(_frag->buffer[dst_framei],dst_ystride,res_buf); - } - else{ - int ref_framei; - int ref_ystride; - int mvoffsets[2]; - ref_framei=_state->ref_frame_idx[OC_FRAME_FOR_MODE[_frag->mbmode]]; - ref_ystride=_state->ref_frame_bufs[ref_framei][_pli].stride; - if(oc_state_get_mv_offsets(_state,mvoffsets,_frag->mv[0],_frag->mv[1], - ref_ystride,_pli)>1){ - oc_frag_recon_inter2_mmx(_frag->buffer[dst_framei],dst_ystride, - _frag->buffer[ref_framei]+mvoffsets[0],ref_ystride, - _frag->buffer[ref_framei]+mvoffsets[1],ref_ystride,res_buf); - } - else{ - oc_frag_recon_inter_mmx(_frag->buffer[dst_framei],dst_ystride, - _frag->buffer[ref_framei]+mvoffsets[0],ref_ystride,res_buf); - } - } - oc_restore_fpu(_state); -} - -/*Copies the fragments specified by the lists of fragment indices from one - frame to another. - _fragis: A pointer to a list of fragment indices. - _nfragis: The number of fragment indices to copy. - _dst_frame: The reference frame to copy to. - _src_frame: The reference frame to copy from. - _pli: The color plane the fragments lie in.*/ -void oc_state_frag_copy_mmx(const oc_theora_state *_state,const int *_fragis, - int _nfragis,int _dst_frame,int _src_frame,int _pli){ - const int *fragi; - const int *fragi_end; - int dst_framei; - ptrdiff_t dst_ystride; - int src_framei; - ptrdiff_t src_ystride; - dst_framei=_state->ref_frame_idx[_dst_frame]; - src_framei=_state->ref_frame_idx[_src_frame]; - dst_ystride=_state->ref_frame_bufs[dst_framei][_pli].stride; - src_ystride=_state->ref_frame_bufs[src_framei][_pli].stride; - fragi_end=_fragis+_nfragis; - for(fragi=_fragis;fragifrags+*fragi; - dst=frag->buffer[dst_framei]; - src=frag->buffer[src_framei]; - __asm__ __volatile__( - /*src+0*src_ystride*/ - "movq (%[src]),%%mm0\n\t" - /*s=src_ystride*3*/ - "lea (%[src_ystride],%[src_ystride],2),%[s]\n\t" - /*src+1*src_ystride*/ - "movq (%[src],%[src_ystride]),%%mm1\n\t" - /*src+2*src_ystride*/ - "movq (%[src],%[src_ystride],2),%%mm2\n\t" - /*src+3*src_ystride*/ - "movq (%[src],%[s]),%%mm3\n\t" - /*dst+0*dst_ystride*/ - "movq %%mm0,(%[dst])\n\t" - /*s=dst_ystride*3*/ - "lea (%[dst_ystride],%[dst_ystride],2),%[s]\n\t" - /*dst+1*dst_ystride*/ - "movq %%mm1,(%[dst],%[dst_ystride])\n\t" - /*Pointer to next 4.*/ - "lea (%[src],%[src_ystride],4),%[src]\n\t" - /*dst+2*dst_ystride*/ - "movq %%mm2,(%[dst],%[dst_ystride],2)\n\t" - /*dst+3*dst_ystride*/ - "movq %%mm3,(%[dst],%[s])\n\t" - /*Pointer to next 4.*/ - "lea (%[dst],%[dst_ystride],4),%[dst]\n\t" - /*src+0*src_ystride*/ - "movq (%[src]),%%mm0\n\t" - /*s=src_ystride*3*/ - "lea (%[src_ystride],%[src_ystride],2),%[s]\n\t" - /*src+1*src_ystride*/ - "movq (%[src],%[src_ystride]),%%mm1\n\t" - /*src+2*src_ystride*/ - "movq (%[src],%[src_ystride],2),%%mm2\n\t" - /*src+3*src_ystride*/ - "movq (%[src],%[s]),%%mm3\n\t" - /*dst+0*dst_ystride*/ - "movq %%mm0,(%[dst])\n\t" - /*s=dst_ystride*3*/ - "lea (%[dst_ystride],%[dst_ystride],2),%[s]\n\t" - /*dst+1*dst_ystride*/ - "movq %%mm1,(%[dst],%[dst_ystride])\n\t" - /*dst+2*dst_ystride*/ - "movq %%mm2,(%[dst],%[dst_ystride],2)\n\t" - /*dst+3*dst_ystride*/ - "movq %%mm3,(%[dst],%[s])\n\t" - :[s]"=&r"(s) - :[dst]"r"(dst),[src]"r"(src),[dst_ystride]"r"(dst_ystride), - [src_ystride]"r"(src_ystride) - :"memory" - ); - } - /*This needs to be removed when decode specific functions are implemented:*/ - __asm__ __volatile__("emms\n\t"); -} - -static void loop_filter_v(unsigned char *_pix,int _ystride, - const ogg_int16_t *_ll){ - ptrdiff_t s; - _pix-=_ystride*2; - __asm__ __volatile__( - /*mm0=0*/ - "pxor %%mm0,%%mm0\n\t" - /*s=_ystride*3*/ - "lea (%[ystride],%[ystride],2),%[s]\n\t" - /*mm7=_pix[0...8]*/ - "movq (%[pix]),%%mm7\n\t" - /*mm4=_pix[0...8+_ystride*3]*/ - "movq (%[pix],%[s]),%%mm4\n\t" - /*mm6=_pix[0...8]*/ - "movq %%mm7,%%mm6\n\t" - /*Expand unsigned _pix[0...3] to 16 bits.*/ - "punpcklbw %%mm0,%%mm6\n\t" - "movq %%mm4,%%mm5\n\t" - /*Expand unsigned _pix[4...8] to 16 bits.*/ - "punpckhbw %%mm0,%%mm7\n\t" - /*Expand other arrays too.*/ - "punpcklbw %%mm0,%%mm4\n\t" - "punpckhbw %%mm0,%%mm5\n\t" - /*mm7:mm6=_p[0...8]-_p[0...8+_ystride*3]:*/ - "psubw %%mm4,%%mm6\n\t" - "psubw %%mm5,%%mm7\n\t" - /*mm5=mm4=_pix[0...8+_ystride]*/ - "movq (%[pix],%[ystride]),%%mm4\n\t" - /*mm1=mm3=mm2=_pix[0..8]+_ystride*2]*/ - "movq (%[pix],%[ystride],2),%%mm2\n\t" - "movq %%mm4,%%mm5\n\t" - "movq %%mm2,%%mm3\n\t" - "movq %%mm2,%%mm1\n\t" - /*Expand these arrays.*/ - "punpckhbw %%mm0,%%mm5\n\t" - "punpcklbw %%mm0,%%mm4\n\t" - "punpckhbw %%mm0,%%mm3\n\t" - "punpcklbw %%mm0,%%mm2\n\t" - /*mm0=3 3 3 3 - mm3:mm2=_pix[0...8+_ystride*2]-_pix[0...8+_ystride]*/ - "pcmpeqw %%mm0,%%mm0\n\t" - "psubw %%mm5,%%mm3\n\t" - "psrlw $14,%%mm0\n\t" - "psubw %%mm4,%%mm2\n\t" - /*Scale by 3.*/ - "pmullw %%mm0,%%mm3\n\t" - "pmullw %%mm0,%%mm2\n\t" - /*mm0=4 4 4 4 - f=mm3:mm2==_pix[0...8]-_pix[0...8+_ystride*3]+ - 3*(_pix[0...8+_ystride*2]-_pix[0...8+_ystride])*/ - "psrlw $1,%%mm0\n\t" - "paddw %%mm7,%%mm3\n\t" - "psllw $2,%%mm0\n\t" - "paddw %%mm6,%%mm2\n\t" - /*Add 4.*/ - "paddw %%mm0,%%mm3\n\t" - "paddw %%mm0,%%mm2\n\t" - /*"Divide" by 8.*/ - "psraw $3,%%mm3\n\t" - "psraw $3,%%mm2\n\t" - /*Now compute lflim of mm3:mm2 cf. Section 7.10 of the sepc.*/ - /*Free up mm5.*/ - "packuswb %%mm5,%%mm4\n\t" - /*mm0=L L L L*/ - "movq (%[ll]),%%mm0\n\t" - /*if(R_i<-2L||R_i>2L)R_i=0:*/ - "movq %%mm2,%%mm5\n\t" - "pxor %%mm6,%%mm6\n\t" - "movq %%mm0,%%mm7\n\t" - "psubw %%mm0,%%mm6\n\t" - "psllw $1,%%mm7\n\t" - "psllw $1,%%mm6\n\t" - /*mm2==R_3 R_2 R_1 R_0*/ - /*mm5==R_3 R_2 R_1 R_0*/ - /*mm6==-2L -2L -2L -2L*/ - /*mm7==2L 2L 2L 2L*/ - "pcmpgtw %%mm2,%%mm7\n\t" - "pcmpgtw %%mm6,%%mm5\n\t" - "pand %%mm7,%%mm2\n\t" - "movq %%mm0,%%mm7\n\t" - "pand %%mm5,%%mm2\n\t" - "psllw $1,%%mm7\n\t" - "movq %%mm3,%%mm5\n\t" - /*mm3==R_7 R_6 R_5 R_4*/ - /*mm5==R_7 R_6 R_5 R_4*/ - /*mm6==-2L -2L -2L -2L*/ - /*mm7==2L 2L 2L 2L*/ - "pcmpgtw %%mm3,%%mm7\n\t" - "pcmpgtw %%mm6,%%mm5\n\t" - "pand %%mm7,%%mm3\n\t" - "movq %%mm0,%%mm7\n\t" - "pand %%mm5,%%mm3\n\t" - /*if(R_i<-L)R_i'=R_i+2L; - if(R_i>L)R_i'=R_i-2L; - if(R_i<-L||R_i>L)R_i=-R_i':*/ - "psraw $1,%%mm6\n\t" - "movq %%mm2,%%mm5\n\t" - "psllw $1,%%mm7\n\t" - /*mm2==R_3 R_2 R_1 R_0*/ - /*mm5==R_3 R_2 R_1 R_0*/ - /*mm6==-L -L -L -L*/ - /*mm0==L L L L*/ - /*mm5=R_i>L?FF:00*/ - "pcmpgtw %%mm0,%%mm5\n\t" - /*mm6=-L>R_i?FF:00*/ - "pcmpgtw %%mm2,%%mm6\n\t" - /*mm7=R_i>L?2L:0*/ - "pand %%mm5,%%mm7\n\t" - /*mm2=R_i>L?R_i-2L:R_i*/ - "psubw %%mm7,%%mm2\n\t" - "movq %%mm0,%%mm7\n\t" - /*mm5=-L>R_i||R_i>L*/ - "por %%mm6,%%mm5\n\t" - "psllw $1,%%mm7\n\t" - /*mm7=-L>R_i?2L:0*/ - "pand %%mm6,%%mm7\n\t" - "pxor %%mm6,%%mm6\n\t" - /*mm2=-L>R_i?R_i+2L:R_i*/ - "paddw %%mm7,%%mm2\n\t" - "psubw %%mm0,%%mm6\n\t" - /*mm5=-L>R_i||R_i>L?-R_i':0*/ - "pand %%mm2,%%mm5\n\t" - "movq %%mm0,%%mm7\n\t" - /*mm2=-L>R_i||R_i>L?0:R_i*/ - "psubw %%mm5,%%mm2\n\t" - "psllw $1,%%mm7\n\t" - /*mm2=-L>R_i||R_i>L?-R_i':R_i*/ - "psubw %%mm5,%%mm2\n\t" - "movq %%mm3,%%mm5\n\t" - /*mm3==R_7 R_6 R_5 R_4*/ - /*mm5==R_7 R_6 R_5 R_4*/ - /*mm6==-L -L -L -L*/ - /*mm0==L L L L*/ - /*mm6=-L>R_i?FF:00*/ - "pcmpgtw %%mm3,%%mm6\n\t" - /*mm5=R_i>L?FF:00*/ - "pcmpgtw %%mm0,%%mm5\n\t" - /*mm7=R_i>L?2L:0*/ - "pand %%mm5,%%mm7\n\t" - /*mm2=R_i>L?R_i-2L:R_i*/ - "psubw %%mm7,%%mm3\n\t" - "psllw $1,%%mm0\n\t" - /*mm5=-L>R_i||R_i>L*/ - "por %%mm6,%%mm5\n\t" - /*mm0=-L>R_i?2L:0*/ - "pand %%mm6,%%mm0\n\t" - /*mm3=-L>R_i?R_i+2L:R_i*/ - "paddw %%mm0,%%mm3\n\t" - /*mm5=-L>R_i||R_i>L?-R_i':0*/ - "pand %%mm3,%%mm5\n\t" - /*mm2=-L>R_i||R_i>L?0:R_i*/ - "psubw %%mm5,%%mm3\n\t" - /*mm2=-L>R_i||R_i>L?-R_i':R_i*/ - "psubw %%mm5,%%mm3\n\t" - /*Unfortunately, there's no unsigned byte+signed byte with unsigned - saturation op code, so we have to promote things back 16 bits.*/ - "pxor %%mm0,%%mm0\n\t" - "movq %%mm4,%%mm5\n\t" - "punpcklbw %%mm0,%%mm4\n\t" - "punpckhbw %%mm0,%%mm5\n\t" - "movq %%mm1,%%mm6\n\t" - "punpcklbw %%mm0,%%mm1\n\t" - "punpckhbw %%mm0,%%mm6\n\t" - /*_pix[0...8+_ystride]+=R_i*/ - "paddw %%mm2,%%mm4\n\t" - "paddw %%mm3,%%mm5\n\t" - /*_pix[0...8+_ystride*2]-=R_i*/ - "psubw %%mm2,%%mm1\n\t" - "psubw %%mm3,%%mm6\n\t" - "packuswb %%mm5,%%mm4\n\t" - "packuswb %%mm6,%%mm1\n\t" - /*Write it back out.*/ - "movq %%mm4,(%[pix],%[ystride])\n\t" - "movq %%mm1,(%[pix],%[ystride],2)\n\t" - :[s]"=&r"(s) - :[pix]"r"(_pix),[ystride]"r"((ptrdiff_t)_ystride),[ll]"r"(_ll) - :"memory" - ); -} - -/*This code implements the bulk of loop_filter_h(). - Data are striped p0 p1 p2 p3 ... p0 p1 p2 p3 ..., so in order to load all - four p0's to one register we must transpose the values in four mmx regs. - When half is done we repeat this for the rest.*/ -static void loop_filter_h4(unsigned char *_pix,ptrdiff_t _ystride, - const ogg_int16_t *_ll){ - ptrdiff_t s; - /*d doesn't technically need to be 64-bit on x86-64, but making it so will - help avoid partial register stalls.*/ - ptrdiff_t d; - __asm__ __volatile__( - /*x x x x 3 2 1 0*/ - "movd (%[pix]),%%mm0\n\t" - /*s=_ystride*3*/ - "lea (%[ystride],%[ystride],2),%[s]\n\t" - /*x x x x 7 6 5 4*/ - "movd (%[pix],%[ystride]),%%mm1\n\t" - /*x x x x B A 9 8*/ - "movd (%[pix],%[ystride],2),%%mm2\n\t" - /*x x x x F E D C*/ - "movd (%[pix],%[s]),%%mm3\n\t" - /*mm0=7 3 6 2 5 1 4 0*/ - "punpcklbw %%mm1,%%mm0\n\t" - /*mm2=F B E A D 9 C 8*/ - "punpcklbw %%mm3,%%mm2\n\t" - /*mm1=7 3 6 2 5 1 4 0*/ - "movq %%mm0,%%mm1\n\t" - /*mm0=F B 7 3 E A 6 2*/ - "punpckhwd %%mm2,%%mm0\n\t" - /*mm1=D 9 5 1 C 8 4 0*/ - "punpcklwd %%mm2,%%mm1\n\t" - "pxor %%mm7,%%mm7\n\t" - /*mm5=D 9 5 1 C 8 4 0*/ - "movq %%mm1,%%mm5\n\t" - /*mm1=x C x 8 x 4 x 0==pix[0]*/ - "punpcklbw %%mm7,%%mm1\n\t" - /*mm5=x D x 9 x 5 x 1==pix[1]*/ - "punpckhbw %%mm7,%%mm5\n\t" - /*mm3=F B 7 3 E A 6 2*/ - "movq %%mm0,%%mm3\n\t" - /*mm0=x E x A x 6 x 2==pix[2]*/ - "punpcklbw %%mm7,%%mm0\n\t" - /*mm3=x F x B x 7 x 3==pix[3]*/ - "punpckhbw %%mm7,%%mm3\n\t" - /*mm1=mm1-mm3==pix[0]-pix[3]*/ - "psubw %%mm3,%%mm1\n\t" - /*Save a copy of pix[2] for later.*/ - "movq %%mm0,%%mm4\n\t" - /*mm2=3 3 3 3 - mm0=mm0-mm5==pix[2]-pix[1]*/ - "pcmpeqw %%mm2,%%mm2\n\t" - "psubw %%mm5,%%mm0\n\t" - "psrlw $14,%%mm2\n\t" - /*Scale by 3.*/ - "pmullw %%mm2,%%mm0\n\t" - /*mm2=4 4 4 4 - f=mm1==_pix[0]-_pix[3]+ 3*(_pix[2]-_pix[1])*/ - "psrlw $1,%%mm2\n\t" - "paddw %%mm1,%%mm0\n\t" - "psllw $2,%%mm2\n\t" - /*Add 4.*/ - "paddw %%mm2,%%mm0\n\t" - /*"Divide" by 8, producing the residuals R_i.*/ - "psraw $3,%%mm0\n\t" - /*Now compute lflim of mm0 cf. Section 7.10 of the sepc.*/ - /*mm6=L L L L*/ - "movq (%[ll]),%%mm6\n\t" - /*if(R_i<-2L||R_i>2L)R_i=0:*/ - "movq %%mm0,%%mm1\n\t" - "pxor %%mm2,%%mm2\n\t" - "movq %%mm6,%%mm3\n\t" - "psubw %%mm6,%%mm2\n\t" - "psllw $1,%%mm3\n\t" - "psllw $1,%%mm2\n\t" - /*mm0==R_3 R_2 R_1 R_0*/ - /*mm1==R_3 R_2 R_1 R_0*/ - /*mm2==-2L -2L -2L -2L*/ - /*mm3==2L 2L 2L 2L*/ - "pcmpgtw %%mm0,%%mm3\n\t" - "pcmpgtw %%mm2,%%mm1\n\t" - "pand %%mm3,%%mm0\n\t" - "pand %%mm1,%%mm0\n\t" - /*if(R_i<-L)R_i'=R_i+2L; - if(R_i>L)R_i'=R_i-2L; - if(R_i<-L||R_i>L)R_i=-R_i':*/ - "psraw $1,%%mm2\n\t" - "movq %%mm0,%%mm1\n\t" - "movq %%mm6,%%mm3\n\t" - /*mm0==R_3 R_2 R_1 R_0*/ - /*mm1==R_3 R_2 R_1 R_0*/ - /*mm2==-L -L -L -L*/ - /*mm6==L L L L*/ - /*mm2=-L>R_i?FF:00*/ - "pcmpgtw %%mm0,%%mm2\n\t" - /*mm1=R_i>L?FF:00*/ - "pcmpgtw %%mm6,%%mm1\n\t" - /*mm3=2L 2L 2L 2L*/ - "psllw $1,%%mm3\n\t" - /*mm6=2L 2L 2L 2L*/ - "psllw $1,%%mm6\n\t" - /*mm3=R_i>L?2L:0*/ - "pand %%mm1,%%mm3\n\t" - /*mm6=-L>R_i?2L:0*/ - "pand %%mm2,%%mm6\n\t" - /*mm0=R_i>L?R_i-2L:R_i*/ - "psubw %%mm3,%%mm0\n\t" - /*mm1=-L>R_i||R_i>L*/ - "por %%mm2,%%mm1\n\t" - /*mm0=-L>R_i?R_i+2L:R_i*/ - "paddw %%mm6,%%mm0\n\t" - /*mm1=-L>R_i||R_i>L?R_i':0*/ - "pand %%mm0,%%mm1\n\t" - /*mm0=-L>R_i||R_i>L?0:R_i*/ - "psubw %%mm1,%%mm0\n\t" - /*mm0=-L>R_i||R_i>L?-R_i':R_i*/ - "psubw %%mm1,%%mm0\n\t" - /*_pix[1]+=R_i;*/ - "paddw %%mm0,%%mm5\n\t" - /*_pix[2]-=R_i;*/ - "psubw %%mm0,%%mm4\n\t" - /*mm5=x x x x D 9 5 1*/ - "packuswb %%mm7,%%mm5\n\t" - /*mm4=x x x x E A 6 2*/ - "packuswb %%mm7,%%mm4\n\t" - /*mm5=E D A 9 6 5 2 1*/ - "punpcklbw %%mm4,%%mm5\n\t" - /*d=6 5 2 1*/ - "movd %%mm5,%[d]\n\t" - "movw %w[d],1(%[pix])\n\t" - /*Why is there such a big stall here?*/ - "psrlq $32,%%mm5\n\t" - "shr $16,%[d]\n\t" - "movw %w[d],1(%[pix],%[ystride])\n\t" - /*d=E D A 9*/ - "movd %%mm5,%[d]\n\t" - "movw %w[d],1(%[pix],%[ystride],2)\n\t" - "shr $16,%[d]\n\t" - "movw %w[d],1(%[pix],%[s])\n\t" - :[s]"=&r"(s),[d]"=&r"(d), - [pix]"+r"(_pix),[ystride]"+r"(_ystride),[ll]"+r"(_ll) - : - :"memory" - ); -} - -static void loop_filter_h(unsigned char *_pix,int _ystride, - const ogg_int16_t *_ll){ - _pix-=2; - loop_filter_h4(_pix,_ystride,_ll); - loop_filter_h4(_pix+(_ystride<<2),_ystride,_ll); -} - -/*We copy the whole function because the MMX routines will be inlined 4 times, - and we can do just a single emms call at the end this way. - We also do not use the _bv lookup table, instead computing the values that - would lie in it on the fly.*/ - -/*Apply the loop filter to a given set of fragment rows in the given plane. - The filter may be run on the bottom edge, affecting pixels in the next row of - fragments, so this row also needs to be available. - _bv: The bounding values array. - _refi: The index of the frame buffer to filter. - _pli: The color plane to filter. - _fragy0: The Y coordinate of the first fragment row to filter. - _fragy_end: The Y coordinate of the fragment row to stop filtering at.*/ -void oc_state_loop_filter_frag_rows_mmx(oc_theora_state *_state,int *_bv, - int _refi,int _pli,int _fragy0,int _fragy_end){ - ogg_int16_t __attribute__((aligned(8))) ll[4]; - th_img_plane *iplane; - oc_fragment_plane *fplane; - oc_fragment *frag_top; - oc_fragment *frag0; - oc_fragment *frag; - oc_fragment *frag_end; - oc_fragment *frag0_end; - oc_fragment *frag_bot; - ll[0]=ll[1]=ll[2]=ll[3]= - (ogg_int16_t)_state->loop_filter_limits[_state->qis[0]]; - iplane=_state->ref_frame_bufs[_refi]+_pli; - fplane=_state->fplanes+_pli; - /*The following loops are constructed somewhat non-intuitively on purpose. - The main idea is: if a block boundary has at least one coded fragment on - it, the filter is applied to it. - However, the order that the filters are applied in matters, and VP3 chose - the somewhat strange ordering used below.*/ - frag_top=_state->frags+fplane->froffset; - frag0=frag_top+_fragy0*fplane->nhfrags; - frag0_end=frag0+(_fragy_end-_fragy0)*fplane->nhfrags; - frag_bot=_state->frags+fplane->froffset+fplane->nfrags; - while(frag0nhfrags; - while(fragcoded){ - if(frag>frag0){ - loop_filter_h(frag->buffer[_refi],iplane->stride,ll); - } - if(frag0>frag_top){ - loop_filter_v(frag->buffer[_refi],iplane->stride,ll); - } - if(frag+1coded){ - loop_filter_h(frag->buffer[_refi]+8,iplane->stride,ll); - } - if(frag+fplane->nhfragsnhfrags)->coded){ - loop_filter_v((frag+fplane->nhfrags)->buffer[_refi], - iplane->stride,ll); - } - } - frag++; - } - frag0+=fplane->nhfrags; - } - /*This needs to be removed when decode specific functions are implemented:*/ - __asm__ __volatile__("emms\n\t"); -} - -#endif diff --git a/Engine/lib/libtheora/lib/dec/x86/x86int.h b/Engine/lib/libtheora/lib/dec/x86/x86int.h deleted file mode 100644 index 05f9c57c1..000000000 --- a/Engine/lib/libtheora/lib/dec/x86/x86int.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: x86int.h 15400 2008-10-15 12:10:58Z tterribe $ - - ********************************************************************/ - -#if !defined(_x86_x86int_H) -# define _x86_x86int_H (1) -# include "../../internal.h" - -void oc_state_vtable_init_x86(oc_theora_state *_state); - -void oc_frag_recon_intra_mmx(unsigned char *_dst,int _dst_ystride, - const ogg_int16_t *_residue); -void oc_frag_recon_inter_mmx(unsigned char *_dst,int _dst_ystride, - const unsigned char *_src,int _src_ystride,const ogg_int16_t *_residue); -void oc_frag_recon_inter2_mmx(unsigned char *_dst,int _dst_ystride, - const unsigned char *_src1,int _src1_ystride,const unsigned char *_src2, - int _src2_ystride,const ogg_int16_t *_residue); -void oc_state_frag_copy_mmx(const oc_theora_state *_state,const int *_fragis, - int _nfragis,int _dst_frame,int _src_frame,int _pli); -void oc_state_frag_recon_mmx(oc_theora_state *_state,oc_fragment *_frag, - int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,int _ncoefs, - ogg_uint16_t _dc_iquant,const ogg_uint16_t _ac_iquant[64]); -void oc_restore_fpu_mmx(void); -void oc_idct8x8_mmx(ogg_int16_t _y[64]); -void oc_idct8x8_10_mmx(ogg_int16_t _y[64]); -void oc_fill_idct_constants_mmx(void); -void oc_state_loop_filter_frag_rows_mmx(oc_theora_state *_state,int *_bv, - int _refi,int _pli,int _fragy0,int _fragy_end); -#endif diff --git a/Engine/lib/libtheora/lib/dec/x86_vc/mmxfrag.c b/Engine/lib/libtheora/lib/dec/x86_vc/mmxfrag.c deleted file mode 100644 index e87e0640d..000000000 --- a/Engine/lib/libtheora/lib/dec/x86_vc/mmxfrag.c +++ /dev/null @@ -1,214 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: - - ********************************************************************/ -#include "../../internal.h" - -/* ------------------------------------------------------------------------ - MMX reconstruction fragment routines for Visual Studio. - Tested with VS2005. Should compile for VS2003 and VC6 as well. - - Initial implementation 2007 by Nils Pipenbrinck. - ---------------------------------------------------------------------*/ - -#if defined(USE_ASM) - -void oc_frag_recon_intra_mmx(unsigned char *_dst,int _dst_ystride, - const ogg_int16_t *_residue){ - /* --------------------------------------------------------------------- - This function does the inter reconstruction step with 8 iterations - unrolled. The iteration for each instruction is noted by the #id in the - comments (in case you want to reconstruct it) - --------------------------------------------------------------------- */ - _asm{ - mov edi, [_residue] /* load residue ptr */ - mov eax, 0x00800080 /* generate constant */ - mov ebx, [_dst_ystride] /* load dst-stride */ - mov edx, [_dst] /* load dest pointer */ - - /* unrolled loop begins here */ - - movd mm0, eax /* load constant */ - movq mm1, [edi+ 8*0] /* #1 load low residue */ - movq mm2, [edi+ 8*1] /* #1 load high residue */ - punpckldq mm0, mm0 /* build constant */ - movq mm3, [edi+ 8*2] /* #2 load low residue */ - movq mm4, [edi+ 8*3] /* #2 load high residue */ - movq mm5, [edi+ 8*4] /* #3 load low residue */ - movq mm6, [edi+ 8*5] /* #3 load high residue */ - paddsw mm1, mm0 /* #1 bias low residue */ - paddsw mm2, mm0 /* #1 bias high residue */ - packuswb mm1, mm2 /* #1 pack to byte */ - paddsw mm3, mm0 /* #2 bias low residue */ - paddsw mm4, mm0 /* #2 bias high residue */ - packuswb mm3, mm4 /* #2 pack to byte */ - paddsw mm5, mm0 /* #3 bias low residue */ - paddsw mm6, mm0 /* #3 bias high residue */ - packuswb mm5, mm6 /* #3 pack to byte */ - movq [edx], mm1 /* #1 write row */ - movq [edx + ebx], mm3 /* #2 write row */ - movq [edx + ebx*2], mm5 /* #3 write row */ - movq mm1, [edi+ 8*6] /* #4 load low residue */ - lea ecx, [ebx + ebx*2] /* make dst_ystride * 3 */ - movq mm2, [edi+ 8*7] /* #4 load high residue */ - movq mm3, [edi+ 8*8] /* #5 load low residue */ - lea esi, [ebx*4 + ebx] /* make dst_ystride * 5 */ - movq mm4, [edi+ 8*9] /* #5 load high residue */ - movq mm5, [edi+ 8*10] /* #6 load low residue */ - lea eax, [ecx*2 + ebx] /* make dst_ystride * 7 */ - movq mm6, [edi+ 8*11] /* #6 load high residue */ - paddsw mm1, mm0 /* #4 bias low residue */ - paddsw mm2, mm0 /* #4 bias high residue */ - packuswb mm1, mm2 /* #4 pack to byte */ - paddsw mm3, mm0 /* #5 bias low residue */ - paddsw mm4, mm0 /* #5 bias high residue */ - packuswb mm3, mm4 /* #5 pack to byte */ - paddsw mm5, mm0 /* #6 bias low residue */ - paddsw mm6, mm0 /* #6 bias high residue */ - packuswb mm5, mm6 /* #6 pack to byte */ - movq [edx + ecx], mm1 /* #4 write row */ - movq [edx + ebx*4], mm3 /* #5 write row */ - movq [edx + esi], mm5 /* #6 write row */ - movq mm1, [edi+ 8*12] /* #7 load low residue */ - movq mm2, [edi+ 8*13] /* #7 load high residue */ - movq mm3, [edi+ 8*14] /* #8 load low residue */ - movq mm4, [edi+ 8*15] /* #8 load high residue */ - paddsw mm1, mm0 /* #7 bias low residue */ - paddsw mm2, mm0 /* #7 bias high residue */ - packuswb mm1, mm2 /* #7 pack to byte */ - paddsw mm3, mm0 /* #8 bias low residue */ - paddsw mm4, mm0 /* #8 bias high residue */ - packuswb mm3, mm4 /* #8 pack to byte */ - movq [edx + ecx*2], mm1 /* #7 write row */ - movq [edx + eax], mm3 /* #8 write row */ - } -} - - - -void oc_frag_recon_inter_mmx (unsigned char *_dst, int _dst_ystride, - const unsigned char *_src, int _src_ystride, const ogg_int16_t *_residue){ - /* --------------------------------------------------------------------- - This function does the inter reconstruction step with two iterations - running in parallel to hide some load-latencies and break the dependency - chains. The iteration for each instruction is noted by the #id in the - comments (in case you want to reconstruct it) - --------------------------------------------------------------------- */ - _asm{ - pxor mm0, mm0 /* generate constant 0 */ - mov esi, [_src] - mov edi, [_residue] - mov eax, [_src_ystride] - mov edx, [_dst] - mov ebx, [_dst_ystride] - mov ecx, 4 - - align 16 - -nextchunk: - movq mm3, [esi] /* #1 load source */ - movq mm1, [edi+0] /* #1 load residium low */ - movq mm2, [edi+8] /* #1 load residium high */ - movq mm7, [esi+eax] /* #2 load source */ - movq mm4, mm3 /* #1 get copy of src */ - movq mm5, [edi+16] /* #2 load residium low */ - punpckhbw mm4, mm0 /* #1 expand high source */ - movq mm6, [edi+24] /* #2 load residium high */ - punpcklbw mm3, mm0 /* #1 expand low source */ - paddsw mm4, mm2 /* #1 add residium high */ - movq mm2, mm7 /* #2 get copy of src */ - paddsw mm3, mm1 /* #1 add residium low */ - punpckhbw mm2, mm0 /* #2 expand high source */ - packuswb mm3, mm4 /* #1 final row pixels */ - punpcklbw mm7, mm0 /* #2 expand low source */ - movq [edx], mm3 /* #1 write row */ - paddsw mm2, mm6 /* #2 add residium high */ - add edi, 32 /* residue += 4 */ - paddsw mm7, mm5 /* #2 add residium low */ - sub ecx, 1 /* update loop counter */ - packuswb mm7, mm2 /* #2 final row */ - lea esi, [esi+eax*2] /* src += stride * 2 */ - movq [edx + ebx], mm7 /* #2 write row */ - lea edx, [edx+ebx*2] /* dst += stride * 2 */ - jne nextchunk - } -} - - -void oc_frag_recon_inter2_mmx(unsigned char *_dst, int _dst_ystride, - const unsigned char *_src1, int _src1_ystride, const unsigned char *_src2, - int _src2_ystride,const ogg_int16_t *_residue){ - /* --------------------------------------------------------------------- - This function does the inter2 reconstruction step.The building of the - average is done with a bit-twiddeling trick to avoid excessive register - copy work during byte to word conversion. - - average = (a & b) + (((a ^ b) & 0xfe) >> 1); - - (shown for a single byte; it's done with 8 of them at a time) - - Slightly faster than the obvious method using add and shift, but not - earthshaking improvement either. - - If anyone comes up with a way that produces bit-identical outputs - using the pavgb instruction let me know and I'll do the 3dnow codepath. - --------------------------------------------------------------------- */ - _asm{ - mov eax, 0xfefefefe - mov esi, [_src1] - mov edi, [_src2] - movd mm1, eax - mov ebx, [_residue] - mov edx, [_dst] - mov eax, [_dst_ystride] - punpckldq mm1, mm1 /* replicate lsb32 */ - mov ecx, 8 /* init loop counter */ - pxor mm0, mm0 /* constant zero */ - sub edx, eax /* dst -= dst_stride */ - - align 16 - -nextrow: - movq mm2, [esi] /* load source1 */ - movq mm3, [edi] /* load source2 */ - movq mm5, [ebx + 0] /* load lower residue */ - movq mm6, [ebx + 8] /* load higer residue */ - add esi, _src1_ystride /* src1 += src1_stride */ - add edi, _src2_ystride /* src2 += src1_stride */ - movq mm4, mm2 /* get copy of source1 */ - pand mm2, mm3 /* s1 & s2 (avg part) */ - pxor mm3, mm4 /* s1 ^ s2 (avg part) */ - add ebx, 16 /* residue++ */ - pand mm3, mm1 /* mask out low bits */ - psrlq mm3, 1 /* shift xor avg-part */ - paddd mm3, mm2 /* build final average */ - add edx, eax /* dst += dst_stride */ - movq mm2, mm3 /* get copy of average */ - punpckhbw mm3, mm0 /* average high */ - punpcklbw mm2, mm0 /* average low */ - paddsw mm3, mm6 /* high + residue */ - paddsw mm2, mm5 /* low + residue */ - sub ecx, 1 /* update loop counter */ - packuswb mm2, mm3 /* pack and saturate */ - movq [edx], mm2 /* write row */ - jne nextrow - } -} - -void oc_restore_fpu_mmx(void){ - _asm { emms } -} - -#endif diff --git a/Engine/lib/libtheora/lib/dec/x86_vc/mmxidct.c b/Engine/lib/libtheora/lib/dec/x86_vc/mmxidct.c deleted file mode 100644 index 2c171594f..000000000 --- a/Engine/lib/libtheora/lib/dec/x86_vc/mmxidct.c +++ /dev/null @@ -1,1006 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: - - ********************************************************************/ - -/* ------------------------------------------------------------------- - MMX based IDCT for the theora codec. - - Originally written by Rudolf Marek, based on code from On2's VP3. - Converted to Visual Studio inline assembly by Nils Pipenbrinck. - - ---------------------------------------------------------------------*/ -#if defined(USE_ASM) - -#include -#include "../dct.h" -#include "../idct.h" -#include "x86int.h" - -/*A table of constants used by the MMX routines.*/ -static const __declspec(align(16)) ogg_uint16_t - OC_IDCT_CONSTS[(7+1)*4]={ - (ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7, - (ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7, - (ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6, - (ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6, - (ogg_uint16_t)OC_C3S5,(ogg_uint16_t)OC_C3S5, - (ogg_uint16_t)OC_C3S5,(ogg_uint16_t)OC_C3S5, - (ogg_uint16_t)OC_C4S4,(ogg_uint16_t)OC_C4S4, - (ogg_uint16_t)OC_C4S4,(ogg_uint16_t)OC_C4S4, - (ogg_uint16_t)OC_C5S3,(ogg_uint16_t)OC_C5S3, - (ogg_uint16_t)OC_C5S3,(ogg_uint16_t)OC_C5S3, - (ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2, - (ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2, - (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1, - (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1, - 8, 8, 8, 8 -}; - - -void oc_idct8x8_10_mmx(ogg_int16_t _y[64]){ - _asm { - mov edx, [_y] - mov eax, offset OC_IDCT_CONSTS - movq mm2, [edx + 30H] - movq mm6, [eax + 10H] - movq mm4, mm2 - movq mm7, [edx + 18H] - pmulhw mm4, mm6 - movq mm1, [eax + 20H] - pmulhw mm6, mm7 - movq mm5, mm1 - pmulhw mm1, mm2 - movq mm3, [edx + 10H] - pmulhw mm5, mm7 - movq mm0, [eax] - paddw mm4, mm2 - paddw mm6, mm7 - paddw mm2, mm1 - movq mm1, [edx + 38H] - paddw mm7, mm5 - movq mm5, mm0 - pmulhw mm0, mm3 - paddw mm4, mm7 - pmulhw mm5, mm1 - movq mm7, [eax + 30H] - psubw mm6, mm2 - paddw mm0, mm3 - pmulhw mm3, mm7 - movq mm2, [edx + 20H] - pmulhw mm7, mm1 - paddw mm5, mm1 - movq mm1, mm2 - pmulhw mm2, [eax + 08H] - psubw mm3, mm5 - movq mm5, [edx + 28H] - paddw mm0, mm7 - movq mm7, mm5 - psubw mm0, mm4 - pmulhw mm5, [eax + 08H] - paddw mm2, mm1 - pmulhw mm1, [eax + 28H] - paddw mm4, mm4 - paddw mm4, mm0 - psubw mm3, mm6 - paddw mm5, mm7 - paddw mm6, mm6 - pmulhw mm7, [eax + 28H] - paddw mm6, mm3 - movq [edx + 10H], mm4 - psubw mm1, mm5 - movq mm4, [eax + 18H] - movq mm5, mm3 - pmulhw mm3, mm4 - paddw mm7, mm2 - movq [edx + 20H], mm6 - movq mm2, mm0 - movq mm6, [edx] - pmulhw mm0, mm4 - paddw mm5, mm3 - movq mm3, [edx + 08H] - psubw mm5, mm1 - paddw mm2, mm0 - psubw mm6, mm3 - movq mm0, mm6 - pmulhw mm6, mm4 - paddw mm3, mm3 - paddw mm1, mm1 - paddw mm3, mm0 - paddw mm1, mm5 - pmulhw mm4, mm3 - paddw mm6, mm0 - psubw mm6, mm2 - paddw mm2, mm2 - movq mm0, [edx + 10H] - paddw mm2, mm6 - paddw mm4, mm3 - psubw mm2, mm1 - movq mm3, [edx + 20H] - psubw mm4, mm7 - paddw mm1, mm1 - paddw mm7, mm7 - paddw mm1, mm2 - paddw mm7, mm4 - psubw mm4, mm3 - paddw mm3, mm3 - psubw mm6, mm5 - paddw mm5, mm5 - paddw mm3, mm4 - paddw mm5, mm6 - psubw mm7, mm0 - paddw mm0, mm0 - movq [edx + 10H], mm1 - paddw mm0, mm7 - movq mm1, mm4 - punpcklwd mm4, mm5 - movq [edx], mm0 - punpckhwd mm1, mm5 - movq mm0, mm6 - punpcklwd mm6, mm7 - movq mm5, mm4 - punpckldq mm4, mm6 - punpckhdq mm5, mm6 - movq mm6, mm1 - movq [edx + 08H], mm4 - punpckhwd mm0, mm7 - movq [edx + 18H], mm5 - punpckhdq mm6, mm0 - movq mm4, [edx] - punpckldq mm1, mm0 - movq mm5, [edx + 10H] - movq mm0, mm4 - movq [edx + 38H], mm6 - punpcklwd mm0, mm5 - movq [edx + 28H], mm1 - punpckhwd mm4, mm5 - movq mm5, mm2 - punpcklwd mm2, mm3 - movq mm1, mm0 - punpckldq mm0, mm2 - punpckhdq mm1, mm2 - movq mm2, mm4 - movq [edx], mm0 - punpckhwd mm5, mm3 - movq [edx + 10H], mm1 - punpckhdq mm4, mm5 - punpckldq mm2, mm5 - movq [edx + 30H], mm4 - movq [edx + 20H], mm2 - movq mm2, [edx + 70H] - movq mm6, [eax + 10H] - movq mm4, mm2 - movq mm7, [edx + 58H] - pmulhw mm4, mm6 - movq mm1, [eax + 20H] - pmulhw mm6, mm7 - movq mm5, mm1 - pmulhw mm1, mm2 - movq mm3, [edx + 50H] - pmulhw mm5, mm7 - movq mm0, [eax] - paddw mm4, mm2 - paddw mm6, mm7 - paddw mm2, mm1 - movq mm1, [edx + 78H] - paddw mm7, mm5 - movq mm5, mm0 - pmulhw mm0, mm3 - paddw mm4, mm7 - pmulhw mm5, mm1 - movq mm7, [eax + 30H] - psubw mm6, mm2 - paddw mm0, mm3 - pmulhw mm3, mm7 - movq mm2, [edx + 60H] - pmulhw mm7, mm1 - paddw mm5, mm1 - movq mm1, mm2 - pmulhw mm2, [eax + 08H] - psubw mm3, mm5 - movq mm5, [edx + 68H] - paddw mm0, mm7 - movq mm7, mm5 - psubw mm0, mm4 - pmulhw mm5, [eax + 08H] - paddw mm2, mm1 - pmulhw mm1, [eax + 28H] - paddw mm4, mm4 - paddw mm4, mm0 - psubw mm3, mm6 - paddw mm5, mm7 - paddw mm6, mm6 - pmulhw mm7, [eax + 28H] - paddw mm6, mm3 - movq [edx + 50H], mm4 - psubw mm1, mm5 - movq mm4, [eax + 18H] - movq mm5, mm3 - pmulhw mm3, mm4 - paddw mm7, mm2 - movq [edx + 60H], mm6 - movq mm2, mm0 - movq mm6, [edx + 40H] - pmulhw mm0, mm4 - paddw mm5, mm3 - movq mm3, [edx + 48H] - psubw mm5, mm1 - paddw mm2, mm0 - psubw mm6, mm3 - movq mm0, mm6 - pmulhw mm6, mm4 - paddw mm3, mm3 - paddw mm1, mm1 - paddw mm3, mm0 - paddw mm1, mm5 - pmulhw mm4, mm3 - paddw mm6, mm0 - psubw mm6, mm2 - paddw mm2, mm2 - movq mm0, [edx + 50H] - paddw mm2, mm6 - paddw mm4, mm3 - psubw mm2, mm1 - movq mm3, [edx + 60H] - psubw mm4, mm7 - paddw mm1, mm1 - paddw mm7, mm7 - paddw mm1, mm2 - paddw mm7, mm4 - psubw mm4, mm3 - paddw mm3, mm3 - psubw mm6, mm5 - paddw mm5, mm5 - paddw mm3, mm4 - paddw mm5, mm6 - psubw mm7, mm0 - paddw mm0, mm0 - movq [edx + 50H], mm1 - paddw mm0, mm7 - movq mm1, mm4 - punpcklwd mm4, mm5 - movq [edx + 40H], mm0 - punpckhwd mm1, mm5 - movq mm0, mm6 - punpcklwd mm6, mm7 - movq mm5, mm4 - punpckldq mm4, mm6 - punpckhdq mm5, mm6 - movq mm6, mm1 - movq [edx + 48H], mm4 - punpckhwd mm0, mm7 - movq [edx + 58H], mm5 - punpckhdq mm6, mm0 - movq mm4, [edx + 40H] - punpckldq mm1, mm0 - movq mm5, [edx + 50H] - movq mm0, mm4 - movq [edx + 78H], mm6 - punpcklwd mm0, mm5 - movq [edx + 68H], mm1 - punpckhwd mm4, mm5 - movq mm5, mm2 - punpcklwd mm2, mm3 - movq mm1, mm0 - punpckldq mm0, mm2 - punpckhdq mm1, mm2 - movq mm2, mm4 - movq [edx + 40H], mm0 - punpckhwd mm5, mm3 - movq [edx + 50H], mm1 - punpckhdq mm4, mm5 - punpckldq mm2, mm5 - movq [edx + 70H], mm4 - movq [edx + 60H], mm2 - movq mm2, [edx + 30H] - movq mm6, [eax + 10H] - movq mm4, mm2 - movq mm7, [edx + 50H] - pmulhw mm4, mm6 - movq mm1, [eax + 20H] - pmulhw mm6, mm7 - movq mm5, mm1 - pmulhw mm1, mm2 - movq mm3, [edx + 10H] - pmulhw mm5, mm7 - movq mm0, [eax] - paddw mm4, mm2 - paddw mm6, mm7 - paddw mm2, mm1 - movq mm1, [edx + 70H] - paddw mm7, mm5 - movq mm5, mm0 - pmulhw mm0, mm3 - paddw mm4, mm7 - pmulhw mm5, mm1 - movq mm7, [eax + 30H] - psubw mm6, mm2 - paddw mm0, mm3 - pmulhw mm3, mm7 - movq mm2, [edx + 20H] - pmulhw mm7, mm1 - paddw mm5, mm1 - movq mm1, mm2 - pmulhw mm2, [eax + 08H] - psubw mm3, mm5 - movq mm5, [edx + 60H] - paddw mm0, mm7 - movq mm7, mm5 - psubw mm0, mm4 - pmulhw mm5, [eax + 08H] - paddw mm2, mm1 - pmulhw mm1, [eax + 28H] - paddw mm4, mm4 - paddw mm4, mm0 - psubw mm3, mm6 - paddw mm5, mm7 - paddw mm6, mm6 - pmulhw mm7, [eax + 28H] - paddw mm6, mm3 - movq [edx + 10H], mm4 - psubw mm1, mm5 - movq mm4, [eax + 18H] - movq mm5, mm3 - pmulhw mm3, mm4 - paddw mm7, mm2 - movq [edx + 20H], mm6 - movq mm2, mm0 - movq mm6, [edx] - pmulhw mm0, mm4 - paddw mm5, mm3 - movq mm3, [edx + 40H] - psubw mm5, mm1 - paddw mm2, mm0 - psubw mm6, mm3 - movq mm0, mm6 - pmulhw mm6, mm4 - paddw mm3, mm3 - paddw mm1, mm1 - paddw mm3, mm0 - paddw mm1, mm5 - pmulhw mm4, mm3 - paddw mm6, mm0 - psubw mm6, mm2 - paddw mm2, mm2 - movq mm0, [edx + 10H] - paddw mm2, mm6 - paddw mm4, mm3 - psubw mm2, mm1 - paddw mm2, [eax + 38H] - paddw mm1, mm1 - paddw mm1, mm2 - psraw mm2, 4 - psubw mm4, mm7 - psraw mm1, 4 - movq mm3, [edx + 20H] - paddw mm7, mm7 - movq [edx + 20H], mm2 - paddw mm7, mm4 - movq [edx + 10H], mm1 - psubw mm4, mm3 - paddw mm4, [eax + 38H] - paddw mm3, mm3 - paddw mm3, mm4 - psraw mm4, 4 - psubw mm6, mm5 - psraw mm3, 4 - paddw mm6, [eax + 38H] - paddw mm5, mm5 - paddw mm5, mm6 - psraw mm6, 4 - movq [edx + 40H], mm4 - psraw mm5, 4 - movq [edx + 30H], mm3 - psubw mm7, mm0 - paddw mm7, [eax + 38H] - paddw mm0, mm0 - paddw mm0, mm7 - psraw mm7, 4 - movq [edx + 60H], mm6 - psraw mm0, 4 - movq [edx + 50H], mm5 - movq [edx + 70H], mm7 - movq [edx], mm0 - movq mm2, [edx + 38H] - movq mm6, [eax + 10H] - movq mm4, mm2 - movq mm7, [edx + 58H] - pmulhw mm4, mm6 - movq mm1, [eax + 20H] - pmulhw mm6, mm7 - movq mm5, mm1 - pmulhw mm1, mm2 - movq mm3, [edx + 18H] - pmulhw mm5, mm7 - movq mm0, [eax] - paddw mm4, mm2 - paddw mm6, mm7 - paddw mm2, mm1 - movq mm1, [edx + 78H] - paddw mm7, mm5 - movq mm5, mm0 - pmulhw mm0, mm3 - paddw mm4, mm7 - pmulhw mm5, mm1 - movq mm7, [eax + 30H] - psubw mm6, mm2 - paddw mm0, mm3 - pmulhw mm3, mm7 - movq mm2, [edx + 28H] - pmulhw mm7, mm1 - paddw mm5, mm1 - movq mm1, mm2 - pmulhw mm2, [eax + 08H] - psubw mm3, mm5 - movq mm5, [edx + 68H] - paddw mm0, mm7 - movq mm7, mm5 - psubw mm0, mm4 - pmulhw mm5, [eax + 08H] - paddw mm2, mm1 - pmulhw mm1, [eax + 28H] - paddw mm4, mm4 - paddw mm4, mm0 - psubw mm3, mm6 - paddw mm5, mm7 - paddw mm6, mm6 - pmulhw mm7, [eax + 28H] - paddw mm6, mm3 - movq [edx + 18H], mm4 - psubw mm1, mm5 - movq mm4, [eax + 18H] - movq mm5, mm3 - pmulhw mm3, mm4 - paddw mm7, mm2 - movq [edx + 28H], mm6 - movq mm2, mm0 - movq mm6, [edx + 08H] - pmulhw mm0, mm4 - paddw mm5, mm3 - movq mm3, [edx + 48H] - psubw mm5, mm1 - paddw mm2, mm0 - psubw mm6, mm3 - movq mm0, mm6 - pmulhw mm6, mm4 - paddw mm3, mm3 - paddw mm1, mm1 - paddw mm3, mm0 - paddw mm1, mm5 - pmulhw mm4, mm3 - paddw mm6, mm0 - psubw mm6, mm2 - paddw mm2, mm2 - movq mm0, [edx + 18H] - paddw mm2, mm6 - paddw mm4, mm3 - psubw mm2, mm1 - paddw mm2, [eax + 38H] - paddw mm1, mm1 - paddw mm1, mm2 - psraw mm2, 4 - psubw mm4, mm7 - psraw mm1, 4 - movq mm3, [edx + 28H] - paddw mm7, mm7 - movq [edx + 28H], mm2 - paddw mm7, mm4 - movq [edx + 18H], mm1 - psubw mm4, mm3 - paddw mm4, [eax + 38H] - paddw mm3, mm3 - paddw mm3, mm4 - psraw mm4, 4 - psubw mm6, mm5 - psraw mm3, 4 - paddw mm6, [eax + 38H] - paddw mm5, mm5 - paddw mm5, mm6 - psraw mm6, 4 - movq [edx + 48H], mm4 - psraw mm5, 4 - movq [edx + 38H], mm3 - psubw mm7, mm0 - paddw mm7, [eax + 38H] - paddw mm0, mm0 - paddw mm0, mm7 - psraw mm7, 4 - movq [edx + 68H], mm6 - psraw mm0, 4 - movq [edx + 58H], mm5 - movq [edx + 78H], mm7 - movq [edx + 08H], mm0 - /* emms */ - } -} - - -void oc_idct8x8_mmx(ogg_int16_t _y[64]){ - _asm { - mov edx, [_y] - mov eax, offset OC_IDCT_CONSTS - movq mm2, [edx + 30H] - movq mm6, [eax + 10H] - movq mm4, mm2 - movq mm7, [edx + 18H] - pmulhw mm4, mm6 - movq mm1, [eax + 20H] - pmulhw mm6, mm7 - movq mm5, mm1 - pmulhw mm1, mm2 - movq mm3, [edx + 10H] - pmulhw mm5, mm7 - movq mm0, [eax] - paddw mm4, mm2 - paddw mm6, mm7 - paddw mm2, mm1 - movq mm1, [edx + 38H] - paddw mm7, mm5 - movq mm5, mm0 - pmulhw mm0, mm3 - paddw mm4, mm7 - pmulhw mm5, mm1 - movq mm7, [eax + 30H] - psubw mm6, mm2 - paddw mm0, mm3 - pmulhw mm3, mm7 - movq mm2, [edx + 20H] - pmulhw mm7, mm1 - paddw mm5, mm1 - movq mm1, mm2 - pmulhw mm2, [eax + 08H] - psubw mm3, mm5 - movq mm5, [edx + 28H] - paddw mm0, mm7 - movq mm7, mm5 - psubw mm0, mm4 - pmulhw mm5, [eax + 08H] - paddw mm2, mm1 - pmulhw mm1, [eax + 28H] - paddw mm4, mm4 - paddw mm4, mm0 - psubw mm3, mm6 - paddw mm5, mm7 - paddw mm6, mm6 - pmulhw mm7, [eax + 28H] - paddw mm6, mm3 - movq [edx + 10H], mm4 - psubw mm1, mm5 - movq mm4, [eax + 18H] - movq mm5, mm3 - pmulhw mm3, mm4 - paddw mm7, mm2 - movq [edx + 20H], mm6 - movq mm2, mm0 - movq mm6, [edx] - pmulhw mm0, mm4 - paddw mm5, mm3 - movq mm3, [edx + 08H] - psubw mm5, mm1 - paddw mm2, mm0 - psubw mm6, mm3 - movq mm0, mm6 - pmulhw mm6, mm4 - paddw mm3, mm3 - paddw mm1, mm1 - paddw mm3, mm0 - paddw mm1, mm5 - pmulhw mm4, mm3 - paddw mm6, mm0 - psubw mm6, mm2 - paddw mm2, mm2 - movq mm0, [edx + 10H] - paddw mm2, mm6 - paddw mm4, mm3 - psubw mm2, mm1 - movq mm3, [edx + 20H] - psubw mm4, mm7 - paddw mm1, mm1 - paddw mm7, mm7 - paddw mm1, mm2 - paddw mm7, mm4 - psubw mm4, mm3 - paddw mm3, mm3 - psubw mm6, mm5 - paddw mm5, mm5 - paddw mm3, mm4 - paddw mm5, mm6 - psubw mm7, mm0 - paddw mm0, mm0 - movq [edx + 10H], mm1 - paddw mm0, mm7 - movq mm1, mm4 - punpcklwd mm4, mm5 - movq [edx], mm0 - punpckhwd mm1, mm5 - movq mm0, mm6 - punpcklwd mm6, mm7 - movq mm5, mm4 - punpckldq mm4, mm6 - punpckhdq mm5, mm6 - movq mm6, mm1 - movq [edx + 08H], mm4 - punpckhwd mm0, mm7 - movq [edx + 18H], mm5 - punpckhdq mm6, mm0 - movq mm4, [edx] - punpckldq mm1, mm0 - movq mm5, [edx + 10H] - movq mm0, mm4 - movq [edx + 38H], mm6 - punpcklwd mm0, mm5 - movq [edx + 28H], mm1 - punpckhwd mm4, mm5 - movq mm5, mm2 - punpcklwd mm2, mm3 - movq mm1, mm0 - punpckldq mm0, mm2 - punpckhdq mm1, mm2 - movq mm2, mm4 - movq [edx], mm0 - punpckhwd mm5, mm3 - movq [edx + 10H], mm1 - punpckhdq mm4, mm5 - punpckldq mm2, mm5 - movq [edx + 30H], mm4 - movq [edx + 20H], mm2 - movq mm2, [edx + 70H] - movq mm6, [eax + 10H] - movq mm4, mm2 - movq mm7, [edx + 58H] - pmulhw mm4, mm6 - movq mm1, [eax + 20H] - pmulhw mm6, mm7 - movq mm5, mm1 - pmulhw mm1, mm2 - movq mm3, [edx + 50H] - pmulhw mm5, mm7 - movq mm0, [eax] - paddw mm4, mm2 - paddw mm6, mm7 - paddw mm2, mm1 - movq mm1, [edx + 78H] - paddw mm7, mm5 - movq mm5, mm0 - pmulhw mm0, mm3 - paddw mm4, mm7 - pmulhw mm5, mm1 - movq mm7, [eax + 30H] - psubw mm6, mm2 - paddw mm0, mm3 - pmulhw mm3, mm7 - movq mm2, [edx + 60H] - pmulhw mm7, mm1 - paddw mm5, mm1 - movq mm1, mm2 - pmulhw mm2, [eax + 08H] - psubw mm3, mm5 - movq mm5, [edx + 68H] - paddw mm0, mm7 - movq mm7, mm5 - psubw mm0, mm4 - pmulhw mm5, [eax + 08H] - paddw mm2, mm1 - pmulhw mm1, [eax + 28H] - paddw mm4, mm4 - paddw mm4, mm0 - psubw mm3, mm6 - paddw mm5, mm7 - paddw mm6, mm6 - pmulhw mm7, [eax + 28H] - paddw mm6, mm3 - movq [edx + 50H], mm4 - psubw mm1, mm5 - movq mm4, [eax + 18H] - movq mm5, mm3 - pmulhw mm3, mm4 - paddw mm7, mm2 - movq [edx + 60H], mm6 - movq mm2, mm0 - movq mm6, [edx + 40H] - pmulhw mm0, mm4 - paddw mm5, mm3 - movq mm3, [edx + 48H] - psubw mm5, mm1 - paddw mm2, mm0 - psubw mm6, mm3 - movq mm0, mm6 - pmulhw mm6, mm4 - paddw mm3, mm3 - paddw mm1, mm1 - paddw mm3, mm0 - paddw mm1, mm5 - pmulhw mm4, mm3 - paddw mm6, mm0 - psubw mm6, mm2 - paddw mm2, mm2 - movq mm0, [edx + 50H] - paddw mm2, mm6 - paddw mm4, mm3 - psubw mm2, mm1 - movq mm3, [edx + 60H] - psubw mm4, mm7 - paddw mm1, mm1 - paddw mm7, mm7 - paddw mm1, mm2 - paddw mm7, mm4 - psubw mm4, mm3 - paddw mm3, mm3 - psubw mm6, mm5 - paddw mm5, mm5 - paddw mm3, mm4 - paddw mm5, mm6 - psubw mm7, mm0 - paddw mm0, mm0 - movq [edx + 50H], mm1 - paddw mm0, mm7 - movq mm1, mm4 - punpcklwd mm4, mm5 - movq [edx + 40H], mm0 - punpckhwd mm1, mm5 - movq mm0, mm6 - punpcklwd mm6, mm7 - movq mm5, mm4 - punpckldq mm4, mm6 - punpckhdq mm5, mm6 - movq mm6, mm1 - movq [edx + 48H], mm4 - punpckhwd mm0, mm7 - movq [edx + 58H], mm5 - punpckhdq mm6, mm0 - movq mm4, [edx + 40H] - punpckldq mm1, mm0 - movq mm5, [edx + 50H] - movq mm0, mm4 - movq [edx + 78H], mm6 - punpcklwd mm0, mm5 - movq [edx + 68H], mm1 - punpckhwd mm4, mm5 - movq mm5, mm2 - punpcklwd mm2, mm3 - movq mm1, mm0 - punpckldq mm0, mm2 - punpckhdq mm1, mm2 - movq mm2, mm4 - movq [edx + 40H], mm0 - punpckhwd mm5, mm3 - movq [edx + 50H], mm1 - punpckhdq mm4, mm5 - punpckldq mm2, mm5 - movq [edx + 70H], mm4 - movq [edx + 60H], mm2 - movq mm2, [edx + 30H] - movq mm6, [eax + 10H] - movq mm4, mm2 - movq mm7, [edx + 50H] - pmulhw mm4, mm6 - movq mm1, [eax + 20H] - pmulhw mm6, mm7 - movq mm5, mm1 - pmulhw mm1, mm2 - movq mm3, [edx + 10H] - pmulhw mm5, mm7 - movq mm0, [eax] - paddw mm4, mm2 - paddw mm6, mm7 - paddw mm2, mm1 - movq mm1, [edx + 70H] - paddw mm7, mm5 - movq mm5, mm0 - pmulhw mm0, mm3 - paddw mm4, mm7 - pmulhw mm5, mm1 - movq mm7, [eax + 30H] - psubw mm6, mm2 - paddw mm0, mm3 - pmulhw mm3, mm7 - movq mm2, [edx + 20H] - pmulhw mm7, mm1 - paddw mm5, mm1 - movq mm1, mm2 - pmulhw mm2, [eax + 08H] - psubw mm3, mm5 - movq mm5, [edx + 60H] - paddw mm0, mm7 - movq mm7, mm5 - psubw mm0, mm4 - pmulhw mm5, [eax + 08H] - paddw mm2, mm1 - pmulhw mm1, [eax + 28H] - paddw mm4, mm4 - paddw mm4, mm0 - psubw mm3, mm6 - paddw mm5, mm7 - paddw mm6, mm6 - pmulhw mm7, [eax + 28H] - paddw mm6, mm3 - movq [edx + 10H], mm4 - psubw mm1, mm5 - movq mm4, [eax + 18H] - movq mm5, mm3 - pmulhw mm3, mm4 - paddw mm7, mm2 - movq [edx + 20H], mm6 - movq mm2, mm0 - movq mm6, [edx] - pmulhw mm0, mm4 - paddw mm5, mm3 - movq mm3, [edx + 40H] - psubw mm5, mm1 - paddw mm2, mm0 - psubw mm6, mm3 - movq mm0, mm6 - pmulhw mm6, mm4 - paddw mm3, mm3 - paddw mm1, mm1 - paddw mm3, mm0 - paddw mm1, mm5 - pmulhw mm4, mm3 - paddw mm6, mm0 - psubw mm6, mm2 - paddw mm2, mm2 - movq mm0, [edx + 10H] - paddw mm2, mm6 - paddw mm4, mm3 - psubw mm2, mm1 - paddw mm2, [eax + 38H] - paddw mm1, mm1 - paddw mm1, mm2 - psraw mm2, 4 - psubw mm4, mm7 - psraw mm1, 4 - movq mm3, [edx + 20H] - paddw mm7, mm7 - movq [edx + 20H], mm2 - paddw mm7, mm4 - movq [edx + 10H], mm1 - psubw mm4, mm3 - paddw mm4, [eax + 38H] - paddw mm3, mm3 - paddw mm3, mm4 - psraw mm4, 4 - psubw mm6, mm5 - psraw mm3, 4 - paddw mm6, [eax + 38H] - paddw mm5, mm5 - paddw mm5, mm6 - psraw mm6, 4 - movq [edx + 40H], mm4 - psraw mm5, 4 - movq [edx + 30H], mm3 - psubw mm7, mm0 - paddw mm7, [eax + 38H] - paddw mm0, mm0 - paddw mm0, mm7 - psraw mm7, 4 - movq [edx + 60H], mm6 - psraw mm0, 4 - movq [edx + 50H], mm5 - movq [edx + 70H], mm7 - movq [edx], mm0 - movq mm2, [edx + 38H] - movq mm6, [eax + 10H] - movq mm4, mm2 - movq mm7, [edx + 58H] - pmulhw mm4, mm6 - movq mm1, [eax + 20H] - pmulhw mm6, mm7 - movq mm5, mm1 - pmulhw mm1, mm2 - movq mm3, [edx + 18H] - pmulhw mm5, mm7 - movq mm0, [eax] - paddw mm4, mm2 - paddw mm6, mm7 - paddw mm2, mm1 - movq mm1, [edx + 78H] - paddw mm7, mm5 - movq mm5, mm0 - pmulhw mm0, mm3 - paddw mm4, mm7 - pmulhw mm5, mm1 - movq mm7, [eax + 30H] - psubw mm6, mm2 - paddw mm0, mm3 - pmulhw mm3, mm7 - movq mm2, [edx + 28H] - pmulhw mm7, mm1 - paddw mm5, mm1 - movq mm1, mm2 - pmulhw mm2, [eax + 08H] - psubw mm3, mm5 - movq mm5, [edx + 68H] - paddw mm0, mm7 - movq mm7, mm5 - psubw mm0, mm4 - pmulhw mm5, [eax + 08H] - paddw mm2, mm1 - pmulhw mm1, [eax + 28H] - paddw mm4, mm4 - paddw mm4, mm0 - psubw mm3, mm6 - paddw mm5, mm7 - paddw mm6, mm6 - pmulhw mm7, [eax + 28H] - paddw mm6, mm3 - movq [edx + 18H], mm4 - psubw mm1, mm5 - movq mm4, [eax + 18H] - movq mm5, mm3 - pmulhw mm3, mm4 - paddw mm7, mm2 - movq [edx + 28H], mm6 - movq mm2, mm0 - movq mm6, [edx + 08H] - pmulhw mm0, mm4 - paddw mm5, mm3 - movq mm3, [edx + 48H] - psubw mm5, mm1 - paddw mm2, mm0 - psubw mm6, mm3 - movq mm0, mm6 - pmulhw mm6, mm4 - paddw mm3, mm3 - paddw mm1, mm1 - paddw mm3, mm0 - paddw mm1, mm5 - pmulhw mm4, mm3 - paddw mm6, mm0 - psubw mm6, mm2 - paddw mm2, mm2 - movq mm0, [edx + 18H] - paddw mm2, mm6 - paddw mm4, mm3 - psubw mm2, mm1 - paddw mm2, [eax + 38H] - paddw mm1, mm1 - paddw mm1, mm2 - psraw mm2, 4 - psubw mm4, mm7 - psraw mm1, 4 - movq mm3, [edx + 28H] - paddw mm7, mm7 - movq [edx + 28H], mm2 - paddw mm7, mm4 - movq [edx + 18H], mm1 - psubw mm4, mm3 - paddw mm4, [eax + 38H] - paddw mm3, mm3 - paddw mm3, mm4 - psraw mm4, 4 - psubw mm6, mm5 - psraw mm3, 4 - paddw mm6, [eax + 38H] - paddw mm5, mm5 - paddw mm5, mm6 - psraw mm6, 4 - movq [edx + 48H], mm4 - psraw mm5, 4 - movq [edx + 38H], mm3 - psubw mm7, mm0 - paddw mm7, [eax + 38H] - paddw mm0, mm0 - paddw mm0, mm7 - psraw mm7, 4 - movq [edx + 68H], mm6 - psraw mm0, 4 - movq [edx + 58H], mm5 - movq [edx + 78H], mm7 - movq [edx + 08H], mm0 - /* emms */ - } -} - -#endif diff --git a/Engine/lib/libtheora/lib/dec/x86_vc/mmxloopfilter.c b/Engine/lib/libtheora/lib/dec/x86_vc/mmxloopfilter.c deleted file mode 100644 index 62d06dc89..000000000 --- a/Engine/lib/libtheora/lib/dec/x86_vc/mmxloopfilter.c +++ /dev/null @@ -1,377 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: - - ********************************************************************/ - -/* ------------------------------------------------------------------- - MMX based loop filter for the theora codec. - - Originally written by Rudolf Marek, based on code from On2's VP3. - Converted to Visual Studio inline assembly by Nils Pipenbrinck. - - Note: I can't test these since my example files never get into the - loop filters, but the code has been converted semi-automatic from - the GCC sources, so it ought to work. - ---------------------------------------------------------------------*/ -#include "../../internal.h" -#include "x86int.h" -#include - -#if defined(USE_ASM) - - - -static void loop_filter_v(unsigned char *_pix,int _ystride, - const ogg_int16_t *_ll){ - _asm { - mov eax, [_pix] - mov edx, [_ystride] - mov ebx, [_ll] - - /* _pix -= ystride */ - sub eax, edx - /* mm0=0 */ - pxor mm0, mm0 - /* _pix -= ystride */ - sub eax, edx - /* esi=_ystride*3 */ - lea esi, [edx + edx*2] - - /* mm7=_pix[0...8]*/ - movq mm7, [eax] - /* mm4=_pix[0...8+_ystride*3]*/ - movq mm4, [eax + esi] - /* mm6=_pix[0...8]*/ - movq mm6, mm7 - /* Expand unsigned _pix[0...3] to 16 bits.*/ - punpcklbw mm6, mm0 - movq mm5, mm4 - /* Expand unsigned _pix[4...7] to 16 bits.*/ - punpckhbw mm7, mm0 - punpcklbw mm4, mm0 - /* Expand other arrays too.*/ - punpckhbw mm5, mm0 - /*mm7:mm6=_p[0...7]-_p[0...7+_ystride*3]:*/ - psubw mm6, mm4 - psubw mm7, mm5 - /*mm5=mm4=_pix[0...7+_ystride]*/ - movq mm4, [eax + edx] - /*mm1=mm3=mm2=_pix[0..7]+_ystride*2]*/ - movq mm2, [eax + edx*2] - movq mm5, mm4 - movq mm3, mm2 - movq mm1, mm2 - /*Expand these arrays.*/ - punpckhbw mm5, mm0 - punpcklbw mm4, mm0 - punpckhbw mm3, mm0 - punpcklbw mm2, mm0 - pcmpeqw mm0, mm0 - /*mm0=3 3 3 3 - mm3:mm2=_pix[0...8+_ystride*2]-_pix[0...8+_ystride]*/ - psubw mm3, mm5 - psrlw mm0, 14 - psubw mm2, mm4 - /*Scale by 3.*/ - pmullw mm3, mm0 - pmullw mm2, mm0 - /*mm0=4 4 4 4 - f=mm3:mm2==_pix[0...8]-_pix[0...8+_ystride*3]+ - 3*(_pix[0...8+_ystride*2]-_pix[0...8+_ystride])*/ - psrlw mm0, 1 - paddw mm3, mm7 - psllw mm0, 2 - paddw mm2, mm6 - /*Add 4.*/ - paddw mm3, mm0 - paddw mm2, mm0 - /*"Divide" by 8.*/ - psraw mm3, 3 - psraw mm2, 3 - /*Now compute lflim of mm3:mm2 cf. Section 7.10 of the sepc.*/ - /*Free up mm5.*/ - packuswb mm4, mm5 - /*mm0=L L L L*/ - movq mm0, [ebx] - /*if(R_i<-2L||R_i>2L)R_i=0:*/ - movq mm5, mm2 - pxor mm6, mm6 - movq mm7, mm0 - psubw mm6, mm0 - psllw mm7, 1 - psllw mm6, 1 - /*mm2==R_3 R_2 R_1 R_0*/ - /*mm5==R_3 R_2 R_1 R_0*/ - /*mm6==-2L -2L -2L -2L*/ - /*mm7==2L 2L 2L 2L*/ - pcmpgtw mm7, mm2 - pcmpgtw mm5, mm6 - pand mm2, mm7 - movq mm7, mm0 - pand mm2, mm5 - psllw mm7, 1 - movq mm5, mm3 - /*mm3==R_7 R_6 R_5 R_4*/ - /*mm5==R_7 R_6 R_5 R_4*/ - /*mm6==-2L -2L -2L -2L*/ - /*mm7==2L 2L 2L 2L*/ - pcmpgtw mm7, mm3 - pcmpgtw mm5, mm6 - pand mm3, mm7 - movq mm7, mm0 - pand mm3, mm5 - /*if(R_i<-L)R_i'=R_i+2L; - if(R_i>L)R_i'=R_i-2L; - if(R_i<-L||R_i>L)R_i=-R_i':*/ - psraw mm6, 1 - movq mm5, mm2 - psllw mm7, 1 - /*mm2==R_3 R_2 R_1 R_0*/ - /*mm5==R_3 R_2 R_1 R_0*/ - /*mm6==-L -L -L -L*/ - /*mm0==L L L L*/ - /*mm5=R_i>L?FF:00*/ - pcmpgtw mm5, mm0 - /*mm6=-L>R_i?FF:00*/ - pcmpgtw mm6, mm2 - /*mm7=R_i>L?2L:0*/ - pand mm7, mm5 - /*mm2=R_i>L?R_i-2L:R_i*/ - psubw mm2, mm7 - movq mm7, mm0 - /*mm5=-L>R_i||R_i>L*/ - por mm5, mm6 - psllw mm7, 1 - /*mm7=-L>R_i?2L:0*/ - pand mm7, mm6 - pxor mm6, mm6 - /*mm2=-L>R_i?R_i+2L:R_i*/ - paddw mm2, mm7 - psubw mm6, mm0 - /*mm5=-L>R_i||R_i>L?-R_i':0*/ - pand mm5, mm2 - movq mm7, mm0 - /*mm2=-L>R_i||R_i>L?0:R_i*/ - psubw mm2, mm5 - psllw mm7, 1 - /*mm2=-L>R_i||R_i>L?-R_i':R_i*/ - psubw mm2, mm5 - movq mm5, mm3 - /*mm3==R_7 R_6 R_5 R_4*/ - /*mm5==R_7 R_6 R_5 R_4*/ - /*mm6==-L -L -L -L*/ - /*mm0==L L L L*/ - /*mm6=-L>R_i?FF:00*/ - pcmpgtw mm6, mm3 - /*mm5=R_i>L?FF:00*/ - pcmpgtw mm5, mm0 - /*mm7=R_i>L?2L:0*/ - pand mm7, mm5 - /*mm2=R_i>L?R_i-2L:R_i*/ - psubw mm3, mm7 - psllw mm0, 1 - /*mm5=-L>R_i||R_i>L*/ - por mm5, mm6 - /*mm0=-L>R_i?2L:0*/ - pand mm0, mm6 - /*mm3=-L>R_i?R_i+2L:R_i*/ - paddw mm3, mm0 - /*mm5=-L>R_i||R_i>L?-R_i':0*/ - pand mm5, mm3 - /*mm2=-L>R_i||R_i>L?0:R_i*/ - psubw mm3, mm5 - /*mm3=-L>R_i||R_i>L?-R_i':R_i*/ - psubw mm3, mm5 - /*Unfortunately, there's no unsigned byte+signed byte with unsigned - saturation op code, so we have to promote things back 16 bits.*/ - pxor mm0, mm0 - movq mm5, mm4 - punpcklbw mm4, mm0 - punpckhbw mm5, mm0 - movq mm6, mm1 - punpcklbw mm1, mm0 - punpckhbw mm6, mm0 - /*_pix[0...8+_ystride]+=R_i*/ - paddw mm4, mm2 - paddw mm5, mm3 - /*_pix[0...8+_ystride*2]-=R_i*/ - psubw mm1, mm2 - psubw mm6, mm3 - packuswb mm4, mm5 - packuswb mm1, mm6 - /*Write it back out.*/ - movq [eax + edx], mm4 - movq [eax + edx*2], mm1 - } -} - -/*This code implements the bulk of loop_filter_h(). - Data are striped p0 p1 p2 p3 ... p0 p1 p2 p3 ..., so in order to load all - four p0's to one register we must transpose the values in four mmx regs. - When half is done we repeat this for the rest.*/ -static void loop_filter_h4(unsigned char *_pix,long _ystride, - const ogg_int16_t *_ll){ - /* todo: merge the comments from the GCC sources */ - _asm { - mov ecx, [_pix] - mov edx, [_ystride] - mov eax, [_ll] - /*esi=_ystride*3*/ - lea esi, [edx + edx*2] - - movd mm0, dword ptr [ecx] - movd mm1, dword ptr [ecx + edx] - movd mm2, dword ptr [ecx + edx*2] - movd mm3, dword ptr [ecx + esi] - punpcklbw mm0, mm1 - punpcklbw mm2, mm3 - movq mm1, mm0 - punpckhwd mm0, mm2 - punpcklwd mm1, mm2 - pxor mm7, mm7 - movq mm5, mm1 - punpcklbw mm1, mm7 - punpckhbw mm5, mm7 - movq mm3, mm0 - punpcklbw mm0, mm7 - punpckhbw mm3, mm7 - psubw mm1, mm3 - movq mm4, mm0 - pcmpeqw mm2, mm2 - psubw mm0, mm5 - psrlw mm2, 14 - pmullw mm0, mm2 - psrlw mm2, 1 - paddw mm0, mm1 - psllw mm2, 2 - paddw mm0, mm2 - psraw mm0, 3 - movq mm6, qword ptr [eax] - movq mm1, mm0 - pxor mm2, mm2 - movq mm3, mm6 - psubw mm2, mm6 - psllw mm3, 1 - psllw mm2, 1 - pcmpgtw mm3, mm0 - pcmpgtw mm1, mm2 - pand mm0, mm3 - pand mm0, mm1 - psraw mm2, 1 - movq mm1, mm0 - movq mm3, mm6 - pcmpgtw mm2, mm0 - pcmpgtw mm1, mm6 - psllw mm3, 1 - psllw mm6, 1 - pand mm3, mm1 - pand mm6, mm2 - psubw mm0, mm3 - por mm1, mm2 - paddw mm0, mm6 - pand mm1, mm0 - psubw mm0, mm1 - psubw mm0, mm1 - paddw mm5, mm0 - psubw mm4, mm0 - packuswb mm5, mm7 - packuswb mm4, mm7 - punpcklbw mm5, mm4 - movd edi, mm5 - mov word ptr [ecx + 01H], di - psrlq mm5, 32 - shr edi, 16 - mov word ptr [ecx + edx + 01H], di - movd edi, mm5 - mov word ptr [ecx + edx*2 + 01H], di - shr edi, 16 - mov word ptr [ecx + esi + 01H], di - } -} - -static void loop_filter_h(unsigned char *_pix,int _ystride, - const ogg_int16_t *_ll){ - _pix-=2; - loop_filter_h4(_pix,_ystride,_ll); - loop_filter_h4(_pix+(_ystride<<2),_ystride,_ll); -} - - -/*We copy the whole function because the MMX routines will be inlined 4 times, - and we can do just a single emms call at the end this way. - We also do not use the _bv lookup table, instead computing the values that - would lie in it on the fly.*/ - -/*Apply the loop filter to a given set of fragment rows in the given plane. - The filter may be run on the bottom edge, affecting pixels in the next row of - fragments, so this row also needs to be available. - _bv: The bounding values array. - _refi: The index of the frame buffer to filter. - _pli: The color plane to filter. - _fragy0: The Y coordinate of the first fragment row to filter. - _fragy_end: The Y coordinate of the fragment row to stop filtering at.*/ -void oc_state_loop_filter_frag_rows_mmx(oc_theora_state *_state,int *_bv, - int _refi,int _pli,int _fragy0,int _fragy_end){ - ogg_int16_t __declspec(align(8)) ll[4]; - th_img_plane *iplane; - oc_fragment_plane *fplane; - oc_fragment *frag_top; - oc_fragment *frag0; - oc_fragment *frag; - oc_fragment *frag_end; - oc_fragment *frag0_end; - oc_fragment *frag_bot; - ll[0]=ll[1]=ll[2]=ll[3]= - (ogg_int16_t)_state->loop_filter_limits[_state->qis[0]]; - iplane=_state->ref_frame_bufs[_refi]+_pli; - fplane=_state->fplanes+_pli; - /*The following loops are constructed somewhat non-intuitively on purpose. - The main idea is: if a block boundary has at least one coded fragment on - it, the filter is applied to it. - However, the order that the filters are applied in matters, and VP3 chose - the somewhat strange ordering used below.*/ - frag_top=_state->frags+fplane->froffset; - frag0=frag_top+_fragy0*fplane->nhfrags; - frag0_end=frag0+(_fragy_end-_fragy0)*fplane->nhfrags; - frag_bot=_state->frags+fplane->froffset+fplane->nfrags; - while(frag0nhfrags; - while(fragcoded){ - if(frag>frag0){ - loop_filter_h(frag->buffer[_refi],iplane->stride,ll); - } - if(frag0>frag_top){ - loop_filter_v(frag->buffer[_refi],iplane->stride,ll); - } - if(frag+1coded){ - loop_filter_h(frag->buffer[_refi]+8,iplane->stride,ll); - } - if(frag+fplane->nhfragsnhfrags)->coded){ - loop_filter_v((frag+fplane->nhfrags)->buffer[_refi], - iplane->stride,ll); - } - } - frag++; - } - frag0+=fplane->nhfrags; - } - - /*This needs to be removed when decode specific functions are implemented:*/ - _mm_empty(); -} - -#endif diff --git a/Engine/lib/libtheora/lib/dec/x86_vc/mmxstate.c b/Engine/lib/libtheora/lib/dec/x86_vc/mmxstate.c deleted file mode 100644 index 526ef53f3..000000000 --- a/Engine/lib/libtheora/lib/dec/x86_vc/mmxstate.c +++ /dev/null @@ -1,189 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2008 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: mmxstate.c 15400 2008-10-15 12:10:58Z tterribe $ - - ********************************************************************/ - -/* ------------------------------------------------------------------------ - MMX acceleration of complete fragment reconstruction algorithm. - Originally written by Rudolf Marek. - - Conversion to MSC intrinsics by Nils Pipenbrinck. - ---------------------------------------------------------------------*/ -#if defined(USE_ASM) - -#include "../../internal.h" -#include "../idct.h" -#include "x86int.h" -#include - -static const unsigned char OC_FZIG_ZAGMMX[64]= -{ - 0, 8, 1, 2, 9,16,24,17, - 10, 3,32,11,18,25, 4,12, - 5,26,19,40,33,34,41,48, - 27, 6,13,20,28,21,14, 7, - 56,49,42,35,43,50,57,36, - 15,22,29,30,23,44,37,58, - 51,59,38,45,52,31,60,53, - 46,39,47,54,61,62,55,63 -}; - -/* Fill a block with value */ -static __inline void loc_fill_mmx_value (__m64 * _dst, __m64 _value){ - __m64 t = _value; - _dst[0] = t; _dst[1] = t; _dst[2] = t; _dst[3] = t; - _dst[4] = t; _dst[5] = t; _dst[6] = t; _dst[7] = t; - _dst[8] = t; _dst[9] = t; _dst[10] = t; _dst[11] = t; - _dst[12] = t; _dst[13] = t; _dst[14] = t; _dst[15] = t; -} - -/* copy a block of 8 byte elements using different strides */ -static __inline void loc_blockcopy_mmx (unsigned char * _dst, int _dst_ystride, - unsigned char * _src, int _src_ystride){ - __m64 a,b,c,d,e,f,g,h; - a = *(__m64*)(_src + 0 * _src_ystride); - b = *(__m64*)(_src + 1 * _src_ystride); - c = *(__m64*)(_src + 2 * _src_ystride); - d = *(__m64*)(_src + 3 * _src_ystride); - e = *(__m64*)(_src + 4 * _src_ystride); - f = *(__m64*)(_src + 5 * _src_ystride); - g = *(__m64*)(_src + 6 * _src_ystride); - h = *(__m64*)(_src + 7 * _src_ystride); - *(__m64*)(_dst + 0 * _dst_ystride) = a; - *(__m64*)(_dst + 1 * _dst_ystride) = b; - *(__m64*)(_dst + 2 * _dst_ystride) = c; - *(__m64*)(_dst + 3 * _dst_ystride) = d; - *(__m64*)(_dst + 4 * _dst_ystride) = e; - *(__m64*)(_dst + 5 * _dst_ystride) = f; - *(__m64*)(_dst + 6 * _dst_ystride) = g; - *(__m64*)(_dst + 7 * _dst_ystride) = h; -} - -void oc_state_frag_recon_mmx(oc_theora_state *_state,const oc_fragment *_frag, - int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,int _ncoefs, - ogg_uint16_t _dc_iquant,const ogg_uint16_t _ac_iquant[64]){ - ogg_int16_t __declspec(align(16)) res_buf[64]; - int dst_framei; - int dst_ystride; - int zzi; - /*_last_zzi is subtly different from an actual count of the number of - coefficients we decoded for this block. - It contains the value of zzi BEFORE the final token in the block was - decoded. - In most cases this is an EOB token (the continuation of an EOB run from a - previous block counts), and so this is the same as the coefficient count. - However, in the case that the last token was NOT an EOB token, but filled - the block up with exactly 64 coefficients, _last_zzi will be less than 64. - Provided the last token was not a pure zero run, the minimum value it can - be is 46, and so that doesn't affect any of the cases in this routine. - However, if the last token WAS a pure zero run of length 63, then _last_zzi - will be 1 while the number of coefficients decoded is 64. - Thus, we will trigger the following special case, where the real - coefficient count would not. - Note also that a zero run of length 64 will give _last_zzi a value of 0, - but we still process the DC coefficient, which might have a non-zero value - due to DC prediction. - Although convoluted, this is arguably the correct behavior: it allows us to - dequantize fewer coefficients and use a smaller transform when the block - ends with a long zero run instead of a normal EOB token. - It could be smarter... multiple separate zero runs at the end of a block - will fool it, but an encoder that generates these really deserves what it - gets. - Needless to say we inherited this approach from VP3.*/ - /*Special case only having a DC component.*/ - if(_last_zzi<2){ - __m64 p; - /*Why is the iquant product rounded in this case and no others? Who knows.*/ - p = _m_from_int((ogg_int32_t)_frag->dc*_dc_iquant+15>>5); - /* broadcast 16 bits into all 4 mmx subregisters */ - p = _m_punpcklwd (p,p); - p = _m_punpckldq (p,p); - loc_fill_mmx_value ((__m64 *)res_buf, p); - } - else{ - /*Then, fill in the remainder of the coefficients with 0's, and perform - the iDCT.*/ - /*First zero the buffer.*/ - /*On K7, etc., this could be replaced with movntq and sfence.*/ - loc_fill_mmx_value ((__m64 *)res_buf, _mm_setzero_si64()); - - res_buf[0]=(ogg_int16_t)((ogg_int32_t)_frag->dc*_dc_iquant); - /*This is planned to be rewritten in MMX.*/ - for(zzi=1;zzi<_ncoefs;zzi++) - { - int ci; - ci=OC_FZIG_ZAG[zzi]; - res_buf[OC_FZIG_ZAGMMX[zzi]]=(ogg_int16_t)((ogg_int32_t)_dct_coeffs[zzi]* - _ac_iquant[ci]); - } - - if(_last_zzi<10){ - oc_idct8x8_10_mmx(res_buf); - } - else { - oc_idct8x8_mmx(res_buf); - } - } - /*Fill in the target buffer.*/ - dst_framei=_state->ref_frame_idx[OC_FRAME_SELF]; - dst_ystride=_state->ref_frame_bufs[dst_framei][_pli].stride; - /*For now ystride values in all ref frames assumed to be equal.*/ - if(_frag->mbmode==OC_MODE_INTRA){ - oc_frag_recon_intra_mmx(_frag->buffer[dst_framei],dst_ystride,res_buf); - } - else{ - int ref_framei; - int ref_ystride; - int mvoffsets[2]; - ref_framei=_state->ref_frame_idx[OC_FRAME_FOR_MODE[_frag->mbmode]]; - ref_ystride=_state->ref_frame_bufs[ref_framei][_pli].stride; - if(oc_state_get_mv_offsets(_state,mvoffsets,_frag->mv[0], - _frag->mv[1],ref_ystride,_pli)>1){ - oc_frag_recon_inter2_mmx(_frag->buffer[dst_framei],dst_ystride, - _frag->buffer[ref_framei]+mvoffsets[0],ref_ystride, - _frag->buffer[ref_framei]+mvoffsets[1],ref_ystride,res_buf); - } - else{ - oc_frag_recon_inter_mmx(_frag->buffer[dst_framei],dst_ystride, - _frag->buffer[ref_framei]+mvoffsets[0],ref_ystride,res_buf); - } - } - - _mm_empty(); -} - - -void oc_state_frag_copy_mmx(const oc_theora_state *_state,const int *_fragis, - int _nfragis,int _dst_frame,int _src_frame,int _pli){ - const int *fragi; - const int *fragi_end; - int dst_framei; - int dst_ystride; - int src_framei; - int src_ystride; - dst_framei=_state->ref_frame_idx[_dst_frame]; - src_framei=_state->ref_frame_idx[_src_frame]; - dst_ystride=_state->ref_frame_bufs[dst_framei][_pli].stride; - src_ystride=_state->ref_frame_bufs[src_framei][_pli].stride; - fragi_end=_fragis+_nfragis; - for(fragi=_fragis;fragifrags+*fragi; - loc_blockcopy_mmx (frag->buffer[dst_framei], dst_ystride, - frag->buffer[src_framei], src_ystride); - } - _m_empty(); -} - -#endif diff --git a/Engine/lib/libtheora/lib/dec/x86_vc/x86int.h b/Engine/lib/libtheora/lib/dec/x86_vc/x86int.h deleted file mode 100644 index be5016100..000000000 --- a/Engine/lib/libtheora/lib/dec/x86_vc/x86int.h +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: x86int.h 15400 2008-10-15 12:10:58Z tterribe $ - - ********************************************************************/ - -#if !defined(_x86_x86int_vc_H) -# define _x86_x86int_vc_H (1) -# include "../../internal.h" - -void oc_state_vtable_init_x86(oc_theora_state *_state); - -void oc_frag_recon_intra_mmx(unsigned char *_dst,int _dst_ystride, - const ogg_int16_t *_residue); - -void oc_frag_recon_inter_mmx(unsigned char *_dst,int _dst_ystride, - const unsigned char *_src,int _src_ystride,const ogg_int16_t *_residue); - -void oc_frag_recon_inter2_mmx(unsigned char *_dst,int _dst_ystride, - const unsigned char *_src1,int _src1_ystride,const unsigned char *_src2, - int _src2_ystride,const ogg_int16_t *_residue); - -void oc_state_frag_copy_mmx(const oc_theora_state *_state,const int *_fragis, - int _nfragis,int _dst_frame,int _src_frame,int _pli); - -void oc_restore_fpu_mmx(void); - -void oc_state_frag_recon_mmx(oc_theora_state *_state,const oc_fragment *_frag, - int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,int _ncoefs, - ogg_uint16_t _dc_iquant,const ogg_uint16_t _ac_iquant[64]); - -void oc_idct8x8_mmx(ogg_int16_t _y[64]); -void oc_idct8x8_10_mmx(ogg_int16_t _y[64]); - -void oc_state_loop_filter_frag_rows_mmx(oc_theora_state *_state,int *_bv, - int _refi,int _pli,int _fragy0,int _fragy_end); - -#endif diff --git a/Engine/lib/libtheora/lib/dec/decapiwrapper.c b/Engine/lib/libtheora/lib/decapiwrapper.c similarity index 95% rename from Engine/lib/libtheora/lib/dec/decapiwrapper.c rename to Engine/lib/libtheora/lib/decapiwrapper.c index bceec6c26..12ea475d1 100644 --- a/Engine/lib/libtheora/lib/dec/decapiwrapper.c +++ b/Engine/lib/libtheora/lib/decapiwrapper.c @@ -5,7 +5,7 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** @@ -19,6 +19,7 @@ #include #include #include "apiwrapper.h" +#include "decint.h" #include "theora/theoradec.h" static void th_dec_api_clear(th_api_wrapper *_api){ @@ -47,7 +48,7 @@ static double theora_decode_granule_time(theora_state *_td,ogg_int64_t _gp){ return th_granule_time(((th_api_wrapper *)_td->i->codec_setup)->decode,_gp); } -static const oc_state_dispatch_vtbl OC_DEC_DISPATCH_VTBL={ +static const oc_state_dispatch_vtable OC_DEC_DISPATCH_VTBL={ (oc_state_clear_func)theora_decode_clear, (oc_state_control_func)theora_decode_control, (oc_state_granule_frame_func)theora_decode_granule_frame, @@ -95,6 +96,7 @@ int theora_decode_init(theora_state *_td,theora_info *_ci){ This avoids having to figure out whether or not we need to free the info struct in either theora_info_clear() or theora_clear().*/ apiinfo=(th_api_info *)_ogg_calloc(1,sizeof(*apiinfo)); + if(apiinfo==NULL)return OC_FAULT; /*Make our own copy of the info struct, since its lifetime should be independent of the one we were passed in.*/ *&apiinfo->info=*_ci; @@ -130,6 +132,7 @@ int theora_decode_header(theora_info *_ci,theora_comment *_cc,ogg_packet *_op){ theora_info struct like the ones that are used in a theora_state struct.*/ if(api==NULL){ _ci->codec_setup=_ogg_calloc(1,sizeof(*api)); + if(_ci->codec_setup==NULL)return OC_FAULT; api=(th_api_wrapper *)_ci->codec_setup; api->clear=(oc_setup_clear_func)th_dec_api_clear; } @@ -167,12 +170,14 @@ int theora_decode_packetin(theora_state *_td,ogg_packet *_op){ int theora_decode_YUVout(theora_state *_td,yuv_buffer *_yuv){ th_api_wrapper *api; + th_dec_ctx *decode; th_ycbcr_buffer buf; int ret; if(!_td||!_td->i||!_td->i->codec_setup)return OC_FAULT; api=(th_api_wrapper *)_td->i->codec_setup; - if(!api->decode)return OC_FAULT; - ret=th_decode_ycbcr_out(api->decode,buf); + decode=(th_dec_ctx *)api->decode; + if(!decode)return OC_FAULT; + ret=th_decode_ycbcr_out(decode,buf); if(ret>=0){ _yuv->y_width=buf[0].width; _yuv->y_height=buf[0].height; diff --git a/Engine/lib/libtheora/lib/dec/decinfo.c b/Engine/lib/libtheora/lib/decinfo.c similarity index 77% rename from Engine/lib/libtheora/lib/dec/decinfo.c rename to Engine/lib/libtheora/lib/decinfo.c index 3c4ba868a..845eb1361 100644 --- a/Engine/lib/libtheora/lib/dec/decinfo.c +++ b/Engine/lib/libtheora/lib/decinfo.c @@ -5,13 +5,13 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: decinfo.c 15400 2008-10-15 12:10:58Z tterribe $ + last mod: $Id: decinfo.c 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ @@ -27,30 +27,30 @@ _opb: The pack buffer to read the octets from. _buf: The byte array to store the unpacked bytes in. _len: The number of octets to unpack.*/ -static void oc_unpack_octets(oggpack_buffer *_opb,char *_buf,size_t _len){ +static void oc_unpack_octets(oc_pack_buf *_opb,char *_buf,size_t _len){ while(_len-->0){ long val; - theorapackB_read(_opb,8,&val); + val=oc_pack_read(_opb,8); *_buf++=(char)val; } } /*Unpacks a 32-bit integer encoded by octets in little-endian form.*/ -static long oc_unpack_length(oggpack_buffer *_opb){ +static long oc_unpack_length(oc_pack_buf *_opb){ long ret[4]; int i; - for(i=0;i<4;i++)theorapackB_read(_opb,8,ret+i); + for(i=0;i<4;i++)ret[i]=oc_pack_read(_opb,8); return ret[0]|ret[1]<<8|ret[2]<<16|ret[3]<<24; } -static int oc_info_unpack(oggpack_buffer *_opb,th_info *_info){ +static int oc_info_unpack(oc_pack_buf *_opb,th_info *_info){ long val; /*Check the codec bitstream version.*/ - theorapackB_read(_opb,8,&val); + val=oc_pack_read(_opb,8); _info->version_major=(unsigned char)val; - theorapackB_read(_opb,8,&val); + val=oc_pack_read(_opb,8); _info->version_minor=(unsigned char)val; - theorapackB_read(_opb,8,&val); + val=oc_pack_read(_opb,8); _info->version_subminor=(unsigned char)val; /*verify we can parse this bitstream version. We accept earlier minors and all subminors, by spec*/ @@ -60,25 +60,21 @@ static int oc_info_unpack(oggpack_buffer *_opb,th_info *_info){ return TH_EVERSION; } /*Read the encoded frame description.*/ - theorapackB_read(_opb,16,&val); + val=oc_pack_read(_opb,16); _info->frame_width=(ogg_uint32_t)val<<4; - theorapackB_read(_opb,16,&val); + val=oc_pack_read(_opb,16); _info->frame_height=(ogg_uint32_t)val<<4; - theorapackB_read(_opb,24,&val); + val=oc_pack_read(_opb,24); _info->pic_width=(ogg_uint32_t)val; - theorapackB_read(_opb,24,&val); + val=oc_pack_read(_opb,24); _info->pic_height=(ogg_uint32_t)val; - theorapackB_read(_opb,8,&val); + val=oc_pack_read(_opb,8); _info->pic_x=(ogg_uint32_t)val; - /*Note: The sense of pic_y is inverted in what we pass back to the - application compared to how it is stored in the bitstream. - This is because the bitstream uses a right-handed coordinate system, while - applications expect a left-handed one.*/ - theorapackB_read(_opb,8,&val); - _info->pic_y=_info->frame_height-_info->pic_height-(ogg_uint32_t)val; - theorapackB_read(_opb,32,&val); + val=oc_pack_read(_opb,8); + _info->pic_y=(ogg_uint32_t)val; + val=oc_pack_read(_opb,32); _info->fps_numerator=(ogg_uint32_t)val; - theorapackB_read(_opb,32,&val); + val=oc_pack_read(_opb,32); _info->fps_denominator=(ogg_uint32_t)val; if(_info->frame_width==0||_info->frame_height==0|| _info->pic_width+_info->pic_x>_info->frame_width|| @@ -86,38 +82,46 @@ static int oc_info_unpack(oggpack_buffer *_opb,th_info *_info){ _info->fps_numerator==0||_info->fps_denominator==0){ return TH_EBADHEADER; } - theorapackB_read(_opb,24,&val); + /*Note: The sense of pic_y is inverted in what we pass back to the + application compared to how it is stored in the bitstream. + This is because the bitstream uses a right-handed coordinate system, while + applications expect a left-handed one.*/ + _info->pic_y=_info->frame_height-_info->pic_height-_info->pic_y; + val=oc_pack_read(_opb,24); _info->aspect_numerator=(ogg_uint32_t)val; - theorapackB_read(_opb,24,&val); + val=oc_pack_read(_opb,24); _info->aspect_denominator=(ogg_uint32_t)val; - theorapackB_read(_opb,8,&val); + val=oc_pack_read(_opb,8); _info->colorspace=(th_colorspace)val; - theorapackB_read(_opb,24,&val); + val=oc_pack_read(_opb,24); _info->target_bitrate=(int)val; - theorapackB_read(_opb,6,&val); + val=oc_pack_read(_opb,6); _info->quality=(int)val; - theorapackB_read(_opb,5,&val); + val=oc_pack_read(_opb,5); _info->keyframe_granule_shift=(int)val; - theorapackB_read(_opb,2,&val); + val=oc_pack_read(_opb,2); _info->pixel_fmt=(th_pixel_fmt)val; if(_info->pixel_fmt==TH_PF_RSVD)return TH_EBADHEADER; - if(theorapackB_read(_opb,3,&val)<0||val!=0)return TH_EBADHEADER; + val=oc_pack_read(_opb,3); + if(val!=0||oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER; return 0; } -static int oc_comment_unpack(oggpack_buffer *_opb,th_comment *_tc){ +static int oc_comment_unpack(oc_pack_buf *_opb,th_comment *_tc){ long len; int i; /*Read the vendor string.*/ len=oc_unpack_length(_opb); - if(len<0||theorapackB_bytes(_opb)+len>_opb->storage)return TH_EBADHEADER; + if(len<0||len>oc_pack_bytes_left(_opb))return TH_EBADHEADER; _tc->vendor=_ogg_malloc((size_t)len+1); + if(_tc->vendor==NULL)return TH_EFAULT; oc_unpack_octets(_opb,_tc->vendor,len); _tc->vendor[len]='\0'; /*Read the user comments.*/ _tc->comments=(int)oc_unpack_length(_opb); - if(_tc->comments<0||_tc->comments>(LONG_MAX>>2)|| - theorapackB_bytes(_opb)+((long)_tc->comments<<2)>_opb->storage){ + len=_tc->comments; + if(len<0||len>(LONG_MAX>>2)||len<<2>oc_pack_bytes_left(_opb)){ + _tc->comments=0; return TH_EBADHEADER; } _tc->comment_lengths=(int *)_ogg_malloc( @@ -126,19 +130,23 @@ static int oc_comment_unpack(oggpack_buffer *_opb,th_comment *_tc){ _tc->comments*sizeof(_tc->user_comments[0])); for(i=0;i<_tc->comments;i++){ len=oc_unpack_length(_opb); - if(len<0||theorapackB_bytes(_opb)+len>_opb->storage){ + if(len<0||len>oc_pack_bytes_left(_opb)){ _tc->comments=i; return TH_EBADHEADER; } _tc->comment_lengths[i]=len; _tc->user_comments[i]=_ogg_malloc((size_t)len+1); + if(_tc->user_comments[i]==NULL){ + _tc->comments=i; + return TH_EFAULT; + } oc_unpack_octets(_opb,_tc->user_comments[i],len); _tc->user_comments[i][len]='\0'; } - return theorapackB_read(_opb,0,&len)<0?TH_EBADHEADER:0; + return oc_pack_bytes_left(_opb)<0?TH_EBADHEADER:0; } -static int oc_setup_unpack(oggpack_buffer *_opb,th_setup_info *_setup){ +static int oc_setup_unpack(oc_pack_buf *_opb,th_setup_info *_setup){ int ret; /*Read the quantizer tables.*/ ret=oc_quant_params_unpack(_opb,&_setup->qinfo); @@ -152,13 +160,13 @@ static void oc_setup_clear(th_setup_info *_setup){ oc_huff_trees_clear(_setup->huff_tables); } -static int oc_dec_headerin(oggpack_buffer *_opb,th_info *_info, +static int oc_dec_headerin(oc_pack_buf *_opb,th_info *_info, th_comment *_tc,th_setup_info **_setup,ogg_packet *_op){ char buffer[6]; long val; int packtype; int ret; - theorapackB_read(_opb,8,&val); + val=oc_pack_read(_opb,8); packtype=(int)val; /*If we're at a data packet and we have received all three headers, we're done.*/ @@ -198,6 +206,7 @@ static int oc_dec_headerin(oggpack_buffer *_opb,th_info *_info, return TH_EBADHEADER; } setup=(oc_setup_info *)_ogg_calloc(1,sizeof(*setup)); + if(setup==NULL)return TH_EFAULT; ret=oc_setup_unpack(_opb,setup); if(ret<0){ oc_setup_clear(setup); @@ -222,13 +231,11 @@ static int oc_dec_headerin(oggpack_buffer *_opb,th_info *_info, stream until it returns 0.*/ int th_decode_headerin(th_info *_info,th_comment *_tc, th_setup_info **_setup,ogg_packet *_op){ - oggpack_buffer opb; - int ret; + oc_pack_buf opb; if(_op==NULL)return TH_EBADHEADER; if(_info==NULL)return TH_EFAULT; - theorapackB_readinit(&opb,_op->packet,_op->bytes); - ret=oc_dec_headerin(&opb,_info,_tc,_setup,_op); - return ret; + oc_pack_readinit(&opb,_op->packet,_op->bytes); + return oc_dec_headerin(&opb,_info,_tc,_setup,_op); } void th_setup_free(th_setup_info *_setup){ diff --git a/Engine/lib/libtheora/lib/dec/decint.h b/Engine/lib/libtheora/lib/decint.h similarity index 68% rename from Engine/lib/libtheora/lib/dec/decint.h rename to Engine/lib/libtheora/lib/decint.h index 7924c0e0c..261b67631 100644 --- a/Engine/lib/libtheora/lib/dec/decint.h +++ b/Engine/lib/libtheora/lib/decint.h @@ -5,13 +5,13 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: decint.h 15400 2008-10-15 12:10:58Z tterribe $ + last mod: $Id: decint.h 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ @@ -19,13 +19,12 @@ #if !defined(_decint_H) # define _decint_H (1) # include "theora/theoradec.h" -# include "../internal.h" +# include "internal.h" # include "bitpack.h" typedef struct th_setup_info oc_setup_info; typedef struct th_dec_ctx oc_dec_ctx; -# include "idct.h" # include "huffdec.h" # include "dequant.h" @@ -54,24 +53,20 @@ struct th_dec_ctx{ when a frame has been processed and a data packet is ready.*/ int packet_state; /*Buffer in which to assemble packets.*/ - oggpack_buffer opb; + oc_pack_buf opb; /*Huffman decode trees.*/ oc_huff_node *huff_tables[TH_NHUFFMAN_TABLES]; - /*The index of one past the last token in each plane for each coefficient. - The final entries are the total number of tokens for each coefficient.*/ - int ti0[3][64]; - /*The index of one past the last extra bits entry in each plane for each - coefficient. - The final entries are the total number of extra bits entries for each - coefficient.*/ - int ebi0[3][64]; + /*The index of the first token in each plane for each coefficient.*/ + ptrdiff_t ti0[3][64]; /*The number of outstanding EOB runs at the start of each coefficient in each plane.*/ - int eob_runs[3][64]; + ptrdiff_t eob_runs[3][64]; /*The DCT token lists.*/ - unsigned char **dct_tokens; + unsigned char *dct_tokens; /*The extra bits associated with DCT tokens.*/ - ogg_uint16_t **extra_bits; + unsigned char *extra_bits; + /*The number of dct tokens unpacked so far.*/ + int dct_tokens_count; /*The out-of-loop post-processing level.*/ int pp_level; /*The DC scale used for out-of-loop deblocking.*/ @@ -85,11 +80,28 @@ struct th_dec_ctx{ /*The storage for the post-processed frame buffer.*/ unsigned char *pp_frame_data; /*Whether or not the post-processsed frame buffer has space for chroma.*/ - int pp_frame_has_chroma; - /*The buffer used for the post-processed frame.*/ + int pp_frame_state; + /*The buffer used for the post-processed frame. + Note that this is _not_ guaranteed to have the same strides and offsets as + the reference frame buffers.*/ th_ycbcr_buffer pp_frame_buf; /*The striped decode callback function.*/ th_stripe_callback stripe_cb; +# if defined(HAVE_CAIRO) + /*Output metrics for debugging.*/ + int telemetry; + int telemetry_mbmode; + int telemetry_mv; + int telemetry_qi; + int telemetry_bits; + int telemetry_frame_bytes; + int telemetry_coding_bytes; + int telemetry_mode_bytes; + int telemetry_mv_bytes; + int telemetry_qi_bytes; + int telemetry_dc_bytes; + unsigned char *telemetry_frame_data; +# endif }; #endif diff --git a/Engine/lib/libtheora/lib/decode.c b/Engine/lib/libtheora/lib/decode.c new file mode 100644 index 000000000..7be66463d --- /dev/null +++ b/Engine/lib/libtheora/lib/decode.c @@ -0,0 +1,2943 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: decode.c 16581 2009-09-25 22:56:16Z gmaxwell $ + + ********************************************************************/ + +#include +#include +#include +#include "decint.h" +#if defined(OC_DUMP_IMAGES) +# include +# include "png.h" +#endif +#if defined(HAVE_CAIRO) +# include +#endif + + +/*No post-processing.*/ +#define OC_PP_LEVEL_DISABLED (0) +/*Keep track of DC qi for each block only.*/ +#define OC_PP_LEVEL_TRACKDCQI (1) +/*Deblock the luma plane.*/ +#define OC_PP_LEVEL_DEBLOCKY (2) +/*Dering the luma plane.*/ +#define OC_PP_LEVEL_DERINGY (3) +/*Stronger luma plane deringing.*/ +#define OC_PP_LEVEL_SDERINGY (4) +/*Deblock the chroma planes.*/ +#define OC_PP_LEVEL_DEBLOCKC (5) +/*Dering the chroma planes.*/ +#define OC_PP_LEVEL_DERINGC (6) +/*Stronger chroma plane deringing.*/ +#define OC_PP_LEVEL_SDERINGC (7) +/*Maximum valid post-processing level.*/ +#define OC_PP_LEVEL_MAX (7) + + + +/*The mode alphabets for the various mode coding schemes. + Scheme 0 uses a custom alphabet, which is not stored in this table.*/ +static const unsigned char OC_MODE_ALPHABETS[7][OC_NMODES]={ + /*Last MV dominates */ + { + OC_MODE_INTER_MV_LAST,OC_MODE_INTER_MV_LAST2,OC_MODE_INTER_MV, + OC_MODE_INTER_NOMV,OC_MODE_INTRA,OC_MODE_GOLDEN_NOMV,OC_MODE_GOLDEN_MV, + OC_MODE_INTER_MV_FOUR + }, + { + OC_MODE_INTER_MV_LAST,OC_MODE_INTER_MV_LAST2,OC_MODE_INTER_NOMV, + OC_MODE_INTER_MV,OC_MODE_INTRA,OC_MODE_GOLDEN_NOMV,OC_MODE_GOLDEN_MV, + OC_MODE_INTER_MV_FOUR + }, + { + OC_MODE_INTER_MV_LAST,OC_MODE_INTER_MV,OC_MODE_INTER_MV_LAST2, + OC_MODE_INTER_NOMV,OC_MODE_INTRA,OC_MODE_GOLDEN_NOMV,OC_MODE_GOLDEN_MV, + OC_MODE_INTER_MV_FOUR + }, + { + OC_MODE_INTER_MV_LAST,OC_MODE_INTER_MV,OC_MODE_INTER_NOMV, + OC_MODE_INTER_MV_LAST2,OC_MODE_INTRA,OC_MODE_GOLDEN_NOMV, + OC_MODE_GOLDEN_MV,OC_MODE_INTER_MV_FOUR + }, + /*No MV dominates.*/ + { + OC_MODE_INTER_NOMV,OC_MODE_INTER_MV_LAST,OC_MODE_INTER_MV_LAST2, + OC_MODE_INTER_MV,OC_MODE_INTRA,OC_MODE_GOLDEN_NOMV,OC_MODE_GOLDEN_MV, + OC_MODE_INTER_MV_FOUR + }, + { + OC_MODE_INTER_NOMV,OC_MODE_GOLDEN_NOMV,OC_MODE_INTER_MV_LAST, + OC_MODE_INTER_MV_LAST2,OC_MODE_INTER_MV,OC_MODE_INTRA,OC_MODE_GOLDEN_MV, + OC_MODE_INTER_MV_FOUR + }, + /*Default ordering.*/ + { + OC_MODE_INTER_NOMV,OC_MODE_INTRA,OC_MODE_INTER_MV,OC_MODE_INTER_MV_LAST, + OC_MODE_INTER_MV_LAST2,OC_MODE_GOLDEN_NOMV,OC_MODE_GOLDEN_MV, + OC_MODE_INTER_MV_FOUR + } +}; + + +/*The original DCT tokens are extended and reordered during the construction of + the Huffman tables. + The extension means more bits can be read with fewer calls to the bitpacker + during the Huffman decoding process (at the cost of larger Huffman tables), + and fewer tokens require additional extra bits (reducing the average storage + per decoded token). + The revised ordering reveals essential information in the token value + itself; specifically, whether or not there are additional extra bits to read + and the parameter to which those extra bits are applied. + The token is used to fetch a code word from the OC_DCT_CODE_WORD table below. + The extra bits are added into code word at the bit position inferred from the + token value, giving the final code word from which all required parameters + are derived. + The number of EOBs and the leading zero run length can be extracted directly. + The coefficient magnitude is optionally negated before extraction, according + to a 'flip' bit.*/ + +/*The number of additional extra bits that are decoded with each of the + internal DCT tokens.*/ +static const unsigned char OC_INTERNAL_DCT_TOKEN_EXTRA_BITS[15]={ + 12,4,3,3,4,4,5,5,8,8,8,8,3,3,6 +}; + +/*Whether or not an internal token needs any additional extra bits.*/ +#define OC_DCT_TOKEN_NEEDS_MORE(token) \ + (token<(sizeof(OC_INTERNAL_DCT_TOKEN_EXTRA_BITS)/ \ + sizeof(*OC_INTERNAL_DCT_TOKEN_EXTRA_BITS))) + +/*This token (OC_DCT_REPEAT_RUN3_TOKEN) requires more than 8 extra bits.*/ +#define OC_DCT_TOKEN_FAT_EOB (0) + +/*The number of EOBs to use for an end-of-frame token. + Note: We want to set eobs to PTRDIFF_MAX here, but that requires C99, which + is not yet available everywhere; this should be equivalent.*/ +#define OC_DCT_EOB_FINISH (~(size_t)0>>1) + +/*The location of the (6) run legth bits in the code word. + These are placed at index 0 and given 8 bits (even though 6 would suffice) + because it may be faster to extract the lower byte on some platforms.*/ +#define OC_DCT_CW_RLEN_SHIFT (0) +/*The location of the (12) EOB bits in the code word.*/ +#define OC_DCT_CW_EOB_SHIFT (8) +/*The location of the (1) flip bit in the code word. + This must be right under the magnitude bits.*/ +#define OC_DCT_CW_FLIP_BIT (20) +/*The location of the (11) token magnitude bits in the code word. + These must be last, and rely on a sign-extending right shift.*/ +#define OC_DCT_CW_MAG_SHIFT (21) + +/*Pack the given fields into a code word.*/ +#define OC_DCT_CW_PACK(_eobs,_rlen,_mag,_flip) \ + ((_eobs)<state,_info,3); + if(ret<0)return ret; + ret=oc_huff_trees_copy(_dec->huff_tables, + (const oc_huff_node *const *)_setup->huff_tables); + if(ret<0){ + oc_state_clear(&_dec->state); + return ret; + } + /*For each fragment, allocate one byte for every DCT coefficient token, plus + one byte for extra-bits for each token, plus one more byte for the long + EOB run, just in case it's the very last token and has a run length of + one.*/ + _dec->dct_tokens=(unsigned char *)_ogg_malloc((64+64+1)* + _dec->state.nfrags*sizeof(_dec->dct_tokens[0])); + if(_dec->dct_tokens==NULL){ + oc_huff_trees_clear(_dec->huff_tables); + oc_state_clear(&_dec->state); + return TH_EFAULT; + } + for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){ + _dec->state.dequant_tables[qi][pli][qti]= + _dec->state.dequant_table_data[qi][pli][qti]; + } + oc_dequant_tables_init(_dec->state.dequant_tables,_dec->pp_dc_scale, + &_setup->qinfo); + for(qi=0;qi<64;qi++){ + int qsum; + qsum=0; + for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){ + qsum+=_dec->state.dequant_tables[qti][pli][qi][12]+ + _dec->state.dequant_tables[qti][pli][qi][17]+ + _dec->state.dequant_tables[qti][pli][qi][18]+ + _dec->state.dequant_tables[qti][pli][qi][24]<<(pli==0); + } + _dec->pp_sharp_mod[qi]=-(qsum>>11); + } + memcpy(_dec->state.loop_filter_limits,_setup->qinfo.loop_filter_limits, + sizeof(_dec->state.loop_filter_limits)); + _dec->pp_level=OC_PP_LEVEL_DISABLED; + _dec->dc_qis=NULL; + _dec->variances=NULL; + _dec->pp_frame_data=NULL; + _dec->stripe_cb.ctx=NULL; + _dec->stripe_cb.stripe_decoded=NULL; +#if defined(HAVE_CAIRO) + _dec->telemetry=0; + _dec->telemetry_bits=0; + _dec->telemetry_qi=0; + _dec->telemetry_mbmode=0; + _dec->telemetry_mv=0; + _dec->telemetry_frame_data=NULL; +#endif + return 0; +} + +static void oc_dec_clear(oc_dec_ctx *_dec){ +#if defined(HAVE_CAIRO) + _ogg_free(_dec->telemetry_frame_data); +#endif + _ogg_free(_dec->pp_frame_data); + _ogg_free(_dec->variances); + _ogg_free(_dec->dc_qis); + _ogg_free(_dec->dct_tokens); + oc_huff_trees_clear(_dec->huff_tables); + oc_state_clear(&_dec->state); +} + + +static int oc_dec_frame_header_unpack(oc_dec_ctx *_dec){ + long val; + /*Check to make sure this is a data packet.*/ + val=oc_pack_read1(&_dec->opb); + if(val!=0)return TH_EBADPACKET; + /*Read in the frame type (I or P).*/ + val=oc_pack_read1(&_dec->opb); + _dec->state.frame_type=(int)val; + /*Read in the qi list.*/ + val=oc_pack_read(&_dec->opb,6); + _dec->state.qis[0]=(unsigned char)val; + val=oc_pack_read1(&_dec->opb); + if(!val)_dec->state.nqis=1; + else{ + val=oc_pack_read(&_dec->opb,6); + _dec->state.qis[1]=(unsigned char)val; + val=oc_pack_read1(&_dec->opb); + if(!val)_dec->state.nqis=2; + else{ + val=oc_pack_read(&_dec->opb,6); + _dec->state.qis[2]=(unsigned char)val; + _dec->state.nqis=3; + } + } + if(_dec->state.frame_type==OC_INTRA_FRAME){ + /*Keyframes have 3 unused configuration bits, holdovers from VP3 days. + Most of the other unused bits in the VP3 headers were eliminated. + I don't know why these remain.*/ + /*I wanted to eliminate wasted bits, but not all config wiggle room + --Monty.*/ + val=oc_pack_read(&_dec->opb,3); + if(val!=0)return TH_EIMPL; + } + return 0; +} + +/*Mark all fragments as coded and in OC_MODE_INTRA. + This also builds up the coded fragment list (in coded order), and clears the + uncoded fragment list. + It does not update the coded macro block list nor the super block flags, as + those are not used when decoding INTRA frames.*/ +static void oc_dec_mark_all_intra(oc_dec_ctx *_dec){ + const oc_sb_map *sb_maps; + const oc_sb_flags *sb_flags; + oc_fragment *frags; + ptrdiff_t *coded_fragis; + ptrdiff_t ncoded_fragis; + ptrdiff_t prev_ncoded_fragis; + unsigned nsbs; + unsigned sbi; + int pli; + coded_fragis=_dec->state.coded_fragis; + prev_ncoded_fragis=ncoded_fragis=0; + sb_maps=(const oc_sb_map *)_dec->state.sb_maps; + sb_flags=_dec->state.sb_flags; + frags=_dec->state.frags; + sbi=nsbs=0; + for(pli=0;pli<3;pli++){ + nsbs+=_dec->state.fplanes[pli].nsbs; + for(;sbi=0){ + frags[fragi].coded=1; + frags[fragi].mb_mode=OC_MODE_INTRA; + coded_fragis[ncoded_fragis++]=fragi; + } + } + } + } + _dec->state.ncoded_fragis[pli]=ncoded_fragis-prev_ncoded_fragis; + prev_ncoded_fragis=ncoded_fragis; + } + _dec->state.ntotal_coded_fragis=ncoded_fragis; +} + +/*Decodes the bit flags indicating whether each super block is partially coded + or not. + Return: The number of partially coded super blocks.*/ +static unsigned oc_dec_partial_sb_flags_unpack(oc_dec_ctx *_dec){ + oc_sb_flags *sb_flags; + unsigned nsbs; + unsigned sbi; + unsigned npartial; + unsigned run_count; + long val; + int flag; + val=oc_pack_read1(&_dec->opb); + flag=(int)val; + sb_flags=_dec->state.sb_flags; + nsbs=_dec->state.nsbs; + sbi=npartial=0; + while(sbiopb); + full_run=run_count>=4129; + do{ + sb_flags[sbi].coded_partially=flag; + sb_flags[sbi].coded_fully=0; + npartial+=flag; + sbi++; + } + while(--run_count>0&&sbiopb); + flag=(int)val; + } + else flag=!flag; + } + /*TODO: run_count should be 0 here. + If it's not, we should issue a warning of some kind.*/ + return npartial; +} + +/*Decodes the bit flags for whether or not each non-partially-coded super + block is fully coded or not. + This function should only be called if there is at least one + non-partially-coded super block. + Return: The number of partially coded super blocks.*/ +static void oc_dec_coded_sb_flags_unpack(oc_dec_ctx *_dec){ + oc_sb_flags *sb_flags; + unsigned nsbs; + unsigned sbi; + unsigned run_count; + long val; + int flag; + sb_flags=_dec->state.sb_flags; + nsbs=_dec->state.nsbs; + /*Skip partially coded super blocks.*/ + for(sbi=0;sb_flags[sbi].coded_partially;sbi++); + val=oc_pack_read1(&_dec->opb); + flag=(int)val; + do{ + int full_run; + run_count=oc_sb_run_unpack(&_dec->opb); + full_run=run_count>=4129; + for(;sbiopb); + flag=(int)val; + } + else flag=!flag; + } + while(sbistate.nsbs)oc_dec_coded_sb_flags_unpack(_dec); + if(npartial>0){ + val=oc_pack_read1(&_dec->opb); + flag=!(int)val; + } + else flag=0; + sb_maps=(const oc_sb_map *)_dec->state.sb_maps; + sb_flags=_dec->state.sb_flags; + frags=_dec->state.frags; + sbi=nsbs=run_count=0; + coded_fragis=_dec->state.coded_fragis; + uncoded_fragis=coded_fragis+_dec->state.nfrags; + prev_ncoded_fragis=ncoded_fragis=nuncoded_fragis=0; + for(pli=0;pli<3;pli++){ + nsbs+=_dec->state.fplanes[pli].nsbs; + for(;sbi=0){ + int coded; + if(sb_flags[sbi].coded_fully)coded=1; + else if(!sb_flags[sbi].coded_partially)coded=0; + else{ + if(run_count<=0){ + run_count=oc_block_run_unpack(&_dec->opb); + flag=!flag; + } + run_count--; + coded=flag; + } + if(coded)coded_fragis[ncoded_fragis++]=fragi; + else *(uncoded_fragis-++nuncoded_fragis)=fragi; + frags[fragi].coded=coded; + } + } + } + } + _dec->state.ncoded_fragis[pli]=ncoded_fragis-prev_ncoded_fragis; + prev_ncoded_fragis=ncoded_fragis; + } + _dec->state.ntotal_coded_fragis=ncoded_fragis; + /*TODO: run_count should be 0 here. + If it's not, we should issue a warning of some kind.*/ +} + + + +typedef int (*oc_mode_unpack_func)(oc_pack_buf *_opb); + +static int oc_vlc_mode_unpack(oc_pack_buf *_opb){ + long val; + int i; + for(i=0;i<7;i++){ + val=oc_pack_read1(_opb); + if(!val)break; + } + return i; +} + +static int oc_clc_mode_unpack(oc_pack_buf *_opb){ + long val; + val=oc_pack_read(_opb,3); + return (int)val; +} + +/*Unpacks the list of macro block modes for INTER frames.*/ +static void oc_dec_mb_modes_unpack(oc_dec_ctx *_dec){ + const oc_mb_map *mb_maps; + signed char *mb_modes; + const oc_fragment *frags; + const unsigned char *alphabet; + unsigned char scheme0_alphabet[8]; + oc_mode_unpack_func mode_unpack; + size_t nmbs; + size_t mbi; + long val; + int mode_scheme; + val=oc_pack_read(&_dec->opb,3); + mode_scheme=(int)val; + if(mode_scheme==0){ + int mi; + /*Just in case, initialize the modes to something. + If the bitstream doesn't contain each index exactly once, it's likely + corrupt and the rest of the packet is garbage anyway, but this way we + won't crash, and we'll decode SOMETHING.*/ + /*LOOP VECTORIZES*/ + for(mi=0;miopb,3); + scheme0_alphabet[val]=OC_MODE_ALPHABETS[6][mi]; + } + alphabet=scheme0_alphabet; + } + else alphabet=OC_MODE_ALPHABETS[mode_scheme-1]; + if(mode_scheme==7)mode_unpack=oc_clc_mode_unpack; + else mode_unpack=oc_vlc_mode_unpack; + mb_modes=_dec->state.mb_modes; + mb_maps=(const oc_mb_map *)_dec->state.mb_maps; + nmbs=_dec->state.nmbs; + frags=_dec->state.frags; + for(mbi=0;mbiopb)]; + /*There were none: INTER_NOMV is forced.*/ + else mb_modes[mbi]=OC_MODE_INTER_NOMV; + } + } +} + + + +typedef int (*oc_mv_comp_unpack_func)(oc_pack_buf *_opb); + +static int oc_vlc_mv_comp_unpack(oc_pack_buf *_opb){ + long bits; + int mask; + int mv; + bits=oc_pack_read(_opb,3); + switch(bits){ + case 0:return 0; + case 1:return 1; + case 2:return -1; + case 3: + case 4:{ + mv=(int)(bits-1); + bits=oc_pack_read1(_opb); + }break; + /*case 5: + case 6: + case 7:*/ + default:{ + mv=1<>1); + bits&=1; + }break; + } + mask=-(int)bits; + return mv+mask^mask; +} + +static int oc_clc_mv_comp_unpack(oc_pack_buf *_opb){ + long bits; + int mask; + int mv; + bits=oc_pack_read(_opb,6); + mv=(int)bits>>1; + mask=-((int)bits&1); + return mv+mask^mask; +} + +/*Unpacks the list of motion vectors for INTER frames, and propagtes the macro + block modes and motion vectors to the individual fragments.*/ +static void oc_dec_mv_unpack_and_frag_modes_fill(oc_dec_ctx *_dec){ + const oc_mb_map *mb_maps; + const signed char *mb_modes; + oc_set_chroma_mvs_func set_chroma_mvs; + oc_mv_comp_unpack_func mv_comp_unpack; + oc_fragment *frags; + oc_mv *frag_mvs; + const unsigned char *map_idxs; + int map_nidxs; + oc_mv last_mv[2]; + oc_mv cbmvs[4]; + size_t nmbs; + size_t mbi; + long val; + set_chroma_mvs=OC_SET_CHROMA_MVS_TABLE[_dec->state.info.pixel_fmt]; + val=oc_pack_read1(&_dec->opb); + mv_comp_unpack=val?oc_clc_mv_comp_unpack:oc_vlc_mv_comp_unpack; + map_idxs=OC_MB_MAP_IDXS[_dec->state.info.pixel_fmt]; + map_nidxs=OC_MB_MAP_NIDXS[_dec->state.info.pixel_fmt]; + memset(last_mv,0,sizeof(last_mv)); + frags=_dec->state.frags; + frag_mvs=_dec->state.frag_mvs; + mb_maps=(const oc_mb_map *)_dec->state.mb_maps; + mb_modes=_dec->state.mb_modes; + nmbs=_dec->state.nmbs; + for(mbi=0;mbi>2][mapi&3]; + if(frags[fragi].coded)coded[ncoded++]=mapi; + } + while(++mapiiopb); + lbmvs[bi][1]=(signed char)(*mv_comp_unpack)(&_dec->opb); + memcpy(frag_mvs[fragi],lbmvs[bi],sizeof(lbmvs[bi])); + } + else lbmvs[bi][0]=lbmvs[bi][1]=0; + } + if(codedi>0){ + memcpy(last_mv[1],last_mv[0],sizeof(last_mv[1])); + memcpy(last_mv[0],lbmvs[coded[codedi-1]],sizeof(last_mv[0])); + } + if(codedi>2][bi]; + frags[fragi].mb_mode=mb_mode; + memcpy(frag_mvs[fragi],cbmvs[bi],sizeof(cbmvs[bi])); + } + } + }break; + case OC_MODE_INTER_MV:{ + memcpy(last_mv[1],last_mv[0],sizeof(last_mv[1])); + mbmv[0]=last_mv[0][0]=(signed char)(*mv_comp_unpack)(&_dec->opb); + mbmv[1]=last_mv[0][1]=(signed char)(*mv_comp_unpack)(&_dec->opb); + }break; + case OC_MODE_INTER_MV_LAST:memcpy(mbmv,last_mv[0],sizeof(mbmv));break; + case OC_MODE_INTER_MV_LAST2:{ + memcpy(mbmv,last_mv[1],sizeof(mbmv)); + memcpy(last_mv[1],last_mv[0],sizeof(last_mv[1])); + memcpy(last_mv[0],mbmv,sizeof(last_mv[0])); + }break; + case OC_MODE_GOLDEN_MV:{ + mbmv[0]=(signed char)(*mv_comp_unpack)(&_dec->opb); + mbmv[1]=(signed char)(*mv_comp_unpack)(&_dec->opb); + }break; + default:memset(mbmv,0,sizeof(mbmv));break; + } + /*4MV mode fills in the fragments itself. + For all other modes we can use this common code.*/ + if(mb_mode!=OC_MODE_INTER_MV_FOUR){ + for(codedi=0;codedi>2][mapi&3]; + frags[fragi].mb_mode=mb_mode; + memcpy(frag_mvs[fragi],mbmv,sizeof(mbmv)); + } + } + } + } +} + +static void oc_dec_block_qis_unpack(oc_dec_ctx *_dec){ + oc_fragment *frags; + const ptrdiff_t *coded_fragis; + ptrdiff_t ncoded_fragis; + ptrdiff_t fragii; + ptrdiff_t fragi; + ncoded_fragis=_dec->state.ntotal_coded_fragis; + if(ncoded_fragis<=0)return; + frags=_dec->state.frags; + coded_fragis=_dec->state.coded_fragis; + if(_dec->state.nqis==1){ + /*If this frame has only a single qi value, then just use it for all coded + fragments.*/ + for(fragii=0;fragiiopb); + flag=(int)val; + nqi1=0; + fragii=0; + while(fragiiopb); + full_run=run_count>=4129; + do{ + frags[coded_fragis[fragii++]].qii=flag; + nqi1+=flag; + } + while(--run_count>0&&fragiiopb); + flag=(int)val; + } + else flag=!flag; + } + /*TODO: run_count should be 0 here. + If it's not, we should issue a warning of some kind.*/ + /*If we have 3 different qi's for this frame, and there was at least one + fragment with a non-zero qi, make the second pass.*/ + if(_dec->state.nqis==3&&nqi1>0){ + /*Skip qii==0 fragments.*/ + for(fragii=0;frags[coded_fragis[fragii]].qii==0;fragii++); + val=oc_pack_read1(&_dec->opb); + flag=(int)val; + do{ + int full_run; + run_count=oc_sb_run_unpack(&_dec->opb); + full_run=run_count>=4129; + for(;fragiiopb); + flag=(int)val; + } + else flag=!flag; + } + while(fragiidct_tokens; + frags=_dec->state.frags; + coded_fragis=_dec->state.coded_fragis; + ncoded_fragis=fragii=eobs=ti=0; + for(pli=0;pli<3;pli++){ + ptrdiff_t run_counts[64]; + ptrdiff_t eob_count; + ptrdiff_t eobi; + int rli; + ncoded_fragis+=_dec->state.ncoded_fragis[pli]; + memset(run_counts,0,sizeof(run_counts)); + _dec->eob_runs[pli][0]=eobs; + _dec->ti0[pli][0]=ti; + /*Continue any previous EOB run, if there was one.*/ + eobi=eobs; + if(ncoded_fragis-fragii0)frags[coded_fragis[fragii++]].dc=0; + while(fragiiopb, + _dec->huff_tables[_huff_idxs[pli+1>>1]]); + dct_tokens[ti++]=(unsigned char)token; + if(OC_DCT_TOKEN_NEEDS_MORE(token)){ + eb=(int)oc_pack_read(&_dec->opb, + OC_INTERNAL_DCT_TOKEN_EXTRA_BITS[token]); + dct_tokens[ti++]=(unsigned char)eb; + if(token==OC_DCT_TOKEN_FAT_EOB)dct_tokens[ti++]=(unsigned char)(eb>>8); + eb<<=OC_DCT_TOKEN_EB_POS(token); + } + else eb=0; + cw=OC_DCT_CODE_WORD[token]+eb; + eobs=cw>>OC_DCT_CW_EOB_SHIFT&0xFFF; + if(cw==OC_DCT_CW_FINISH)eobs=OC_DCT_EOB_FINISH; + if(eobs){ + eobi=OC_MINI(eobs,ncoded_fragis-fragii); + eob_count+=eobi; + eobs-=eobi; + while(eobi-->0)frags[coded_fragis[fragii++]].dc=0; + } + else{ + int coeff; + skip=(unsigned char)(cw>>OC_DCT_CW_RLEN_SHIFT); + cw^=-(cw&1<>OC_DCT_CW_MAG_SHIFT; + if(skip)coeff=0; + run_counts[skip]++; + frags[coded_fragis[fragii++]].dc=coeff; + } + } + /*Add the total EOB count to the longest run length.*/ + run_counts[63]+=eob_count; + /*And convert the run_counts array to a moment table.*/ + for(rli=63;rli-->0;)run_counts[rli]+=run_counts[rli+1]; + /*Finally, subtract off the number of coefficients that have been + accounted for by runs started in this coefficient.*/ + for(rli=64;rli-->0;)_ntoks_left[pli][rli]-=run_counts[rli]; + } + _dec->dct_tokens_count=ti; + return eobs; +} + +/*Unpacks the AC coefficient tokens. + This can completely discard coefficient values while unpacking, and so is + somewhat simpler than unpacking the DC coefficient tokens. + _huff_idx: The index of the Huffman table to use for each color plane. + _ntoks_left: The number of tokens left to be decoded in each color plane for + each coefficient. + This is updated as EOB tokens and zero run tokens are decoded. + _eobs: The length of any outstanding EOB run from previous + coefficients. + Return: The length of any outstanding EOB run.*/ +static int oc_dec_ac_coeff_unpack(oc_dec_ctx *_dec,int _zzi,int _huff_idxs[2], + ptrdiff_t _ntoks_left[3][64],ptrdiff_t _eobs){ + unsigned char *dct_tokens; + ptrdiff_t ti; + int pli; + dct_tokens=_dec->dct_tokens; + ti=_dec->dct_tokens_count; + for(pli=0;pli<3;pli++){ + ptrdiff_t run_counts[64]; + ptrdiff_t eob_count; + size_t ntoks_left; + size_t ntoks; + int rli; + _dec->eob_runs[pli][_zzi]=_eobs; + _dec->ti0[pli][_zzi]=ti; + ntoks_left=_ntoks_left[pli][_zzi]; + memset(run_counts,0,sizeof(run_counts)); + eob_count=0; + ntoks=0; + while(ntoks+_eobsopb, + _dec->huff_tables[_huff_idxs[pli+1>>1]]); + dct_tokens[ti++]=(unsigned char)token; + if(OC_DCT_TOKEN_NEEDS_MORE(token)){ + eb=(int)oc_pack_read(&_dec->opb, + OC_INTERNAL_DCT_TOKEN_EXTRA_BITS[token]); + dct_tokens[ti++]=(unsigned char)eb; + if(token==OC_DCT_TOKEN_FAT_EOB)dct_tokens[ti++]=(unsigned char)(eb>>8); + eb<<=OC_DCT_TOKEN_EB_POS(token); + } + else eb=0; + cw=OC_DCT_CODE_WORD[token]+eb; + skip=(unsigned char)(cw>>OC_DCT_CW_RLEN_SHIFT); + _eobs=cw>>OC_DCT_CW_EOB_SHIFT&0xFFF; + if(cw==OC_DCT_CW_FINISH)_eobs=OC_DCT_EOB_FINISH; + if(_eobs==0){ + run_counts[skip]++; + ntoks++; + } + } + /*Add the portion of the last EOB run actually used by this coefficient.*/ + eob_count+=ntoks_left-ntoks; + /*And remove it from the remaining EOB count.*/ + _eobs-=ntoks_left-ntoks; + /*Add the total EOB count to the longest run length.*/ + run_counts[63]+=eob_count; + /*And convert the run_counts array to a moment table.*/ + for(rli=63;rli-->0;)run_counts[rli]+=run_counts[rli+1]; + /*Finally, subtract off the number of coefficients that have been + accounted for by runs started in this coefficient.*/ + for(rli=64-_zzi;rli-->0;)_ntoks_left[pli][_zzi+rli]-=run_counts[rli]; + } + _dec->dct_tokens_count=ti; + return _eobs; +} + +/*Tokens describing the DCT coefficients that belong to each fragment are + stored in the bitstream grouped by coefficient, not by fragment. + + This means that we either decode all the tokens in order, building up a + separate coefficient list for each fragment as we go, and then go back and + do the iDCT on each fragment, or we have to create separate lists of tokens + for each coefficient, so that we can pull the next token required off the + head of the appropriate list when decoding a specific fragment. + + The former was VP3's choice, and it meant 2*w*h extra storage for all the + decoded coefficient values. + + We take the second option, which lets us store just one to three bytes per + token (generally far fewer than the number of coefficients, due to EOB + tokens and zero runs), and which requires us to only maintain a counter for + each of the 64 coefficients, instead of a counter for every fragment to + determine where the next token goes. + + We actually use 3 counters per coefficient, one for each color plane, so we + can decode all color planes simultaneously. + This lets color conversion, etc., be done as soon as a full MCU (one or + two super block rows) is decoded, while the image data is still in cache.*/ + +static void oc_dec_residual_tokens_unpack(oc_dec_ctx *_dec){ + static const unsigned char OC_HUFF_LIST_MAX[5]={1,6,15,28,64}; + ptrdiff_t ntoks_left[3][64]; + int huff_idxs[2]; + ptrdiff_t eobs; + long val; + int pli; + int zzi; + int hgi; + for(pli=0;pli<3;pli++)for(zzi=0;zzi<64;zzi++){ + ntoks_left[pli][zzi]=_dec->state.ncoded_fragis[pli]; + } + val=oc_pack_read(&_dec->opb,4); + huff_idxs[0]=(int)val; + val=oc_pack_read(&_dec->opb,4); + huff_idxs[1]=(int)val; + _dec->eob_runs[0][0]=0; + eobs=oc_dec_dc_coeff_unpack(_dec,huff_idxs,ntoks_left); +#if defined(HAVE_CAIRO) + _dec->telemetry_dc_bytes=oc_pack_bytes_left(&_dec->opb); +#endif + val=oc_pack_read(&_dec->opb,4); + huff_idxs[0]=(int)val; + val=oc_pack_read(&_dec->opb,4); + huff_idxs[1]=(int)val; + zzi=1; + for(hgi=1;hgi<5;hgi++){ + huff_idxs[0]+=16; + huff_idxs[1]+=16; + for(;zzipp_level<=OC_PP_LEVEL_DISABLED){ + if(_dec->dc_qis!=NULL){ + _ogg_free(_dec->dc_qis); + _dec->dc_qis=NULL; + _ogg_free(_dec->variances); + _dec->variances=NULL; + _ogg_free(_dec->pp_frame_data); + _dec->pp_frame_data=NULL; + } + return 1; + } + if(_dec->dc_qis==NULL){ + /*If we haven't been tracking DC quantization indices, there's no point in + starting now.*/ + if(_dec->state.frame_type!=OC_INTRA_FRAME)return 1; + _dec->dc_qis=(unsigned char *)_ogg_malloc( + _dec->state.nfrags*sizeof(_dec->dc_qis[0])); + if(_dec->dc_qis==NULL)return 1; + memset(_dec->dc_qis,_dec->state.qis[0],_dec->state.nfrags); + } + else{ + unsigned char *dc_qis; + const ptrdiff_t *coded_fragis; + ptrdiff_t ncoded_fragis; + ptrdiff_t fragii; + unsigned char qi0; + /*Update the DC quantization index of each coded block.*/ + dc_qis=_dec->dc_qis; + coded_fragis=_dec->state.coded_fragis; + ncoded_fragis=_dec->state.ncoded_fragis[0]+ + _dec->state.ncoded_fragis[1]+_dec->state.ncoded_fragis[2]; + qi0=(unsigned char)_dec->state.qis[0]; + for(fragii=0;fragiipp_level<=OC_PP_LEVEL_TRACKDCQI){ + if(_dec->variances!=NULL){ + _ogg_free(_dec->variances); + _dec->variances=NULL; + _ogg_free(_dec->pp_frame_data); + _dec->pp_frame_data=NULL; + } + return 1; + } + if(_dec->variances==NULL){ + size_t frame_sz; + size_t c_sz; + int c_w; + int c_h; + frame_sz=_dec->state.info.frame_width*(size_t)_dec->state.info.frame_height; + c_w=_dec->state.info.frame_width>>!(_dec->state.info.pixel_fmt&1); + c_h=_dec->state.info.frame_height>>!(_dec->state.info.pixel_fmt&2); + c_sz=c_w*(size_t)c_h; + /*Allocate space for the chroma planes, even if we're not going to use + them; this simplifies allocation state management, though it may waste + memory on the few systems that don't overcommit pages.*/ + frame_sz+=c_sz<<1; + _dec->pp_frame_data=(unsigned char *)_ogg_malloc( + frame_sz*sizeof(_dec->pp_frame_data[0])); + _dec->variances=(int *)_ogg_malloc( + _dec->state.nfrags*sizeof(_dec->variances[0])); + if(_dec->variances==NULL||_dec->pp_frame_data==NULL){ + _ogg_free(_dec->pp_frame_data); + _dec->pp_frame_data=NULL; + _ogg_free(_dec->variances); + _dec->variances=NULL; + return 1; + } + /*Force an update of the PP buffer pointers.*/ + _dec->pp_frame_state=0; + } + /*Update the PP buffer pointers if necessary.*/ + if(_dec->pp_frame_state!=1+(_dec->pp_level>=OC_PP_LEVEL_DEBLOCKC)){ + if(_dec->pp_levelpp_frame_buf[0].width=_dec->state.info.frame_width; + _dec->pp_frame_buf[0].height=_dec->state.info.frame_height; + _dec->pp_frame_buf[0].stride=-_dec->pp_frame_buf[0].width; + _dec->pp_frame_buf[0].data=_dec->pp_frame_data+ + (1-_dec->pp_frame_buf[0].height)*(ptrdiff_t)_dec->pp_frame_buf[0].stride; + } + else{ + size_t y_sz; + size_t c_sz; + int c_w; + int c_h; + /*Otherwise, set up pointers to all three PP planes.*/ + y_sz=_dec->state.info.frame_width*(size_t)_dec->state.info.frame_height; + c_w=_dec->state.info.frame_width>>!(_dec->state.info.pixel_fmt&1); + c_h=_dec->state.info.frame_height>>!(_dec->state.info.pixel_fmt&2); + c_sz=c_w*(size_t)c_h; + _dec->pp_frame_buf[0].width=_dec->state.info.frame_width; + _dec->pp_frame_buf[0].height=_dec->state.info.frame_height; + _dec->pp_frame_buf[0].stride=_dec->pp_frame_buf[0].width; + _dec->pp_frame_buf[0].data=_dec->pp_frame_data; + _dec->pp_frame_buf[1].width=c_w; + _dec->pp_frame_buf[1].height=c_h; + _dec->pp_frame_buf[1].stride=_dec->pp_frame_buf[1].width; + _dec->pp_frame_buf[1].data=_dec->pp_frame_buf[0].data+y_sz; + _dec->pp_frame_buf[2].width=c_w; + _dec->pp_frame_buf[2].height=c_h; + _dec->pp_frame_buf[2].stride=_dec->pp_frame_buf[2].width; + _dec->pp_frame_buf[2].data=_dec->pp_frame_buf[1].data+c_sz; + oc_ycbcr_buffer_flip(_dec->pp_frame_buf,_dec->pp_frame_buf); + } + _dec->pp_frame_state=1+(_dec->pp_level>=OC_PP_LEVEL_DEBLOCKC); + } + /*If we're not processing chroma, copy the reference frame's chroma planes.*/ + if(_dec->pp_levelpp_frame_buf+1, + _dec->state.ref_frame_bufs[_dec->state.ref_frame_idx[OC_FRAME_SELF]]+1, + sizeof(_dec->pp_frame_buf[1])*2); + } + return 0; +} + + + +typedef struct{ + int bounding_values[256]; + ptrdiff_t ti[3][64]; + ptrdiff_t eob_runs[3][64]; + const ptrdiff_t *coded_fragis[3]; + const ptrdiff_t *uncoded_fragis[3]; + ptrdiff_t ncoded_fragis[3]; + ptrdiff_t nuncoded_fragis[3]; + const ogg_uint16_t *dequant[3][3][2]; + int fragy0[3]; + int fragy_end[3]; + int pred_last[3][3]; + int mcu_nvfrags; + int loop_filter; + int pp_level; +}oc_dec_pipeline_state; + + + +/*Initialize the main decoding pipeline.*/ +static void oc_dec_pipeline_init(oc_dec_ctx *_dec, + oc_dec_pipeline_state *_pipe){ + const ptrdiff_t *coded_fragis; + const ptrdiff_t *uncoded_fragis; + int pli; + int qii; + int qti; + /*If chroma is sub-sampled in the vertical direction, we have to decode two + super block rows of Y' for each super block row of Cb and Cr.*/ + _pipe->mcu_nvfrags=4<state.info.pixel_fmt&2); + /*Initialize the token and extra bits indices for each plane and + coefficient.*/ + memcpy(_pipe->ti,_dec->ti0,sizeof(_pipe->ti)); + /*Also copy over the initial the EOB run counts.*/ + memcpy(_pipe->eob_runs,_dec->eob_runs,sizeof(_pipe->eob_runs)); + /*Set up per-plane pointers to the coded and uncoded fragments lists.*/ + coded_fragis=_dec->state.coded_fragis; + uncoded_fragis=coded_fragis+_dec->state.nfrags; + for(pli=0;pli<3;pli++){ + ptrdiff_t ncoded_fragis; + _pipe->coded_fragis[pli]=coded_fragis; + _pipe->uncoded_fragis[pli]=uncoded_fragis; + ncoded_fragis=_dec->state.ncoded_fragis[pli]; + coded_fragis+=ncoded_fragis; + uncoded_fragis+=ncoded_fragis-_dec->state.fplanes[pli].nfrags; + } + /*Set up condensed quantizer tables.*/ + for(pli=0;pli<3;pli++){ + for(qii=0;qii<_dec->state.nqis;qii++){ + for(qti=0;qti<2;qti++){ + _pipe->dequant[pli][qii][qti]= + _dec->state.dequant_tables[_dec->state.qis[qii]][pli][qti]; + } + } + } + /*Set the previous DC predictor to 0 for all color planes and frame types.*/ + memset(_pipe->pred_last,0,sizeof(_pipe->pred_last)); + /*Initialize the bounding value array for the loop filter.*/ + _pipe->loop_filter=!oc_state_loop_filter_init(&_dec->state, + _pipe->bounding_values); + /*Initialize any buffers needed for post-processing. + We also save the current post-processing level, to guard against the user + changing it from a callback.*/ + if(!oc_dec_postprocess_init(_dec))_pipe->pp_level=_dec->pp_level; + /*If we don't have enough information to post-process, disable it, regardless + of the user-requested level.*/ + else{ + _pipe->pp_level=OC_PP_LEVEL_DISABLED; + memcpy(_dec->pp_frame_buf, + _dec->state.ref_frame_bufs[_dec->state.ref_frame_idx[OC_FRAME_SELF]], + sizeof(_dec->pp_frame_buf[0])*3); + } +} + +/*Undo the DC prediction in a single plane of an MCU (one or two super block + rows). + As a side effect, the number of coded and uncoded fragments in this plane of + the MCU is also computed.*/ +static void oc_dec_dc_unpredict_mcu_plane(oc_dec_ctx *_dec, + oc_dec_pipeline_state *_pipe,int _pli){ + const oc_fragment_plane *fplane; + oc_fragment *frags; + int *pred_last; + ptrdiff_t ncoded_fragis; + ptrdiff_t fragi; + int fragx; + int fragy; + int fragy0; + int fragy_end; + int nhfrags; + /*Compute the first and last fragment row of the current MCU for this + plane.*/ + fplane=_dec->state.fplanes+_pli; + fragy0=_pipe->fragy0[_pli]; + fragy_end=_pipe->fragy_end[_pli]; + nhfrags=fplane->nhfrags; + pred_last=_pipe->pred_last[_pli]; + frags=_dec->state.frags; + ncoded_fragis=0; + fragi=fplane->froffset+fragy0*(ptrdiff_t)nhfrags; + for(fragy=fragy0;fragy=nhfrags)ur_ref=-1; + else{ + ur_ref=u_frags[fragi+1].coded? + OC_FRAME_FOR_MODE(u_frags[fragi+1].mb_mode):-1; + } + if(frags[fragi].coded){ + int pred; + int ref; + ref=OC_FRAME_FOR_MODE(frags[fragi].mb_mode); + /*We break out a separate case based on which of our neighbors use + the same reference frames. + This is somewhat faster than trying to make a generic case which + handles all of them, since it reduces lots of poorly predicted + jumps to one switch statement, and also lets a number of the + multiplications be optimized out by strength reduction.*/ + switch((l_ref==ref)|(ul_ref==ref)<<1| + (u_ref==ref)<<2|(ur_ref==ref)<<3){ + default:pred=pred_last[ref];break; + case 1: + case 3:pred=frags[fragi-1].dc;break; + case 2:pred=u_frags[fragi-1].dc;break; + case 4: + case 6: + case 12:pred=u_frags[fragi].dc;break; + case 5:pred=(frags[fragi-1].dc+u_frags[fragi].dc)/2;break; + case 8:pred=u_frags[fragi+1].dc;break; + case 9: + case 11: + case 13:{ + pred=(75*frags[fragi-1].dc+53*u_frags[fragi+1].dc)/128; + }break; + case 10:pred=(u_frags[fragi-1].dc+u_frags[fragi+1].dc)/2;break; + case 14:{ + pred=(3*(u_frags[fragi-1].dc+u_frags[fragi+1].dc) + +10*u_frags[fragi].dc)/16; + }break; + case 7: + case 15:{ + int p0; + int p1; + int p2; + p0=frags[fragi-1].dc; + p1=u_frags[fragi-1].dc; + p2=u_frags[fragi].dc; + pred=(29*(p0+p2)-26*p1)/32; + if(abs(pred-p2)>128)pred=p2; + else if(abs(pred-p0)>128)pred=p0; + else if(abs(pred-p1)>128)pred=p1; + }break; + } + pred_last[ref]=frags[fragi].dc+=pred; + ncoded_fragis++; + l_ref=ref; + } + else l_ref=-1; + ul_ref=u_ref; + u_ref=ur_ref; + } + } + } + _pipe->ncoded_fragis[_pli]=ncoded_fragis; + /*Also save the number of uncoded fragments so we know how many to copy.*/ + _pipe->nuncoded_fragis[_pli]= + (fragy_end-fragy0)*(ptrdiff_t)nhfrags-ncoded_fragis; +} + +/*Reconstructs all coded fragments in a single MCU (one or two super block + rows). + This requires that each coded fragment have a proper macro block mode and + motion vector (if not in INTRA mode), and have it's DC value decoded, with + the DC prediction process reversed, and the number of coded and uncoded + fragments in this plane of the MCU be counted. + The token lists for each color plane and coefficient should also be filled + in, along with initial token offsets, extra bits offsets, and EOB run + counts.*/ +static void oc_dec_frags_recon_mcu_plane(oc_dec_ctx *_dec, + oc_dec_pipeline_state *_pipe,int _pli){ + unsigned char *dct_tokens; + const unsigned char *dct_fzig_zag; + ogg_uint16_t dc_quant[2]; + const oc_fragment *frags; + const ptrdiff_t *coded_fragis; + ptrdiff_t ncoded_fragis; + ptrdiff_t fragii; + ptrdiff_t *ti; + ptrdiff_t *eob_runs; + int qti; + dct_tokens=_dec->dct_tokens; + dct_fzig_zag=_dec->state.opt_data.dct_fzig_zag; + frags=_dec->state.frags; + coded_fragis=_pipe->coded_fragis[_pli]; + ncoded_fragis=_pipe->ncoded_fragis[_pli]; + ti=_pipe->ti[_pli]; + eob_runs=_pipe->eob_runs[_pli]; + for(qti=0;qti<2;qti++)dc_quant[qti]=_pipe->dequant[_pli][0][qti][0]; + for(fragii=0;fragiidequant[_pli][frags[fragi].qii][qti]; + /*Decode the AC coefficients.*/ + for(zzi=0;zzi<64;){ + int token; + last_zzi=zzi; + if(eob_runs[zzi]){ + eob_runs[zzi]--; + break; + } + else{ + ptrdiff_t eob; + int cw; + int rlen; + int coeff; + int lti; + lti=ti[zzi]; + token=dct_tokens[lti++]; + cw=OC_DCT_CODE_WORD[token]; + /*These parts could be done branchless, but the branches are fairly + predictable and the C code translates into more than a few + instructions, so it's worth it to avoid them.*/ + if(OC_DCT_TOKEN_NEEDS_MORE(token)){ + cw+=dct_tokens[lti++]<>OC_DCT_CW_EOB_SHIFT&0xFFF; + if(token==OC_DCT_TOKEN_FAT_EOB){ + eob+=dct_tokens[lti++]<<8; + if(eob==0)eob=OC_DCT_EOB_FINISH; + } + rlen=(unsigned char)(cw>>OC_DCT_CW_RLEN_SHIFT); + cw^=-(cw&1<>OC_DCT_CW_MAG_SHIFT; + eob_runs[zzi]=eob; + ti[zzi]=lti; + zzi+=rlen; + dct_coeffs[dct_fzig_zag[zzi]]=(ogg_int16_t)(coeff*(int)ac_quant[zzi]); + zzi+=!eob; + } + } + /*TODO: zzi should be exactly 64 here. + If it's not, we should report some kind of warning.*/ + zzi=OC_MINI(zzi,64); + dct_coeffs[0]=(ogg_int16_t)frags[fragi].dc; + /*last_zzi is always initialized. + If your compiler thinks otherwise, it is dumb.*/ + oc_state_frag_recon(&_dec->state,fragi,_pli, + dct_coeffs,last_zzi,dc_quant[qti]); + } + _pipe->coded_fragis[_pli]+=ncoded_fragis; + /*Right now the reconstructed MCU has only the coded blocks in it.*/ + /*TODO: We make the decision here to always copy the uncoded blocks into it + from the reference frame. + We could also copy the coded blocks back over the reference frame, if we + wait for an additional MCU to be decoded, which might be faster if only a + small number of blocks are coded. + However, this introduces more latency, creating a larger cache footprint. + It's unknown which decision is better, but this one results in simpler + code, and the hard case (high bitrate, high resolution) is handled + correctly.*/ + /*Copy the uncoded blocks from the previous reference frame.*/ + _pipe->uncoded_fragis[_pli]-=_pipe->nuncoded_fragis[_pli]; + oc_state_frag_copy_list(&_dec->state,_pipe->uncoded_fragis[_pli], + _pipe->nuncoded_fragis[_pli],OC_FRAME_SELF,OC_FRAME_PREV,_pli); +} + +/*Filter a horizontal block edge.*/ +static void oc_filter_hedge(unsigned char *_dst,int _dst_ystride, + const unsigned char *_src,int _src_ystride,int _qstep,int _flimit, + int *_variance0,int *_variance1){ + unsigned char *rdst; + const unsigned char *rsrc; + unsigned char *cdst; + const unsigned char *csrc; + int r[10]; + int sum0; + int sum1; + int bx; + int by; + rdst=_dst; + rsrc=_src; + for(bx=0;bx<8;bx++){ + cdst=rdst; + csrc=rsrc; + for(by=0;by<10;by++){ + r[by]=*csrc; + csrc+=_src_ystride; + } + sum0=sum1=0; + for(by=0;by<4;by++){ + sum0+=abs(r[by+1]-r[by]); + sum1+=abs(r[by+5]-r[by+6]); + } + *_variance0+=OC_MINI(255,sum0); + *_variance1+=OC_MINI(255,sum1); + if(sum0<_flimit&&sum1<_flimit&&r[5]-r[4]<_qstep&&r[4]-r[5]<_qstep){ + *cdst=(unsigned char)(r[0]*3+r[1]*2+r[2]+r[3]+r[4]+4>>3); + cdst+=_dst_ystride; + *cdst=(unsigned char)(r[0]*2+r[1]+r[2]*2+r[3]+r[4]+r[5]+4>>3); + cdst+=_dst_ystride; + for(by=0;by<4;by++){ + *cdst=(unsigned char)(r[by]+r[by+1]+r[by+2]+r[by+3]*2+ + r[by+4]+r[by+5]+r[by+6]+4>>3); + cdst+=_dst_ystride; + } + *cdst=(unsigned char)(r[4]+r[5]+r[6]+r[7]*2+r[8]+r[9]*2+4>>3); + cdst+=_dst_ystride; + *cdst=(unsigned char)(r[5]+r[6]+r[7]+r[8]*2+r[9]*3+4>>3); + } + else{ + for(by=1;by<=8;by++){ + *cdst=(unsigned char)r[by]; + cdst+=_dst_ystride; + } + } + rdst++; + rsrc++; + } +} + +/*Filter a vertical block edge.*/ +static void oc_filter_vedge(unsigned char *_dst,int _dst_ystride, + int _qstep,int _flimit,int *_variances){ + unsigned char *rdst; + const unsigned char *rsrc; + unsigned char *cdst; + int r[10]; + int sum0; + int sum1; + int bx; + int by; + cdst=_dst; + for(by=0;by<8;by++){ + rsrc=cdst-1; + rdst=cdst; + for(bx=0;bx<10;bx++)r[bx]=*rsrc++; + sum0=sum1=0; + for(bx=0;bx<4;bx++){ + sum0+=abs(r[bx+1]-r[bx]); + sum1+=abs(r[bx+5]-r[bx+6]); + } + _variances[0]+=OC_MINI(255,sum0); + _variances[1]+=OC_MINI(255,sum1); + if(sum0<_flimit&&sum1<_flimit&&r[5]-r[4]<_qstep&&r[4]-r[5]<_qstep){ + *rdst++=(unsigned char)(r[0]*3+r[1]*2+r[2]+r[3]+r[4]+4>>3); + *rdst++=(unsigned char)(r[0]*2+r[1]+r[2]*2+r[3]+r[4]+r[5]+4>>3); + for(bx=0;bx<4;bx++){ + *rdst++=(unsigned char)(r[bx]+r[bx+1]+r[bx+2]+r[bx+3]*2+ + r[bx+4]+r[bx+5]+r[bx+6]+4>>3); + } + *rdst++=(unsigned char)(r[4]+r[5]+r[6]+r[7]*2+r[8]+r[9]*2+4>>3); + *rdst=(unsigned char)(r[5]+r[6]+r[7]+r[8]*2+r[9]*3+4>>3); + } + cdst+=_dst_ystride; + } +} + +static void oc_dec_deblock_frag_rows(oc_dec_ctx *_dec, + th_img_plane *_dst,th_img_plane *_src,int _pli,int _fragy0, + int _fragy_end){ + oc_fragment_plane *fplane; + int *variance; + unsigned char *dc_qi; + unsigned char *dst; + const unsigned char *src; + ptrdiff_t froffset; + int dst_ystride; + int src_ystride; + int nhfrags; + int width; + int notstart; + int notdone; + int flimit; + int qstep; + int y_end; + int y; + int x; + _dst+=_pli; + _src+=_pli; + fplane=_dec->state.fplanes+_pli; + nhfrags=fplane->nhfrags; + froffset=fplane->froffset+_fragy0*(ptrdiff_t)nhfrags; + variance=_dec->variances+froffset; + dc_qi=_dec->dc_qis+froffset; + notstart=_fragy0>0; + notdone=_fragy_endnvfrags; + /*We want to clear an extra row of variances, except at the end.*/ + memset(variance+(nhfrags&-notstart),0, + (_fragy_end+notdone-_fragy0-notstart)*(nhfrags*sizeof(variance[0]))); + /*Except for the first time, we want to point to the middle of the row.*/ + y=(_fragy0<<3)+(notstart<<2); + dst_ystride=_dst->stride; + src_ystride=_src->stride; + dst=_dst->data+y*(ptrdiff_t)dst_ystride; + src=_src->data+y*(ptrdiff_t)src_ystride; + width=_dst->width; + for(;y<4;y++){ + memcpy(dst,src,width*sizeof(dst[0])); + dst+=dst_ystride; + src+=src_ystride; + } + /*We also want to skip the last row in the frame for this loop.*/ + y_end=_fragy_end-!notdone<<3; + for(;ypp_dc_scale[*dc_qi]; + flimit=(qstep*3)>>2; + oc_filter_hedge(dst,dst_ystride,src-src_ystride,src_ystride, + qstep,flimit,variance,variance+nhfrags); + variance++; + dc_qi++; + for(x=8;xpp_dc_scale[*dc_qi]; + flimit=(qstep*3)>>2; + oc_filter_hedge(dst+x,dst_ystride,src+x-src_ystride,src_ystride, + qstep,flimit,variance,variance+nhfrags); + oc_filter_vedge(dst+x-(dst_ystride<<2)-4,dst_ystride, + qstep,flimit,variance-1); + variance++; + dc_qi++; + } + dst+=dst_ystride<<3; + src+=src_ystride<<3; + } + /*And finally, handle the last row in the frame, if it's in the range.*/ + if(!notdone){ + int height; + height=_dst->height; + for(;ypp_dc_scale[*dc_qi++]; + flimit=(qstep*3)>>2; + oc_filter_vedge(dst+x-(dst_ystride<<3)-4,dst_ystride, + qstep,flimit,variance++); + } + } +} + +static void oc_dering_block(unsigned char *_idata,int _ystride,int _b, + int _dc_scale,int _sharp_mod,int _strong){ + static const unsigned char OC_MOD_MAX[2]={24,32}; + static const unsigned char OC_MOD_SHIFT[2]={1,0}; + const unsigned char *psrc; + const unsigned char *src; + const unsigned char *nsrc; + unsigned char *dst; + int vmod[72]; + int hmod[72]; + int mod_hi; + int by; + int bx; + mod_hi=OC_MINI(3*_dc_scale,OC_MOD_MAX[_strong]); + dst=_idata; + src=dst; + psrc=src-(_ystride&-!(_b&4)); + for(by=0;by<9;by++){ + for(bx=0;bx<8;bx++){ + int mod; + mod=32+_dc_scale-(abs(src[bx]-psrc[bx])<>7); + for(bx=1;bx<7;bx++){ + a=128; + b=64; + w=hmod[(bx<<3)+by]; + a-=w; + b+=w*src[bx-1]; + w=vmod[(by<<3)+bx]; + a-=w; + b+=w*psrc[bx]; + w=vmod[(by+1<<3)+bx]; + a-=w; + b+=w*nsrc[bx]; + w=hmod[(bx+1<<3)+by]; + a-=w; + b+=w*src[bx+1]; + dst[bx]=OC_CLAMP255(a*src[bx]+b>>7); + } + a=128; + b=64; + w=hmod[(7<<3)+by]; + a-=w; + b+=w*src[6]; + w=vmod[(by<<3)+7]; + a-=w; + b+=w*psrc[7]; + w=vmod[(by+1<<3)+7]; + a-=w; + b+=w*nsrc[7]; + w=hmod[(8<<3)+by]; + a-=w; + b+=w*src[7+!(_b&2)]; + dst[7]=OC_CLAMP255(a*src[7]+b>>7); + dst+=_ystride; + psrc=src; + src=nsrc; + nsrc+=_ystride&-(!(_b&8)|by<6); + } +} + +#define OC_DERING_THRESH1 (384) +#define OC_DERING_THRESH2 (4*OC_DERING_THRESH1) +#define OC_DERING_THRESH3 (5*OC_DERING_THRESH1) +#define OC_DERING_THRESH4 (10*OC_DERING_THRESH1) + +static void oc_dec_dering_frag_rows(oc_dec_ctx *_dec,th_img_plane *_img, + int _pli,int _fragy0,int _fragy_end){ + th_img_plane *iplane; + oc_fragment_plane *fplane; + oc_fragment *frag; + int *variance; + unsigned char *idata; + ptrdiff_t froffset; + int ystride; + int nhfrags; + int sthresh; + int strong; + int y_end; + int width; + int height; + int y; + int x; + iplane=_img+_pli; + fplane=_dec->state.fplanes+_pli; + nhfrags=fplane->nhfrags; + froffset=fplane->froffset+_fragy0*(ptrdiff_t)nhfrags; + variance=_dec->variances+froffset; + frag=_dec->state.frags+froffset; + strong=_dec->pp_level>=(_pli?OC_PP_LEVEL_SDERINGC:OC_PP_LEVEL_SDERINGY); + sthresh=_pli?OC_DERING_THRESH4:OC_DERING_THRESH3; + y=_fragy0<<3; + ystride=iplane->stride; + idata=iplane->data+y*(ptrdiff_t)ystride; + y_end=_fragy_end<<3; + width=iplane->width; + height=iplane->height; + for(;ystate.qis[frag->qii]; + var=*variance; + b=(x<=0)|(x+8>=width)<<1|(y<=0)<<2|(y+8>=height)<<3; + if(strong&&var>sthresh){ + oc_dering_block(idata+x,ystride,b, + _dec->pp_dc_scale[qi],_dec->pp_sharp_mod[qi],1); + if(_pli||!(b&1)&&*(variance-1)>OC_DERING_THRESH4|| + !(b&2)&&variance[1]>OC_DERING_THRESH4|| + !(b&4)&&*(variance-nhfrags)>OC_DERING_THRESH4|| + !(b&8)&&variance[nhfrags]>OC_DERING_THRESH4){ + oc_dering_block(idata+x,ystride,b, + _dec->pp_dc_scale[qi],_dec->pp_sharp_mod[qi],1); + oc_dering_block(idata+x,ystride,b, + _dec->pp_dc_scale[qi],_dec->pp_sharp_mod[qi],1); + } + } + else if(var>OC_DERING_THRESH2){ + oc_dering_block(idata+x,ystride,b, + _dec->pp_dc_scale[qi],_dec->pp_sharp_mod[qi],1); + } + else if(var>OC_DERING_THRESH1){ + oc_dering_block(idata+x,ystride,b, + _dec->pp_dc_scale[qi],_dec->pp_sharp_mod[qi],0); + } + frag++; + variance++; + } + idata+=ystride<<3; + } +} + + + +th_dec_ctx *th_decode_alloc(const th_info *_info,const th_setup_info *_setup){ + oc_dec_ctx *dec; + if(_info==NULL||_setup==NULL)return NULL; + dec=_ogg_malloc(sizeof(*dec)); + if(dec==NULL||oc_dec_init(dec,_info,_setup)<0){ + _ogg_free(dec); + return NULL; + } + dec->state.curframe_num=0; + return dec; +} + +void th_decode_free(th_dec_ctx *_dec){ + if(_dec!=NULL){ + oc_dec_clear(_dec); + _ogg_free(_dec); + } +} + +int th_decode_ctl(th_dec_ctx *_dec,int _req,void *_buf, + size_t _buf_sz){ + switch(_req){ + case TH_DECCTL_GET_PPLEVEL_MAX:{ + if(_dec==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(int))return TH_EINVAL; + (*(int *)_buf)=OC_PP_LEVEL_MAX; + return 0; + }break; + case TH_DECCTL_SET_PPLEVEL:{ + int pp_level; + if(_dec==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(int))return TH_EINVAL; + pp_level=*(int *)_buf; + if(pp_level<0||pp_level>OC_PP_LEVEL_MAX)return TH_EINVAL; + _dec->pp_level=pp_level; + return 0; + }break; + case TH_DECCTL_SET_GRANPOS:{ + ogg_int64_t granpos; + if(_dec==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(ogg_int64_t))return TH_EINVAL; + granpos=*(ogg_int64_t *)_buf; + if(granpos<0)return TH_EINVAL; + _dec->state.granpos=granpos; + _dec->state.keyframe_num=(granpos>>_dec->state.info.keyframe_granule_shift) + -_dec->state.granpos_bias; + _dec->state.curframe_num=_dec->state.keyframe_num + +(granpos&(1<<_dec->state.info.keyframe_granule_shift)-1); + return 0; + }break; + case TH_DECCTL_SET_STRIPE_CB:{ + th_stripe_callback *cb; + if(_dec==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(th_stripe_callback))return TH_EINVAL; + cb=(th_stripe_callback *)_buf; + _dec->stripe_cb.ctx=cb->ctx; + _dec->stripe_cb.stripe_decoded=cb->stripe_decoded; + return 0; + }break; +#ifdef HAVE_CAIRO + case TH_DECCTL_SET_TELEMETRY_MBMODE:{ + if(_dec==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(int))return TH_EINVAL; + _dec->telemetry=1; + _dec->telemetry_mbmode=*(int *)_buf; + return 0; + }break; + case TH_DECCTL_SET_TELEMETRY_MV:{ + if(_dec==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(int))return TH_EINVAL; + _dec->telemetry=1; + _dec->telemetry_mv=*(int *)_buf; + return 0; + }break; + case TH_DECCTL_SET_TELEMETRY_QI:{ + if(_dec==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(int))return TH_EINVAL; + _dec->telemetry=1; + _dec->telemetry_qi=*(int *)_buf; + return 0; + }break; + case TH_DECCTL_SET_TELEMETRY_BITS:{ + if(_dec==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(int))return TH_EINVAL; + _dec->telemetry=1; + _dec->telemetry_bits=*(int *)_buf; + return 0; + }break; +#endif + default:return TH_EIMPL; + } +} + +/*We're decoding an INTER frame, but have no initialized reference + buffers (i.e., decoding did not start on a key frame). + We initialize them to a solid gray here.*/ +static void oc_dec_init_dummy_frame(th_dec_ctx *_dec){ + th_info *info; + size_t yplane_sz; + size_t cplane_sz; + int yhstride; + int yheight; + int chstride; + int cheight; + _dec->state.ref_frame_idx[OC_FRAME_GOLD]=0; + _dec->state.ref_frame_idx[OC_FRAME_PREV]=0; + _dec->state.ref_frame_idx[OC_FRAME_SELF]=1; + info=&_dec->state.info; + yhstride=info->frame_width+2*OC_UMV_PADDING; + yheight=info->frame_height+2*OC_UMV_PADDING; + chstride=yhstride>>!(info->pixel_fmt&1); + cheight=yheight>>!(info->pixel_fmt&2); + yplane_sz=yhstride*(size_t)yheight; + cplane_sz=chstride*(size_t)cheight; + memset(_dec->state.ref_frame_data[0],0x80,yplane_sz+2*cplane_sz); +} + +int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op, + ogg_int64_t *_granpos){ + int ret; + if(_dec==NULL||_op==NULL)return TH_EFAULT; + /*A completely empty packet indicates a dropped frame and is treated exactly + like an inter frame with no coded blocks. + Only proceed if we have a non-empty packet.*/ + if(_op->bytes!=0){ + oc_dec_pipeline_state pipe; + th_ycbcr_buffer stripe_buf; + int stripe_fragy; + int refi; + int pli; + int notstart; + int notdone; + oc_pack_readinit(&_dec->opb,_op->packet,_op->bytes); +#if defined(HAVE_CAIRO) + _dec->telemetry_frame_bytes=_op->bytes; +#endif + ret=oc_dec_frame_header_unpack(_dec); + if(ret<0)return ret; + /*Select a free buffer to use for the reconstructed version of this + frame.*/ + if(_dec->state.frame_type!=OC_INTRA_FRAME&& + (_dec->state.ref_frame_idx[OC_FRAME_GOLD]<0|| + _dec->state.ref_frame_idx[OC_FRAME_PREV]<0)){ + /*No reference frames yet!*/ + oc_dec_init_dummy_frame(_dec); + refi=_dec->state.ref_frame_idx[OC_FRAME_SELF]; + } + else{ + for(refi=0;refi==_dec->state.ref_frame_idx[OC_FRAME_GOLD]|| + refi==_dec->state.ref_frame_idx[OC_FRAME_PREV];refi++); + _dec->state.ref_frame_idx[OC_FRAME_SELF]=refi; + } + if(_dec->state.frame_type==OC_INTRA_FRAME){ + oc_dec_mark_all_intra(_dec); + _dec->state.keyframe_num=_dec->state.curframe_num; +#if defined(HAVE_CAIRO) + _dec->telemetry_coding_bytes= + _dec->telemetry_mode_bytes= + _dec->telemetry_mv_bytes=oc_pack_bytes_left(&_dec->opb); +#endif + } + else{ + oc_dec_coded_flags_unpack(_dec); +#if defined(HAVE_CAIRO) + _dec->telemetry_coding_bytes=oc_pack_bytes_left(&_dec->opb); +#endif + oc_dec_mb_modes_unpack(_dec); +#if defined(HAVE_CAIRO) + _dec->telemetry_mode_bytes=oc_pack_bytes_left(&_dec->opb); +#endif + oc_dec_mv_unpack_and_frag_modes_fill(_dec); +#if defined(HAVE_CAIRO) + _dec->telemetry_mv_bytes=oc_pack_bytes_left(&_dec->opb); +#endif + } + oc_dec_block_qis_unpack(_dec); +#if defined(HAVE_CAIRO) + _dec->telemetry_qi_bytes=oc_pack_bytes_left(&_dec->opb); +#endif + oc_dec_residual_tokens_unpack(_dec); + /*Update granule position. + This must be done before the striped decode callbacks so that the + application knows what to do with the frame data.*/ + _dec->state.granpos=(_dec->state.keyframe_num+_dec->state.granpos_bias<< + _dec->state.info.keyframe_granule_shift) + +(_dec->state.curframe_num-_dec->state.keyframe_num); + _dec->state.curframe_num++; + if(_granpos!=NULL)*_granpos=_dec->state.granpos; + /*All of the rest of the operations -- DC prediction reversal, + reconstructing coded fragments, copying uncoded fragments, loop + filtering, extending borders, and out-of-loop post-processing -- should + be pipelined. + I.e., DC prediction reversal, reconstruction, and uncoded fragment + copying are done for one or two super block rows, then loop filtering is + run as far as it can, then bordering copying, then post-processing. + For 4:2:0 video a Minimum Codable Unit or MCU contains two luma super + block rows, and one chroma. + Otherwise, an MCU consists of one super block row from each plane. + Inside each MCU, we perform all of the steps on one color plane before + moving on to the next. + After reconstruction, the additional filtering stages introduce a delay + since they need some pixels from the next fragment row. + Thus the actual number of decoded rows available is slightly smaller for + the first MCU, and slightly larger for the last. + + This entire process allows us to operate on the data while it is still in + cache, resulting in big performance improvements. + An application callback allows further application processing (blitting + to video memory, color conversion, etc.) to also use the data while it's + in cache.*/ + oc_dec_pipeline_init(_dec,&pipe); + oc_ycbcr_buffer_flip(stripe_buf,_dec->pp_frame_buf); + notstart=0; + notdone=1; + for(stripe_fragy=0;notdone;stripe_fragy+=pipe.mcu_nvfrags){ + int avail_fragy0; + int avail_fragy_end; + avail_fragy0=avail_fragy_end=_dec->state.fplanes[0].nvfrags; + notdone=stripe_fragy+pipe.mcu_nvfragsstate.fplanes+pli; + /*Compute the first and last fragment row of the current MCU for this + plane.*/ + frag_shift=pli!=0&&!(_dec->state.info.pixel_fmt&2); + pipe.fragy0[pli]=stripe_fragy>>frag_shift; + pipe.fragy_end[pli]=OC_MINI(fplane->nvfrags, + pipe.fragy0[pli]+(pipe.mcu_nvfrags>>frag_shift)); + oc_dec_dc_unpredict_mcu_plane(_dec,&pipe,pli); + oc_dec_frags_recon_mcu_plane(_dec,&pipe,pli); + sdelay=edelay=0; + if(pipe.loop_filter){ + sdelay+=notstart; + edelay+=notdone; + oc_state_loop_filter_frag_rows(&_dec->state,pipe.bounding_values, + refi,pli,pipe.fragy0[pli]-sdelay,pipe.fragy_end[pli]-edelay); + } + /*To fill the borders, we have an additional two pixel delay, since a + fragment in the next row could filter its top edge, using two pixels + from a fragment in this row. + But there's no reason to delay a full fragment between the two.*/ + oc_state_borders_fill_rows(&_dec->state,refi,pli, + (pipe.fragy0[pli]-sdelay<<3)-(sdelay<<1), + (pipe.fragy_end[pli]-edelay<<3)-(edelay<<1)); + /*Out-of-loop post-processing.*/ + pp_offset=3*(pli!=0); + if(pipe.pp_level>=OC_PP_LEVEL_DEBLOCKY+pp_offset){ + /*Perform de-blocking in one plane.*/ + sdelay+=notstart; + edelay+=notdone; + oc_dec_deblock_frag_rows(_dec,_dec->pp_frame_buf, + _dec->state.ref_frame_bufs[refi],pli, + pipe.fragy0[pli]-sdelay,pipe.fragy_end[pli]-edelay); + if(pipe.pp_level>=OC_PP_LEVEL_DERINGY+pp_offset){ + /*Perform de-ringing in one plane.*/ + sdelay+=notstart; + edelay+=notdone; + oc_dec_dering_frag_rows(_dec,_dec->pp_frame_buf,pli, + pipe.fragy0[pli]-sdelay,pipe.fragy_end[pli]-edelay); + } + } + /*If no post-processing is done, we still need to delay a row for the + loop filter, thanks to the strange filtering order VP3 chose.*/ + else if(pipe.loop_filter){ + sdelay+=notstart; + edelay+=notdone; + } + /*Compute the intersection of the available rows in all planes. + If chroma is sub-sampled, the effect of each of its delays is + doubled, but luma might have more post-processing filters enabled + than chroma, so we don't know up front which one is the limiting + factor.*/ + avail_fragy0=OC_MINI(avail_fragy0,pipe.fragy0[pli]-sdelay<stripe_cb.stripe_decoded!=NULL){ + /*The callback might want to use the FPU, so let's make sure they can. + We violate all kinds of ABI restrictions by not doing this until + now, but none of them actually matter since we don't use floating + point ourselves.*/ + oc_restore_fpu(&_dec->state); + /*Make the callback, ensuring we flip the sense of the "start" and + "end" of the available region upside down.*/ + (*_dec->stripe_cb.stripe_decoded)(_dec->stripe_cb.ctx,stripe_buf, + _dec->state.fplanes[0].nvfrags-avail_fragy_end, + _dec->state.fplanes[0].nvfrags-avail_fragy0); + } + notstart=1; + } + /*Finish filling in the reference frame borders.*/ + for(pli=0;pli<3;pli++)oc_state_borders_fill_caps(&_dec->state,refi,pli); + /*Update the reference frame indices.*/ + if(_dec->state.frame_type==OC_INTRA_FRAME){ + /*The new frame becomes both the previous and gold reference frames.*/ + _dec->state.ref_frame_idx[OC_FRAME_GOLD]= + _dec->state.ref_frame_idx[OC_FRAME_PREV]= + _dec->state.ref_frame_idx[OC_FRAME_SELF]; + } + else{ + /*Otherwise, just replace the previous reference frame.*/ + _dec->state.ref_frame_idx[OC_FRAME_PREV]= + _dec->state.ref_frame_idx[OC_FRAME_SELF]; + } + /*Restore the FPU before dump_frame, since that _does_ use the FPU (for PNG + gamma values, if nothing else).*/ + oc_restore_fpu(&_dec->state); +#if defined(OC_DUMP_IMAGES) + /*Don't dump images for dropped frames.*/ + oc_state_dump_frame(&_dec->state,OC_FRAME_SELF,"dec"); +#endif + return 0; + } + else{ + if(_dec->state.ref_frame_idx[OC_FRAME_GOLD]<0|| + _dec->state.ref_frame_idx[OC_FRAME_PREV]<0){ + int refi; + /*No reference frames yet!*/ + oc_dec_init_dummy_frame(_dec); + refi=_dec->state.ref_frame_idx[OC_FRAME_PREV]; + _dec->state.ref_frame_idx[OC_FRAME_SELF]=refi; + memcpy(_dec->pp_frame_buf,_dec->state.ref_frame_bufs[refi], + sizeof(_dec->pp_frame_buf[0])*3); + } + /*Just update the granule position and return.*/ + _dec->state.granpos=(_dec->state.keyframe_num+_dec->state.granpos_bias<< + _dec->state.info.keyframe_granule_shift) + +(_dec->state.curframe_num-_dec->state.keyframe_num); + _dec->state.curframe_num++; + if(_granpos!=NULL)*_granpos=_dec->state.granpos; + return TH_DUPFRAME; + } +} + +int th_decode_ycbcr_out(th_dec_ctx *_dec,th_ycbcr_buffer _ycbcr){ + if(_dec==NULL||_ycbcr==NULL)return TH_EFAULT; + oc_ycbcr_buffer_flip(_ycbcr,_dec->pp_frame_buf); +#if defined(HAVE_CAIRO) + /*If telemetry ioctls are active, we need to draw to the output buffer. + Stuff the plane into cairo.*/ + if(_dec->telemetry){ + cairo_surface_t *cs; + unsigned char *data; + unsigned char *y_row; + unsigned char *u_row; + unsigned char *v_row; + unsigned char *rgb_row; + int cstride; + int w; + int h; + int x; + int y; + int hdec; + int vdec; + w=_ycbcr[0].width; + h=_ycbcr[0].height; + hdec=!(_dec->state.info.pixel_fmt&1); + vdec=!(_dec->state.info.pixel_fmt&2); + /*Lazy data buffer init. + We could try to re-use the post-processing buffer, which would save + memory, but complicate the allocation logic there. + I don't think anyone cares about memory usage when using telemetry; it is + not meant for embedded devices.*/ + if(_dec->telemetry_frame_data==NULL){ + _dec->telemetry_frame_data=_ogg_malloc( + (w*h+2*(w>>hdec)*(h>>vdec))*sizeof(*_dec->telemetry_frame_data)); + if(_dec->telemetry_frame_data==NULL)return 0; + } + cs=cairo_image_surface_create(CAIRO_FORMAT_RGB24,w,h); + /*Sadly, no YUV support in Cairo (yet); convert into the RGB buffer.*/ + data=cairo_image_surface_get_data(cs); + if(data==NULL){ + cairo_surface_destroy(cs); + return 0; + } + cstride=cairo_image_surface_get_stride(cs); + y_row=_ycbcr[0].data; + u_row=_ycbcr[1].data; + v_row=_ycbcr[2].data; + rgb_row=data; + for(y=0;y>hdec]-363703744)/1635200; + g=(3827562*y_row[x]-1287801*u_row[x>>hdec] + -2672387*v_row[x>>hdec]+447306710)/3287200; + b=(952000*y_row[x]+1649289*u_row[x>>hdec]-225932192)/817600; + rgb_row[4*x+0]=OC_CLAMP255(b); + rgb_row[4*x+1]=OC_CLAMP255(g); + rgb_row[4*x+2]=OC_CLAMP255(r); + } + y_row+=_ycbcr[0].stride; + u_row+=_ycbcr[1].stride&-((y&1)|!vdec); + v_row+=_ycbcr[2].stride&-((y&1)|!vdec); + rgb_row+=cstride; + } + /*Draw coded identifier for each macroblock (stored in Hilbert order).*/ + { + cairo_t *c; + const oc_fragment *frags; + oc_mv *frag_mvs; + const signed char *mb_modes; + oc_mb_map *mb_maps; + size_t nmbs; + size_t mbi; + int row2; + int col2; + int qim[3]={0,0,0}; + if(_dec->state.nqis==2){ + int bqi; + bqi=_dec->state.qis[0]; + if(_dec->state.qis[1]>bqi)qim[1]=1; + if(_dec->state.qis[1]state.nqis==3){ + int bqi; + int cqi; + int dqi; + bqi=_dec->state.qis[0]; + cqi=_dec->state.qis[1]; + dqi=_dec->state.qis[2]; + if(cqi>bqi&&dqi>bqi){ + if(dqi>cqi){ + qim[1]=1; + qim[2]=2; + } + else{ + qim[1]=2; + qim[2]=1; + } + } + else if(cqistate.frags; + frag_mvs=_dec->state.frag_mvs; + mb_modes=_dec->state.mb_modes; + mb_maps=_dec->state.mb_maps; + nmbs=_dec->state.nmbs; + row2=0; + col2=0; + for(mbi=0;mbi>1)&1))*16-16; + x=(col2>>1)*16; + cairo_set_line_width(c,1.); + /*Keyframe (all intra) red box.*/ + if(_dec->state.frame_type==OC_INTRA_FRAME){ + if(_dec->telemetry_mbmode&0x02){ + cairo_set_source_rgba(c,1.,0,0,.5); + cairo_rectangle(c,x+2.5,y+2.5,11,11); + cairo_stroke_preserve(c); + cairo_set_source_rgba(c,1.,0,0,.25); + cairo_fill(c); + } + } + else{ + const signed char *frag_mv; + ptrdiff_t fragi; + for(bi=0;bi<4;bi++){ + fragi=mb_maps[mbi][0][bi]; + if(fragi>=0&&frags[fragi].coded){ + frag_mv=frag_mvs[fragi]; + break; + } + } + if(bi<4){ + switch(mb_modes[mbi]){ + case OC_MODE_INTRA:{ + if(_dec->telemetry_mbmode&0x02){ + cairo_set_source_rgba(c,1.,0,0,.5); + cairo_rectangle(c,x+2.5,y+2.5,11,11); + cairo_stroke_preserve(c); + cairo_set_source_rgba(c,1.,0,0,.25); + cairo_fill(c); + } + }break; + case OC_MODE_INTER_NOMV:{ + if(_dec->telemetry_mbmode&0x01){ + cairo_set_source_rgba(c,0,0,1.,.5); + cairo_rectangle(c,x+2.5,y+2.5,11,11); + cairo_stroke_preserve(c); + cairo_set_source_rgba(c,0,0,1.,.25); + cairo_fill(c); + } + }break; + case OC_MODE_INTER_MV:{ + if(_dec->telemetry_mbmode&0x04){ + cairo_rectangle(c,x+2.5,y+2.5,11,11); + cairo_set_source_rgba(c,0,1.,0,.5); + cairo_stroke(c); + } + if(_dec->telemetry_mv&0x04){ + cairo_move_to(c,x+8+frag_mv[0],y+8-frag_mv[1]); + cairo_set_source_rgba(c,1.,1.,1.,.9); + cairo_set_line_width(c,3.); + cairo_line_to(c,x+8+frag_mv[0]*.66,y+8-frag_mv[1]*.66); + cairo_stroke_preserve(c); + cairo_set_line_width(c,2.); + cairo_line_to(c,x+8+frag_mv[0]*.33,y+8-frag_mv[1]*.33); + cairo_stroke_preserve(c); + cairo_set_line_width(c,1.); + cairo_line_to(c,x+8,y+8); + cairo_stroke(c); + } + }break; + case OC_MODE_INTER_MV_LAST:{ + if(_dec->telemetry_mbmode&0x08){ + cairo_rectangle(c,x+2.5,y+2.5,11,11); + cairo_set_source_rgba(c,0,1.,0,.5); + cairo_move_to(c,x+13.5,y+2.5); + cairo_line_to(c,x+2.5,y+8); + cairo_line_to(c,x+13.5,y+13.5); + cairo_stroke(c); + } + if(_dec->telemetry_mv&0x08){ + cairo_move_to(c,x+8+frag_mv[0],y+8-frag_mv[1]); + cairo_set_source_rgba(c,1.,1.,1.,.9); + cairo_set_line_width(c,3.); + cairo_line_to(c,x+8+frag_mv[0]*.66,y+8-frag_mv[1]*.66); + cairo_stroke_preserve(c); + cairo_set_line_width(c,2.); + cairo_line_to(c,x+8+frag_mv[0]*.33,y+8-frag_mv[1]*.33); + cairo_stroke_preserve(c); + cairo_set_line_width(c,1.); + cairo_line_to(c,x+8,y+8); + cairo_stroke(c); + } + }break; + case OC_MODE_INTER_MV_LAST2:{ + if(_dec->telemetry_mbmode&0x10){ + cairo_rectangle(c,x+2.5,y+2.5,11,11); + cairo_set_source_rgba(c,0,1.,0,.5); + cairo_move_to(c,x+8,y+2.5); + cairo_line_to(c,x+2.5,y+8); + cairo_line_to(c,x+8,y+13.5); + cairo_move_to(c,x+13.5,y+2.5); + cairo_line_to(c,x+8,y+8); + cairo_line_to(c,x+13.5,y+13.5); + cairo_stroke(c); + } + if(_dec->telemetry_mv&0x10){ + cairo_move_to(c,x+8+frag_mv[0],y+8-frag_mv[1]); + cairo_set_source_rgba(c,1.,1.,1.,.9); + cairo_set_line_width(c,3.); + cairo_line_to(c,x+8+frag_mv[0]*.66,y+8-frag_mv[1]*.66); + cairo_stroke_preserve(c); + cairo_set_line_width(c,2.); + cairo_line_to(c,x+8+frag_mv[0]*.33,y+8-frag_mv[1]*.33); + cairo_stroke_preserve(c); + cairo_set_line_width(c,1.); + cairo_line_to(c,x+8,y+8); + cairo_stroke(c); + } + }break; + case OC_MODE_GOLDEN_NOMV:{ + if(_dec->telemetry_mbmode&0x20){ + cairo_set_source_rgba(c,1.,1.,0,.5); + cairo_rectangle(c,x+2.5,y+2.5,11,11); + cairo_stroke_preserve(c); + cairo_set_source_rgba(c,1.,1.,0,.25); + cairo_fill(c); + } + }break; + case OC_MODE_GOLDEN_MV:{ + if(_dec->telemetry_mbmode&0x40){ + cairo_rectangle(c,x+2.5,y+2.5,11,11); + cairo_set_source_rgba(c,1.,1.,0,.5); + cairo_stroke(c); + } + if(_dec->telemetry_mv&0x40){ + cairo_move_to(c,x+8+frag_mv[0],y+8-frag_mv[1]); + cairo_set_source_rgba(c,1.,1.,1.,.9); + cairo_set_line_width(c,3.); + cairo_line_to(c,x+8+frag_mv[0]*.66,y+8-frag_mv[1]*.66); + cairo_stroke_preserve(c); + cairo_set_line_width(c,2.); + cairo_line_to(c,x+8+frag_mv[0]*.33,y+8-frag_mv[1]*.33); + cairo_stroke_preserve(c); + cairo_set_line_width(c,1.); + cairo_line_to(c,x+8,y+8); + cairo_stroke(c); + } + }break; + case OC_MODE_INTER_MV_FOUR:{ + if(_dec->telemetry_mbmode&0x80){ + cairo_rectangle(c,x+2.5,y+2.5,4,4); + cairo_rectangle(c,x+9.5,y+2.5,4,4); + cairo_rectangle(c,x+2.5,y+9.5,4,4); + cairo_rectangle(c,x+9.5,y+9.5,4,4); + cairo_set_source_rgba(c,0,1.,0,.5); + cairo_stroke(c); + } + /*4mv is odd, coded in raster order.*/ + fragi=mb_maps[mbi][0][0]; + if(frags[fragi].coded&&_dec->telemetry_mv&0x80){ + frag_mv=frag_mvs[fragi]; + cairo_move_to(c,x+4+frag_mv[0],y+12-frag_mv[1]); + cairo_set_source_rgba(c,1.,1.,1.,.9); + cairo_set_line_width(c,3.); + cairo_line_to(c,x+4+frag_mv[0]*.66,y+12-frag_mv[1]*.66); + cairo_stroke_preserve(c); + cairo_set_line_width(c,2.); + cairo_line_to(c,x+4+frag_mv[0]*.33,y+12-frag_mv[1]*.33); + cairo_stroke_preserve(c); + cairo_set_line_width(c,1.); + cairo_line_to(c,x+4,y+12); + cairo_stroke(c); + } + fragi=mb_maps[mbi][0][1]; + if(frags[fragi].coded&&_dec->telemetry_mv&0x80){ + frag_mv=frag_mvs[fragi]; + cairo_move_to(c,x+12+frag_mv[0],y+12-frag_mv[1]); + cairo_set_source_rgba(c,1.,1.,1.,.9); + cairo_set_line_width(c,3.); + cairo_line_to(c,x+12+frag_mv[0]*.66,y+12-frag_mv[1]*.66); + cairo_stroke_preserve(c); + cairo_set_line_width(c,2.); + cairo_line_to(c,x+12+frag_mv[0]*.33,y+12-frag_mv[1]*.33); + cairo_stroke_preserve(c); + cairo_set_line_width(c,1.); + cairo_line_to(c,x+12,y+12); + cairo_stroke(c); + } + fragi=mb_maps[mbi][0][2]; + if(frags[fragi].coded&&_dec->telemetry_mv&0x80){ + frag_mv=frag_mvs[fragi]; + cairo_move_to(c,x+4+frag_mv[0],y+4-frag_mv[1]); + cairo_set_source_rgba(c,1.,1.,1.,.9); + cairo_set_line_width(c,3.); + cairo_line_to(c,x+4+frag_mv[0]*.66,y+4-frag_mv[1]*.66); + cairo_stroke_preserve(c); + cairo_set_line_width(c,2.); + cairo_line_to(c,x+4+frag_mv[0]*.33,y+4-frag_mv[1]*.33); + cairo_stroke_preserve(c); + cairo_set_line_width(c,1.); + cairo_line_to(c,x+4,y+4); + cairo_stroke(c); + } + fragi=mb_maps[mbi][0][3]; + if(frags[fragi].coded&&_dec->telemetry_mv&0x80){ + frag_mv=frag_mvs[fragi]; + cairo_move_to(c,x+12+frag_mv[0],y+4-frag_mv[1]); + cairo_set_source_rgba(c,1.,1.,1.,.9); + cairo_set_line_width(c,3.); + cairo_line_to(c,x+12+frag_mv[0]*.66,y+4-frag_mv[1]*.66); + cairo_stroke_preserve(c); + cairo_set_line_width(c,2.); + cairo_line_to(c,x+12+frag_mv[0]*.33,y+4-frag_mv[1]*.33); + cairo_stroke_preserve(c); + cairo_set_line_width(c,1.); + cairo_line_to(c,x+12,y+4); + cairo_stroke(c); + } + }break; + } + } + } + /*qii illustration.*/ + if(_dec->telemetry_qi&0x2){ + cairo_set_line_cap(c,CAIRO_LINE_CAP_SQUARE); + for(bi=0;bi<4;bi++){ + ptrdiff_t fragi; + int qiv; + int xp; + int yp; + xp=x+(bi&1)*8; + yp=y+8-(bi&2)*4; + fragi=mb_maps[mbi][0][bi]; + if(fragi>=0&&frags[fragi].coded){ + qiv=qim[frags[fragi].qii]; + cairo_set_line_width(c,3.); + cairo_set_source_rgba(c,0.,0.,0.,.5); + switch(qiv){ + /*Double plus:*/ + case 2:{ + if((bi&1)^((bi&2)>>1)){ + cairo_move_to(c,xp+2.5,yp+1.5); + cairo_line_to(c,xp+2.5,yp+3.5); + cairo_move_to(c,xp+1.5,yp+2.5); + cairo_line_to(c,xp+3.5,yp+2.5); + cairo_move_to(c,xp+5.5,yp+4.5); + cairo_line_to(c,xp+5.5,yp+6.5); + cairo_move_to(c,xp+4.5,yp+5.5); + cairo_line_to(c,xp+6.5,yp+5.5); + cairo_stroke_preserve(c); + cairo_set_source_rgba(c,0.,1.,1.,1.); + } + else{ + cairo_move_to(c,xp+5.5,yp+1.5); + cairo_line_to(c,xp+5.5,yp+3.5); + cairo_move_to(c,xp+4.5,yp+2.5); + cairo_line_to(c,xp+6.5,yp+2.5); + cairo_move_to(c,xp+2.5,yp+4.5); + cairo_line_to(c,xp+2.5,yp+6.5); + cairo_move_to(c,xp+1.5,yp+5.5); + cairo_line_to(c,xp+3.5,yp+5.5); + cairo_stroke_preserve(c); + cairo_set_source_rgba(c,0.,1.,1.,1.); + } + }break; + /*Double minus:*/ + case -2:{ + cairo_move_to(c,xp+2.5,yp+2.5); + cairo_line_to(c,xp+5.5,yp+2.5); + cairo_move_to(c,xp+2.5,yp+5.5); + cairo_line_to(c,xp+5.5,yp+5.5); + cairo_stroke_preserve(c); + cairo_set_source_rgba(c,1.,1.,1.,1.); + }break; + /*Plus:*/ + case 1:{ + if(bi&2==0)yp-=2; + if(bi&1==0)xp-=2; + cairo_move_to(c,xp+4.5,yp+2.5); + cairo_line_to(c,xp+4.5,yp+6.5); + cairo_move_to(c,xp+2.5,yp+4.5); + cairo_line_to(c,xp+6.5,yp+4.5); + cairo_stroke_preserve(c); + cairo_set_source_rgba(c,.1,1.,.3,1.); + break; + } + /*Fall through.*/ + /*Minus:*/ + case -1:{ + cairo_move_to(c,xp+2.5,yp+4.5); + cairo_line_to(c,xp+6.5,yp+4.5); + cairo_stroke_preserve(c); + cairo_set_source_rgba(c,1.,.3,.1,1.); + }break; + default:continue; + } + cairo_set_line_width(c,1.); + cairo_stroke(c); + } + } + } + col2++; + if((col2>>1)>=_dec->state.nhmbs){ + col2=0; + row2+=2; + } + } + /*Bit usage indicator[s]:*/ + if(_dec->telemetry_bits){ + int widths[6]; + int fpsn; + int fpsd; + int mult; + int fullw; + int padw; + int i; + fpsn=_dec->state.info.fps_numerator; + fpsd=_dec->state.info.fps_denominator; + mult=(_dec->telemetry_bits>=0xFF?1:_dec->telemetry_bits); + fullw=250.f*h*fpsd*mult/fpsn; + padw=w-24; + /*Header and coded block bits.*/ + if(_dec->telemetry_frame_bytes<0|| + _dec->telemetry_frame_bytes==OC_LOTS_OF_BITS){ + _dec->telemetry_frame_bytes=0; + } + if(_dec->telemetry_coding_bytes<0|| + _dec->telemetry_coding_bytes>_dec->telemetry_frame_bytes){ + _dec->telemetry_coding_bytes=0; + } + if(_dec->telemetry_mode_bytes<0|| + _dec->telemetry_mode_bytes>_dec->telemetry_frame_bytes){ + _dec->telemetry_mode_bytes=0; + } + if(_dec->telemetry_mv_bytes<0|| + _dec->telemetry_mv_bytes>_dec->telemetry_frame_bytes){ + _dec->telemetry_mv_bytes=0; + } + if(_dec->telemetry_qi_bytes<0|| + _dec->telemetry_qi_bytes>_dec->telemetry_frame_bytes){ + _dec->telemetry_qi_bytes=0; + } + if(_dec->telemetry_dc_bytes<0|| + _dec->telemetry_dc_bytes>_dec->telemetry_frame_bytes){ + _dec->telemetry_dc_bytes=0; + } + widths[0]=padw*(_dec->telemetry_frame_bytes-_dec->telemetry_coding_bytes)/fullw; + widths[1]=padw*(_dec->telemetry_coding_bytes-_dec->telemetry_mode_bytes)/fullw; + widths[2]=padw*(_dec->telemetry_mode_bytes-_dec->telemetry_mv_bytes)/fullw; + widths[3]=padw*(_dec->telemetry_mv_bytes-_dec->telemetry_qi_bytes)/fullw; + widths[4]=padw*(_dec->telemetry_qi_bytes-_dec->telemetry_dc_bytes)/fullw; + widths[5]=padw*(_dec->telemetry_dc_bytes)/fullw; + for(i=0;i<6;i++)if(widths[i]>w)widths[i]=w; + cairo_set_source_rgba(c,.0,.0,.0,.6); + cairo_rectangle(c,10,h-33,widths[0]+1,5); + cairo_rectangle(c,10,h-29,widths[1]+1,5); + cairo_rectangle(c,10,h-25,widths[2]+1,5); + cairo_rectangle(c,10,h-21,widths[3]+1,5); + cairo_rectangle(c,10,h-17,widths[4]+1,5); + cairo_rectangle(c,10,h-13,widths[5]+1,5); + cairo_fill(c); + cairo_set_source_rgb(c,1,0,0); + cairo_rectangle(c,10.5,h-32.5,widths[0],4); + cairo_fill(c); + cairo_set_source_rgb(c,0,1,0); + cairo_rectangle(c,10.5,h-28.5,widths[1],4); + cairo_fill(c); + cairo_set_source_rgb(c,0,0,1); + cairo_rectangle(c,10.5,h-24.5,widths[2],4); + cairo_fill(c); + cairo_set_source_rgb(c,.6,.4,.0); + cairo_rectangle(c,10.5,h-20.5,widths[3],4); + cairo_fill(c); + cairo_set_source_rgb(c,.3,.3,.3); + cairo_rectangle(c,10.5,h-16.5,widths[4],4); + cairo_fill(c); + cairo_set_source_rgb(c,.5,.5,.8); + cairo_rectangle(c,10.5,h-12.5,widths[5],4); + cairo_fill(c); + } + /*Master qi indicator[s]:*/ + if(_dec->telemetry_qi&0x1){ + cairo_text_extents_t extents; + char buffer[10]; + int p; + int y; + p=0; + y=h-7.5; + if(_dec->state.qis[0]>=10)buffer[p++]=48+_dec->state.qis[0]/10; + buffer[p++]=48+_dec->state.qis[0]%10; + if(_dec->state.nqis>=2){ + buffer[p++]=' '; + if(_dec->state.qis[1]>=10)buffer[p++]=48+_dec->state.qis[1]/10; + buffer[p++]=48+_dec->state.qis[1]%10; + } + if(_dec->state.nqis==3){ + buffer[p++]=' '; + if(_dec->state.qis[2]>=10)buffer[p++]=48+_dec->state.qis[2]/10; + buffer[p++]=48+_dec->state.qis[2]%10; + } + buffer[p++]='\0'; + cairo_select_font_face(c,"sans", + CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size(c,18); + cairo_text_extents(c,buffer,&extents); + cairo_set_source_rgb(c,1,1,1); + cairo_move_to(c,w-extents.x_advance-10,y); + cairo_show_text(c,buffer); + cairo_set_source_rgb(c,0,0,0); + cairo_move_to(c,w-extents.x_advance-10,y); + cairo_text_path(c,buffer); + cairo_set_line_width(c,.8); + cairo_set_line_join(c,CAIRO_LINE_JOIN_ROUND); + cairo_stroke(c); + } + cairo_destroy(c); + } + /*Out of the Cairo plane into the telemetry YUV buffer.*/ + _ycbcr[0].data=_dec->telemetry_frame_data; + _ycbcr[0].stride=_ycbcr[0].width; + _ycbcr[1].data=_ycbcr[0].data+h*_ycbcr[0].stride; + _ycbcr[1].stride=_ycbcr[1].width; + _ycbcr[2].data=_ycbcr[1].data+(h>>vdec)*_ycbcr[1].stride; + _ycbcr[2].stride=_ycbcr[2].width; + y_row=_ycbcr[0].data; + u_row=_ycbcr[1].data; + v_row=_ycbcr[2].data; + rgb_row=data; + /*This is one of the few places it's worth handling chroma on a + case-by-case basis.*/ + switch(_dec->state.info.pixel_fmt){ + case TH_PF_420:{ + for(y=0;y>1]=OC_CLAMP255(u); + v_row[x>>1]=OC_CLAMP255(v); + } + y_row+=_ycbcr[0].stride<<1; + u_row+=_ycbcr[1].stride; + v_row+=_ycbcr[2].stride; + rgb_row+=cstride<<1; + } + }break; + case TH_PF_422:{ + for(y=0;y>1]=OC_CLAMP255(u); + v_row[x>>1]=OC_CLAMP255(v); + } + y_row+=_ycbcr[0].stride; + u_row+=_ycbcr[1].stride; + v_row+=_ycbcr[2].stride; + rgb_row+=cstride; + } + }break; + /*case TH_PF_444:*/ + default:{ + for(y=0;yloop_filter_limits[qi]=(unsigned char)val; } - theorapackB_read(_opb,4,&val); + val=oc_pack_read(_opb,4); nbits=(int)val+1; for(qi=0;qi<64;qi++){ - theorapackB_read(_opb,nbits,&val); + val=oc_pack_read(_opb,nbits); _qinfo->ac_scale[qi]=(ogg_uint16_t)val; } - theorapackB_read(_opb,4,&val); + val=oc_pack_read(_opb,4); nbits=(int)val+1; for(qi=0;qi<64;qi++){ - theorapackB_read(_opb,nbits,&val); + val=oc_pack_read(_opb,nbits); _qinfo->dc_scale[qi]=(ogg_uint16_t)val; } - theorapackB_read(_opb,9,&val); + val=oc_pack_read(_opb,9); nbase_mats=(int)val+1; base_mats=_ogg_malloc(nbase_mats*sizeof(base_mats[0])); + if(base_mats==NULL)return TH_EFAULT; for(bmi=0;bmiqi_ranges[qti]+pli; if(i>0){ - theorapackB_read1(_opb,&val); + val=oc_pack_read1(_opb); if(!val){ int qtj; int plj; if(qti>0){ - theorapackB_read1(_opb,&val); + val=oc_pack_read1(_opb); if(val){ qtj=qti-1; plj=pli; @@ -95,13 +95,13 @@ int oc_quant_params_unpack(oggpack_buffer *_opb, continue; } } - theorapackB_read(_opb,nbits,&val); + val=oc_pack_read(_opb,nbits); indices[0]=(int)val; for(qi=qri=0;qi<63;){ - theorapackB_read(_opb,oc_ilog(62-qi),&val); + val=oc_pack_read(_opb,oc_ilog(62-qi)); sizes[qri]=(int)val+1; qi+=(int)val+1; - theorapackB_read(_opb,nbits,&val); + val=oc_pack_read(_opb,nbits); indices[++qri]=(int)val; } /*Note: The caller is responsible for cleaning up any partially @@ -112,8 +112,20 @@ int oc_quant_params_unpack(oggpack_buffer *_opb, } qranges->nranges=qri; qranges->sizes=qrsizes=(int *)_ogg_malloc(qri*sizeof(qrsizes[0])); + if(qranges->sizes==NULL){ + /*Note: The caller is responsible for cleaning up any partially + constructed qinfo.*/ + _ogg_free(base_mats); + return TH_EFAULT; + } memcpy(qrsizes,sizes,qri*sizeof(qrsizes[0])); qrbms=(th_quant_base *)_ogg_malloc((qri+1)*sizeof(qrbms[0])); + if(qrbms==NULL){ + /*Note: The caller is responsible for cleaning up any partially + constructed qinfo.*/ + _ogg_free(base_mats); + return TH_EFAULT; + } qranges->base_matrices=(const th_quant_base *)qrbms; do{ bmi=indices[qri]; diff --git a/Engine/lib/libtheora/lib/dec/dequant.h b/Engine/lib/libtheora/lib/dequant.h similarity index 82% rename from Engine/lib/libtheora/lib/dec/dequant.h rename to Engine/lib/libtheora/lib/dequant.h index 928b509e5..ef25838e3 100644 --- a/Engine/lib/libtheora/lib/dec/dequant.h +++ b/Engine/lib/libtheora/lib/dequant.h @@ -5,21 +5,22 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: dequant.h 15400 2008-10-15 12:10:58Z tterribe $ + last mod: $Id: dequant.h 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ #if !defined(_dequant_H) # define _dequant_H (1) # include "quant.h" +# include "bitpack.h" -int oc_quant_params_unpack(oggpack_buffer *_opb, +int oc_quant_params_unpack(oc_pack_buf *_opb, th_quant_info *_qinfo); void oc_quant_params_clear(th_quant_info *_qinfo); diff --git a/Engine/lib/libtheora/lib/enc/block_inline.h b/Engine/lib/libtheora/lib/enc/block_inline.h deleted file mode 100644 index 008977095..000000000 --- a/Engine/lib/libtheora/lib/enc/block_inline.h +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: block_inline.h 14059 2007-10-28 23:43:27Z xiphmont $ - - ********************************************************************/ - -#include "codec_internal.h" - -static const ogg_int32_t MBOrderMap[4] = { 0, 2, 3, 1 }; -static const ogg_int32_t BlockOrderMap1[4][4] = { - { 0, 1, 3, 2 }, - { 0, 2, 3, 1 }, - { 0, 2, 3, 1 }, - { 3, 2, 0, 1 } -}; - -static ogg_int32_t QuadMapToIndex1( ogg_int32_t (*BlockMap)[4][4], - ogg_uint32_t SB, ogg_uint32_t MB, - ogg_uint32_t B ){ - return BlockMap[SB][MBOrderMap[MB]][BlockOrderMap1[MB][B]]; -} - -static ogg_int32_t QuadMapToMBTopLeft( ogg_int32_t (*BlockMap)[4][4], - ogg_uint32_t SB, ogg_uint32_t MB ){ - return BlockMap[SB][MBOrderMap[MB]][0]; -} diff --git a/Engine/lib/libtheora/lib/enc/blockmap.c b/Engine/lib/libtheora/lib/enc/blockmap.c deleted file mode 100644 index 5f3478fc2..000000000 --- a/Engine/lib/libtheora/lib/enc/blockmap.c +++ /dev/null @@ -1,99 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: blockmap.c 14059 2007-10-28 23:43:27Z xiphmont $ - - ********************************************************************/ - -#include "codec_internal.h" - -static void CreateMapping ( ogg_int32_t (*BlockMap)[4][4], - ogg_uint32_t FirstSB, - ogg_uint32_t FirstFrag, ogg_uint32_t HFrags, - ogg_uint32_t VFrags ){ - ogg_uint32_t i, j = 0; - ogg_uint32_t xpos; - ogg_uint32_t ypos; - ogg_uint32_t SBrow, SBcol; - ogg_uint32_t SBRows, SBCols; - ogg_uint32_t MB, B; - - ogg_uint32_t SB=FirstSB; - ogg_uint32_t FragIndex=FirstFrag; - - /* Set Super-Block dimensions */ - SBRows = VFrags/4 + ( VFrags%4 ? 1 : 0 ); - SBCols = HFrags/4 + ( HFrags%4 ? 1 : 0 ); - - /* Map each Super-Block */ - for ( SBrow=0; SBrow - FragIndex */ - - /* Coded flag arrays and counters for them */ - unsigned char *SBCodedFlags; - unsigned char *SBFullyFlags; - unsigned char *MBCodedFlags; - unsigned char *MBFullyFlags; - - /**********************************************************************/ - ogg_uint32_t EOB_Run; - - COORDINATE *FragCoordinates; - MOTION_VECTOR MVector; - ogg_int32_t ReconPtr2Offset; /* Offset for second reconstruction - in half pixel MC */ - Q_LIST_ENTRY *quantized_list; - ogg_int16_t *ReconDataBuffer; - Q_LIST_ENTRY InvLastIntraDC; - Q_LIST_ENTRY InvLastInterDC; - Q_LIST_ENTRY LastIntraDC; - Q_LIST_ENTRY LastInterDC; - - ogg_uint32_t BlocksToDecode; /* Blocks to be decoded this frame */ - ogg_uint32_t DcHuffChoice; /* Huffman table selection variables */ - unsigned char ACHuffChoice; - ogg_uint32_t QuadMBListIndex; - - ogg_int32_t ByteCount; - - ogg_uint32_t bit_pattern; - unsigned char bits_so_far; - unsigned char NextBit; - ogg_int32_t BitsLeft; - - ogg_int16_t *DequantBuffer; - - ogg_int32_t fp_quant_InterUV_coeffs[64]; - ogg_int32_t fp_quant_InterUV_round[64]; - ogg_int32_t fp_ZeroBinSize_InterUV[64]; - - ogg_int16_t *TmpReconBuffer; - ogg_int16_t *TmpDataBuffer; - - /* Loop filter bounding values */ - ogg_int16_t FiltBoundingValue[256]; - - /* Naming convention for all quant matrices and related data structures: - * Fields containing "Inter" in their name are for Inter frames, the - * rest is Intra. */ - - /* Dequantiser and rounding tables */ - ogg_uint16_t *QThreshTable; - Q_LIST_ENTRY dequant_Y_coeffs[64]; - Q_LIST_ENTRY dequant_U_coeffs[64]; - Q_LIST_ENTRY dequant_V_coeffs[64]; - Q_LIST_ENTRY dequant_InterY_coeffs[64]; - Q_LIST_ENTRY dequant_InterU_coeffs[64]; - Q_LIST_ENTRY dequant_InterV_coeffs[64]; - - Q_LIST_ENTRY *dequant_coeffs; /* currently active quantizer */ - unsigned int zigzag_index[64]; - - HUFF_ENTRY *HuffRoot_VP3x[NUM_HUFF_TABLES]; - ogg_uint32_t *HuffCodeArray_VP3x[NUM_HUFF_TABLES]; - unsigned char *HuffCodeLengthArray_VP3x[NUM_HUFF_TABLES]; - const unsigned char *ExtraBitLengths_VP3x; - - th_quant_info quant_info; - oc_quant_tables quant_tables[2][3]; - - /* Quantiser and rounding tables */ - /* this is scheduled to be replaced a new mechanism - that will simply reuse the dequantizer information. */ - ogg_int32_t fp_quant_Y_coeffs[64]; /* used in reiniting quantizers */ - ogg_int32_t fp_quant_U_coeffs[64]; - ogg_int32_t fp_quant_V_coeffs[64]; - ogg_int32_t fp_quant_Inter_Y_coeffs[64]; - ogg_int32_t fp_quant_Inter_U_coeffs[64]; - ogg_int32_t fp_quant_Inter_V_coeffs[64]; - - ogg_int32_t fp_quant_Y_round[64]; - ogg_int32_t fp_quant_U_round[64]; - ogg_int32_t fp_quant_V_round[64]; - ogg_int32_t fp_quant_Inter_Y_round[64]; - ogg_int32_t fp_quant_Inter_U_round[64]; - ogg_int32_t fp_quant_Inter_V_round[64]; - - ogg_int32_t fp_ZeroBinSize_Y[64]; - ogg_int32_t fp_ZeroBinSize_U[64]; - ogg_int32_t fp_ZeroBinSize_V[64]; - ogg_int32_t fp_ZeroBinSize_Inter_Y[64]; - ogg_int32_t fp_ZeroBinSize_Inter_U[64]; - ogg_int32_t fp_ZeroBinSize_Inter_V[64]; - - ogg_int32_t *fquant_coeffs; - ogg_int32_t *fquant_round; - ogg_int32_t *fquant_ZbSize; - - /* Predictor used in choosing entropy table for decoding block patterns. */ - unsigned char BlockPatternPredictor; - - short Modifier[4][512]; - short *ModifierPointer[4]; - - unsigned char *DataOutputInPtr; - - DspFunctions dsp; /* Selected functions for this platform */ - -}; - -/* Encoder (Compressor) instance -- installed in a theora_state */ -typedef struct CP_INSTANCE { - /*This structure must be first. - It contains entry points accessed by the decoder library's API wrapper, and - is the only assumption that library makes about our internal format.*/ - oc_state_dispatch_vtbl dispatch_vtbl; - - /* Compressor Configuration */ - SCAN_CONFIG_DATA ScanConfig; - CONFIG_TYPE2 Configuration; - int GoldenFrameEnabled; - int InterPrediction; - int MotionCompensation; - - ogg_uint32_t LastKeyFrame ; - ogg_int32_t DropCount ; - ogg_int32_t MaxConsDroppedFrames ; - ogg_int32_t DropFrameTriggerBytes; - int DropFrameCandidate; - - /* Compressor Statistics */ - double TotErrScore; - ogg_int64_t KeyFrameCount; /* Count of key frames. */ - ogg_int64_t TotKeyFrameBytes; - ogg_uint32_t LastKeyFrameSize; - ogg_uint32_t PriorKeyFrameSize[KEY_FRAME_CONTEXT]; - ogg_uint32_t PriorKeyFrameDistance[KEY_FRAME_CONTEXT]; - ogg_int32_t FrameQuality[6]; - int DecoderErrorCode; /* Decoder error flag. */ - ogg_int32_t ThreshMapThreshold; - ogg_int32_t TotalMotionScore; - ogg_int64_t TotalByteCount; - ogg_int32_t FixedQ; - - /* Frame Statistics */ - signed char InterCodeCount; - ogg_int64_t CurrentFrame; - ogg_int64_t CarryOver ; - ogg_uint32_t LastFrameSize; - ogg_uint32_t FrameBitCount; - int ThisIsFirstFrame; - int ThisIsKeyFrame; - - ogg_int32_t MotionScore; - ogg_uint32_t RegulationBlocks; - ogg_int32_t RecoveryMotionScore; - int RecoveryBlocksAdded ; - double ProportionRecBlocks; - double MaxRecFactor ; - - /* Rate Targeting variables. */ - ogg_uint32_t ThisFrameTargetBytes; - double BpbCorrectionFactor; - - /* Up regulation variables */ - ogg_uint32_t FinalPassLastPos; /* Used to regulate a final - unrestricted high quality - pass. */ - ogg_uint32_t LastEndSB; /* Where we were in the loop - last time. */ - ogg_uint32_t ResidueLastEndSB; /* Where we were in the residue - update loop last time. */ - - /* Controlling Block Selection */ - ogg_uint32_t MVChangeFactor; - ogg_uint32_t FourMvChangeFactor; - ogg_uint32_t MinImprovementForNewMV; - ogg_uint32_t ExhaustiveSearchThresh; - ogg_uint32_t MinImprovementForFourMV; - ogg_uint32_t FourMVThreshold; - - /* Module shared data structures. */ - ogg_int32_t frame_target_rate; - ogg_int32_t BaseLineFrameTargetRate; - ogg_int32_t min_blocks_per_frame; - ogg_uint32_t tot_bytes_old; - - /*********************************************************************/ - /* Frames Used in the selecetive convolution filtering of the Y plane. */ - unsigned char *ConvDestBuffer; - YUV_BUFFER_ENTRY *yuv0ptr; - YUV_BUFFER_ENTRY *yuv1ptr; - /*********************************************************************/ - - /*********************************************************************/ - /* Token Buffers */ - ogg_uint32_t *OptimisedTokenListEb; /* Optimised token list extra bits */ - unsigned char *OptimisedTokenList; /* Optimised token list. */ - unsigned char *OptimisedTokenListHi; /* Optimised token list huffman - table index */ - - unsigned char *OptimisedTokenListPl; /* Plane to which the token - belongs Y = 0 or UV = 1 */ - ogg_int32_t OptimisedTokenCount; /* Count of Optimized tokens */ - ogg_uint32_t RunHuffIndex; /* Huffman table in force at - the start of a run */ - ogg_uint32_t RunPlaneIndex; /* The plane (Y=0 UV=1) to - which the first token in - an EOB run belonged. */ - - - ogg_uint32_t TotTokenCount; - ogg_int32_t TokensToBeCoded; - ogg_int32_t TokensCoded; - /********************************************************************/ - - /* SuperBlock, MacroBLock and Fragment Information */ - /* Coded flag arrays and counters for them */ - unsigned char *PartiallyCodedFlags; - unsigned char *PartiallyCodedMbPatterns; - unsigned char *UncodedMbFlags; - - unsigned char *extra_fragments; /* extra updates not - recommended by pre-processor */ - ogg_int16_t *OriginalDC; - - ogg_uint32_t *FragmentLastQ; /* Array used to keep track of - quality at which each - fragment was last - updated. */ - unsigned char *FragTokens; - ogg_uint32_t *FragTokenCounts; /* Number of tokens per fragment */ - - ogg_uint32_t *RunHuffIndices; - ogg_uint32_t *LastCodedErrorScore; - ogg_uint32_t *ModeList; - MOTION_VECTOR *MVList; - - unsigned char *BlockCodedFlags; - - ogg_uint32_t MvListCount; - ogg_uint32_t ModeListCount; - - - unsigned char *DataOutputBuffer; - /*********************************************************************/ - - ogg_uint32_t RunLength; - ogg_uint32_t MaxBitTarget; /* Cut off target for rate capping */ - double BitRateCapFactor; /* Factor relating delta frame target - to cut off target. */ - - unsigned char MBCodingMode; /* Coding mode flags */ - - ogg_int32_t MVPixelOffsetY[MAX_SEARCH_SITES]; - ogg_uint32_t InterTripOutThresh; - unsigned char MVEnabled; - ogg_uint32_t MotionVectorSearchCount; - ogg_uint32_t FrameMVSearcOunt; - ogg_int32_t MVSearchSteps; - ogg_int32_t MVOffsetX[MAX_SEARCH_SITES]; - ogg_int32_t MVOffsetY[MAX_SEARCH_SITES]; - ogg_int32_t HalfPixelRef2Offset[9]; /* Offsets for half pixel - compensation */ - signed char HalfPixelXOffset[9]; /* Half pixel MV offsets for X */ - signed char HalfPixelYOffset[9]; /* Half pixel MV offsets for Y */ - - ogg_uint32_t bit_pattern ; - unsigned char bits_so_far ; - ogg_uint32_t lastval ; - ogg_uint32_t lastrun ; - - Q_LIST_ENTRY *quantized_list; - - MOTION_VECTOR MVector; - ogg_uint32_t TempBitCount; - ogg_int16_t *DCT_codes; /* Buffer that stores the result of - Forward DCT */ - ogg_int16_t *DCTDataBuffer; /* Input data buffer for Forward DCT */ - - /* Motion compensation related variables */ - ogg_uint32_t MvMaxExtent; - - double QTargetModifier[Q_TABLE_SIZE]; - - /* instances (used for reconstructing buffers and to hold tokens etc.) */ - PP_INSTANCE pp; /* preprocessor */ - PB_INSTANCE pb; /* playback */ - - /* ogg bitpacker for use in packet coding, other API state */ - oggpack_buffer *oggbuffer; - int readyflag; - int packetflag; - int doneflag; - - DspFunctions dsp; /* Selected functions for this platform */ - -} CP_INSTANCE; - -#define clamp255(x) ((unsigned char)((((x)<0)-1) & ((x) | -((x)>255)))) - -extern void ConfigurePP( PP_INSTANCE *ppi, int Level ) ; -extern ogg_uint32_t YUVAnalyseFrame( PP_INSTANCE *ppi, - ogg_uint32_t * KFIndicator ); - -extern void ClearPPInstance(PP_INSTANCE *ppi); -extern void InitPPInstance(PP_INSTANCE *ppi, DspFunctions *funcs); -extern void InitPBInstance(PB_INSTANCE *pbi); -extern void ClearPBInstance(PB_INSTANCE *pbi); - -extern void IDct1( Q_LIST_ENTRY * InputData, - ogg_int16_t *QuantMatrix, - ogg_int16_t * OutputData ); - -extern void ReconIntra( PB_INSTANCE *pbi, unsigned char * ReconPtr, - ogg_int16_t * ChangePtr, ogg_uint32_t LineStep ); - -extern void ReconInter( PB_INSTANCE *pbi, unsigned char * ReconPtr, - unsigned char * RefPtr, ogg_int16_t * ChangePtr, - ogg_uint32_t LineStep ) ; - -extern void ReconInterHalfPixel2( PB_INSTANCE *pbi, unsigned char * ReconPtr, - unsigned char * RefPtr1, - unsigned char * RefPtr2, - ogg_int16_t * ChangePtr, - ogg_uint32_t LineStep ) ; - -extern void SetupLoopFilter(PB_INSTANCE *pbi); -extern void CopyBlock(unsigned char *src, - unsigned char *dest, - unsigned int srcstride); -extern void LoopFilter(PB_INSTANCE *pbi); -extern void ReconRefFrames (PB_INSTANCE *pbi); -extern void ExpandToken( Q_LIST_ENTRY * ExpandedBlock, - unsigned char * CoeffIndex, ogg_uint32_t Token, - ogg_int32_t ExtraBits ); -extern void ClearDownQFragData(PB_INSTANCE *pbi); - -extern void select_quantiser (PB_INSTANCE *pbi, int type); - -extern void quantize( PB_INSTANCE *pbi, - ogg_int16_t * DCT_block, - Q_LIST_ENTRY * quantized_list); -extern void UpdateQ( PB_INSTANCE *pbi, int NewQIndex ); -extern void UpdateQC( CP_INSTANCE *cpi, ogg_uint32_t NewQ ); -extern void fdct_short ( ogg_int16_t * InputData, ogg_int16_t * OutputData ); -extern ogg_uint32_t DPCMTokenizeBlock (CP_INSTANCE *cpi, - ogg_int32_t FragIndex); -extern void TransformQuantizeBlock (CP_INSTANCE *cpi, ogg_int32_t FragIndex, - ogg_uint32_t PixelsPerLine ) ; -extern void ClearFragmentInfo(PB_INSTANCE * pbi); -extern void InitFragmentInfo(PB_INSTANCE * pbi); -extern void ClearFrameInfo(PB_INSTANCE * pbi); -extern void InitFrameInfo(PB_INSTANCE * pbi, unsigned int FrameSize); -extern void InitializeFragCoordinates(PB_INSTANCE *pbi); -extern void InitFrameDetails(PB_INSTANCE *pbi); -extern void WriteQTables(PB_INSTANCE *pbi,oggpack_buffer *opb); -extern void InitQTables( PB_INSTANCE *pbi ); -extern void quant_tables_init( PB_INSTANCE *pbi, const th_quant_info *qinfo); -extern void InitHuffmanSet( PB_INSTANCE *pbi ); -extern void ClearHuffmanSet( PB_INSTANCE *pbi ); -extern int ReadHuffmanTrees(codec_setup_info *ci, oggpack_buffer *opb); -extern void WriteHuffmanTrees(HUFF_ENTRY *HuffRoot[NUM_HUFF_TABLES], - oggpack_buffer *opb); -extern void InitHuffmanTrees(PB_INSTANCE *pbi, const codec_setup_info *ci); -extern void ClearHuffmanTrees(HUFF_ENTRY *HuffRoot[NUM_HUFF_TABLES]); -extern int ReadFilterTables(codec_setup_info *ci, oggpack_buffer *opb); -extern void QuadDecodeDisplayFragments ( PB_INSTANCE *pbi ); -extern void PackAndWriteDFArray( CP_INSTANCE *cpi ); -extern void UpdateFragQIndex(PB_INSTANCE *pbi); -extern void PostProcess(PB_INSTANCE *pbi); -extern void InitMotionCompensation ( CP_INSTANCE *cpi ); -extern ogg_uint32_t GetMBIntraError (CP_INSTANCE *cpi, ogg_uint32_t FragIndex, - ogg_uint32_t PixelsPerLine ) ; -extern ogg_uint32_t GetMBInterError (CP_INSTANCE *cpi, - unsigned char * SrcPtr, - unsigned char * RefPtr, - ogg_uint32_t FragIndex, - ogg_int32_t LastXMV, - ogg_int32_t LastYMV, - ogg_uint32_t PixelsPerLine ) ; -extern void WriteFrameHeader( CP_INSTANCE *cpi) ; -extern ogg_uint32_t GetMBMVInterError (CP_INSTANCE *cpi, - unsigned char * RefFramePtr, - ogg_uint32_t FragIndex, - ogg_uint32_t PixelsPerLine, - ogg_int32_t *MVPixelOffset, - MOTION_VECTOR *MV ); -extern ogg_uint32_t GetMBMVExhaustiveSearch (CP_INSTANCE *cpi, - unsigned char * RefFramePtr, - ogg_uint32_t FragIndex, - ogg_uint32_t PixelsPerLine, - MOTION_VECTOR *MV ); -extern ogg_uint32_t GetFOURMVExhaustiveSearch (CP_INSTANCE *cpi, - unsigned char * RefFramePtr, - ogg_uint32_t FragIndex, - ogg_uint32_t PixelsPerLine, - MOTION_VECTOR *MV ) ; -extern ogg_uint32_t EncodeData(CP_INSTANCE *cpi); -extern ogg_uint32_t PickIntra( CP_INSTANCE *cpi, - ogg_uint32_t SBRows, - ogg_uint32_t SBCols); -extern ogg_uint32_t PickModes(CP_INSTANCE *cpi, - ogg_uint32_t SBRows, - ogg_uint32_t SBCols, - ogg_uint32_t PixelsPerLine, - ogg_uint32_t *InterError, - ogg_uint32_t *IntraError); - -extern CODING_MODE FrArrayUnpackMode(PB_INSTANCE *pbi); -extern void CreateBlockMapping ( ogg_int32_t (*BlockMap)[4][4], - ogg_uint32_t YSuperBlocks, - ogg_uint32_t UVSuperBlocks, - ogg_uint32_t HFrags, ogg_uint32_t VFrags ); -extern void UpRegulateDataStream (CP_INSTANCE *cpi, ogg_uint32_t RegulationQ, - ogg_int32_t RecoveryBlocks ) ; -extern void RegulateQ( CP_INSTANCE *cpi, ogg_int32_t UpdateScore ); -extern void CopyBackExtraFrags(CP_INSTANCE *cpi); - -extern void UpdateUMVBorder( PB_INSTANCE *pbi, - unsigned char * DestReconPtr ); -extern void PInitFrameInfo(PP_INSTANCE * ppi); - -extern double GetEstimatedBpb( CP_INSTANCE *cpi, ogg_uint32_t TargetQ ); -extern void ClearTmpBuffers(PB_INSTANCE * pbi); -extern void InitTmpBuffers(PB_INSTANCE * pbi); -extern void ScanYUVInit( PP_INSTANCE * ppi, - SCAN_CONFIG_DATA * ScanConfigPtr); - -#endif /* ENCODER_INTERNAL_H */ diff --git a/Engine/lib/libtheora/lib/enc/dct.c b/Engine/lib/libtheora/lib/enc/dct.c deleted file mode 100644 index 29bf8f269..000000000 --- a/Engine/lib/libtheora/lib/enc/dct.c +++ /dev/null @@ -1,268 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: dct.c 13884 2007-09-22 08:38:10Z giles $ - - ********************************************************************/ - -#include "codec_internal.h" -#include "dsp.h" -#include "../cpu.h" - -static ogg_int32_t xC1S7 = 64277; -static ogg_int32_t xC2S6 = 60547; -static ogg_int32_t xC3S5 = 54491; -static ogg_int32_t xC4S4 = 46341; -static ogg_int32_t xC5S3 = 36410; -static ogg_int32_t xC6S2 = 25080; -static ogg_int32_t xC7S1 = 12785; - -#define SIGNBITDUPPED(X) ((signed )(((X) & 0x80000000)) >> 31) -#define DOROUND(X) ( (SIGNBITDUPPED(X) & (0xffff)) + (X) ) - -static void fdct_short__c ( ogg_int16_t * InputData, ogg_int16_t * OutputData ){ - int loop; - - ogg_int32_t is07, is12, is34, is56; - ogg_int32_t is0734, is1256; - ogg_int32_t id07, id12, id34, id56; - - ogg_int32_t irot_input_x, irot_input_y; - ogg_int32_t icommon_product1; /* Re-used product (c4s4 * (s12 - s56)). */ - ogg_int32_t icommon_product2; /* Re-used product (c4s4 * (d12 + d56)). */ - - ogg_int32_t temp1, temp2; /* intermediate variable for computation */ - - ogg_int32_t InterData[64]; - ogg_int32_t *ip = InterData; - ogg_int16_t * op = OutputData; - for (loop = 0; loop < 8; loop++){ - /* Pre calculate some common sums and differences. */ - is07 = InputData[0] + InputData[7]; - is12 = InputData[1] + InputData[2]; - is34 = InputData[3] + InputData[4]; - is56 = InputData[5] + InputData[6]; - - id07 = InputData[0] - InputData[7]; - id12 = InputData[1] - InputData[2]; - id34 = InputData[3] - InputData[4]; - id56 = InputData[5] - InputData[6]; - - is0734 = is07 + is34; - is1256 = is12 + is56; - - /* Pre-Calculate some common product terms. */ - icommon_product1 = xC4S4*(is12 - is56); - icommon_product1 = DOROUND(icommon_product1); - icommon_product1>>=16; - - icommon_product2 = xC4S4*(id12 + id56); - icommon_product2 = DOROUND(icommon_product2); - icommon_product2>>=16; - - - ip[0] = (xC4S4*(is0734 + is1256)); - ip[0] = DOROUND(ip[0]); - ip[0] >>= 16; - - ip[4] = (xC4S4*(is0734 - is1256)); - ip[4] = DOROUND(ip[4]); - ip[4] >>= 16; - - /* Define inputs to rotation for outputs 2 and 6 */ - irot_input_x = id12 - id56; - irot_input_y = is07 - is34; - - /* Apply rotation for outputs 2 and 6. */ - temp1=xC6S2*irot_input_x; - temp1=DOROUND(temp1); - temp1>>=16; - temp2=xC2S6*irot_input_y; - temp2=DOROUND(temp2); - temp2>>=16; - ip[2] = temp1 + temp2; - - temp1=xC6S2*irot_input_y; - temp1=DOROUND(temp1); - temp1>>=16; - temp2=xC2S6*irot_input_x ; - temp2=DOROUND(temp2); - temp2>>=16; - ip[6] = temp1 -temp2 ; - - /* Define inputs to rotation for outputs 1 and 7 */ - irot_input_x = icommon_product1 + id07; - irot_input_y = -( id34 + icommon_product2 ); - - /* Apply rotation for outputs 1 and 7. */ - - temp1=xC1S7*irot_input_x; - temp1=DOROUND(temp1); - temp1>>=16; - temp2=xC7S1*irot_input_y; - temp2=DOROUND(temp2); - temp2>>=16; - ip[1] = temp1 - temp2; - - temp1=xC7S1*irot_input_x; - temp1=DOROUND(temp1); - temp1>>=16; - temp2=xC1S7*irot_input_y ; - temp2=DOROUND(temp2); - temp2>>=16; - ip[7] = temp1 + temp2 ; - - /* Define inputs to rotation for outputs 3 and 5 */ - irot_input_x = id07 - icommon_product1; - irot_input_y = id34 - icommon_product2; - - /* Apply rotation for outputs 3 and 5. */ - temp1=xC3S5*irot_input_x; - temp1=DOROUND(temp1); - temp1>>=16; - temp2=xC5S3*irot_input_y ; - temp2=DOROUND(temp2); - temp2>>=16; - ip[3] = temp1 - temp2 ; - - temp1=xC5S3*irot_input_x; - temp1=DOROUND(temp1); - temp1>>=16; - temp2=xC3S5*irot_input_y; - temp2=DOROUND(temp2); - temp2>>=16; - ip[5] = temp1 + temp2; - - /* Increment data pointer for next row. */ - InputData += 8 ; - ip += 8; /* advance pointer to next row */ - - } - - - /* Performed DCT on rows, now transform the columns */ - ip = InterData; - for (loop = 0; loop < 8; loop++){ - /* Pre calculate some common sums and differences. */ - is07 = ip[0 * 8] + ip[7 * 8]; - is12 = ip[1 * 8] + ip[2 * 8]; - is34 = ip[3 * 8] + ip[4 * 8]; - is56 = ip[5 * 8] + ip[6 * 8]; - - id07 = ip[0 * 8] - ip[7 * 8]; - id12 = ip[1 * 8] - ip[2 * 8]; - id34 = ip[3 * 8] - ip[4 * 8]; - id56 = ip[5 * 8] - ip[6 * 8]; - - is0734 = is07 + is34; - is1256 = is12 + is56; - - /* Pre-Calculate some common product terms. */ - icommon_product1 = xC4S4*(is12 - is56) ; - icommon_product2 = xC4S4*(id12 + id56) ; - icommon_product1 = DOROUND(icommon_product1); - icommon_product2 = DOROUND(icommon_product2); - icommon_product1>>=16; - icommon_product2>>=16; - - - temp1 = xC4S4*(is0734 + is1256) ; - temp2 = xC4S4*(is0734 - is1256) ; - temp1 = DOROUND(temp1); - temp2 = DOROUND(temp2); - temp1>>=16; - temp2>>=16; - op[0*8] = (ogg_int16_t) temp1; - op[4*8] = (ogg_int16_t) temp2; - - /* Define inputs to rotation for outputs 2 and 6 */ - irot_input_x = id12 - id56; - irot_input_y = is07 - is34; - - /* Apply rotation for outputs 2 and 6. */ - temp1=xC6S2*irot_input_x; - temp1=DOROUND(temp1); - temp1>>=16; - temp2=xC2S6*irot_input_y; - temp2=DOROUND(temp2); - temp2>>=16; - op[2*8] = (ogg_int16_t) (temp1 + temp2); - - temp1=xC6S2*irot_input_y; - temp1=DOROUND(temp1); - temp1>>=16; - temp2=xC2S6*irot_input_x ; - temp2=DOROUND(temp2); - temp2>>=16; - op[6*8] = (ogg_int16_t) (temp1 -temp2) ; - - /* Define inputs to rotation for outputs 1 and 7 */ - irot_input_x = icommon_product1 + id07; - irot_input_y = -( id34 + icommon_product2 ); - - /* Apply rotation for outputs 1 and 7. */ - temp1=xC1S7*irot_input_x; - temp1=DOROUND(temp1); - temp1>>=16; - temp2=xC7S1*irot_input_y; - temp2=DOROUND(temp2); - temp2>>=16; - op[1*8] = (ogg_int16_t) (temp1 - temp2); - - temp1=xC7S1*irot_input_x; - temp1=DOROUND(temp1); - temp1>>=16; - temp2=xC1S7*irot_input_y ; - temp2=DOROUND(temp2); - temp2>>=16; - op[7*8] = (ogg_int16_t) (temp1 + temp2); - - /* Define inputs to rotation for outputs 3 and 5 */ - irot_input_x = id07 - icommon_product1; - irot_input_y = id34 - icommon_product2; - - /* Apply rotation for outputs 3 and 5. */ - temp1=xC3S5*irot_input_x; - temp1=DOROUND(temp1); - temp1>>=16; - temp2=xC5S3*irot_input_y ; - temp2=DOROUND(temp2); - temp2>>=16; - op[3*8] = (ogg_int16_t) (temp1 - temp2) ; - - temp1=xC5S3*irot_input_x; - temp1=DOROUND(temp1); - temp1>>=16; - temp2=xC3S5*irot_input_y; - temp2=DOROUND(temp2); - temp2>>=16; - op[5*8] = (ogg_int16_t) (temp1 + temp2); - - /* Increment data pointer for next column. */ - ip ++; - op ++; - } -} - -void dsp_dct_init (DspFunctions *funcs, ogg_uint32_t cpu_flags) -{ - funcs->fdct_short = fdct_short__c; - dsp_dct_decode_init(funcs, cpu_flags); - dsp_idct_init(funcs, cpu_flags); -#if defined(USE_ASM) - if (cpu_flags & OC_CPU_X86_MMX) { - dsp_mmx_fdct_init(funcs); - } -#endif -} - diff --git a/Engine/lib/libtheora/lib/enc/dct_decode.c b/Engine/lib/libtheora/lib/enc/dct_decode.c deleted file mode 100644 index e27611610..000000000 --- a/Engine/lib/libtheora/lib/enc/dct_decode.c +++ /dev/null @@ -1,941 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: dct_decode.c 15400 2008-10-15 12:10:58Z tterribe $ - - ********************************************************************/ - -#include -#include -#include "codec_internal.h" -#include "quant_lookup.h" - - -#define GOLDEN_FRAME_THRESH_Q 50 -#define PUR 8 -#define PU 4 -#define PUL 2 -#define PL 1 -#define HIGHBITDUPPED(X) (((signed short) X) >> 15) - - -static const int ModeUsesMC[MAX_MODES] = { 0, 0, 1, 1, 1, 0, 1, 1 }; - -static void SetupBoundingValueArray_Generic(ogg_int16_t *BoundingValuePtr, - ogg_int32_t FLimit){ - - ogg_int32_t i; - - /* Set up the bounding value array. */ - memset ( BoundingValuePtr, 0, (256*sizeof(*BoundingValuePtr)) ); - for ( i = 0; i < FLimit; i++ ){ - BoundingValuePtr[127-i-FLimit] = (-FLimit+i); - BoundingValuePtr[127-i] = -i; - BoundingValuePtr[127+i] = i; - BoundingValuePtr[127+i+FLimit] = FLimit-i; - } -} - -static void ExpandKFBlock ( PB_INSTANCE *pbi, ogg_int32_t FragmentNumber ){ - ogg_uint32_t ReconPixelsPerLine; - ogg_int32_t ReconPixelIndex; - - /* Select the appropriate inverse Q matrix and line stride */ - if ( FragmentNumber<(ogg_int32_t)pbi->YPlaneFragments ){ - ReconPixelsPerLine = pbi->YStride; - pbi->dequant_coeffs = pbi->dequant_Y_coeffs; - }else if ( FragmentNumber<(ogg_int32_t)(pbi->YPlaneFragments + pbi->UVPlaneFragments) ){ - ReconPixelsPerLine = pbi->UVStride; - pbi->dequant_coeffs = pbi->dequant_U_coeffs; - }else{ - ReconPixelsPerLine = pbi->UVStride; - pbi->dequant_coeffs = pbi->dequant_V_coeffs; - } - - /* Set up pointer into the quantisation buffer. */ - pbi->quantized_list = &pbi->QFragData[FragmentNumber][0]; - - /* Invert quantisation and DCT to get pixel data. */ - switch(pbi->FragCoefEOB[FragmentNumber]){ - case 0:case 1: - IDct1( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer ); - break; - case 2: case 3: - dsp_IDct3(pbi->dsp, pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer ); - break; - case 4:case 5:case 6:case 7:case 8: case 9:case 10: - dsp_IDct10(pbi->dsp, pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer ); - break; - default: - dsp_IDctSlow(pbi->dsp, pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer ); - } - - /* Convert fragment number to a pixel offset in a reconstruction buffer. */ - ReconPixelIndex = pbi->recon_pixel_index_table[FragmentNumber]; - - /* Get the pixel index for the first pixel in the fragment. */ - dsp_recon_intra8x8 (pbi->dsp, (unsigned char *)(&pbi->ThisFrameRecon[ReconPixelIndex]), - (ogg_int16_t *)pbi->ReconDataBuffer, ReconPixelsPerLine); -} - -static void ExpandBlock ( PB_INSTANCE *pbi, ogg_int32_t FragmentNumber){ - unsigned char *LastFrameRecPtr; /* Pointer into previous frame - reconstruction. */ - unsigned char *LastFrameRecPtr2; /* Pointer into previous frame - reconstruction for 1/2 pixel MC. */ - - ogg_uint32_t ReconPixelsPerLine; /* Pixels per line */ - ogg_int32_t ReconPixelIndex; /* Offset for block into a - reconstruction buffer */ - ogg_int32_t ReconPtr2Offset; /* Offset for second - reconstruction in half pixel - MC */ - ogg_int32_t MVOffset; /* Baseline motion vector offset */ - ogg_int32_t MvShift ; /* Shift to correct to 1/2 or 1/4 pixel */ - ogg_int32_t MvModMask; /* Mask to determine whether 1/2 - pixel is used */ - - /* Get coding mode for this block */ - if ( pbi->FrameType == KEY_FRAME ){ - pbi->CodingMode = CODE_INTRA; - }else{ - /* Get Motion vector and mode for this block. */ - pbi->CodingMode = pbi->FragCodingMethod[FragmentNumber]; - } - - /* Select the appropriate inverse Q matrix and line stride */ - if ( FragmentNumber<(ogg_int32_t)pbi->YPlaneFragments ) { - ReconPixelsPerLine = pbi->YStride; - MvShift = 1; - MvModMask = 0x00000001; - - /* Select appropriate dequantiser matrix. */ - if ( pbi->CodingMode == CODE_INTRA ) - pbi->dequant_coeffs = pbi->dequant_Y_coeffs; - else - pbi->dequant_coeffs = pbi->dequant_InterY_coeffs; - }else{ - ReconPixelsPerLine = pbi->UVStride; - MvShift = 2; - MvModMask = 0x00000003; - - /* Select appropriate dequantiser matrix. */ - if ( pbi->CodingMode == CODE_INTRA ) - if ( FragmentNumber < - (ogg_int32_t)(pbi->YPlaneFragments + pbi->UVPlaneFragments) ) - pbi->dequant_coeffs = pbi->dequant_U_coeffs; - else - pbi->dequant_coeffs = pbi->dequant_V_coeffs; - else - if ( FragmentNumber < - (ogg_int32_t)(pbi->YPlaneFragments + pbi->UVPlaneFragments) ) - pbi->dequant_coeffs = pbi->dequant_InterU_coeffs; - else - pbi->dequant_coeffs = pbi->dequant_InterV_coeffs; - } - - /* Set up pointer into the quantisation buffer. */ - pbi->quantized_list = &pbi->QFragData[FragmentNumber][0]; - - /* Invert quantisation and DCT to get pixel data. */ - switch(pbi->FragCoefEOB[FragmentNumber]){ - case 0:case 1: - IDct1( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer ); - break; - case 2: case 3: - dsp_IDct3(pbi->dsp, pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer ); - break; - case 4:case 5:case 6:case 7:case 8: case 9:case 10: - dsp_IDct10(pbi->dsp, pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer ); - break; - default: - dsp_IDctSlow(pbi->dsp, pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer ); - } - - /* Convert fragment number to a pixel offset in a reconstruction buffer. */ - ReconPixelIndex = pbi->recon_pixel_index_table[FragmentNumber]; - - /* Action depends on decode mode. */ - if ( pbi->CodingMode == CODE_INTER_NO_MV ){ - /* Inter with no motion vector */ - /* Reconstruct the pixel data using the last frame reconstruction - and change data when the motion vector is (0,0), the recon is - based on the lastframe without loop filtering---- for testing */ - dsp_recon_inter8x8 (pbi->dsp, &pbi->ThisFrameRecon[ReconPixelIndex], - &pbi->LastFrameRecon[ReconPixelIndex], - pbi->ReconDataBuffer, ReconPixelsPerLine); - }else if ( ModeUsesMC[pbi->CodingMode] ) { - /* The mode uses a motion vector. */ - /* Get vector from list */ - pbi->MVector.x = pbi->FragMVect[FragmentNumber].x; - pbi->MVector.y = pbi->FragMVect[FragmentNumber].y; - - /* Work out the base motion vector offset and the 1/2 pixel offset - if any. For the U and V planes the MV specifies 1/4 pixel - accuracy. This is adjusted to 1/2 pixel as follows ( 0->0, - 1/4->1/2, 1/2->1/2, 3/4->1/2 ). */ - MVOffset = 0; - ReconPtr2Offset = 0; - if ( pbi->MVector.x > 0 ){ - MVOffset = pbi->MVector.x >> MvShift; - if ( pbi->MVector.x & MvModMask ) - ReconPtr2Offset += 1; - } else if ( pbi->MVector.x < 0 ) { - MVOffset -= (-pbi->MVector.x) >> MvShift; - if ( (-pbi->MVector.x) & MvModMask ) - ReconPtr2Offset -= 1; - } - - if ( pbi->MVector.y > 0 ){ - MVOffset += (pbi->MVector.y >> MvShift) * ReconPixelsPerLine; - if ( pbi->MVector.y & MvModMask ) - ReconPtr2Offset += ReconPixelsPerLine; - } else if ( pbi->MVector.y < 0 ){ - MVOffset -= ((-pbi->MVector.y) >> MvShift) * ReconPixelsPerLine; - if ( (-pbi->MVector.y) & MvModMask ) - ReconPtr2Offset -= ReconPixelsPerLine; - } - - /* Set up the first of the two reconstruction buffer pointers. */ - if ( pbi->CodingMode==CODE_GOLDEN_MV ) { - LastFrameRecPtr = &pbi->GoldenFrame[ReconPixelIndex] + MVOffset; - }else{ - LastFrameRecPtr = &pbi->LastFrameRecon[ReconPixelIndex] + MVOffset; - } - - /* Set up the second of the two reconstruction pointers. */ - LastFrameRecPtr2 = LastFrameRecPtr + ReconPtr2Offset; - - /* Select the appropriate reconstruction function */ - if ( (int)(LastFrameRecPtr - LastFrameRecPtr2) == 0 ) { - /* Reconstruct the pixel dats from the reference frame and change data - (no half pixel in this case as the two references were the same. */ - dsp_recon_inter8x8 (pbi->dsp, - &pbi->ThisFrameRecon[ReconPixelIndex], - LastFrameRecPtr, pbi->ReconDataBuffer, - ReconPixelsPerLine); - }else{ - /* Fractional pixel reconstruction. */ - /* Note that we only use two pixels per reconstruction even for - the diagonal. */ - dsp_recon_inter8x8_half(pbi->dsp, &pbi->ThisFrameRecon[ReconPixelIndex], - LastFrameRecPtr, LastFrameRecPtr2, - pbi->ReconDataBuffer, ReconPixelsPerLine); - } - } else if ( pbi->CodingMode == CODE_USING_GOLDEN ){ - /* Golden frame with motion vector */ - /* Reconstruct the pixel data using the golden frame - reconstruction and change data */ - dsp_recon_inter8x8 (pbi->dsp, &pbi->ThisFrameRecon[ReconPixelIndex], - &pbi->GoldenFrame[ ReconPixelIndex ], - pbi->ReconDataBuffer, ReconPixelsPerLine); - } else { - /* Simple Intra coding */ - /* Get the pixel index for the first pixel in the fragment. */ - dsp_recon_intra8x8 (pbi->dsp, &pbi->ThisFrameRecon[ReconPixelIndex], - pbi->ReconDataBuffer, ReconPixelsPerLine); - } -} - -static void UpdateUMV_HBorders( PB_INSTANCE *pbi, - unsigned char * DestReconPtr, - ogg_uint32_t PlaneFragOffset ) { - ogg_uint32_t i; - ogg_uint32_t PixelIndex; - - ogg_uint32_t PlaneStride; - ogg_uint32_t BlockVStep; - ogg_uint32_t PlaneFragments; - ogg_uint32_t LineFragments; - ogg_uint32_t PlaneBorderWidth; - - unsigned char *SrcPtr1; - unsigned char *SrcPtr2; - unsigned char *DestPtr1; - unsigned char *DestPtr2; - - /* Work out various plane specific values */ - if ( PlaneFragOffset == 0 ) { - /* Y Plane */ - BlockVStep = (pbi->YStride * - (VFRAGPIXELS - 1)); - PlaneStride = pbi->YStride; - PlaneBorderWidth = UMV_BORDER; - PlaneFragments = pbi->YPlaneFragments; - LineFragments = pbi->HFragments; - }else{ - /* U or V plane. */ - BlockVStep = (pbi->UVStride * - (VFRAGPIXELS - 1)); - PlaneStride = pbi->UVStride; - PlaneBorderWidth = UMV_BORDER / 2; - PlaneFragments = pbi->UVPlaneFragments; - LineFragments = pbi->HFragments / 2; - } - - /* Setup the source and destination pointers for the top and bottom - borders */ - PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset]; - SrcPtr1 = &DestReconPtr[ PixelIndex - PlaneBorderWidth ]; - DestPtr1 = SrcPtr1 - (PlaneBorderWidth * PlaneStride); - - PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset + - PlaneFragments - LineFragments] + - BlockVStep; - SrcPtr2 = &DestReconPtr[ PixelIndex - PlaneBorderWidth]; - DestPtr2 = SrcPtr2 + PlaneStride; - - /* Now copy the top and bottom source lines into each line of the - respective borders */ - for ( i = 0; i < PlaneBorderWidth; i++ ) { - memcpy( DestPtr1, SrcPtr1, PlaneStride ); - memcpy( DestPtr2, SrcPtr2, PlaneStride ); - DestPtr1 += PlaneStride; - DestPtr2 += PlaneStride; - } -} - -static void UpdateUMV_VBorders( PB_INSTANCE *pbi, - unsigned char * DestReconPtr, - ogg_uint32_t PlaneFragOffset ){ - ogg_uint32_t i; - ogg_uint32_t PixelIndex; - - ogg_uint32_t PlaneStride; - ogg_uint32_t LineFragments; - ogg_uint32_t PlaneBorderWidth; - ogg_uint32_t PlaneHeight; - - unsigned char *SrcPtr1; - unsigned char *SrcPtr2; - unsigned char *DestPtr1; - unsigned char *DestPtr2; - - /* Work out various plane specific values */ - if ( PlaneFragOffset == 0 ) { - /* Y Plane */ - PlaneStride = pbi->YStride; - PlaneBorderWidth = UMV_BORDER; - LineFragments = pbi->HFragments; - PlaneHeight = pbi->info.height; - }else{ - /* U or V plane. */ - PlaneStride = pbi->UVStride; - PlaneBorderWidth = UMV_BORDER / 2; - LineFragments = pbi->HFragments / 2; - PlaneHeight = pbi->info.height / 2; - } - - /* Setup the source data values and destination pointers for the - left and right edge borders */ - PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset]; - SrcPtr1 = &DestReconPtr[ PixelIndex ]; - DestPtr1 = &DestReconPtr[ PixelIndex - PlaneBorderWidth ]; - - PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset + - LineFragments - 1] + - (HFRAGPIXELS - 1); - SrcPtr2 = &DestReconPtr[ PixelIndex ]; - DestPtr2 = &DestReconPtr[ PixelIndex + 1 ]; - - /* Now copy the top and bottom source lines into each line of the - respective borders */ - for ( i = 0; i < PlaneHeight; i++ ) { - memset( DestPtr1, SrcPtr1[0], PlaneBorderWidth ); - memset( DestPtr2, SrcPtr2[0], PlaneBorderWidth ); - SrcPtr1 += PlaneStride; - SrcPtr2 += PlaneStride; - DestPtr1 += PlaneStride; - DestPtr2 += PlaneStride; - } -} - -void UpdateUMVBorder( PB_INSTANCE *pbi, - unsigned char * DestReconPtr ) { - ogg_uint32_t PlaneFragOffset; - - /* Y plane */ - PlaneFragOffset = 0; - UpdateUMV_VBorders( pbi, DestReconPtr, PlaneFragOffset ); - UpdateUMV_HBorders( pbi, DestReconPtr, PlaneFragOffset ); - - /* Then the U and V Planes */ - PlaneFragOffset = pbi->YPlaneFragments; - UpdateUMV_VBorders( pbi, DestReconPtr, PlaneFragOffset ); - UpdateUMV_HBorders( pbi, DestReconPtr, PlaneFragOffset ); - - PlaneFragOffset = pbi->YPlaneFragments + pbi->UVPlaneFragments; - UpdateUMV_VBorders( pbi, DestReconPtr, PlaneFragOffset ); - UpdateUMV_HBorders( pbi, DestReconPtr, PlaneFragOffset ); -} - -static void CopyRecon( PB_INSTANCE *pbi, unsigned char * DestReconPtr, - unsigned char * SrcReconPtr ) { - ogg_uint32_t i; - ogg_uint32_t PlaneLineStep; /* Pixels per line */ - ogg_uint32_t PixelIndex; - - unsigned char *SrcPtr; /* Pointer to line of source image data */ - unsigned char *DestPtr; /* Pointer to line of destination image data */ - - /* Copy over only updated blocks.*/ - - /* First Y plane */ - PlaneLineStep = pbi->YStride; - for ( i = 0; i < pbi->YPlaneFragments; i++ ) { - if ( pbi->display_fragments[i] ) { - PixelIndex = pbi->recon_pixel_index_table[i]; - SrcPtr = &SrcReconPtr[ PixelIndex ]; - DestPtr = &DestReconPtr[ PixelIndex ]; - - dsp_copy8x8 (pbi->dsp, SrcPtr, DestPtr, PlaneLineStep); - } - } - - /* Then U and V */ - PlaneLineStep = pbi->UVStride; - for ( i = pbi->YPlaneFragments; i < pbi->UnitFragments; i++ ) { - if ( pbi->display_fragments[i] ) { - PixelIndex = pbi->recon_pixel_index_table[i]; - SrcPtr = &SrcReconPtr[ PixelIndex ]; - DestPtr = &DestReconPtr[ PixelIndex ]; - - dsp_copy8x8 (pbi->dsp, SrcPtr, DestPtr, PlaneLineStep); - - } - } -} - -static void CopyNotRecon( PB_INSTANCE *pbi, unsigned char * DestReconPtr, - unsigned char * SrcReconPtr ) { - ogg_uint32_t i; - ogg_uint32_t PlaneLineStep; /* Pixels per line */ - ogg_uint32_t PixelIndex; - - unsigned char *SrcPtr; /* Pointer to line of source image data */ - unsigned char *DestPtr; /* Pointer to line of destination image data*/ - - /* Copy over only updated blocks. */ - - /* First Y plane */ - PlaneLineStep = pbi->YStride; - for ( i = 0; i < pbi->YPlaneFragments; i++ ) { - if ( !pbi->display_fragments[i] ) { - PixelIndex = pbi->recon_pixel_index_table[i]; - SrcPtr = &SrcReconPtr[ PixelIndex ]; - DestPtr = &DestReconPtr[ PixelIndex ]; - - dsp_copy8x8 (pbi->dsp, SrcPtr, DestPtr, PlaneLineStep); - } - } - - /* Then U and V */ - PlaneLineStep = pbi->UVStride; - for ( i = pbi->YPlaneFragments; i < pbi->UnitFragments; i++ ) { - if ( !pbi->display_fragments[i] ) { - PixelIndex = pbi->recon_pixel_index_table[i]; - SrcPtr = &SrcReconPtr[ PixelIndex ]; - DestPtr = &DestReconPtr[ PixelIndex ]; - - dsp_copy8x8 (pbi->dsp, SrcPtr, DestPtr, PlaneLineStep); - - } - } -} - -void ExpandToken( Q_LIST_ENTRY * ExpandedBlock, - unsigned char * CoeffIndex, ogg_uint32_t Token, - ogg_int32_t ExtraBits ){ - /* Is the token is a combination run and value token. */ - if ( Token >= DCT_RUN_CATEGORY1 ){ - /* Expand the token and additional bits to a zero run length and - data value. */ - if ( Token < DCT_RUN_CATEGORY2 ) { - /* Decoding method depends on token */ - if ( Token < DCT_RUN_CATEGORY1B ) { - /* Step on by the zero run length */ - *CoeffIndex += (unsigned char)((Token - DCT_RUN_CATEGORY1) + 1); - - /* The extra bit determines the sign. */ - if ( ExtraBits & 0x01 ) - ExpandedBlock[*CoeffIndex] = -1; - else - ExpandedBlock[*CoeffIndex] = 1; - } else if ( Token == DCT_RUN_CATEGORY1B ) { - /* Bits 0-1 determines the zero run length */ - *CoeffIndex += (6 + (ExtraBits & 0x03)); - - /* Bit 2 determines the sign */ - if ( ExtraBits & 0x04 ) - ExpandedBlock[*CoeffIndex] = -1; - else - ExpandedBlock[*CoeffIndex] = 1; - }else{ - /* Bits 0-2 determines the zero run length */ - *CoeffIndex += (10 + (ExtraBits & 0x07)); - - /* Bit 3 determines the sign */ - if ( ExtraBits & 0x08 ) - ExpandedBlock[*CoeffIndex] = -1; - else - ExpandedBlock[*CoeffIndex] = 1; - } - }else{ - /* If token == DCT_RUN_CATEGORY2 we have a single 0 followed by - a value */ - if ( Token == DCT_RUN_CATEGORY2 ){ - /* Step on by the zero run length */ - *CoeffIndex += 1; - - /* Bit 1 determines sign, bit 0 the value */ - if ( ExtraBits & 0x02 ) - ExpandedBlock[*CoeffIndex] = -(2 + (ExtraBits & 0x01)); - else - ExpandedBlock[*CoeffIndex] = 2 + (ExtraBits & 0x01); - }else{ - /* else we have 2->3 zeros followed by a value */ - /* Bit 0 determines the zero run length */ - *CoeffIndex += 2 + (ExtraBits & 0x01); - - /* Bit 2 determines the sign, bit 1 the value */ - if ( ExtraBits & 0x04 ) - ExpandedBlock[*CoeffIndex] = -(2 + ((ExtraBits & 0x02) >> 1)); - else - ExpandedBlock[*CoeffIndex] = 2 + ((ExtraBits & 0x02) >> 1); - } - } - - /* Step on over value */ - *CoeffIndex += 1; - - } else if ( Token == DCT_SHORT_ZRL_TOKEN ) { - /* Token is a ZRL token so step on by the appropriate number of zeros */ - *CoeffIndex += ExtraBits + 1; - } else if ( Token == DCT_ZRL_TOKEN ) { - /* Token is a ZRL token so step on by the appropriate number of zeros */ - *CoeffIndex += ExtraBits + 1; - } else if ( Token < LOW_VAL_TOKENS ) { - /* Token is a small single value token. */ - switch ( Token ) { - case ONE_TOKEN: - ExpandedBlock[*CoeffIndex] = 1; - break; - case MINUS_ONE_TOKEN: - ExpandedBlock[*CoeffIndex] = -1; - break; - case TWO_TOKEN: - ExpandedBlock[*CoeffIndex] = 2; - break; - case MINUS_TWO_TOKEN: - ExpandedBlock[*CoeffIndex] = -2; - break; - } - - /* Step on the coefficient index. */ - *CoeffIndex += 1; - }else{ - /* Token is a larger single value token */ - /* Expand the token and additional bits to a data value. */ - if ( Token < DCT_VAL_CATEGORY3 ) { - /* Offset from LOW_VAL_TOKENS determines value */ - Token = Token - LOW_VAL_TOKENS; - - /* Extra bit determines sign */ - if ( ExtraBits ) - ExpandedBlock[*CoeffIndex] = - -((Q_LIST_ENTRY)(Token + DCT_VAL_CAT2_MIN)); - else - ExpandedBlock[*CoeffIndex] = - (Q_LIST_ENTRY)(Token + DCT_VAL_CAT2_MIN); - } else if ( Token == DCT_VAL_CATEGORY3 ) { - /* Bit 1 determines sign, Bit 0 the value */ - if ( ExtraBits & 0x02 ) - ExpandedBlock[*CoeffIndex] = -(DCT_VAL_CAT3_MIN + (ExtraBits & 0x01)); - else - ExpandedBlock[*CoeffIndex] = DCT_VAL_CAT3_MIN + (ExtraBits & 0x01); - } else if ( Token == DCT_VAL_CATEGORY4 ) { - /* Bit 2 determines sign, Bit 0-1 the value */ - if ( ExtraBits & 0x04 ) - ExpandedBlock[*CoeffIndex] = -(DCT_VAL_CAT4_MIN + (ExtraBits & 0x03)); - else - ExpandedBlock[*CoeffIndex] = DCT_VAL_CAT4_MIN + (ExtraBits & 0x03); - } else if ( Token == DCT_VAL_CATEGORY5 ) { - /* Bit 3 determines sign, Bit 0-2 the value */ - if ( ExtraBits & 0x08 ) - ExpandedBlock[*CoeffIndex] = -(DCT_VAL_CAT5_MIN + (ExtraBits & 0x07)); - else - ExpandedBlock[*CoeffIndex] = DCT_VAL_CAT5_MIN + (ExtraBits & 0x07); - } else if ( Token == DCT_VAL_CATEGORY6 ) { - /* Bit 4 determines sign, Bit 0-3 the value */ - if ( ExtraBits & 0x10 ) - ExpandedBlock[*CoeffIndex] = -(DCT_VAL_CAT6_MIN + (ExtraBits & 0x0F)); - else - ExpandedBlock[*CoeffIndex] = DCT_VAL_CAT6_MIN + (ExtraBits & 0x0F); - } else if ( Token == DCT_VAL_CATEGORY7 ) { - /* Bit 5 determines sign, Bit 0-4 the value */ - if ( ExtraBits & 0x20 ) - ExpandedBlock[*CoeffIndex] = -(DCT_VAL_CAT7_MIN + (ExtraBits & 0x1F)); - else - ExpandedBlock[*CoeffIndex] = DCT_VAL_CAT7_MIN + (ExtraBits & 0x1F); - } else if ( Token == DCT_VAL_CATEGORY8 ) { - /* Bit 9 determines sign, Bit 0-8 the value */ - if ( ExtraBits & 0x200 ) - ExpandedBlock[*CoeffIndex] = -(DCT_VAL_CAT8_MIN + (ExtraBits & 0x1FF)); - else - ExpandedBlock[*CoeffIndex] = DCT_VAL_CAT8_MIN + (ExtraBits & 0x1FF); - } - - /* Step on the coefficient index. */ - *CoeffIndex += 1; - } -} - -void ClearDownQFragData(PB_INSTANCE *pbi){ - ogg_int32_t i; - Q_LIST_ENTRY * QFragPtr; - - for ( i = 0; i < pbi->CodedBlockIndex; i++ ) { - /* Get the linear index for the current fragment. */ - QFragPtr = pbi->QFragData[pbi->CodedBlockList[i]]; - memset(QFragPtr, 0, 64*sizeof(Q_LIST_ENTRY)); - } -} - -static void loop_filter_h(unsigned char * PixelPtr, - ogg_int32_t LineLength, - ogg_int16_t *BoundingValuePtr){ - ogg_int32_t j; - ogg_int32_t FiltVal; - PixelPtr-=2; - - for ( j = 0; j < 8; j++ ){ - FiltVal = - ( PixelPtr[0] ) - - ( PixelPtr[1] * 3 ) + - ( PixelPtr[2] * 3 ) - - ( PixelPtr[3] ); - - FiltVal = *(BoundingValuePtr+((FiltVal + 4) >> 3)); - - PixelPtr[1] = clamp255(PixelPtr[1] + FiltVal); - PixelPtr[2] = clamp255(PixelPtr[2] - FiltVal); - - PixelPtr += LineLength; - } -} - -static void loop_filter_v(unsigned char * PixelPtr, - ogg_int32_t LineLength, - ogg_int16_t *BoundingValuePtr){ - ogg_int32_t j; - ogg_int32_t FiltVal; - PixelPtr -= 2*LineLength; - - for ( j = 0; j < 8; j++ ) { - FiltVal = ( (ogg_int32_t)PixelPtr[0] ) - - ( (ogg_int32_t)PixelPtr[LineLength] * 3 ) + - ( (ogg_int32_t)PixelPtr[2 * LineLength] * 3 ) - - ( (ogg_int32_t)PixelPtr[3 * LineLength] ); - - FiltVal = *(BoundingValuePtr+((FiltVal + 4) >> 3)); - - PixelPtr[LineLength] = clamp255(PixelPtr[LineLength] + FiltVal); - PixelPtr[2 * LineLength] = clamp255(PixelPtr[2*LineLength] - FiltVal); - - PixelPtr ++; - } -} - -static void LoopFilter__c(PB_INSTANCE *pbi, int FLimit){ - - int j; - ogg_int16_t BoundingValues[256]; - ogg_int16_t *bvp = BoundingValues+127; - unsigned char *cp = pbi->display_fragments; - ogg_uint32_t *bp = pbi->recon_pixel_index_table; - - if ( FLimit == 0 ) return; - SetupBoundingValueArray_Generic(BoundingValues, FLimit); - - for ( j = 0; j < 3 ; j++){ - ogg_uint32_t *bp_begin = bp; - ogg_uint32_t *bp_end; - int stride; - int h; - - switch(j) { - case 0: /* y */ - bp_end = bp + pbi->YPlaneFragments; - h = pbi->HFragments; - stride = pbi->YStride; - break; - default: /* u,v, 4:20 specific */ - bp_end = bp + pbi->UVPlaneFragments; - h = pbi->HFragments >> 1; - stride = pbi->UVStride; - break; - } - - while(bpbp_left) - loop_filter_h(&pbi->LastFrameRecon[bp[0]],stride,bvp); - if(bp_left>bp_begin) - loop_filter_v(&pbi->LastFrameRecon[bp[0]],stride,bvp); - if(bp+1LastFrameRecon[bp[0]]+8,stride,bvp); - if(bp+hLastFrameRecon[bp[h]],stride,bvp); - } - bp++; - cp++; - } - } - } -} - -void ReconRefFrames (PB_INSTANCE *pbi){ - ogg_int32_t i; - unsigned char *SwapReconBuffersTemp; - - /* predictor multiplier up-left, up, up-right,left, shift - Entries are packed in the order L, UL, U, UR, with missing entries - moved to the end (before the shift parameters). */ - static const ogg_int16_t pc[16][6]={ - {0,0,0,0,0,0}, - {1,0,0,0,0,0}, /* PL */ - {1,0,0,0,0,0}, /* PUL */ - {1,0,0,0,0,0}, /* PUL|PL */ - {1,0,0,0,0,0}, /* PU */ - {1,1,0,0,1,1}, /* PU|PL */ - {0,1,0,0,0,0}, /* PU|PUL */ - {29,-26,29,0,5,31}, /* PU|PUL|PL */ - {1,0,0,0,0,0}, /* PUR */ - {75,53,0,0,7,127}, /* PUR|PL */ - {1,1,0,0,1,1}, /* PUR|PUL */ - {75,0,53,0,7,127}, /* PUR|PUL|PL */ - {1,0,0,0,0,0}, /* PUR|PU */ - {75,0,53,0,7,127}, /* PUR|PU|PL */ - {3,10,3,0,4,15}, /* PUR|PU|PUL */ - {29,-26,29,0,5,31} /* PUR|PU|PUL|PL */ - }; - - /* boundary case bit masks. */ - static const int bc_mask[8]={ - /* normal case no boundary condition */ - PUR|PU|PUL|PL, - /* left column */ - PUR|PU, - /* top row */ - PL, - /* top row, left column */ - 0, - /* right column */ - PU|PUL|PL, - /* right and left column */ - PU, - /* top row, right column */ - PL, - /* top row, right and left column */ - 0 - }; - - /* value left value up-left, value up, value up-right, missing - values skipped. */ - int v[4]; - - /* fragment number left, up-left, up, up-right */ - int fn[4]; - - /* predictor count. */ - int pcount; - - short wpc; - static const short Mode2Frame[] = { - 1, /* CODE_INTER_NO_MV 0 => Encoded diff from same MB last frame */ - 0, /* CODE_INTRA 1 => DCT Encoded Block */ - 1, /* CODE_INTER_PLUS_MV 2 => Encoded diff from included MV MB last frame */ - 1, /* CODE_INTER_LAST_MV 3 => Encoded diff from MRU MV MB last frame */ - 1, /* CODE_INTER_PRIOR_MV 4 => Encoded diff from included 4 separate MV blocks */ - 2, /* CODE_USING_GOLDEN 5 => Encoded diff from same MB golden frame */ - 2, /* CODE_GOLDEN_MV 6 => Encoded diff from included MV MB golden frame */ - 1 /* CODE_INTER_FOUR_MV 7 => Encoded diff from included 4 separate MV blocks */ - }; - short Last[3]; - short PredictedDC; - int FragsAcross=pbi->HFragments; - int FromFragment,ToFragment; - int FragsDown = pbi->VFragments; - - int WhichFrame; - int WhichCase; - int j,k,m,n; - - void (*ExpandBlockA) ( PB_INSTANCE *pbi, ogg_int32_t FragmentNumber ); - - if ( pbi->FrameType == KEY_FRAME ) - ExpandBlockA=ExpandKFBlock; - else - ExpandBlockA=ExpandBlock; - - /* for y,u,v */ - for ( j = 0; j < 3 ; j++) { - /* pick which fragments based on Y, U, V */ - switch(j){ - case 0: /* y */ - FromFragment = 0; - ToFragment = pbi->YPlaneFragments; - FragsAcross = pbi->HFragments; - FragsDown = pbi->VFragments; - break; - case 1: /* u */ - FromFragment = pbi->YPlaneFragments; - ToFragment = pbi->YPlaneFragments + pbi->UVPlaneFragments ; - FragsAcross = pbi->HFragments >> 1; - FragsDown = pbi->VFragments >> 1; - break; - /*case 2: v */ - default: - FromFragment = pbi->YPlaneFragments + pbi->UVPlaneFragments; - ToFragment = pbi->YPlaneFragments + (2 * pbi->UVPlaneFragments) ; - FragsAcross = pbi->HFragments >> 1; - FragsDown = pbi->VFragments >> 1; - break; - } - - /* initialize our array of last used DC Components */ - for(k=0;k<3;k++) - Last[k]=0; - - i=FromFragment; - - /* do prediction on all of Y, U or V */ - for ( m = 0 ; m < FragsDown ; m++) { - for ( n = 0 ; n < FragsAcross ; n++, i++){ - - /* only do 2 prediction if fragment coded and on non intra or - if all fragments are intra */ - if( pbi->display_fragments[i] || (pbi->FrameType == KEY_FRAME) ){ - /* Type of Fragment */ - WhichFrame = Mode2Frame[pbi->FragCodingMethod[i]]; - - /* Check Borderline Cases */ - WhichCase = (n==0) + ((m==0) << 1) + ((n+1 == FragsAcross) << 2); - - fn[0]=i-1; - fn[1]=i-FragsAcross-1; - fn[2]=i-FragsAcross; - fn[3]=i-FragsAcross+1; - - /* fragment valid for prediction use if coded and it comes - from same frame as the one we are predicting */ - for(k=pcount=wpc=0; k<4; k++) { - int pflag; - pflag=1<display_fragments[fn[k]] && - (Mode2Frame[pbi->FragCodingMethod[fn[k]]] == WhichFrame)){ - v[pcount]=pbi->QFragData[fn[k]][0]; - wpc|=pflag; - pcount++; - } - } - - if(wpc==0){ - /* fall back to the last coded fragment */ - pbi->QFragData[i][0] += Last[WhichFrame]; - - }else{ - - /* don't do divide if divisor is 1 or 0 */ - PredictedDC = pc[wpc][0]*v[0]; - for(k=1; k>= pc[wpc][4]; - } - - /* check for outranging on the two predictors that can outrange */ - if((wpc&(PU|PUL|PL)) == (PU|PUL|PL)){ - if( abs(PredictedDC - v[2]) > 128) { - PredictedDC = v[2]; - } else if( abs(PredictedDC - v[0]) > 128) { - PredictedDC = v[0]; - } else if( abs(PredictedDC - v[1]) > 128) { - PredictedDC = v[1]; - } - } - - pbi->QFragData[i][0] += PredictedDC; - - } - - /* Save the last fragment coded for whatever frame we are - predicting from */ - Last[WhichFrame] = pbi->QFragData[i][0]; - - /* Inverse DCT and reconstitute buffer in thisframe */ - ExpandBlockA( pbi, i ); - } - } - } - } - - /* Copy the current reconstruction back to the last frame recon buffer. */ - if(pbi->CodedBlockIndex > (ogg_int32_t) (pbi->UnitFragments >> 1)){ - SwapReconBuffersTemp = pbi->ThisFrameRecon; - pbi->ThisFrameRecon = pbi->LastFrameRecon; - pbi->LastFrameRecon = SwapReconBuffersTemp; - CopyNotRecon( pbi, pbi->LastFrameRecon, pbi->ThisFrameRecon ); - }else{ - CopyRecon( pbi, pbi->LastFrameRecon, pbi->ThisFrameRecon ); - } - - /* Apply a loop filter to edge pixels of updated blocks */ - dsp_LoopFilter(pbi->dsp, pbi, pbi->quant_info.loop_filter_limits[pbi->FrameQIndex]); - - /* We may need to update the UMV border */ - UpdateUMVBorder(pbi, pbi->LastFrameRecon); - - /* Reconstruct the golden frame if necessary. - For VFW codec only on key frames */ - if ( pbi->FrameType == KEY_FRAME ){ - CopyRecon( pbi, pbi->GoldenFrame, pbi->LastFrameRecon ); - /* We may need to update the UMV border */ - UpdateUMVBorder(pbi, pbi->GoldenFrame); - } -} - -void dsp_dct_decode_init (DspFunctions *funcs, ogg_uint32_t cpu_flags) -{ - funcs->LoopFilter = LoopFilter__c; -#if defined(USE_ASM) - // Todo: Port the dct for MSC one day. -#if !defined (_MSC_VER) - if (cpu_flags & OC_CPU_X86_MMX) { - dsp_mmx_dct_decode_init(funcs); - } -#endif -#endif -} diff --git a/Engine/lib/libtheora/lib/enc/dct_encode.c b/Engine/lib/libtheora/lib/enc/dct_encode.c deleted file mode 100644 index 3a3c47778..000000000 --- a/Engine/lib/libtheora/lib/enc/dct_encode.c +++ /dev/null @@ -1,469 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: dct_encode.c 15153 2008-08-04 18:37:55Z tterribe $ - - ********************************************************************/ - -#include -#include "codec_internal.h" -#include "dsp.h" -#include "quant_lookup.h" - - -static int ModeUsesMC[MAX_MODES] = { 0, 0, 1, 1, 1, 0, 1, 1 }; - -static unsigned char TokenizeDctValue (ogg_int16_t DataValue, - ogg_uint32_t * TokenListPtr ){ - unsigned char tokens_added = 0; - ogg_uint32_t AbsDataVal = abs( (ogg_int32_t)DataValue ); - - /* Values are tokenised as category value and a number of additional - bits that define the position within the category. */ - - if ( DataValue == 0 ) return 0; - - if ( AbsDataVal == 1 ){ - if ( DataValue == 1 ) - TokenListPtr[0] = ONE_TOKEN; - else - TokenListPtr[0] = MINUS_ONE_TOKEN; - tokens_added = 1; - } else if ( AbsDataVal == 2 ) { - if ( DataValue == 2 ) - TokenListPtr[0] = TWO_TOKEN; - else - TokenListPtr[0] = MINUS_TWO_TOKEN; - tokens_added = 1; - } else if ( AbsDataVal <= MAX_SINGLE_TOKEN_VALUE ) { - TokenListPtr[0] = LOW_VAL_TOKENS + (AbsDataVal - DCT_VAL_CAT2_MIN); - if ( DataValue > 0 ) - TokenListPtr[1] = 0; - else - TokenListPtr[1] = 1; - tokens_added = 2; - } else if ( AbsDataVal <= 8 ) { - /* Bit 1 determines sign, Bit 0 the value */ - TokenListPtr[0] = DCT_VAL_CATEGORY3; - if ( DataValue > 0 ) - TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT3_MIN); - else - TokenListPtr[1] = (0x02) + (AbsDataVal - DCT_VAL_CAT3_MIN); - tokens_added = 2; - } else if ( AbsDataVal <= 12 ) { - /* Bit 2 determines sign, Bit 0-2 the value */ - TokenListPtr[0] = DCT_VAL_CATEGORY4; - if ( DataValue > 0 ) - TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT4_MIN); - else - TokenListPtr[1] = (0x04) + (AbsDataVal - DCT_VAL_CAT4_MIN); - tokens_added = 2; - } else if ( AbsDataVal <= 20 ) { - /* Bit 3 determines sign, Bit 0-2 the value */ - TokenListPtr[0] = DCT_VAL_CATEGORY5; - if ( DataValue > 0 ) - TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT5_MIN); - else - TokenListPtr[1] = (0x08) + (AbsDataVal - DCT_VAL_CAT5_MIN); - tokens_added = 2; - } else if ( AbsDataVal <= 36 ) { - /* Bit 4 determines sign, Bit 0-3 the value */ - TokenListPtr[0] = DCT_VAL_CATEGORY6; - if ( DataValue > 0 ) - TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT6_MIN); - else - TokenListPtr[1] = (0x010) + (AbsDataVal - DCT_VAL_CAT6_MIN); - tokens_added = 2; - } else if ( AbsDataVal <= 68 ) { - /* Bit 5 determines sign, Bit 0-4 the value */ - TokenListPtr[0] = DCT_VAL_CATEGORY7; - if ( DataValue > 0 ) - TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT7_MIN); - else - TokenListPtr[1] = (0x20) + (AbsDataVal - DCT_VAL_CAT7_MIN); - tokens_added = 2; - } else if ( AbsDataVal <= 511 ) { - /* Bit 9 determines sign, Bit 0-8 the value */ - TokenListPtr[0] = DCT_VAL_CATEGORY8; - if ( DataValue > 0 ) - TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT8_MIN); - else - TokenListPtr[1] = (0x200) + (AbsDataVal - DCT_VAL_CAT8_MIN); - tokens_added = 2; - } else { - TokenListPtr[0] = DCT_VAL_CATEGORY8; - if ( DataValue > 0 ) - TokenListPtr[1] = (511 - DCT_VAL_CAT8_MIN); - else - TokenListPtr[1] = (0x200) + (511 - DCT_VAL_CAT8_MIN); - tokens_added = 2; - } - - /* Return the total number of tokens added */ - return tokens_added; -} - -static unsigned char TokenizeDctRunValue (unsigned char RunLength, - ogg_int16_t DataValue, - ogg_uint32_t * TokenListPtr ){ - unsigned char tokens_added = 0; - ogg_uint32_t AbsDataVal = abs( (ogg_int32_t)DataValue ); - - /* Values are tokenised as category value and a number of additional - bits that define the category. */ - if ( DataValue == 0 ) return 0; - if ( AbsDataVal == 1 ) { - /* Zero runs of 1-5 */ - if ( RunLength <= 5 ) { - TokenListPtr[0] = DCT_RUN_CATEGORY1 + (RunLength - 1); - if ( DataValue > 0 ) - TokenListPtr[1] = 0; - else - TokenListPtr[1] = 1; - } else if ( RunLength <= 9 ) { - /* Zero runs of 6-9 */ - TokenListPtr[0] = DCT_RUN_CATEGORY1B; - if ( DataValue > 0 ) - TokenListPtr[1] = (RunLength - 6); - else - TokenListPtr[1] = 0x04 + (RunLength - 6); - } else { - /* Zero runs of 10-17 */ - TokenListPtr[0] = DCT_RUN_CATEGORY1C; - if ( DataValue > 0 ) - TokenListPtr[1] = (RunLength - 10); - else - TokenListPtr[1] = 0x08 + (RunLength - 10); - } - tokens_added = 2; - } else if ( AbsDataVal <= 3 ) { - if ( RunLength == 1 ) { - TokenListPtr[0] = DCT_RUN_CATEGORY2; - - /* Extra bits token bit 1 indicates sign, bit 0 indicates value */ - if ( DataValue > 0 ) - TokenListPtr[1] = (AbsDataVal - 2); - else - TokenListPtr[1] = (0x02) + (AbsDataVal - 2); - tokens_added = 2; - }else{ - TokenListPtr[0] = DCT_RUN_CATEGORY2 + 1; - - /* Extra bits token. */ - /* bit 2 indicates sign, bit 1 indicates value, bit 0 indicates - run length */ - if ( DataValue > 0 ) - TokenListPtr[1] = ((AbsDataVal - 2) << 1) + (RunLength - 2); - else - TokenListPtr[1] = (0x04) + ((AbsDataVal - 2) << 1) + (RunLength - 2); - tokens_added = 2; - } - } else { - tokens_added = 2; /* ERROR */ - /*IssueWarning( "Bad Input to TokenizeDctRunValue" );*/ - } - - /* Return the total number of tokens added */ - return tokens_added; -} - -static unsigned char TokenizeDctBlock (ogg_int16_t * RawData, - ogg_uint32_t * TokenListPtr ) { - ogg_uint32_t i; - unsigned char run_count; - unsigned char token_count = 0; /* Number of tokens crated. */ - ogg_uint32_t AbsData; - - - /* Tokenize the block */ - for( i = 0; i < BLOCK_SIZE; i++ ){ - run_count = 0; - - /* Look for a zero run. */ - /* NOTE the use of & instead of && which is faster (and - equivalent) in this instance. */ - /* NO, NO IT ISN'T --Monty */ - while( (i < BLOCK_SIZE) && (!RawData[i]) ){ - run_count++; - i++; - } - - /* If we have reached the end of the block then code EOB */ - if ( i == BLOCK_SIZE ){ - TokenListPtr[token_count] = DCT_EOB_TOKEN; - token_count++; - }else{ - /* If we have a short zero run followed by a low data value code - the two as a composite token. */ - if ( run_count ){ - AbsData = abs(RawData[i]); - - if ( ((AbsData == 1) && (run_count <= 17)) || - ((AbsData <= 3) && (run_count <= 3)) ) { - /* Tokenise the run and subsequent value combination value */ - token_count += TokenizeDctRunValue( run_count, - RawData[i], - &TokenListPtr[token_count] ); - }else{ - - /* Else if we have a long non-EOB run or a run followed by a - value token > MAX_RUN_VAL then code the run and token - seperately */ - if ( run_count <= 8 ) - TokenListPtr[token_count] = DCT_SHORT_ZRL_TOKEN; - else - TokenListPtr[token_count] = DCT_ZRL_TOKEN; - - token_count++; - TokenListPtr[token_count] = run_count - 1; - token_count++; - - /* Now tokenize the value */ - token_count += TokenizeDctValue( RawData[i], - &TokenListPtr[token_count] ); - } - }else{ - /* Else there was NO zero run. */ - /* Tokenise the value */ - token_count += TokenizeDctValue( RawData[i], - &TokenListPtr[token_count] ); - } - } - } - - /* Return the total number of tokens (including additional bits - tokens) used. */ - return token_count; -} - -ogg_uint32_t DPCMTokenizeBlock (CP_INSTANCE *cpi, - ogg_int32_t FragIndex){ - ogg_uint32_t token_count; - - if ( cpi->pb.FrameType == KEY_FRAME ){ - /* Key frame so code block in INTRA mode. */ - cpi->pb.CodingMode = CODE_INTRA; - }else{ - /* Get Motion vector and mode for this block. */ - cpi->pb.CodingMode = cpi->pb.FragCodingMethod[FragIndex]; - } - - /* Tokenise the dct data. */ - token_count = TokenizeDctBlock( cpi->pb.QFragData[FragIndex], - cpi->pb.TokenList[FragIndex] ); - - cpi->FragTokenCounts[FragIndex] = token_count; - cpi->TotTokenCount += token_count; - - /* Return number of pixels coded (i.e. 8x8). */ - return BLOCK_SIZE; -} - -static int AllZeroDctData( Q_LIST_ENTRY * QuantList ){ - ogg_uint32_t i; - - for ( i = 0; i < 64; i ++ ) - if ( QuantList[i] != 0 ) - return 0; - - return 1; -} - -static void MotionBlockDifference (CP_INSTANCE * cpi, unsigned char * FiltPtr, - ogg_int16_t *DctInputPtr, ogg_int32_t MvDevisor, - unsigned char* old_ptr1, unsigned char* new_ptr1, - ogg_uint32_t FragIndex,ogg_uint32_t PixelsPerLine, - ogg_uint32_t ReconPixelsPerLine) { - - ogg_int32_t MvShift; - ogg_int32_t MvModMask; - ogg_int32_t AbsRefOffset; - ogg_int32_t AbsXOffset; - ogg_int32_t AbsYOffset; - ogg_int32_t MVOffset; /* Baseline motion vector offset */ - ogg_int32_t ReconPtr2Offset; /* Offset for second reconstruction in - half pixel MC */ - unsigned char *ReconPtr1; /* DCT reconstructed image pointers */ - unsigned char *ReconPtr2; /* Pointer used in half pixel MC */ - - switch(MvDevisor) { - case 2: - MvShift = 1; - MvModMask = 1; - break; - case 4: - MvShift = 2; - MvModMask = 3; - break; - default: - break; - } - - cpi->MVector.x = cpi->pb.FragMVect[FragIndex].x; - cpi->MVector.y = cpi->pb.FragMVect[FragIndex].y; - - /* Set up the baseline offset for the motion vector. */ - MVOffset = ((cpi->MVector.y / MvDevisor) * ReconPixelsPerLine) + - (cpi->MVector.x / MvDevisor); - - /* Work out the offset of the second reference position for 1/2 - pixel interpolation. For the U and V planes the MV specifies 1/4 - pixel accuracy. This is adjusted to 1/2 pixel as follows ( 0->0, - 1/4->1/2, 1/2->1/2, 3/4->1/2 ). */ - ReconPtr2Offset = 0; - AbsXOffset = cpi->MVector.x % MvDevisor; - AbsYOffset = cpi->MVector.y % MvDevisor; - - if ( AbsXOffset ) { - if ( cpi->MVector.x > 0 ) - ReconPtr2Offset += 1; - else - ReconPtr2Offset -= 1; - } - - if ( AbsYOffset ) { - if ( cpi->MVector.y > 0 ) - ReconPtr2Offset += ReconPixelsPerLine; - else - ReconPtr2Offset -= ReconPixelsPerLine; - } - - if ( cpi->pb.CodingMode==CODE_GOLDEN_MV ) { - ReconPtr1 = &cpi-> - pb.GoldenFrame[cpi->pb.recon_pixel_index_table[FragIndex]]; - } else { - ReconPtr1 = &cpi-> - pb.LastFrameRecon[cpi->pb.recon_pixel_index_table[FragIndex]]; - } - - ReconPtr1 += MVOffset; - ReconPtr2 = ReconPtr1 + ReconPtr2Offset; - - AbsRefOffset = abs((int)(ReconPtr1 - ReconPtr2)); - - /* Is the MV offset exactly pixel alligned */ - if ( AbsRefOffset == 0 ){ - dsp_sub8x8(cpi->dsp, FiltPtr, ReconPtr1, DctInputPtr, - PixelsPerLine, ReconPixelsPerLine); - dsp_copy8x8 (cpi->dsp, new_ptr1, old_ptr1, PixelsPerLine); - } else { - /* Fractional pixel MVs. */ - /* Note that we only use two pixel values even for the diagonal */ - dsp_sub8x8avg2(cpi->dsp, FiltPtr, ReconPtr1,ReconPtr2,DctInputPtr, - PixelsPerLine, ReconPixelsPerLine); - dsp_copy8x8 (cpi->dsp, new_ptr1, old_ptr1, PixelsPerLine); - } -} - -void TransformQuantizeBlock (CP_INSTANCE *cpi, ogg_int32_t FragIndex, - ogg_uint32_t PixelsPerLine) { - unsigned char *new_ptr1; /* Pointers into current frame */ - unsigned char *old_ptr1; /* Pointers into old frame */ - unsigned char *FiltPtr; /* Pointers to srf filtered pixels */ - ogg_int16_t *DctInputPtr; /* Pointer into buffer containing input to DCT */ - int LeftEdge; /* Flag if block at left edge of component */ - ogg_uint32_t ReconPixelsPerLine; /* Line length for recon buffers. */ - - unsigned char *ReconPtr1; /* DCT reconstructed image pointers */ - ogg_int32_t MvDevisor; /* Defines MV resolution (2 = 1/2 - pixel for Y or 4 = 1/4 for UV) */ - - new_ptr1 = &cpi->yuv1ptr[cpi->pb.pixel_index_table[FragIndex]]; - old_ptr1 = &cpi->yuv0ptr[cpi->pb.pixel_index_table[FragIndex]]; - DctInputPtr = cpi->DCTDataBuffer; - - /* Set plane specific values */ - if (FragIndex < (ogg_int32_t)cpi->pb.YPlaneFragments){ - ReconPixelsPerLine = cpi->pb.YStride; - MvDevisor = 2; /* 1/2 pixel accuracy in Y */ - }else{ - ReconPixelsPerLine = cpi->pb.UVStride; - MvDevisor = 4; /* UV planes at 1/2 resolution of Y */ - } - - /* adjusted / filtered pointers */ - FiltPtr = &cpi->ConvDestBuffer[cpi->pb.pixel_index_table[FragIndex]]; - - if ( cpi->pb.FrameType == KEY_FRAME ) { - /* Key frame so code block in INTRA mode. */ - cpi->pb.CodingMode = CODE_INTRA; - }else{ - /* Get Motion vector and mode for this block. */ - cpi->pb.CodingMode = cpi->pb.FragCodingMethod[FragIndex]; - } - - /* Selection of Quantiser matrix and set other plane related values. */ - if ( FragIndex < (ogg_int32_t)cpi->pb.YPlaneFragments ){ - LeftEdge = !(FragIndex%cpi->pb.HFragments); - - /* Select the appropriate Y quantiser matrix */ - if ( cpi->pb.CodingMode == CODE_INTRA ) - select_quantiser(&cpi->pb, BLOCK_Y); - else - select_quantiser(&cpi->pb, BLOCK_INTER_Y); - } else { - LeftEdge = !((FragIndex-cpi->pb.YPlaneFragments)%(cpi->pb.HFragments>>1)); - - if(FragIndex < (ogg_int32_t)cpi->pb.YPlaneFragments + (ogg_int32_t)cpi->pb.UVPlaneFragments) { - /* U plane */ - if ( cpi->pb.CodingMode == CODE_INTRA ) - select_quantiser(&cpi->pb, BLOCK_U); - else - select_quantiser(&cpi->pb, BLOCK_INTER_U); - } else { - /* V plane */ - if ( cpi->pb.CodingMode == CODE_INTRA ) - select_quantiser(&cpi->pb, BLOCK_V); - else - select_quantiser(&cpi->pb, BLOCK_INTER_V); - } - } - - if ( ModeUsesMC[cpi->pb.CodingMode] ){ - - MotionBlockDifference(cpi, FiltPtr, DctInputPtr, MvDevisor, - old_ptr1, new_ptr1, FragIndex, PixelsPerLine, - ReconPixelsPerLine); - - } else if ( (cpi->pb.CodingMode==CODE_INTER_NO_MV ) || - ( cpi->pb.CodingMode==CODE_USING_GOLDEN ) ) { - if ( cpi->pb.CodingMode==CODE_INTER_NO_MV ) { - ReconPtr1 = &cpi-> - pb.LastFrameRecon[cpi->pb.recon_pixel_index_table[FragIndex]]; - } else { - ReconPtr1 = &cpi-> - pb.GoldenFrame[cpi->pb.recon_pixel_index_table[FragIndex]]; - } - - dsp_sub8x8(cpi->dsp, FiltPtr, ReconPtr1, DctInputPtr, - PixelsPerLine, ReconPixelsPerLine); - dsp_copy8x8 (cpi->dsp, new_ptr1, old_ptr1, PixelsPerLine); - } else if ( cpi->pb.CodingMode==CODE_INTRA ) { - dsp_sub8x8_128(cpi->dsp, FiltPtr, DctInputPtr, PixelsPerLine); - dsp_copy8x8 (cpi->dsp, new_ptr1, old_ptr1, PixelsPerLine); - } - - /* Proceed to encode the data into the encode buffer if the encoder - is enabled. */ - /* Perform a 2D DCT transform on the data. */ - dsp_fdct_short(cpi->dsp, cpi->DCTDataBuffer, cpi->DCT_codes ); - - /* Quantize that transform data. */ - quantize ( &cpi->pb, cpi->DCT_codes, cpi->pb.QFragData[FragIndex] ); - - if ( (cpi->pb.CodingMode == CODE_INTER_NO_MV) && - ( AllZeroDctData(cpi->pb.QFragData[FragIndex]) ) ) { - cpi->pb.display_fragments[FragIndex] = 0; - } - -} diff --git a/Engine/lib/libtheora/lib/enc/dsp.c b/Engine/lib/libtheora/lib/enc/dsp.c deleted file mode 100644 index 9fe402d4e..000000000 --- a/Engine/lib/libtheora/lib/enc/dsp.c +++ /dev/null @@ -1,422 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: dsp.c 15427 2008-10-21 02:36:19Z xiphmont $ - - ********************************************************************/ - -#include -#include "codec_internal.h" -#include "../cpu.c" - -#define DSP_OP_AVG(a,b) ((((int)(a)) + ((int)(b)))/2) -#define DSP_OP_DIFF(a,b) (((int)(a)) - ((int)(b))) -#define DSP_OP_ABS_DIFF(a,b) abs((((int)(a)) - ((int)(b)))) - -static void sub8x8__c (unsigned char *FiltPtr, unsigned char *ReconPtr, - ogg_int16_t *DctInputPtr, ogg_uint32_t PixelsPerLine, - ogg_uint32_t ReconPixelsPerLine) { - int i; - - /* For each block row */ - for (i=8; i; i--) { - DctInputPtr[0] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[0], ReconPtr[0]); - DctInputPtr[1] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[1], ReconPtr[1]); - DctInputPtr[2] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[2], ReconPtr[2]); - DctInputPtr[3] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[3], ReconPtr[3]); - DctInputPtr[4] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[4], ReconPtr[4]); - DctInputPtr[5] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[5], ReconPtr[5]); - DctInputPtr[6] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[6], ReconPtr[6]); - DctInputPtr[7] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[7], ReconPtr[7]); - - /* Start next row */ - FiltPtr += PixelsPerLine; - ReconPtr += ReconPixelsPerLine; - DctInputPtr += 8; - } -} - -static void sub8x8_128__c (unsigned char *FiltPtr, ogg_int16_t *DctInputPtr, - ogg_uint32_t PixelsPerLine) { - int i; - /* For each block row */ - for (i=8; i; i--) { - /* INTRA mode so code raw image data */ - /* We convert the data to 8 bit signed (by subtracting 128) as - this reduces the internal precision requirments in the DCT - transform. */ - DctInputPtr[0] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[0], 128); - DctInputPtr[1] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[1], 128); - DctInputPtr[2] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[2], 128); - DctInputPtr[3] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[3], 128); - DctInputPtr[4] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[4], 128); - DctInputPtr[5] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[5], 128); - DctInputPtr[6] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[6], 128); - DctInputPtr[7] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[7], 128); - - /* Start next row */ - FiltPtr += PixelsPerLine; - DctInputPtr += 8; - } -} - -static void sub8x8avg2__c (unsigned char *FiltPtr, unsigned char *ReconPtr1, - unsigned char *ReconPtr2, ogg_int16_t *DctInputPtr, - ogg_uint32_t PixelsPerLine, - ogg_uint32_t ReconPixelsPerLine) -{ - int i; - - /* For each block row */ - for (i=8; i; i--) { - DctInputPtr[0] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[0], DSP_OP_AVG (ReconPtr1[0], ReconPtr2[0])); - DctInputPtr[1] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[1], DSP_OP_AVG (ReconPtr1[1], ReconPtr2[1])); - DctInputPtr[2] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[2], DSP_OP_AVG (ReconPtr1[2], ReconPtr2[2])); - DctInputPtr[3] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[3], DSP_OP_AVG (ReconPtr1[3], ReconPtr2[3])); - DctInputPtr[4] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[4], DSP_OP_AVG (ReconPtr1[4], ReconPtr2[4])); - DctInputPtr[5] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[5], DSP_OP_AVG (ReconPtr1[5], ReconPtr2[5])); - DctInputPtr[6] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[6], DSP_OP_AVG (ReconPtr1[6], ReconPtr2[6])); - DctInputPtr[7] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[7], DSP_OP_AVG (ReconPtr1[7], ReconPtr2[7])); - - /* Start next row */ - FiltPtr += PixelsPerLine; - ReconPtr1 += ReconPixelsPerLine; - ReconPtr2 += ReconPixelsPerLine; - DctInputPtr += 8; - } -} - -static ogg_uint32_t row_sad8__c (unsigned char *Src1, unsigned char *Src2) -{ - ogg_uint32_t SadValue; - ogg_uint32_t SadValue1; - - SadValue = DSP_OP_ABS_DIFF (Src1[0], Src2[0]) + - DSP_OP_ABS_DIFF (Src1[1], Src2[1]) + - DSP_OP_ABS_DIFF (Src1[2], Src2[2]) + - DSP_OP_ABS_DIFF (Src1[3], Src2[3]); - - SadValue1 = DSP_OP_ABS_DIFF (Src1[4], Src2[4]) + - DSP_OP_ABS_DIFF (Src1[5], Src2[5]) + - DSP_OP_ABS_DIFF (Src1[6], Src2[6]) + - DSP_OP_ABS_DIFF (Src1[7], Src2[7]); - - SadValue = ( SadValue > SadValue1 ) ? SadValue : SadValue1; - - return SadValue; -} - -static ogg_uint32_t col_sad8x8__c (unsigned char *Src1, unsigned char *Src2, - ogg_uint32_t stride) -{ - ogg_uint32_t SadValue[8] = {0,0,0,0,0,0,0,0}; - ogg_uint32_t SadValue2[8] = {0,0,0,0,0,0,0,0}; - ogg_uint32_t MaxSad = 0; - ogg_uint32_t i; - - for ( i = 0; i < 4; i++ ){ - SadValue[0] += abs(Src1[0] - Src2[0]); - SadValue[1] += abs(Src1[1] - Src2[1]); - SadValue[2] += abs(Src1[2] - Src2[2]); - SadValue[3] += abs(Src1[3] - Src2[3]); - SadValue[4] += abs(Src1[4] - Src2[4]); - SadValue[5] += abs(Src1[5] - Src2[5]); - SadValue[6] += abs(Src1[6] - Src2[6]); - SadValue[7] += abs(Src1[7] - Src2[7]); - - Src1 += stride; - Src2 += stride; - } - - for ( i = 0; i < 4; i++ ){ - SadValue2[0] += abs(Src1[0] - Src2[0]); - SadValue2[1] += abs(Src1[1] - Src2[1]); - SadValue2[2] += abs(Src1[2] - Src2[2]); - SadValue2[3] += abs(Src1[3] - Src2[3]); - SadValue2[4] += abs(Src1[4] - Src2[4]); - SadValue2[5] += abs(Src1[5] - Src2[5]); - SadValue2[6] += abs(Src1[6] - Src2[6]); - SadValue2[7] += abs(Src1[7] - Src2[7]); - - Src1 += stride; - Src2 += stride; - } - - for ( i = 0; i < 8; i++ ){ - if ( SadValue[i] > MaxSad ) - MaxSad = SadValue[i]; - if ( SadValue2[i] > MaxSad ) - MaxSad = SadValue2[i]; - } - - return MaxSad; -} - -static ogg_uint32_t sad8x8__c (unsigned char *ptr1, ogg_uint32_t stride1, - unsigned char *ptr2, ogg_uint32_t stride2) -{ - ogg_uint32_t i; - ogg_uint32_t sad = 0; - - for (i=8; i; i--) { - sad += DSP_OP_ABS_DIFF(ptr1[0], ptr2[0]); - sad += DSP_OP_ABS_DIFF(ptr1[1], ptr2[1]); - sad += DSP_OP_ABS_DIFF(ptr1[2], ptr2[2]); - sad += DSP_OP_ABS_DIFF(ptr1[3], ptr2[3]); - sad += DSP_OP_ABS_DIFF(ptr1[4], ptr2[4]); - sad += DSP_OP_ABS_DIFF(ptr1[5], ptr2[5]); - sad += DSP_OP_ABS_DIFF(ptr1[6], ptr2[6]); - sad += DSP_OP_ABS_DIFF(ptr1[7], ptr2[7]); - - /* Step to next row of block. */ - ptr1 += stride1; - ptr2 += stride2; - } - - return sad; -} - -static ogg_uint32_t sad8x8_thres__c (unsigned char *ptr1, ogg_uint32_t stride1, - unsigned char *ptr2, ogg_uint32_t stride2, - ogg_uint32_t thres) -{ - ogg_uint32_t i; - ogg_uint32_t sad = 0; - - for (i=8; i; i--) { - sad += DSP_OP_ABS_DIFF(ptr1[0], ptr2[0]); - sad += DSP_OP_ABS_DIFF(ptr1[1], ptr2[1]); - sad += DSP_OP_ABS_DIFF(ptr1[2], ptr2[2]); - sad += DSP_OP_ABS_DIFF(ptr1[3], ptr2[3]); - sad += DSP_OP_ABS_DIFF(ptr1[4], ptr2[4]); - sad += DSP_OP_ABS_DIFF(ptr1[5], ptr2[5]); - sad += DSP_OP_ABS_DIFF(ptr1[6], ptr2[6]); - sad += DSP_OP_ABS_DIFF(ptr1[7], ptr2[7]); - - if (sad > thres ) - break; - - /* Step to next row of block. */ - ptr1 += stride1; - ptr2 += stride2; - } - - return sad; -} - -static ogg_uint32_t sad8x8_xy2_thres__c (unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr1, - unsigned char *RefDataPtr2, ogg_uint32_t RefStride, - ogg_uint32_t thres) -{ - ogg_uint32_t i; - ogg_uint32_t sad = 0; - - for (i=8; i; i--) { - sad += DSP_OP_ABS_DIFF(SrcData[0], DSP_OP_AVG (RefDataPtr1[0], RefDataPtr2[0])); - sad += DSP_OP_ABS_DIFF(SrcData[1], DSP_OP_AVG (RefDataPtr1[1], RefDataPtr2[1])); - sad += DSP_OP_ABS_DIFF(SrcData[2], DSP_OP_AVG (RefDataPtr1[2], RefDataPtr2[2])); - sad += DSP_OP_ABS_DIFF(SrcData[3], DSP_OP_AVG (RefDataPtr1[3], RefDataPtr2[3])); - sad += DSP_OP_ABS_DIFF(SrcData[4], DSP_OP_AVG (RefDataPtr1[4], RefDataPtr2[4])); - sad += DSP_OP_ABS_DIFF(SrcData[5], DSP_OP_AVG (RefDataPtr1[5], RefDataPtr2[5])); - sad += DSP_OP_ABS_DIFF(SrcData[6], DSP_OP_AVG (RefDataPtr1[6], RefDataPtr2[6])); - sad += DSP_OP_ABS_DIFF(SrcData[7], DSP_OP_AVG (RefDataPtr1[7], RefDataPtr2[7])); - - if ( sad > thres ) - break; - - /* Step to next row of block. */ - SrcData += SrcStride; - RefDataPtr1 += RefStride; - RefDataPtr2 += RefStride; - } - - return sad; -} - -static ogg_uint32_t intra8x8_err__c (unsigned char *DataPtr, ogg_uint32_t Stride) -{ - ogg_uint32_t i; - ogg_uint32_t XSum=0; - ogg_uint32_t XXSum=0; - - for (i=8; i; i--) { - /* Examine alternate pixel locations. */ - XSum += DataPtr[0]; - XXSum += DataPtr[0]*DataPtr[0]; - XSum += DataPtr[1]; - XXSum += DataPtr[1]*DataPtr[1]; - XSum += DataPtr[2]; - XXSum += DataPtr[2]*DataPtr[2]; - XSum += DataPtr[3]; - XXSum += DataPtr[3]*DataPtr[3]; - XSum += DataPtr[4]; - XXSum += DataPtr[4]*DataPtr[4]; - XSum += DataPtr[5]; - XXSum += DataPtr[5]*DataPtr[5]; - XSum += DataPtr[6]; - XXSum += DataPtr[6]*DataPtr[6]; - XSum += DataPtr[7]; - XXSum += DataPtr[7]*DataPtr[7]; - - /* Step to next row of block. */ - DataPtr += Stride; - } - - /* Compute population variance as mis-match metric. */ - return (( (XXSum<<6) - XSum*XSum ) ); -} - -static ogg_uint32_t inter8x8_err__c (unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr, ogg_uint32_t RefStride) -{ - ogg_uint32_t i; - ogg_uint32_t XSum=0; - ogg_uint32_t XXSum=0; - ogg_int32_t DiffVal; - - for (i=8; i; i--) { - DiffVal = DSP_OP_DIFF (SrcData[0], RefDataPtr[0]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF (SrcData[1], RefDataPtr[1]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF (SrcData[2], RefDataPtr[2]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF (SrcData[3], RefDataPtr[3]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF (SrcData[4], RefDataPtr[4]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF (SrcData[5], RefDataPtr[5]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF (SrcData[6], RefDataPtr[6]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF (SrcData[7], RefDataPtr[7]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - /* Step to next row of block. */ - SrcData += SrcStride; - RefDataPtr += RefStride; - } - - /* Compute and return population variance as mis-match metric. */ - return (( (XXSum<<6) - XSum*XSum )); -} - -static ogg_uint32_t inter8x8_err_xy2__c (unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr1, - unsigned char *RefDataPtr2, ogg_uint32_t RefStride) -{ - ogg_uint32_t i; - ogg_uint32_t XSum=0; - ogg_uint32_t XXSum=0; - ogg_int32_t DiffVal; - - for (i=8; i; i--) { - DiffVal = DSP_OP_DIFF(SrcData[0], DSP_OP_AVG (RefDataPtr1[0], RefDataPtr2[0])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF(SrcData[1], DSP_OP_AVG (RefDataPtr1[1], RefDataPtr2[1])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF(SrcData[2], DSP_OP_AVG (RefDataPtr1[2], RefDataPtr2[2])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF(SrcData[3], DSP_OP_AVG (RefDataPtr1[3], RefDataPtr2[3])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF(SrcData[4], DSP_OP_AVG (RefDataPtr1[4], RefDataPtr2[4])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF(SrcData[5], DSP_OP_AVG (RefDataPtr1[5], RefDataPtr2[5])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF(SrcData[6], DSP_OP_AVG (RefDataPtr1[6], RefDataPtr2[6])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF(SrcData[7], DSP_OP_AVG (RefDataPtr1[7], RefDataPtr2[7])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - /* Step to next row of block. */ - SrcData += SrcStride; - RefDataPtr1 += RefStride; - RefDataPtr2 += RefStride; - } - - /* Compute and return population variance as mis-match metric. */ - return (( (XXSum<<6) - XSum*XSum )); -} - -static void nop (void) { /* NOP */ } - -void dsp_init(DspFunctions *funcs) -{ - funcs->save_fpu = nop; - funcs->restore_fpu = nop; - funcs->sub8x8 = sub8x8__c; - funcs->sub8x8_128 = sub8x8_128__c; - funcs->sub8x8avg2 = sub8x8avg2__c; - funcs->row_sad8 = row_sad8__c; - funcs->col_sad8x8 = col_sad8x8__c; - funcs->sad8x8 = sad8x8__c; - funcs->sad8x8_thres = sad8x8_thres__c; - funcs->sad8x8_xy2_thres = sad8x8_xy2_thres__c; - funcs->intra8x8_err = intra8x8_err__c; - funcs->inter8x8_err = inter8x8_err__c; - funcs->inter8x8_err_xy2 = inter8x8_err_xy2__c; -} - -void dsp_static_init(DspFunctions *funcs) -{ - ogg_uint32_t cpuflags; - - cpuflags = oc_cpu_flags_get (); - dsp_init (funcs); - - dsp_recon_init (funcs, cpuflags); - dsp_dct_init (funcs, cpuflags); -#if defined(USE_ASM) - if (cpuflags & OC_CPU_X86_MMX) { - dsp_mmx_init(funcs); - } -# ifndef WIN32 - /* This is implemented for win32 yet */ - if (cpuflags & OC_CPU_X86_MMXEXT) { - dsp_mmxext_init(funcs); - } -# endif -#endif -} - diff --git a/Engine/lib/libtheora/lib/enc/dsp.h b/Engine/lib/libtheora/lib/enc/dsp.h deleted file mode 100644 index 7f96f7f84..000000000 --- a/Engine/lib/libtheora/lib/enc/dsp.h +++ /dev/null @@ -1,166 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: dsp.h 15153 2008-08-04 18:37:55Z tterribe $ - - ********************************************************************/ - -#ifndef DSP_H -#define DSP_H - -#include "theora/theora.h" -#include "../cpu.h" - -typedef struct -{ - void (*save_fpu) (void); - void (*restore_fpu) (void); - - void (*sub8x8) (unsigned char *FiltPtr, unsigned char *ReconPtr, - ogg_int16_t *DctInputPtr, ogg_uint32_t PixelsPerLine, - ogg_uint32_t ReconPixelsPerLine); - - void (*sub8x8_128) (unsigned char *FiltPtr, ogg_int16_t *DctInputPtr, - ogg_uint32_t PixelsPerLine); - - void (*sub8x8avg2) (unsigned char *FiltPtr, unsigned char *ReconPtr1, - unsigned char *ReconPtr2, ogg_int16_t *DctInputPtr, - ogg_uint32_t PixelsPerLine, - ogg_uint32_t ReconPixelsPerLine); - - void (*copy8x8) (unsigned char *src, unsigned char *dest, - ogg_uint32_t stride); - - void (*recon_intra8x8) (unsigned char *ReconPtr, ogg_int16_t *ChangePtr, - ogg_uint32_t LineStep); - - void (*recon_inter8x8) (unsigned char *ReconPtr, unsigned char *RefPtr, - ogg_int16_t *ChangePtr, ogg_uint32_t LineStep); - - void (*recon_inter8x8_half) (unsigned char *ReconPtr, unsigned char *RefPtr1, - unsigned char *RefPtr2, ogg_int16_t *ChangePtr, - ogg_uint32_t LineStep); - - void (*fdct_short) (ogg_int16_t *InputData, ogg_int16_t *OutputData); - - ogg_uint32_t (*row_sad8) (unsigned char *Src1, unsigned char *Src2); - - ogg_uint32_t (*col_sad8x8) (unsigned char *Src1, unsigned char *Src2, - ogg_uint32_t stride); - - ogg_uint32_t (*sad8x8) (unsigned char *ptr1, ogg_uint32_t stride1, - unsigned char *ptr2, ogg_uint32_t stride2); - - ogg_uint32_t (*sad8x8_thres) (unsigned char *ptr1, ogg_uint32_t stride1, - unsigned char *ptr2, ogg_uint32_t stride2, - ogg_uint32_t thres); - - ogg_uint32_t (*sad8x8_xy2_thres)(unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr1, - unsigned char *RefDataPtr2, ogg_uint32_t RefStride, - ogg_uint32_t thres); - - ogg_uint32_t (*intra8x8_err) (unsigned char *DataPtr, ogg_uint32_t Stride); - - ogg_uint32_t (*inter8x8_err) (unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr, ogg_uint32_t RefStride); - - ogg_uint32_t (*inter8x8_err_xy2)(unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr1, - unsigned char *RefDataPtr2, ogg_uint32_t RefStride); - - void (*LoopFilter) (PB_INSTANCE *pbi, int FLimit); - - void (*FilterVert) (unsigned char * PixelPtr, - ogg_int32_t LineLength, ogg_int16_t *BoundingValuePtr); - - void (*IDctSlow) (ogg_int16_t *InputData, - ogg_int16_t *QuantMatrix, ogg_int16_t *OutputData); - - void (*IDct3) (ogg_int16_t *InputData, - ogg_int16_t *QuantMatrix, ogg_int16_t *OutputData); - - void (*IDct10) (ogg_int16_t *InputData, - ogg_int16_t *QuantMatrix, ogg_int16_t *OutputData); -} DspFunctions; - -extern void dsp_dct_init(DspFunctions *funcs, ogg_uint32_t cpu_flags); -extern void dsp_recon_init (DspFunctions *funcs, ogg_uint32_t cpu_flags); -extern void dsp_dct_decode_init(DspFunctions *funcs, ogg_uint32_t cpu_flags); -extern void dsp_idct_init(DspFunctions *funcs, ogg_uint32_t cpu_flags); - -void dsp_init(DspFunctions *funcs); -void dsp_static_init(DspFunctions *funcs); -#if defined(USE_ASM) && (defined(__i386__) || defined(__x86_64__) || defined(WIN32)) -extern void dsp_mmx_init(DspFunctions *funcs); -extern void dsp_mmxext_init(DspFunctions *funcs); -extern void dsp_mmx_fdct_init(DspFunctions *funcs); -extern void dsp_mmx_recon_init(DspFunctions *funcs); -extern void dsp_mmx_dct_decode_init(DspFunctions *funcs); -extern void dsp_mmx_idct_init(DspFunctions *funcs); -#endif - -#define dsp_save_fpu(funcs) (funcs.save_fpu ()) - -#define dsp_restore_fpu(funcs) (funcs.restore_fpu ()) - -#define dsp_sub8x8(funcs,a1,a2,a3,a4,a5) (funcs.sub8x8 (a1,a2,a3,a4,a5)) - -#define dsp_sub8x8_128(funcs,a1,a2,a3) (funcs.sub8x8_128 (a1,a2,a3)) - -#define dsp_sub8x8avg2(funcs,a1,a2,a3,a4,a5,a6) (funcs.sub8x8avg2 (a1,a2,a3,a4,a5,a6)) - -#define dsp_copy8x8(funcs,ptr1,ptr2,str1) (funcs.copy8x8 (ptr1,ptr2,str1)) - -#define dsp_recon_intra8x8(funcs,ptr1,ptr2,str1) (funcs.recon_intra8x8 (ptr1,ptr2,str1)) - -#define dsp_recon_inter8x8(funcs,ptr1,ptr2,ptr3,str1) \ - (funcs.recon_inter8x8 (ptr1,ptr2,ptr3,str1)) - -#define dsp_recon_inter8x8_half(funcs,ptr1,ptr2,ptr3,ptr4,str1) \ - (funcs.recon_inter8x8_half (ptr1,ptr2,ptr3,ptr4,str1)) - -#define dsp_fdct_short(funcs,in,out) (funcs.fdct_short (in,out)) - -#define dsp_row_sad8(funcs,ptr1,ptr2) (funcs.row_sad8 (ptr1,ptr2)) - -#define dsp_col_sad8x8(funcs,ptr1,ptr2,str1) (funcs.col_sad8x8 (ptr1,ptr2,str1)) - -#define dsp_sad8x8(funcs,ptr1,str1,ptr2,str2) (funcs.sad8x8 (ptr1,str1,ptr2,str2)) - -#define dsp_sad8x8_thres(funcs,ptr1,str1,ptr2,str2,t) (funcs.sad8x8_thres (ptr1,str1,ptr2,str2,t)) - -#define dsp_sad8x8_xy2_thres(funcs,ptr1,str1,ptr2,ptr3,str2,t) \ - (funcs.sad8x8_xy2_thres (ptr1,str1,ptr2,ptr3,str2,t)) - -#define dsp_intra8x8_err(funcs,ptr1,str1) (funcs.intra8x8_err (ptr1,str1)) - -#define dsp_inter8x8_err(funcs,ptr1,str1,ptr2,str2) \ - (funcs.inter8x8_err (ptr1,str1,ptr2,str2)) - -#define dsp_inter8x8_err_xy2(funcs,ptr1,str1,ptr2,ptr3,str2) \ - (funcs.inter8x8_err_xy2 (ptr1,str1,ptr2,ptr3,str2)) - -#define dsp_LoopFilter(funcs, ptr1, i) \ - (funcs.LoopFilter(ptr1, i)) - -#define dsp_IDctSlow(funcs, ptr1, ptr2, ptr3) \ - (funcs.IDctSlow(ptr1, ptr2, ptr3)) - -#define dsp_IDct3(funcs, ptr1, ptr2, ptr3) \ - (funcs.IDctSlow(ptr1, ptr2, ptr3)) - -#define dsp_IDct10(funcs, ptr1, ptr2, ptr3) \ - (funcs.IDctSlow(ptr1, ptr2, ptr3)) - -#endif /* DSP_H */ diff --git a/Engine/lib/libtheora/lib/enc/encode.c b/Engine/lib/libtheora/lib/enc/encode.c deleted file mode 100644 index 5dc89f2af..000000000 --- a/Engine/lib/libtheora/lib/enc/encode.c +++ /dev/null @@ -1,1479 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: encode.c 15383 2008-10-10 14:33:46Z xiphmont $ - - ********************************************************************/ - -#include -#include -#include "codec_internal.h" -#include "encoder_lookup.h" -#include "block_inline.h" - -#define PUR 8 -#define PU 4 -#define PUL 2 -#define PL 1 -#define HIGHBITDUPPED(X) (((ogg_int16_t) X) >> 15) - -static ogg_uint32_t QuadCodeComponent ( CP_INSTANCE *cpi, - ogg_uint32_t FirstSB, - ogg_uint32_t SBRows, - ogg_uint32_t SBCols, - ogg_uint32_t PixelsPerLine){ - - ogg_int32_t FragIndex; /* Fragment number */ - ogg_uint32_t MB, B; /* Macro-Block, Block indices */ - ogg_uint32_t SBrow; /* Super-Block row number */ - ogg_uint32_t SBcol; /* Super-Block row number */ - ogg_uint32_t SB=FirstSB; /* Super-Block index, initialised to first - of this component */ - ogg_uint32_t coded_pixels=0; /* Number of pixels coded */ - int MBCodedFlag; - - /* actually transform and quantize the image now that we've decided - on the modes Parse in quad-tree ordering */ - - for ( SBrow=0; SBrowpb.BlockMap,SB,MB) >= 0 ) { - - MBCodedFlag = 0; - - /* Now actually code the blocks */ - for ( B=0; B<4; B++ ) { - FragIndex = QuadMapToIndex1( cpi->pb.BlockMap, SB, MB, B ); - - /* Does Block lie in frame: */ - if ( FragIndex >= 0 ) { - - /* In Frame: Is it coded: */ - if ( cpi->pb.display_fragments[FragIndex] ) { - - /* transform and quantize block */ - TransformQuantizeBlock( cpi, FragIndex, PixelsPerLine ); - - /* Has the block got struck off (no MV and no data - generated after DCT) If not then mark it and the - assosciated MB as coded. */ - if ( cpi->pb.display_fragments[FragIndex] ) { - /* Create linear list of coded block indices */ - cpi->pb.CodedBlockList[cpi->pb.CodedBlockIndex] = FragIndex; - cpi->pb.CodedBlockIndex++; - - /* MB is still coded */ - MBCodedFlag = 1; - cpi->MBCodingMode = cpi->pb.FragCodingMethod[FragIndex]; - - } - } - } - } - /* If the MB is marked as coded and we are in the Y plane then */ - /* the mode list needs to be updated. */ - if ( MBCodedFlag && (FirstSB == 0) ){ - /* Make a note of the selected mode in the mode list */ - cpi->ModeList[cpi->ModeListCount] = cpi->MBCodingMode; - cpi->ModeListCount++; - } - } - } - - SB++; - - } - } - - /* Return number of pixels coded */ - return coded_pixels; -} - -static void EncodeDcTokenList (CP_INSTANCE *cpi) { - ogg_int32_t i,j; - ogg_uint32_t Token; - ogg_uint32_t ExtraBitsToken; - ogg_uint32_t HuffIndex; - - ogg_uint32_t BestDcBits; - ogg_uint32_t DcHuffChoice[2]; - ogg_uint32_t EntropyTableBits[2][DC_HUFF_CHOICES]; - - oggpack_buffer *opb=cpi->oggbuffer; - - /* Clear table data structure */ - memset ( EntropyTableBits, 0, sizeof(ogg_uint32_t)*DC_HUFF_CHOICES*2 ); - - /* Analyse token list to see which is the best entropy table to use */ - for ( i = 0; i < cpi->OptimisedTokenCount; i++ ) { - /* Count number of bits for each table option */ - Token = (ogg_uint32_t)cpi->OptimisedTokenList[i]; - for ( j = 0; j < DC_HUFF_CHOICES; j++ ){ - EntropyTableBits[cpi->OptimisedTokenListPl[i]][j] += - cpi->pb.HuffCodeLengthArray_VP3x[DC_HUFF_OFFSET + j][Token]; - } - } - - /* Work out which table option is best for Y */ - BestDcBits = EntropyTableBits[0][0]; - DcHuffChoice[0] = 0; - for ( j = 1; j < DC_HUFF_CHOICES; j++ ) { - if ( EntropyTableBits[0][j] < BestDcBits ) { - BestDcBits = EntropyTableBits[0][j]; - DcHuffChoice[0] = j; - } - } - - /* Add the DC huffman table choice to the bitstream */ - oggpackB_write( opb, DcHuffChoice[0], DC_HUFF_CHOICE_BITS ); - - /* Work out which table option is best for UV */ - BestDcBits = EntropyTableBits[1][0]; - DcHuffChoice[1] = 0; - for ( j = 1; j < DC_HUFF_CHOICES; j++ ) { - if ( EntropyTableBits[1][j] < BestDcBits ) { - BestDcBits = EntropyTableBits[1][j]; - DcHuffChoice[1] = j; - } - } - - /* Add the DC huffman table choice to the bitstream */ - oggpackB_write( opb, DcHuffChoice[1], DC_HUFF_CHOICE_BITS ); - - /* Encode the token list */ - for ( i = 0; i < cpi->OptimisedTokenCount; i++ ) { - - /* Get the token and extra bits */ - Token = (ogg_uint32_t)cpi->OptimisedTokenList[i]; - ExtraBitsToken = (ogg_uint32_t)cpi->OptimisedTokenListEb[i]; - - /* Select the huffman table */ - if ( cpi->OptimisedTokenListPl[i] == 0) - HuffIndex = (ogg_uint32_t)DC_HUFF_OFFSET + (ogg_uint32_t)DcHuffChoice[0]; - else - HuffIndex = (ogg_uint32_t)DC_HUFF_OFFSET + (ogg_uint32_t)DcHuffChoice[1]; - - /* Add the bits to the encode holding buffer. */ - cpi->FrameBitCount += cpi->pb.HuffCodeLengthArray_VP3x[HuffIndex][Token]; - oggpackB_write( opb, cpi->pb.HuffCodeArray_VP3x[HuffIndex][Token], - (ogg_uint32_t)cpi-> - pb.HuffCodeLengthArray_VP3x[HuffIndex][Token] ); - - /* If the token is followed by an extra bits token then code it */ - if ( cpi->pb.ExtraBitLengths_VP3x[Token] > 0 ) { - /* Add the bits to the encode holding buffer. */ - cpi->FrameBitCount += cpi->pb.ExtraBitLengths_VP3x[Token]; - oggpackB_write( opb, ExtraBitsToken, - (ogg_uint32_t)cpi->pb.ExtraBitLengths_VP3x[Token] ); - } - - } - - /* Reset the count of second order optimised tokens */ - cpi->OptimisedTokenCount = 0; -} - -static void EncodeAcTokenList (CP_INSTANCE *cpi) { - ogg_int32_t i,j; - ogg_uint32_t Token; - ogg_uint32_t ExtraBitsToken; - ogg_uint32_t HuffIndex; - - ogg_uint32_t BestAcBits; - ogg_uint32_t AcHuffChoice[2]; - ogg_uint32_t EntropyTableBits[2][AC_HUFF_CHOICES]; - - oggpack_buffer *opb=cpi->oggbuffer; - - memset ( EntropyTableBits, 0, sizeof(ogg_uint32_t)*AC_HUFF_CHOICES*2 ); - - /* Analyse token list to see which is the best entropy table to use */ - for ( i = 0; i < cpi->OptimisedTokenCount; i++ ) { - /* Count number of bits for each table option */ - Token = (ogg_uint32_t)cpi->OptimisedTokenList[i]; - HuffIndex = cpi->OptimisedTokenListHi[i]; - for ( j = 0; j < AC_HUFF_CHOICES; j++ ) { - EntropyTableBits[cpi->OptimisedTokenListPl[i]][j] += - cpi->pb.HuffCodeLengthArray_VP3x[HuffIndex + j][Token]; - } - } - - /* Select the best set of AC tables for Y */ - BestAcBits = EntropyTableBits[0][0]; - AcHuffChoice[0] = 0; - for ( j = 1; j < AC_HUFF_CHOICES; j++ ) { - if ( EntropyTableBits[0][j] < BestAcBits ) { - BestAcBits = EntropyTableBits[0][j]; - AcHuffChoice[0] = j; - } - } - - /* Add the AC-Y huffman table choice to the bitstream */ - oggpackB_write( opb, AcHuffChoice[0], AC_HUFF_CHOICE_BITS ); - - /* Select the best set of AC tables for UV */ - BestAcBits = EntropyTableBits[1][0]; - AcHuffChoice[1] = 0; - for ( j = 1; j < AC_HUFF_CHOICES; j++ ) { - if ( EntropyTableBits[1][j] < BestAcBits ) { - BestAcBits = EntropyTableBits[1][j]; - AcHuffChoice[1] = j; - } - } - - /* Add the AC-UV huffman table choice to the bitstream */ - oggpackB_write( opb, AcHuffChoice[1], AC_HUFF_CHOICE_BITS ); - - /* Encode the token list */ - for ( i = 0; i < cpi->OptimisedTokenCount; i++ ) { - /* Get the token and extra bits */ - Token = (ogg_uint32_t)cpi->OptimisedTokenList[i]; - ExtraBitsToken = (ogg_uint32_t)cpi->OptimisedTokenListEb[i]; - - /* Select the huffman table */ - HuffIndex = (ogg_uint32_t)cpi->OptimisedTokenListHi[i] + - AcHuffChoice[cpi->OptimisedTokenListPl[i]]; - - /* Add the bits to the encode holding buffer. */ - cpi->FrameBitCount += cpi->pb.HuffCodeLengthArray_VP3x[HuffIndex][Token]; - oggpackB_write( opb, cpi->pb.HuffCodeArray_VP3x[HuffIndex][Token], - (ogg_uint32_t)cpi-> - pb.HuffCodeLengthArray_VP3x[HuffIndex][Token] ); - - /* If the token is followed by an extra bits token then code it */ - if ( cpi->pb.ExtraBitLengths_VP3x[Token] > 0 ) { - /* Add the bits to the encode holding buffer. */ - cpi->FrameBitCount += cpi->pb.ExtraBitLengths_VP3x[Token]; - oggpackB_write( opb, ExtraBitsToken, - (ogg_uint32_t)cpi->pb.ExtraBitLengths_VP3x[Token] ); - } - } - - /* Reset the count of second order optimised tokens */ - cpi->OptimisedTokenCount = 0; -} - -static void PackModes (CP_INSTANCE *cpi) { - ogg_uint32_t i,j; - unsigned char ModeIndex; - const unsigned char *SchemeList; - - unsigned char BestModeSchemes[MAX_MODES]; - ogg_int32_t ModeCount[MAX_MODES]; - ogg_int32_t TmpFreq = -1; - ogg_int32_t TmpIndex = -1; - - ogg_uint32_t BestScheme; - ogg_uint32_t BestSchemeScore; - ogg_uint32_t SchemeScore; - - oggpack_buffer *opb=cpi->oggbuffer; - - /* Build a frequency map for the modes in this frame */ - memset( ModeCount, 0, MAX_MODES*sizeof(ogg_int32_t) ); - for ( i = 0; i < cpi->ModeListCount; i++ ) - ModeCount[cpi->ModeList[i]] ++; - - /* Order the modes from most to least frequent. Store result as - scheme 0 */ - for ( j = 0; j < MAX_MODES; j++ ) { - TmpFreq = -1; /* need to re-initialize for each loop */ - /* Find the most frequent */ - for ( i = 0; i < MAX_MODES; i++ ) { - /* Is this the best scheme so far ??? */ - if ( ModeCount[i] > TmpFreq ) { - TmpFreq = ModeCount[i]; - TmpIndex = i; - } - } - /* I don't know if the above loop ever fails to match, but it's - better safe than sorry. Plus this takes care of gcc warning */ - if ( TmpIndex != -1 ) { - ModeCount[TmpIndex] = -1; - BestModeSchemes[TmpIndex] = (unsigned char)j; - } - } - - /* Default/ fallback scheme uses MODE_BITS bits per mode entry */ - BestScheme = (MODE_METHODS - 1); - BestSchemeScore = cpi->ModeListCount * 3; - /* Get a bit score for the available schemes. */ - for ( j = 0; j < (MODE_METHODS - 1); j++ ) { - - /* Reset the scheme score */ - if ( j == 0 ){ - /* Scheme 0 additional cost of sending frequency order */ - SchemeScore = 24; - SchemeList = BestModeSchemes; - } else { - SchemeScore = 0; - SchemeList = ModeSchemes[j-1]; - } - - /* Find the total bits to code using each avaialable scheme */ - for ( i = 0; i < cpi->ModeListCount; i++ ) - SchemeScore += ModeBitLengths[SchemeList[cpi->ModeList[i]]]; - - /* Is this the best scheme so far ??? */ - if ( SchemeScore < BestSchemeScore ) { - BestSchemeScore = SchemeScore; - BestScheme = j; - } - } - - /* Encode the best scheme. */ - oggpackB_write( opb, BestScheme, (ogg_uint32_t)MODE_METHOD_BITS ); - - /* If the chosen schems is scheme 0 send details of the mode - frequency order */ - if ( BestScheme == 0 ) { - for ( j = 0; j < MAX_MODES; j++ ){ - /* Note that the last two entries are implicit */ - oggpackB_write( opb, BestModeSchemes[j], (ogg_uint32_t)MODE_BITS ); - } - SchemeList = BestModeSchemes; - } - else { - SchemeList = ModeSchemes[BestScheme-1]; - } - - /* Are we using one of the alphabet based schemes or the fallback scheme */ - if ( BestScheme < (MODE_METHODS - 1)) { - /* Pack and encode the Mode list */ - for ( i = 0; i < cpi->ModeListCount; i++) { - /* Add the appropriate mode entropy token. */ - ModeIndex = SchemeList[cpi->ModeList[i]]; - oggpackB_write( opb, ModeBitPatterns[ModeIndex], - (ogg_uint32_t)ModeBitLengths[ModeIndex] ); - } - }else{ - /* Fall back to MODE_BITS per entry */ - for ( i = 0; i < cpi->ModeListCount; i++) - /* Add the appropriate mode entropy token. */ - oggpackB_write( opb, cpi->ModeList[i], MODE_BITS ); - } - -} - -static void PackMotionVectors (CP_INSTANCE *cpi) { - ogg_int32_t i; - ogg_uint32_t MethodBits[2] = {0,0}; - const ogg_uint32_t * MvBitsPtr; - const ogg_uint32_t * MvPatternPtr; - - oggpack_buffer *opb=cpi->oggbuffer; - - /* Choose the coding method */ - MvBitsPtr = &MvBits[MAX_MV_EXTENT]; - for ( i = 0; i < (ogg_int32_t)cpi->MvListCount; i++ ) { - MethodBits[0] += MvBitsPtr[cpi->MVList[i].x]; - MethodBits[0] += MvBitsPtr[cpi->MVList[i].y]; - MethodBits[1] += 12; /* Simple six bits per mv component fallback - mechanism */ - } - - /* Select entropy table */ - if ( MethodBits[0] < MethodBits[1] ) { - oggpackB_write( opb, 0, 1 ); - MvBitsPtr = &MvBits[MAX_MV_EXTENT]; - MvPatternPtr = &MvPattern[MAX_MV_EXTENT]; - }else{ - oggpackB_write( opb, 1, 1 ); - MvBitsPtr = &MvBits2[MAX_MV_EXTENT]; - MvPatternPtr = &MvPattern2[MAX_MV_EXTENT]; - } - - /* Pack and encode the motion vectors */ - for ( i = 0; i < (ogg_int32_t)cpi->MvListCount; i++ ) { - oggpackB_write( opb, MvPatternPtr[cpi->MVList[i].x], - (ogg_uint32_t)MvBitsPtr[cpi->MVList[i].x] ); - oggpackB_write( opb, MvPatternPtr[cpi->MVList[i].y], - (ogg_uint32_t)MvBitsPtr[cpi->MVList[i].y] ); - } - -} - -static void PackEOBRun( CP_INSTANCE *cpi) { - if(cpi->RunLength == 0) - return; - - /* Note the appropriate EOB or EOB run token and any extra bits in - the optimised token list. Use the huffman index assosciated with - the first token in the run */ - - /* Mark out which plane the block belonged to */ - cpi->OptimisedTokenListPl[cpi->OptimisedTokenCount] = - (unsigned char)cpi->RunPlaneIndex; - - /* Note the huffman index to be used */ - cpi->OptimisedTokenListHi[cpi->OptimisedTokenCount] = - (unsigned char)cpi->RunHuffIndex; - - if ( cpi->RunLength <= 3 ) { - if ( cpi->RunLength == 1 ) { - cpi->OptimisedTokenList[cpi->OptimisedTokenCount] = DCT_EOB_TOKEN; - } else if ( cpi->RunLength == 2 ) { - cpi->OptimisedTokenList[cpi->OptimisedTokenCount] = DCT_EOB_PAIR_TOKEN; - } else { - cpi->OptimisedTokenList[cpi->OptimisedTokenCount] = DCT_EOB_TRIPLE_TOKEN; - } - - cpi->RunLength = 0; - - } else { - - /* Choose a token appropriate to the run length. */ - if ( cpi->RunLength < 8 ) { - cpi->OptimisedTokenList[cpi->OptimisedTokenCount] = - DCT_REPEAT_RUN_TOKEN; - cpi->OptimisedTokenListEb[cpi->OptimisedTokenCount] = - cpi->RunLength - 4; - cpi->RunLength = 0; - } else if ( cpi->RunLength < 16 ) { - cpi->OptimisedTokenList[cpi->OptimisedTokenCount] = - DCT_REPEAT_RUN2_TOKEN; - cpi->OptimisedTokenListEb[cpi->OptimisedTokenCount] = - cpi->RunLength - 8; - cpi->RunLength = 0; - } else if ( cpi->RunLength < 32 ) { - cpi->OptimisedTokenList[cpi->OptimisedTokenCount] = - DCT_REPEAT_RUN3_TOKEN; - cpi->OptimisedTokenListEb[cpi->OptimisedTokenCount] = - cpi->RunLength - 16; - cpi->RunLength = 0; - } else if ( cpi->RunLength < 4096) { - cpi->OptimisedTokenList[cpi->OptimisedTokenCount] = - DCT_REPEAT_RUN4_TOKEN; - cpi->OptimisedTokenListEb[cpi->OptimisedTokenCount] = - cpi->RunLength; - cpi->RunLength = 0; - } - - } - - cpi->OptimisedTokenCount++; - /* Reset run EOB length */ - cpi->RunLength = 0; -} - -static void PackToken ( CP_INSTANCE *cpi, ogg_int32_t FragmentNumber, - ogg_uint32_t HuffIndex ) { - ogg_uint32_t Token = - cpi->pb.TokenList[FragmentNumber][cpi->FragTokens[FragmentNumber]]; - ogg_uint32_t ExtraBitsToken = - cpi->pb.TokenList[FragmentNumber][cpi->FragTokens[FragmentNumber] + 1]; - ogg_uint32_t OneOrTwo; - ogg_uint32_t OneOrZero; - - /* Update the record of what coefficient we have got up to for this - block and unpack the encoded token back into the quantised data - array. */ - if ( Token == DCT_EOB_TOKEN ) - cpi->pb.FragCoeffs[FragmentNumber] = BLOCK_SIZE; - else - ExpandToken( cpi->pb.QFragData[FragmentNumber], - &cpi->pb.FragCoeffs[FragmentNumber], - Token, ExtraBitsToken ); - - /* Update record of tokens coded and where we are in this fragment. */ - /* Is there an extra bits token */ - OneOrTwo= 1 + ( cpi->pb.ExtraBitLengths_VP3x[Token] > 0 ); - /* Advance to the next real token. */ - cpi->FragTokens[FragmentNumber] += (unsigned char)OneOrTwo; - - /* Update the counts of tokens coded */ - cpi->TokensCoded += OneOrTwo; - cpi->TokensToBeCoded -= OneOrTwo; - - OneOrZero = ( FragmentNumber < (ogg_int32_t)cpi->pb.YPlaneFragments ); - - if ( Token == DCT_EOB_TOKEN ) { - if ( cpi->RunLength == 0 ) { - cpi->RunHuffIndex = HuffIndex; - cpi->RunPlaneIndex = 1 - OneOrZero; - } - cpi->RunLength++; - - /* we have exceeded our longest run length xmit an eob run token; */ - if ( cpi->RunLength == 4095 ) PackEOBRun(cpi); - - }else{ - - /* If we have an EOB run then code it up first */ - if ( cpi->RunLength > 0 ) PackEOBRun( cpi); - - /* Mark out which plane the block belonged to */ - cpi->OptimisedTokenListPl[cpi->OptimisedTokenCount] = - (unsigned char)(1 - OneOrZero); - - /* Note the token, extra bits and hufman table in the optimised - token list */ - cpi->OptimisedTokenList[cpi->OptimisedTokenCount] = - (unsigned char)Token; - cpi->OptimisedTokenListEb[cpi->OptimisedTokenCount] = - ExtraBitsToken; - cpi->OptimisedTokenListHi[cpi->OptimisedTokenCount] = - (unsigned char)HuffIndex; - - cpi->OptimisedTokenCount++; - } -} - -static ogg_uint32_t GetBlockReconErrorSlow( CP_INSTANCE *cpi, - ogg_int32_t BlockIndex ) { - ogg_uint32_t ErrorVal; - - unsigned char * SrcDataPtr = - &cpi->ConvDestBuffer[cpi->pb.pixel_index_table[BlockIndex]]; - unsigned char * RecDataPtr = - &cpi->pb.LastFrameRecon[cpi->pb.recon_pixel_index_table[BlockIndex]]; - ogg_int32_t SrcStride; - ogg_int32_t RecStride; - - /* Is the block a Y block or a UV block. */ - if ( BlockIndex < (ogg_int32_t)cpi->pb.YPlaneFragments ) { - SrcStride = cpi->pb.info.width; - RecStride = cpi->pb.YStride; - }else{ - SrcStride = cpi->pb.info.width >> 1; - RecStride = cpi->pb.UVStride; - } - - ErrorVal = dsp_sad8x8 (cpi->dsp, SrcDataPtr, SrcStride, RecDataPtr, RecStride); - - return ErrorVal; -} - -static void PackCodedVideo (CP_INSTANCE *cpi) { - ogg_int32_t i; - ogg_int32_t EncodedCoeffs = 1; - ogg_int32_t FragIndex; - ogg_uint32_t HuffIndex; /* Index to group of tables used to code a token */ - - /* Reset the count of second order optimised tokens */ - cpi->OptimisedTokenCount = 0; - - cpi->TokensToBeCoded = cpi->TotTokenCount; - cpi->TokensCoded = 0; - - /* Calculate the bit rate at which this frame should be capped. */ - cpi->MaxBitTarget = (ogg_uint32_t)((double)(cpi->ThisFrameTargetBytes * 8) * - cpi->BitRateCapFactor); - - /* Blank the various fragment data structures before we start. */ - memset(cpi->pb.FragCoeffs, 0, cpi->pb.UnitFragments); - memset(cpi->FragTokens, 0, cpi->pb.UnitFragments); - - /* Clear down the QFragData structure for all coded blocks. */ - ClearDownQFragData(&cpi->pb); - - /* The tree is not needed (implicit) for key frames */ - if ( cpi->pb.FrameType != KEY_FRAME ){ - /* Pack the quad tree fragment mapping. */ - PackAndWriteDFArray( cpi ); - } - - /* Note the number of bits used to code the tree itself. */ - cpi->FrameBitCount = oggpackB_bytes(cpi->oggbuffer) << 3; - - /* Mode and MV data not needed for key frames. */ - if ( cpi->pb.FrameType != KEY_FRAME ){ - /* Pack and code the mode list. */ - PackModes(cpi); - /* Pack the motion vectors */ - PackMotionVectors (cpi); - } - - cpi->FrameBitCount = oggpackB_bytes(cpi->oggbuffer) << 3; - - /* Optimise the DC tokens */ - for ( i = 0; i < cpi->pb.CodedBlockIndex; i++ ) { - /* Get the linear index for the current fragment. */ - FragIndex = cpi->pb.CodedBlockList[i]; - - cpi->pb.FragCoefEOB[FragIndex]=(unsigned char)EncodedCoeffs; - PackToken(cpi, FragIndex, DC_HUFF_OFFSET ); - - } - - /* Pack any outstanding EOB tokens */ - PackEOBRun(cpi); - - /* Now output the optimised DC token list using the appropriate - entropy tables. */ - EncodeDcTokenList(cpi); - - /* Work out the number of DC bits coded */ - - /* Optimise the AC tokens */ - while ( EncodedCoeffs < 64 ) { - /* Huffman table adjustment based upon coefficient number. */ - if ( EncodedCoeffs <= AC_TABLE_2_THRESH ) - HuffIndex = AC_HUFF_OFFSET; - else if ( EncodedCoeffs <= AC_TABLE_3_THRESH ) - HuffIndex = AC_HUFF_OFFSET + AC_HUFF_CHOICES; - else if ( EncodedCoeffs <= AC_TABLE_4_THRESH ) - HuffIndex = AC_HUFF_OFFSET + (AC_HUFF_CHOICES * 2); - else - HuffIndex = AC_HUFF_OFFSET + (AC_HUFF_CHOICES * 3); - - /* Repeatedly scan through the list of blocks. */ - for ( i = 0; i < cpi->pb.CodedBlockIndex; i++ ) { - /* Get the linear index for the current fragment. */ - FragIndex = cpi->pb.CodedBlockList[i]; - - /* Should we code a token for this block on this pass. */ - if ( cpi->FragTokens[FragIndex] < cpi->FragTokenCounts[FragIndex] - && cpi->pb.FragCoeffs[FragIndex] <= EncodedCoeffs ) { - /* Bit pack and a token for this block */ - cpi->pb.FragCoefEOB[FragIndex]=(unsigned char)EncodedCoeffs; - PackToken( cpi, FragIndex, HuffIndex ); - } - } - - EncodedCoeffs ++; - } - - /* Pack any outstanding EOB tokens */ - PackEOBRun(cpi); - - /* Now output the optimised AC token list using the appropriate - entropy tables. */ - EncodeAcTokenList(cpi); - -} - -static ogg_uint32_t QuadCodeDisplayFragments (CP_INSTANCE *cpi) { - ogg_int32_t i,j; - ogg_uint32_t coded_pixels=0; - int QIndex; - int k,m,n; - - /* predictor multiplier up-left, up, up-right,left, shift - Entries are packed in the order L, UL, U, UR, with missing entries - moved to the end (before the shift parameters). */ - static const ogg_int16_t pc[16][6]={ - {0,0,0,0,0,0}, - {1,0,0,0,0,0}, /* PL */ - {1,0,0,0,0,0}, /* PUL */ - {1,0,0,0,0,0}, /* PUL|PL */ - {1,0,0,0,0,0}, /* PU */ - {1,1,0,0,1,1}, /* PU|PL */ - {0,1,0,0,0,0}, /* PU|PUL */ - {29,-26,29,0,5,31}, /* PU|PUL|PL */ - {1,0,0,0,0,0}, /* PUR */ - {75,53,0,0,7,127}, /* PUR|PL */ - {1,1,0,0,1,1}, /* PUR|PUL */ - {75,0,53,0,7,127}, /* PUR|PUL|PL */ - {1,0,0,0,0,0}, /* PUR|PU */ - {75,0,53,0,7,127}, /* PUR|PU|PL */ - {3,10,3,0,4,15}, /* PUR|PU|PUL */ - {29,-26,29,0,5,31} /* PUR|PU|PUL|PL */ - }; - - /* boundary case bit masks. */ - static const int bc_mask[8]={ - /* normal case no boundary condition */ - PUR|PU|PUL|PL, - /* left column */ - PUR|PU, - /* top row */ - PL, - /* top row, left column */ - 0, - /* right column */ - PU|PUL|PL, - /* right and left column */ - PU, - /* top row, right column */ - PL, - /* top row, right and left column */ - 0 - }; - - /* value left value up-left, value up, value up-right, missing - values skipped. */ - int v[4]; - - /* fragment number left, up-left, up, up-right */ - int fn[4]; - - /* predictor count. */ - int pcount; - - /*which predictor constants to use */ - ogg_int16_t wpc; - - /* last used inter predictor (Raster Order) */ - ogg_int16_t Last[3]; /* last value used for given frame */ - - int FragsAcross=cpi->pb.HFragments; - int FragsDown = cpi->pb.VFragments; - int FromFragment,ToFragment; - ogg_int32_t FragIndex; - int WhichFrame; - int WhichCase; - - static const ogg_int16_t Mode2Frame[] = { - 1, /* CODE_INTER_NO_MV 0 => Encoded diff from same MB last frame */ - 0, /* CODE_INTRA 1 => DCT Encoded Block */ - 1, /* CODE_INTER_PLUS_MV 2 => Encoded diff from included MV MB last frame */ - 1, /* CODE_INTER_LAST_MV 3 => Encoded diff from MRU MV MB last frame */ - 1, /* CODE_INTER_PRIOR_MV 4 => Encoded diff from included 4 separate MV blocks */ - 2, /* CODE_USING_GOLDEN 5 => Encoded diff from same MB golden frame */ - 2, /* CODE_GOLDEN_MV 6 => Encoded diff from included MV MB golden frame */ - 1 /* CODE_INTER_FOUR_MV 7 => Encoded diff from included 4 separate MV blocks */ - }; - - ogg_int16_t PredictedDC; - - /* Initialise the coded block indices variables. These allow - subsequent linear access to the quad tree ordered list of coded - blocks */ - cpi->pb.CodedBlockIndex = 0; - - /* Set the inter/intra descision control variables. */ - QIndex = Q_TABLE_SIZE - 1; - while ( QIndex >= 0 ) { - if ( (QIndex == 0) || - ( cpi->pb.QThreshTable[QIndex] >= cpi->pb.ThisFrameQualityValue) ) - break; - QIndex --; - } - - - /* Encode and tokenise the Y, U and V components */ - coded_pixels = QuadCodeComponent(cpi, 0, cpi->pb.YSBRows, cpi->pb.YSBCols, - cpi->pb.info.width ); - coded_pixels += QuadCodeComponent(cpi, cpi->pb.YSuperBlocks, - cpi->pb.UVSBRows, - cpi->pb.UVSBCols, - cpi->pb.info.width>>1 ); - coded_pixels += QuadCodeComponent(cpi, - cpi->pb.YSuperBlocks+cpi->pb.UVSuperBlocks, - cpi->pb.UVSBRows, cpi->pb.UVSBCols, - cpi->pb.info.width>>1 ); - - /* for y,u,v */ - for ( j = 0; j < 3 ; j++) { - /* pick which fragments based on Y, U, V */ - switch(j){ - case 0: /* y */ - FromFragment = 0; - ToFragment = cpi->pb.YPlaneFragments; - FragsAcross = cpi->pb.HFragments; - FragsDown = cpi->pb.VFragments; - break; - case 1: /* u */ - FromFragment = cpi->pb.YPlaneFragments; - ToFragment = cpi->pb.YPlaneFragments + cpi->pb.UVPlaneFragments ; - FragsAcross = cpi->pb.HFragments >> 1; - FragsDown = cpi->pb.VFragments >> 1; - break; - /*case 2: v */ - default: - FromFragment = cpi->pb.YPlaneFragments + cpi->pb.UVPlaneFragments; - ToFragment = cpi->pb.YPlaneFragments + (2 * cpi->pb.UVPlaneFragments) ; - FragsAcross = cpi->pb.HFragments >> 1; - FragsDown = cpi->pb.VFragments >> 1; - break; - } - - /* initialize our array of last used DC Components */ - for(k=0;k<3;k++)Last[k]=0; - i=FromFragment; - - /* do prediction on all of Y, U or V */ - for ( m = 0 ; m < FragsDown ; m++) { - for ( n = 0 ; n < FragsAcross ; n++, i++) { - cpi->OriginalDC[i] = cpi->pb.QFragData[i][0]; - - /* only do 2 prediction if fragment coded and on non intra or - if all fragments are intra */ - if( cpi->pb.display_fragments[i] || - (cpi->pb.FrameType == KEY_FRAME) ) { - /* Type of Fragment */ - - WhichFrame = Mode2Frame[cpi->pb.FragCodingMethod[i]]; - - /* Check Borderline Cases */ - WhichCase = (n==0) + ((m==0) << 1) + ((n+1 == FragsAcross) << 2); - - fn[0]=i-1; - fn[1]=i-FragsAcross-1; - fn[2]=i-FragsAcross; - fn[3]=i-FragsAcross+1; - - /* fragment valid for prediction use if coded and it comes - from same frame as the one we are predicting */ - for(k=pcount=wpc=0; k<4; k++) { - int pflag; - pflag=1<pb.display_fragments[fn[k]] && - (Mode2Frame[cpi->pb.FragCodingMethod[fn[k]]] == WhichFrame)){ - v[pcount]=cpi->OriginalDC[fn[k]]; - wpc|=pflag; - pcount++; - } - } - - if(wpc==0) { - - /* fall back to the last coded fragment */ - cpi->pb.QFragData[i][0] -= Last[WhichFrame]; - - } else { - - /* don't do divide if divisor is 1 or 0 */ - PredictedDC = pc[wpc][0]*v[0]; - for(k=1; k>= pc[wpc][4]; - - } - - /* check for outranging on the two predictors that can outrange */ - if((wpc&(PU|PUL|PL)) == (PU|PUL|PL)){ - if( abs(PredictedDC - v[2]) > 128) { - PredictedDC = v[2]; - } else if( abs(PredictedDC - v[0]) > 128) { - PredictedDC = v[0]; - } else if( abs(PredictedDC - v[1]) > 128) { - PredictedDC = v[1]; - } - } - - cpi->pb.QFragData[i][0] -= PredictedDC; - } - - /* Save the last fragment coded for whatever frame we are - predicting from */ - - Last[WhichFrame] = cpi->OriginalDC[i]; - - } - } - } - } - - /* Pack DC tokens and adjust the ones we couldn't predict 2d */ - for ( i = 0; i < cpi->pb.CodedBlockIndex; i++ ) { - /* Get the linear index for the current coded fragment. */ - FragIndex = cpi->pb.CodedBlockList[i]; - coded_pixels += DPCMTokenizeBlock ( cpi, FragIndex); - - } - - /* Bit pack the video data data */ - PackCodedVideo(cpi); - - /* End the bit packing run. */ - /* EndAddBitsToBuffer(cpi); */ - - /* Reconstruct the reference frames */ - ReconRefFrames(&cpi->pb); - - UpdateFragQIndex(&cpi->pb); - - /* Measure the inter reconstruction error for all the blocks that - were coded */ - /* for use as part of the recovery monitoring process in subsequent frames. */ - for ( i = 0; i < cpi->pb.CodedBlockIndex; i++ ) { - cpi->LastCodedErrorScore[ cpi->pb.CodedBlockList[i] ] = - GetBlockReconErrorSlow( cpi, cpi->pb.CodedBlockList[i] ); - - } - - /* Return total number of coded pixels */ - return coded_pixels; -} - -ogg_uint32_t EncodeData(CP_INSTANCE *cpi){ - ogg_uint32_t coded_pixels = 0; - - /* Zero the count of tokens so far this frame. */ - cpi->TotTokenCount = 0; - - /* Zero the mode and MV list indices. */ - cpi->ModeListCount = 0; - - /* Zero Decoder EOB run count */ - cpi->pb.EOB_Run = 0; - - dsp_save_fpu (cpi->dsp); - - /* Encode any fragments coded using DCT. */ - coded_pixels += QuadCodeDisplayFragments (cpi); - - dsp_restore_fpu (cpi->dsp); - - return coded_pixels; - -} - -ogg_uint32_t PickIntra( CP_INSTANCE *cpi, - ogg_uint32_t SBRows, - ogg_uint32_t SBCols){ - - ogg_int32_t FragIndex; /* Fragment number */ - ogg_uint32_t MB, B; /* Macro-Block, Block indices */ - ogg_uint32_t SBrow; /* Super-Block row number */ - ogg_uint32_t SBcol; /* Super-Block row number */ - ogg_uint32_t SB=0; /* Super-Block index, initialised to first of - this component */ - ogg_uint32_t UVRow; - ogg_uint32_t UVColumn; - ogg_uint32_t UVFragOffset; - - /* decide what block type and motion vectors to use on all of the frames */ - for ( SBrow=0; SBrowpb.BlockMap,SB,MB) >= 0 ) { - - cpi->MBCodingMode = CODE_INTRA; - - /* Now actually code the blocks. */ - for ( B=0; B<4; B++ ) { - FragIndex = QuadMapToIndex1( cpi->pb.BlockMap, SB, MB, B ); - cpi->pb.FragCodingMethod[FragIndex] = cpi->MBCodingMode; - } - - /* Matching fragments in the U and V planes */ - UVRow = (FragIndex / (cpi->pb.HFragments * 2)); - UVColumn = (FragIndex % cpi->pb.HFragments) / 2; - UVFragOffset = (UVRow * (cpi->pb.HFragments / 2)) + UVColumn; - - cpi->pb.FragCodingMethod[cpi->pb.YPlaneFragments + UVFragOffset] = - cpi->MBCodingMode; - cpi->pb.FragCodingMethod[cpi->pb.YPlaneFragments + - cpi->pb.UVPlaneFragments + UVFragOffset] = - cpi->MBCodingMode; - } - } - - /* Next Super-Block */ - SB++; - } - } - return 0; -} - -static void AddMotionVector(CP_INSTANCE *cpi, - MOTION_VECTOR *ThisMotionVector) { - cpi->MVList[cpi->MvListCount].x = ThisMotionVector->x; - cpi->MVList[cpi->MvListCount].y = ThisMotionVector->y; - cpi->MvListCount++; -} - -static void SetFragMotionVectorAndMode(CP_INSTANCE *cpi, - ogg_int32_t FragIndex, - MOTION_VECTOR *ThisMotionVector){ - /* Note the coding mode and vector for each block */ - cpi->pb.FragMVect[FragIndex].x = ThisMotionVector->x; - cpi->pb.FragMVect[FragIndex].y = ThisMotionVector->y; - cpi->pb.FragCodingMethod[FragIndex] = cpi->MBCodingMode; -} - -static void SetMBMotionVectorsAndMode(CP_INSTANCE *cpi, - ogg_int32_t YFragIndex, - ogg_int32_t UFragIndex, - ogg_int32_t VFragIndex, - MOTION_VECTOR *ThisMotionVector){ - SetFragMotionVectorAndMode(cpi, YFragIndex, ThisMotionVector); - SetFragMotionVectorAndMode(cpi, YFragIndex + 1, ThisMotionVector); - SetFragMotionVectorAndMode(cpi, YFragIndex + cpi->pb.HFragments, - ThisMotionVector); - SetFragMotionVectorAndMode(cpi, YFragIndex + cpi->pb.HFragments + 1, - ThisMotionVector); - SetFragMotionVectorAndMode(cpi, UFragIndex, ThisMotionVector); - SetFragMotionVectorAndMode(cpi, VFragIndex, ThisMotionVector); -} - -ogg_uint32_t PickModes(CP_INSTANCE *cpi, - ogg_uint32_t SBRows, ogg_uint32_t SBCols, - ogg_uint32_t PixelsPerLine, - ogg_uint32_t *InterError, ogg_uint32_t *IntraError) { - ogg_int32_t YFragIndex; - ogg_int32_t UFragIndex; - ogg_int32_t VFragIndex; - ogg_uint32_t MB, B; /* Macro-Block, Block indices */ - ogg_uint32_t SBrow; /* Super-Block row number */ - ogg_uint32_t SBcol; /* Super-Block row number */ - ogg_uint32_t SB=0; /* Super-Block index, initialised to first - of this component */ - - ogg_uint32_t MBIntraError; /* Intra error for macro block */ - ogg_uint32_t MBGFError; /* Golden frame macro block error */ - ogg_uint32_t MBGF_MVError; /* Golden frame plus MV error */ - ogg_uint32_t LastMBGF_MVError; /* Golden frame error with - last used GF motion - vector. */ - ogg_uint32_t MBInterError; /* Inter no MV macro block error */ - ogg_uint32_t MBLastInterError; /* Inter with last used MV */ - ogg_uint32_t MBPriorLastInterError; /* Inter with prior last MV */ - ogg_uint32_t MBInterMVError; /* Inter MV macro block error */ - ogg_uint32_t MBInterMVExError; /* Inter MV (exhaustive - search) macro block error */ - ogg_uint32_t MBInterFOURMVError; /* Inter MV error when using 4 - motion vectors per macro - block */ - ogg_uint32_t BestError; /* Best error so far. */ - - MOTION_VECTOR FourMVect[6]; /* storage for last used vectors (one - entry for each block in MB) */ - MOTION_VECTOR LastInterMVect; /* storage for last used Inter frame - MB motion vector */ - MOTION_VECTOR PriorLastInterMVect; /* storage for prior last used - Inter frame MB motion vector */ - MOTION_VECTOR TmpMVect; /* Temporary MV storage */ - MOTION_VECTOR LastGFMVect; /* storage for last used Golden - Frame MB motion vector */ - MOTION_VECTOR InterMVect; /* storage for motion vector */ - MOTION_VECTOR InterMVectEx; /* storage for motion vector result - from exhaustive search */ - MOTION_VECTOR GFMVect; /* storage for motion vector */ - MOTION_VECTOR ZeroVect; - - ogg_uint32_t UVRow; - ogg_uint32_t UVColumn; - ogg_uint32_t UVFragOffset; - - int MBCodedFlag; - unsigned char QIndex; - - /* initialize error scores */ - *InterError = 0; - *IntraError = 0; - - /* clear down the default motion vector. */ - cpi->MvListCount = 0; - FourMVect[0].x = 0; - FourMVect[0].y = 0; - FourMVect[1].x = 0; - FourMVect[1].y = 0; - FourMVect[2].x = 0; - FourMVect[2].y = 0; - FourMVect[3].x = 0; - FourMVect[3].y = 0; - FourMVect[4].x = 0; - FourMVect[4].y = 0; - FourMVect[5].x = 0; - FourMVect[5].y = 0; - LastInterMVect.x = 0; - LastInterMVect.y = 0; - PriorLastInterMVect.x = 0; - PriorLastInterMVect.y = 0; - LastGFMVect.x = 0; - LastGFMVect.y = 0; - InterMVect.x = 0; - InterMVect.y = 0; - GFMVect.x = 0; - GFMVect.y = 0; - - ZeroVect.x = 0; - ZeroVect.y = 0; - - QIndex = (unsigned char)cpi->pb.FrameQIndex; - - - /* change the quatization matrix to the one at best Q to compute the - new error score */ - cpi->MinImprovementForNewMV = (MvThreshTable[QIndex] << 12); - cpi->InterTripOutThresh = (5000<<12); - cpi->MVChangeFactor = MVChangeFactorTable[QIndex]; /* 0.9 */ - - if ( cpi->pb.info.quick_p ) { - cpi->ExhaustiveSearchThresh = (1000<<12); - cpi->FourMVThreshold = (2500<<12); - } else { - cpi->ExhaustiveSearchThresh = (250<<12); - cpi->FourMVThreshold = (500<<12); - } - cpi->MinImprovementForFourMV = cpi->MinImprovementForNewMV * 4; - - if(cpi->MinImprovementForFourMV < (40<<12)) - cpi->MinImprovementForFourMV = (40<<12); - - cpi->FourMvChangeFactor = 8; /* cpi->MVChangeFactor - 0.05; */ - - /* decide what block type and motion vectors to use on all of the frames */ - for ( SBrow=0; SBrowpb.BlockMap,SB,MB) < 0 ) continue; - - /* Is the current macro block coded (in part or in whole) */ - MBCodedFlag = 0; - for ( B=0; B<4; B++ ) { - YFragIndex = QuadMapToIndex1( cpi->pb.BlockMap, SB, MB, B ); - - /* Does Block lie in frame: */ - if ( YFragIndex >= 0 ) { - /* In Frame: Is it coded: */ - if ( cpi->pb.display_fragments[YFragIndex] ) { - MBCodedFlag = 1; - break; - } - } else - MBCodedFlag = 0; - } - - /* This one isn't coded go to the next one */ - if(!MBCodedFlag) continue; - - /* Calculate U and V FragIndex from YFragIndex */ - YFragIndex = QuadMapToMBTopLeft(cpi->pb.BlockMap, SB,MB); - UVRow = (YFragIndex / (cpi->pb.HFragments * 2)); - UVColumn = (YFragIndex % cpi->pb.HFragments) / 2; - UVFragOffset = (UVRow * (cpi->pb.HFragments / 2)) + UVColumn; - UFragIndex = cpi->pb.YPlaneFragments + UVFragOffset; - VFragIndex = cpi->pb.YPlaneFragments + cpi->pb.UVPlaneFragments + - UVFragOffset; - - - /************************************************************** - Find the block choice with the lowest error - - NOTE THAT if U or V is coded but no Y from a macro block then - the mode will be CODE_INTER_NO_MV as this is the default - state to which the mode data structure is initialised in - encoder and decoder at the start of each frame. */ - - BestError = HUGE_ERROR; - - - /* Look at the intra coding error. */ - MBIntraError = GetMBIntraError( cpi, YFragIndex, PixelsPerLine ); - BestError = (BestError > MBIntraError) ? MBIntraError : BestError; - - /* Get the golden frame error */ - MBGFError = GetMBInterError( cpi, cpi->ConvDestBuffer, - cpi->pb.GoldenFrame, YFragIndex, - 0, 0, PixelsPerLine ); - BestError = (BestError > MBGFError) ? MBGFError : BestError; - - /* Calculate the 0,0 case. */ - MBInterError = GetMBInterError( cpi, cpi->ConvDestBuffer, - cpi->pb.LastFrameRecon, - YFragIndex, 0, 0, PixelsPerLine ); - BestError = (BestError > MBInterError) ? MBInterError : BestError; - - /* Measure error for last MV */ - MBLastInterError = GetMBInterError( cpi, cpi->ConvDestBuffer, - cpi->pb.LastFrameRecon, - YFragIndex, LastInterMVect.x, - LastInterMVect.y, PixelsPerLine ); - BestError = (BestError > MBLastInterError) ? - MBLastInterError : BestError; - - /* Measure error for prior last MV */ - MBPriorLastInterError = GetMBInterError( cpi, cpi->ConvDestBuffer, - cpi->pb.LastFrameRecon, - YFragIndex, - PriorLastInterMVect.x, - PriorLastInterMVect.y, - PixelsPerLine ); - BestError = (BestError > MBPriorLastInterError) ? - MBPriorLastInterError : BestError; - - /* Temporarily force usage of no motionvector blocks */ - MBInterMVError = HUGE_ERROR; - InterMVect.x = 0; /* Set 0,0 motion vector */ - InterMVect.y = 0; - - /* If the best error is above the required threshold search - for a new inter MV */ - if ( BestError > cpi->MinImprovementForNewMV && cpi->MotionCompensation) { - /* Use a mix of heirachical and exhaustive searches for - quick mode. */ - if ( cpi->pb.info.quick_p ) { - MBInterMVError = GetMBMVInterError( cpi, cpi->pb.LastFrameRecon, - YFragIndex, PixelsPerLine, - cpi->MVPixelOffsetY, - &InterMVect ); - - /* If we still do not have a good match try an exhaustive - MBMV search */ - if ( (MBInterMVError > cpi->ExhaustiveSearchThresh) && - (BestError > cpi->ExhaustiveSearchThresh) ) { - - MBInterMVExError = - GetMBMVExhaustiveSearch( cpi, cpi->pb.LastFrameRecon, - YFragIndex, PixelsPerLine, - &InterMVectEx ); - - /* Is the Variance measure for the EX search - better... If so then use it. */ - if ( MBInterMVExError < MBInterMVError ) { - MBInterMVError = MBInterMVExError; - InterMVect.x = InterMVectEx.x; - InterMVect.y = InterMVectEx.y; - } - } - }else{ - /* Use an exhaustive search */ - MBInterMVError = - GetMBMVExhaustiveSearch( cpi, cpi->pb.LastFrameRecon, - YFragIndex, PixelsPerLine, - &InterMVect ); - } - - - /* Is the improvement, if any, good enough to justify a new MV */ - if ( (16 * MBInterMVError < (BestError * cpi->MVChangeFactor)) && - ((MBInterMVError + cpi->MinImprovementForNewMV) < BestError) ){ - BestError = MBInterMVError; - } - - } - - /* If the best error is still above the required threshold - search for a golden frame MV */ - MBGF_MVError = HUGE_ERROR; - GFMVect.x = 0; /* Set 0,0 motion vector */ - GFMVect.y = 0; - if ( BestError > cpi->MinImprovementForNewMV && cpi->MotionCompensation) { - /* Do an MV search in the golden reference frame */ - MBGF_MVError = GetMBMVInterError( cpi, cpi->pb.GoldenFrame, - YFragIndex, PixelsPerLine, - cpi->MVPixelOffsetY, &GFMVect ); - - /* Measure error for last GFMV */ - LastMBGF_MVError = GetMBInterError( cpi, cpi->ConvDestBuffer, - cpi->pb.GoldenFrame, - YFragIndex, LastGFMVect.x, - LastGFMVect.y, PixelsPerLine ); - - /* Check against last GF motion vector and reset if the - search has thrown a worse result. */ - if ( LastMBGF_MVError < MBGF_MVError ) { - GFMVect.x = LastGFMVect.x; - GFMVect.y = LastGFMVect.y; - MBGF_MVError = LastMBGF_MVError; - }else{ - LastGFMVect.x = GFMVect.x; - LastGFMVect.y = GFMVect.y; - } - - /* Is the improvement, if any, good enough to justify a new MV */ - if ( (16 * MBGF_MVError < (BestError * cpi->MVChangeFactor)) && - ((MBGF_MVError + cpi->MinImprovementForNewMV) < BestError) ) { - BestError = MBGF_MVError; - } - } - - /* Finally... If the best error is still to high then consider - the 4MV mode */ - MBInterFOURMVError = HUGE_ERROR; - if ( BestError > cpi->FourMVThreshold && cpi->MotionCompensation) { - /* Get the 4MV error. */ - MBInterFOURMVError = - GetFOURMVExhaustiveSearch( cpi, cpi->pb.LastFrameRecon, - YFragIndex, PixelsPerLine, FourMVect ); - - /* If the improvement is great enough then use the four MV mode */ - if ( ((MBInterFOURMVError + cpi->MinImprovementForFourMV) < - BestError) && (16 * MBInterFOURMVError < - (BestError * cpi->FourMvChangeFactor))) { - BestError = MBInterFOURMVError; - } - } - - /******************************************************** - end finding the best error - ******************************************************* - - Figure out what to do with the block we chose - - Over-ride and force intra if error high and Intra error similar - Now choose a mode based on lowest error (with bias towards no MV) */ - - if ( (BestError > cpi->InterTripOutThresh) && - (10 * BestError > MBIntraError * 7 ) ) { - cpi->MBCodingMode = CODE_INTRA; - SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex, - VFragIndex,&ZeroVect); - } else if ( BestError == MBInterError ) { - cpi->MBCodingMode = CODE_INTER_NO_MV; - SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex, - VFragIndex,&ZeroVect); - } else if ( BestError == MBGFError ) { - cpi->MBCodingMode = CODE_USING_GOLDEN; - SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex, - VFragIndex,&ZeroVect); - } else if ( BestError == MBLastInterError ) { - cpi->MBCodingMode = CODE_INTER_LAST_MV; - SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex, - VFragIndex,&LastInterMVect); - } else if ( BestError == MBPriorLastInterError ) { - cpi->MBCodingMode = CODE_INTER_PRIOR_LAST; - SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex, - VFragIndex,&PriorLastInterMVect); - - /* Swap the prior and last MV cases over */ - TmpMVect.x = PriorLastInterMVect.x; - TmpMVect.y = PriorLastInterMVect.y; - PriorLastInterMVect.x = LastInterMVect.x; - PriorLastInterMVect.y = LastInterMVect.y; - LastInterMVect.x = TmpMVect.x; - LastInterMVect.y = TmpMVect.y; - - } else if ( BestError == MBInterMVError ) { - - cpi->MBCodingMode = CODE_INTER_PLUS_MV; - SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex, - VFragIndex,&InterMVect); - - /* Update Prior last mv with last mv */ - PriorLastInterMVect.x = LastInterMVect.x; - PriorLastInterMVect.y = LastInterMVect.y; - - /* Note last inter MV for future use */ - LastInterMVect.x = InterMVect.x; - LastInterMVect.y = InterMVect.y; - - AddMotionVector( cpi, &InterMVect); - - } else if ( BestError == MBGF_MVError ) { - - cpi->MBCodingMode = CODE_GOLDEN_MV; - SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex, - VFragIndex,&GFMVect); - - /* Note last inter GF MV for future use */ - LastGFMVect.x = GFMVect.x; - LastGFMVect.y = GFMVect.y; - - AddMotionVector( cpi, &GFMVect); - } else if ( BestError == MBInterFOURMVError ) { - cpi->MBCodingMode = CODE_INTER_FOURMV; - - /* Calculate the UV vectors as the average of the Y plane ones. */ - /* First .x component */ - FourMVect[4].x = FourMVect[0].x + FourMVect[1].x + - FourMVect[2].x + FourMVect[3].x; - if ( FourMVect[4].x >= 0 ) - FourMVect[4].x = (FourMVect[4].x + 2) / 4; - else - FourMVect[4].x = (FourMVect[4].x - 2) / 4; - FourMVect[5].x = FourMVect[4].x; - - /* Then .y component */ - FourMVect[4].y = FourMVect[0].y + FourMVect[1].y + - FourMVect[2].y + FourMVect[3].y; - if ( FourMVect[4].y >= 0 ) - FourMVect[4].y = (FourMVect[4].y + 2) / 4; - else - FourMVect[4].y = (FourMVect[4].y - 2) / 4; - FourMVect[5].y = FourMVect[4].y; - - SetFragMotionVectorAndMode(cpi, YFragIndex, &FourMVect[0]); - SetFragMotionVectorAndMode(cpi, YFragIndex + 1, &FourMVect[1]); - SetFragMotionVectorAndMode(cpi, YFragIndex + cpi->pb.HFragments, - &FourMVect[2]); - SetFragMotionVectorAndMode(cpi, YFragIndex + cpi->pb.HFragments + 1, - &FourMVect[3]); - SetFragMotionVectorAndMode(cpi, UFragIndex, &FourMVect[4]); - SetFragMotionVectorAndMode(cpi, VFragIndex, &FourMVect[5]); - - /* Note the four MVs values for current macro-block. */ - AddMotionVector( cpi, &FourMVect[0]); - AddMotionVector( cpi, &FourMVect[1]); - AddMotionVector( cpi, &FourMVect[2]); - AddMotionVector( cpi, &FourMVect[3]); - - /* Update Prior last mv with last mv */ - PriorLastInterMVect.x = LastInterMVect.x; - PriorLastInterMVect.y = LastInterMVect.y; - - /* Note last inter MV for future use */ - LastInterMVect.x = FourMVect[3].x; - LastInterMVect.y = FourMVect[3].y; - - } else { - - cpi->MBCodingMode = CODE_INTRA; - SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex, - VFragIndex,&ZeroVect); - } - - - /* setting up mode specific block types - *******************************************************/ - - *InterError += (BestError>>8); - *IntraError += (MBIntraError>>8); - - - } - SB++; - - } - } - - /* Return number of pixels coded */ - return 0; -} - -void WriteFrameHeader( CP_INSTANCE *cpi) { - ogg_uint32_t i; - oggpack_buffer *opb=cpi->oggbuffer; - /* Output the frame type (base/key frame or inter frame) */ - oggpackB_write( opb, cpi->pb.FrameType, 1 ); - /* Write out details of the current value of Q... variable resolution. */ - for ( i = 0; i < Q_TABLE_SIZE; i++ ) { - if ( cpi->pb.ThisFrameQualityValue == cpi->pb.QThreshTable[i] ) { - oggpackB_write( opb, i, 6 ); - break; - } - } - - if ( i == Q_TABLE_SIZE ) { - /* An invalid DCT value was specified. */ - /*IssueWarning( "Invalid Q Multiplier" );*/ - oggpackB_write( opb, 31, 6 ); - } - - /* we only support one Q index per frame */ - oggpackB_write( opb, 0, 1 ); - - /* If the frame was a base frame then write out the frame dimensions. */ - if ( cpi->pb.FrameType == KEY_FRAME ) { - /* all bits reserved! */ - oggpackB_write( opb, 0, 3 ); - } -} - diff --git a/Engine/lib/libtheora/lib/enc/encoder_huffman.c b/Engine/lib/libtheora/lib/enc/encoder_huffman.c deleted file mode 100644 index 191ada75c..000000000 --- a/Engine/lib/libtheora/lib/enc/encoder_huffman.c +++ /dev/null @@ -1,310 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: encoder_huffman.c 13884 2007-09-22 08:38:10Z giles $ - - ********************************************************************/ - -#include -#include -#include "codec_internal.h" -#include "hufftables.h" - -static void CreateHuffmanList(HUFF_ENTRY ** HuffRoot, - ogg_uint32_t HIndex, - const ogg_uint32_t *FreqList ) { - int i; - HUFF_ENTRY *entry_ptr; - HUFF_ENTRY *search_ptr; - - /* Create a HUFF entry for token zero. */ - HuffRoot[HIndex] = (HUFF_ENTRY *)_ogg_calloc(1,sizeof(*HuffRoot[HIndex])); - - HuffRoot[HIndex]->Previous = NULL; - HuffRoot[HIndex]->Next = NULL; - HuffRoot[HIndex]->ZeroChild = NULL; - HuffRoot[HIndex]->OneChild = NULL; - HuffRoot[HIndex]->Value = 0; - HuffRoot[HIndex]->Frequency = FreqList[0]; - - if ( HuffRoot[HIndex]->Frequency == 0 ) - HuffRoot[HIndex]->Frequency = 1; - - /* Now add entries for all the other possible tokens. */ - for ( i = 1; i < MAX_ENTROPY_TOKENS; i++ ) { - entry_ptr = (HUFF_ENTRY *)_ogg_calloc(1,sizeof(*entry_ptr)); - - entry_ptr->Value = i; - entry_ptr->Frequency = FreqList[i]; - entry_ptr->ZeroChild = NULL; - entry_ptr->OneChild = NULL; - - /* Force min value of 1. This prevents the tree getting too deep. */ - if ( entry_ptr->Frequency == 0 ) - entry_ptr->Frequency = 1; - - if ( entry_ptr->Frequency <= HuffRoot[HIndex]->Frequency ){ - entry_ptr->Next = HuffRoot[HIndex]; - HuffRoot[HIndex]->Previous = entry_ptr; - entry_ptr->Previous = NULL; - HuffRoot[HIndex] = entry_ptr; - }else{ - search_ptr = HuffRoot[HIndex]; - while ( (search_ptr->Next != NULL) && - (search_ptr->Frequency < entry_ptr->Frequency) ){ - search_ptr = (HUFF_ENTRY *)search_ptr->Next; - } - - if ( search_ptr->Frequency < entry_ptr->Frequency ){ - entry_ptr->Next = NULL; - entry_ptr->Previous = search_ptr; - search_ptr->Next = entry_ptr; - }else{ - entry_ptr->Next = search_ptr; - entry_ptr->Previous = search_ptr->Previous; - search_ptr->Previous->Next = entry_ptr; - search_ptr->Previous = entry_ptr; - } - } - } -} - -static void CreateCodeArray( HUFF_ENTRY * HuffRoot, - ogg_uint32_t *HuffCodeArray, - unsigned char *HuffCodeLengthArray, - ogg_uint32_t CodeValue, - unsigned char CodeLength ) { - - /* If we are at a leaf then fill in a code array entry. */ - if ( ( HuffRoot->ZeroChild == NULL ) && ( HuffRoot->OneChild == NULL ) ){ - HuffCodeArray[HuffRoot->Value] = CodeValue; - HuffCodeLengthArray[HuffRoot->Value] = CodeLength; - }else{ - /* Recursive calls to scan down the tree. */ - CodeLength++; - CreateCodeArray(HuffRoot->ZeroChild, HuffCodeArray, HuffCodeLengthArray, - ((CodeValue << 1) + 0), CodeLength); - CreateCodeArray(HuffRoot->OneChild, HuffCodeArray, HuffCodeLengthArray, - ((CodeValue << 1) + 1), CodeLength); - } -} - -static void BuildHuffmanTree( HUFF_ENTRY **HuffRoot, - ogg_uint32_t *HuffCodeArray, - unsigned char *HuffCodeLengthArray, - ogg_uint32_t HIndex, - const ogg_uint32_t *FreqList ){ - - HUFF_ENTRY *entry_ptr; - HUFF_ENTRY *search_ptr; - - /* First create a sorted linked list representing the frequencies of - each token. */ - CreateHuffmanList( HuffRoot, HIndex, FreqList ); - - /* Now build the tree from the list. */ - - /* While there are at least two items left in the list. */ - while ( HuffRoot[HIndex]->Next != NULL ){ - /* Create the new node as the parent of the first two in the list. */ - entry_ptr = (HUFF_ENTRY *)_ogg_calloc(1,sizeof(*entry_ptr)); - entry_ptr->Value = -1; - entry_ptr->Frequency = HuffRoot[HIndex]->Frequency + - HuffRoot[HIndex]->Next->Frequency ; - entry_ptr->ZeroChild = HuffRoot[HIndex]; - entry_ptr->OneChild = HuffRoot[HIndex]->Next; - - /* If there are still more items in the list then insert the new - node into the list. */ - if (entry_ptr->OneChild->Next != NULL ){ - /* Set up the provisional 'new root' */ - HuffRoot[HIndex] = entry_ptr->OneChild->Next; - HuffRoot[HIndex]->Previous = NULL; - - /* Now scan through the remaining list to insert the new entry - at the appropriate point. */ - if ( entry_ptr->Frequency <= HuffRoot[HIndex]->Frequency ){ - entry_ptr->Next = HuffRoot[HIndex]; - HuffRoot[HIndex]->Previous = entry_ptr; - entry_ptr->Previous = NULL; - HuffRoot[HIndex] = entry_ptr; - }else{ - search_ptr = HuffRoot[HIndex]; - while ( (search_ptr->Next != NULL) && - (search_ptr->Frequency < entry_ptr->Frequency) ){ - search_ptr = search_ptr->Next; - } - - if ( search_ptr->Frequency < entry_ptr->Frequency ){ - entry_ptr->Next = NULL; - entry_ptr->Previous = search_ptr; - search_ptr->Next = entry_ptr; - }else{ - entry_ptr->Next = search_ptr; - entry_ptr->Previous = search_ptr->Previous; - search_ptr->Previous->Next = entry_ptr; - search_ptr->Previous = entry_ptr; - } - } - }else{ - /* Build has finished. */ - entry_ptr->Next = NULL; - entry_ptr->Previous = NULL; - HuffRoot[HIndex] = entry_ptr; - } - - /* Delete the Next/Previous properties of the children (PROB NOT NEC). */ - entry_ptr->ZeroChild->Next = NULL; - entry_ptr->ZeroChild->Previous = NULL; - entry_ptr->OneChild->Next = NULL; - entry_ptr->OneChild->Previous = NULL; - - } - - /* Now build a code array from the tree. */ - CreateCodeArray( HuffRoot[HIndex], HuffCodeArray, - HuffCodeLengthArray, 0, 0); -} - -static void DestroyHuffTree(HUFF_ENTRY *root_ptr){ - if (root_ptr){ - if ( root_ptr->ZeroChild ) - DestroyHuffTree(root_ptr->ZeroChild); - - if ( root_ptr->OneChild ) - DestroyHuffTree(root_ptr->OneChild); - - _ogg_free(root_ptr); - } -} - -void ClearHuffmanSet( PB_INSTANCE *pbi ){ - int i; - - ClearHuffmanTrees(pbi->HuffRoot_VP3x); - - for ( i = 0; i < NUM_HUFF_TABLES; i++ ) - if (pbi->HuffCodeArray_VP3x[i]) - _ogg_free (pbi->HuffCodeArray_VP3x[i]); - - for ( i = 0; i < NUM_HUFF_TABLES; i++ ) - if (pbi->HuffCodeLengthArray_VP3x[i]) - _ogg_free (pbi->HuffCodeLengthArray_VP3x[i]); -} - -void InitHuffmanSet( PB_INSTANCE *pbi ){ - int i; - - ClearHuffmanSet(pbi); - - pbi->ExtraBitLengths_VP3x = ExtraBitLengths_VP31; - - for ( i = 0; i < NUM_HUFF_TABLES; i++ ){ - pbi->HuffCodeArray_VP3x[i] = - _ogg_calloc(MAX_ENTROPY_TOKENS, - sizeof(*pbi->HuffCodeArray_VP3x[i])); - pbi->HuffCodeLengthArray_VP3x[i] = - _ogg_calloc(MAX_ENTROPY_TOKENS, - sizeof(*pbi->HuffCodeLengthArray_VP3x[i])); - BuildHuffmanTree( pbi->HuffRoot_VP3x, - pbi->HuffCodeArray_VP3x[i], - pbi->HuffCodeLengthArray_VP3x[i], - i, FrequencyCounts_VP3[i]); - } -} - -static int ReadHuffTree(HUFF_ENTRY * HuffRoot, int depth, - oggpack_buffer *opb) { - long bit; - long ret; - theora_read(opb,1,&bit); - if(bit < 0) return OC_BADHEADER; - else if(!bit) { - int ret; - if (++depth > 32) return OC_BADHEADER; - HuffRoot->ZeroChild = (HUFF_ENTRY *)_ogg_calloc(1, sizeof(HUFF_ENTRY)); - ret = ReadHuffTree(HuffRoot->ZeroChild, depth, opb); - if (ret < 0) return ret; - HuffRoot->OneChild = (HUFF_ENTRY *)_ogg_calloc(1, sizeof(HUFF_ENTRY)); - ret = ReadHuffTree(HuffRoot->OneChild, depth, opb); - if (ret < 0) return ret; - HuffRoot->Value = -1; - } else { - HuffRoot->ZeroChild = NULL; - HuffRoot->OneChild = NULL; - theora_read(opb,5,&ret); - HuffRoot->Value=ret;; - if (HuffRoot->Value < 0) return OC_BADHEADER; - } - return 0; -} - -int ReadHuffmanTrees(codec_setup_info *ci, oggpack_buffer *opb) { - int i; - for (i=0; iHuffRoot[i] = (HUFF_ENTRY *)_ogg_calloc(1, sizeof(HUFF_ENTRY)); - ret = ReadHuffTree(ci->HuffRoot[i], 0, opb); - if (ret) return ret; - } - return 0; -} - -static void WriteHuffTree(HUFF_ENTRY *HuffRoot, oggpack_buffer *opb) { - if (HuffRoot->Value >= 0) { - oggpackB_write(opb, 1, 1); - oggpackB_write(opb, HuffRoot->Value, 5); - } else { - oggpackB_write(opb, 0, 1); - WriteHuffTree(HuffRoot->ZeroChild, opb); - WriteHuffTree(HuffRoot->OneChild, opb); - } -} - -void WriteHuffmanTrees(HUFF_ENTRY *HuffRoot[NUM_HUFF_TABLES], - oggpack_buffer *opb) { - int i; - for(i=0; iValue = HuffSrc->Value; - if (HuffSrc->Value < 0) { - HuffDst->ZeroChild = CopyHuffTree(HuffSrc->ZeroChild); - HuffDst->OneChild = CopyHuffTree(HuffSrc->OneChild); - } - return HuffDst; - } - return NULL; -} - -void InitHuffmanTrees(PB_INSTANCE *pbi, const codec_setup_info *ci) { - int i; - pbi->ExtraBitLengths_VP3x = ExtraBitLengths_VP31; - for(i=0; iHuffRoot_VP3x[i] = CopyHuffTree(ci->HuffRoot[i]); - } -} - -void ClearHuffmanTrees(HUFF_ENTRY *HuffRoot[NUM_HUFF_TABLES]){ - int i; - for(i=0; i -#include "codec_internal.h" - -#include "quant_lookup.h" - -#define IdctAdjustBeforeShift 8 -/* cos(n*pi/16) or sin(8-n)*pi/16) */ -#define xC1S7 64277 -#define xC2S6 60547 -#define xC3S5 54491 -#define xC4S4 46341 -#define xC5S3 36410 -#define xC6S2 25080 -#define xC7S1 12785 - -/* compute the 16 bit signed 1D inverse DCT - spec version */ -/* -static void idct_short__c ( ogg_int16_t * InputData, ogg_int16_t * OutputData ) { - ogg_int32_t t[8], r; - ogg_int16_t *y = InputData; - ogg_int16_t *x = OutputData; - - t[0] = y[0] + y[4]; - t[0] &= 0xffff; - t[0] = (xC4S4 * t[0]) >> 16; - - t[1] = y[0] - y[4]; - t[1] &= 0xffff; - t[1] = (xC4S4 * t[1]) >> 16; - - t[2] = ((xC6S2 * y[2]) >> 16) - ((xC2S6 * y[6]) >> 16); - t[3] = ((xC2S6 * y[2]) >> 16) + ((xC6S2 * y[6]) >> 16); - t[4] = ((xC7S1 * y[1]) >> 16) - ((xC1S7 * y[7]) >> 16); - t[5] = ((xC3S5 * y[5]) >> 16) - ((xC5S3 * y[3]) >> 16); - t[6] = ((xC5S3 * y[5]) >> 16) + ((xC3S5 * y[3]) >> 16); - t[7] = ((xC1S7 * y[1]) >> 16) + ((xC7S1 * y[7]) >> 16); - - r = t[4] + t[5]; - t[5] = t[4] - t[5]; - t[5] &= 0xffff; - t[5] = (xC4S4 * (-t[5])) >> 16; - t[4] = r; - - r = t[7] + t[6]; - t[6] = t[7] - t[6]; - t[6] &= 0xffff; - t[6] = (xC4S4 * t[6]) >> 16; - t[7] = r; - - r = t[0] + t[3]; - t[3] = t[0] - t[3]; - t[0] = r; - - r = t[1] + t[2]; - t[2] = t[1] - t[2]; - t[1] = r; - - r = t[6] + t[5]; - t[5] = t[6] - t[5]; - t[6] = r; - - r = t[0] + t[7]; - r &= 0xffff; - x[0] = r; - - r = t[1] + t[6]; - r &= 0xffff; - x[1] = r; - - r = t[2] + t[5]; - r &= 0xffff; - x[2] = r; - - r = t[3] + t[4]; - r &= 0xffff; - x[3] = r; - - r = t[3] - t[4]; - r &= 0xffff; - x[4] = r; - - r = t[2] - t[5]; - r &= 0xffff; - x[5] = r; - - r = t[1] - t[6]; - r &= 0xffff; - x[6] = r; - - r = t[0] - t[7]; - r &= 0xffff; - x[7] = r; - -} -*/ - -static void dequant_slow( ogg_int16_t * dequant_coeffs, - ogg_int16_t * quantized_list, - ogg_int32_t * DCT_block) { - int i; - for(i=0;i<64;i++) - DCT_block[dezigzag_index[i]] = quantized_list[i] * dequant_coeffs[i]; -} - - - -void IDctSlow__c( Q_LIST_ENTRY * InputData, - ogg_int16_t *QuantMatrix, - ogg_int16_t * OutputData ) { - ogg_int32_t IntermediateData[64]; - ogg_int32_t * ip = IntermediateData; - ogg_int16_t * op = OutputData; - - ogg_int32_t _A, _B, _C, _D, _Ad, _Bd, _Cd, _Dd, _E, _F, _G, _H; - ogg_int32_t _Ed, _Gd, _Add, _Bdd, _Fd, _Hd; - ogg_int32_t t1, t2; - - int loop; - - dequant_slow( QuantMatrix, InputData, IntermediateData); - - /* Inverse DCT on the rows now */ - for ( loop = 0; loop < 8; loop++){ - /* Check for non-zero values */ - if ( ip[0] | ip[1] | ip[2] | ip[3] | ip[4] | ip[5] | ip[6] | ip[7] ) { - t1 = (xC1S7 * ip[1]); - t2 = (xC7S1 * ip[7]); - t1 >>= 16; - t2 >>= 16; - _A = t1 + t2; - - t1 = (xC7S1 * ip[1]); - t2 = (xC1S7 * ip[7]); - t1 >>= 16; - t2 >>= 16; - _B = t1 - t2; - - t1 = (xC3S5 * ip[3]); - t2 = (xC5S3 * ip[5]); - t1 >>= 16; - t2 >>= 16; - _C = t1 + t2; - - t1 = (xC3S5 * ip[5]); - t2 = (xC5S3 * ip[3]); - t1 >>= 16; - t2 >>= 16; - _D = t1 - t2; - - t1 = (xC4S4 * (ogg_int16_t)(_A - _C)); - t1 >>= 16; - _Ad = t1; - - t1 = (xC4S4 * (ogg_int16_t)(_B - _D)); - t1 >>= 16; - _Bd = t1; - - - _Cd = _A + _C; - _Dd = _B + _D; - - t1 = (xC4S4 * (ogg_int16_t)(ip[0] + ip[4])); - t1 >>= 16; - _E = t1; - - t1 = (xC4S4 * (ogg_int16_t)(ip[0] - ip[4])); - t1 >>= 16; - _F = t1; - - t1 = (xC2S6 * ip[2]); - t2 = (xC6S2 * ip[6]); - t1 >>= 16; - t2 >>= 16; - _G = t1 + t2; - - t1 = (xC6S2 * ip[2]); - t2 = (xC2S6 * ip[6]); - t1 >>= 16; - t2 >>= 16; - _H = t1 - t2; - - - _Ed = _E - _G; - _Gd = _E + _G; - - _Add = _F + _Ad; - _Bdd = _Bd - _H; - - _Fd = _F - _Ad; - _Hd = _Bd + _H; - - /* Final sequence of operations over-write original inputs. */ - ip[0] = (ogg_int16_t)((_Gd + _Cd ) >> 0); - ip[7] = (ogg_int16_t)((_Gd - _Cd ) >> 0); - - ip[1] = (ogg_int16_t)((_Add + _Hd ) >> 0); - ip[2] = (ogg_int16_t)((_Add - _Hd ) >> 0); - - ip[3] = (ogg_int16_t)((_Ed + _Dd ) >> 0); - ip[4] = (ogg_int16_t)((_Ed - _Dd ) >> 0); - - ip[5] = (ogg_int16_t)((_Fd + _Bdd ) >> 0); - ip[6] = (ogg_int16_t)((_Fd - _Bdd ) >> 0); - - } - - ip += 8; /* next row */ - } - - ip = IntermediateData; - - for ( loop = 0; loop < 8; loop++){ - /* Check for non-zero values (bitwise or faster than ||) */ - if ( ip[0 * 8] | ip[1 * 8] | ip[2 * 8] | ip[3 * 8] | - ip[4 * 8] | ip[5 * 8] | ip[6 * 8] | ip[7 * 8] ) { - - t1 = (xC1S7 * ip[1*8]); - t2 = (xC7S1 * ip[7*8]); - t1 >>= 16; - t2 >>= 16; - _A = t1 + t2; - - t1 = (xC7S1 * ip[1*8]); - t2 = (xC1S7 * ip[7*8]); - t1 >>= 16; - t2 >>= 16; - _B = t1 - t2; - - t1 = (xC3S5 * ip[3*8]); - t2 = (xC5S3 * ip[5*8]); - t1 >>= 16; - t2 >>= 16; - _C = t1 + t2; - - t1 = (xC3S5 * ip[5*8]); - t2 = (xC5S3 * ip[3*8]); - t1 >>= 16; - t2 >>= 16; - _D = t1 - t2; - - t1 = (xC4S4 * (ogg_int16_t)(_A - _C)); - t1 >>= 16; - _Ad = t1; - - t1 = (xC4S4 * (ogg_int16_t)(_B - _D)); - t1 >>= 16; - _Bd = t1; - - - _Cd = _A + _C; - _Dd = _B + _D; - - t1 = (xC4S4 * (ogg_int16_t)(ip[0*8] + ip[4*8])); - t1 >>= 16; - _E = t1; - - t1 = (xC4S4 * (ogg_int16_t)(ip[0*8] - ip[4*8])); - t1 >>= 16; - _F = t1; - - t1 = (xC2S6 * ip[2*8]); - t2 = (xC6S2 * ip[6*8]); - t1 >>= 16; - t2 >>= 16; - _G = t1 + t2; - - t1 = (xC6S2 * ip[2*8]); - t2 = (xC2S6 * ip[6*8]); - t1 >>= 16; - t2 >>= 16; - _H = t1 - t2; - - _Ed = _E - _G; - _Gd = _E + _G; - - _Add = _F + _Ad; - _Bdd = _Bd - _H; - - _Fd = _F - _Ad; - _Hd = _Bd + _H; - - _Gd += IdctAdjustBeforeShift; - _Add += IdctAdjustBeforeShift; - _Ed += IdctAdjustBeforeShift; - _Fd += IdctAdjustBeforeShift; - - /* Final sequence of operations over-write original inputs. */ - op[0*8] = (ogg_int16_t)((_Gd + _Cd ) >> 4); - op[7*8] = (ogg_int16_t)((_Gd - _Cd ) >> 4); - - op[1*8] = (ogg_int16_t)((_Add + _Hd ) >> 4); - op[2*8] = (ogg_int16_t)((_Add - _Hd ) >> 4); - - op[3*8] = (ogg_int16_t)((_Ed + _Dd ) >> 4); - op[4*8] = (ogg_int16_t)((_Ed - _Dd ) >> 4); - - op[5*8] = (ogg_int16_t)((_Fd + _Bdd ) >> 4); - op[6*8] = (ogg_int16_t)((_Fd - _Bdd ) >> 4); - }else{ - op[0*8] = 0; - op[7*8] = 0; - op[1*8] = 0; - op[2*8] = 0; - op[3*8] = 0; - op[4*8] = 0; - op[5*8] = 0; - op[6*8] = 0; - } - - ip++; /* next column */ - op++; - } -} - -/************************ - x x x x 0 0 0 0 - x x x 0 0 0 0 0 - x x 0 0 0 0 0 0 - x 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 -*************************/ - -static void dequant_slow10( ogg_int16_t * dequant_coeffs, - ogg_int16_t * quantized_list, - ogg_int32_t * DCT_block){ - int i; - memset(DCT_block,0, 128); - for(i=0;i<10;i++) - DCT_block[dezigzag_index[i]] = quantized_list[i] * dequant_coeffs[i]; - -} - -void IDct10__c( Q_LIST_ENTRY * InputData, - ogg_int16_t *QuantMatrix, - ogg_int16_t * OutputData ){ - ogg_int32_t IntermediateData[64]; - ogg_int32_t * ip = IntermediateData; - ogg_int16_t * op = OutputData; - - ogg_int32_t _A, _B, _C, _D, _Ad, _Bd, _Cd, _Dd, _E, _F, _G, _H; - ogg_int32_t _Ed, _Gd, _Add, _Bdd, _Fd, _Hd; - ogg_int32_t t1, t2; - - int loop; - - dequant_slow10( QuantMatrix, InputData, IntermediateData); - - /* Inverse DCT on the rows now */ - for ( loop = 0; loop < 4; loop++){ - /* Check for non-zero values */ - if ( ip[0] | ip[1] | ip[2] | ip[3] ){ - t1 = (xC1S7 * ip[1]); - t1 >>= 16; - _A = t1; - - t1 = (xC7S1 * ip[1]); - t1 >>= 16; - _B = t1 ; - - t1 = (xC3S5 * ip[3]); - t1 >>= 16; - _C = t1; - - t2 = (xC5S3 * ip[3]); - t2 >>= 16; - _D = -t2; - - - t1 = (xC4S4 * (ogg_int16_t)(_A - _C)); - t1 >>= 16; - _Ad = t1; - - t1 = (xC4S4 * (ogg_int16_t)(_B - _D)); - t1 >>= 16; - _Bd = t1; - - - _Cd = _A + _C; - _Dd = _B + _D; - - t1 = (xC4S4 * ip[0] ); - t1 >>= 16; - _E = t1; - - _F = t1; - - t1 = (xC2S6 * ip[2]); - t1 >>= 16; - _G = t1; - - t1 = (xC6S2 * ip[2]); - t1 >>= 16; - _H = t1 ; - - - _Ed = _E - _G; - _Gd = _E + _G; - - _Add = _F + _Ad; - _Bdd = _Bd - _H; - - _Fd = _F - _Ad; - _Hd = _Bd + _H; - - /* Final sequence of operations over-write original inputs. */ - ip[0] = (ogg_int16_t)((_Gd + _Cd ) >> 0); - ip[7] = (ogg_int16_t)((_Gd - _Cd ) >> 0); - - ip[1] = (ogg_int16_t)((_Add + _Hd ) >> 0); - ip[2] = (ogg_int16_t)((_Add - _Hd ) >> 0); - - ip[3] = (ogg_int16_t)((_Ed + _Dd ) >> 0); - ip[4] = (ogg_int16_t)((_Ed - _Dd ) >> 0); - - ip[5] = (ogg_int16_t)((_Fd + _Bdd ) >> 0); - ip[6] = (ogg_int16_t)((_Fd - _Bdd ) >> 0); - - } - - ip += 8; /* next row */ - } - - ip = IntermediateData; - - for ( loop = 0; loop < 8; loop++) { - /* Check for non-zero values (bitwise or faster than ||) */ - if ( ip[0 * 8] | ip[1 * 8] | ip[2 * 8] | ip[3 * 8] ) { - - t1 = (xC1S7 * ip[1*8]); - t1 >>= 16; - _A = t1 ; - - t1 = (xC7S1 * ip[1*8]); - t1 >>= 16; - _B = t1 ; - - t1 = (xC3S5 * ip[3*8]); - t1 >>= 16; - _C = t1 ; - - t2 = (xC5S3 * ip[3*8]); - t2 >>= 16; - _D = - t2; - - - t1 = (xC4S4 * (ogg_int16_t)(_A - _C)); - t1 >>= 16; - _Ad = t1; - - t1 = (xC4S4 * (ogg_int16_t)(_B - _D)); - t1 >>= 16; - _Bd = t1; - - - _Cd = _A + _C; - _Dd = _B + _D; - - t1 = (xC4S4 * ip[0*8]); - t1 >>= 16; - _E = t1; - _F = t1; - - t1 = (xC2S6 * ip[2*8]); - t1 >>= 16; - _G = t1; - - t1 = (xC6S2 * ip[2*8]); - t1 >>= 16; - _H = t1; - - - _Ed = _E - _G; - _Gd = _E + _G; - - _Add = _F + _Ad; - _Bdd = _Bd - _H; - - _Fd = _F - _Ad; - _Hd = _Bd + _H; - - _Gd += IdctAdjustBeforeShift; - _Add += IdctAdjustBeforeShift; - _Ed += IdctAdjustBeforeShift; - _Fd += IdctAdjustBeforeShift; - - /* Final sequence of operations over-write original inputs. */ - op[0*8] = (ogg_int16_t)((_Gd + _Cd ) >> 4); - op[7*8] = (ogg_int16_t)((_Gd - _Cd ) >> 4); - - op[1*8] = (ogg_int16_t)((_Add + _Hd ) >> 4); - op[2*8] = (ogg_int16_t)((_Add - _Hd ) >> 4); - - op[3*8] = (ogg_int16_t)((_Ed + _Dd ) >> 4); - op[4*8] = (ogg_int16_t)((_Ed - _Dd ) >> 4); - - op[5*8] = (ogg_int16_t)((_Fd + _Bdd ) >> 4); - op[6*8] = (ogg_int16_t)((_Fd - _Bdd ) >> 4); - }else{ - op[0*8] = 0; - op[7*8] = 0; - op[1*8] = 0; - op[2*8] = 0; - op[3*8] = 0; - op[4*8] = 0; - op[5*8] = 0; - op[6*8] = 0; - } - - ip++; /* next column */ - op++; - } -} - -/*************************** - x 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 -**************************/ - -void IDct1( Q_LIST_ENTRY * InputData, - ogg_int16_t *QuantMatrix, - ogg_int16_t * OutputData ){ - int loop; - - ogg_int16_t OutD; - - OutD=(ogg_int16_t) ((ogg_int32_t)(InputData[0]*QuantMatrix[0]+15)>>5); - - for(loop=0;loop<64;loop++) - OutputData[loop]=OutD; - -} - -void dsp_idct_init (DspFunctions *funcs, ogg_uint32_t cpu_flags) -{ - funcs->IDctSlow = IDctSlow__c; - funcs->IDct10 = IDct10__c; - funcs->IDct3 = IDct10__c; -#if defined(USE_ASM) - // todo: make mmx encoder idct for MSC one day... -#if !defined (_MSC_VER) - if (cpu_flags & OC_CPU_X86_MMX) { - dsp_mmx_idct_init(funcs); - } -#endif -#endif -} diff --git a/Engine/lib/libtheora/lib/enc/encoder_lookup.h b/Engine/lib/libtheora/lib/enc/encoder_lookup.h deleted file mode 100644 index c5759869a..000000000 --- a/Engine/lib/libtheora/lib/enc/encoder_lookup.h +++ /dev/null @@ -1,120 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: simple static lookups for VP3 frame encoder - last mod: $Id: encoder_lookup.h 15323 2008-09-19 19:43:59Z giles $ - - ********************************************************************/ - -#include "codec_internal.h" - -static const ogg_uint32_t MvPattern[(MAX_MV_EXTENT * 2) + 1] = { - 0x000000ff, 0x000000fd, 0x000000fb, 0x000000f9, - 0x000000f7, 0x000000f5, 0x000000f3, 0x000000f1, - 0x000000ef, 0x000000ed, 0x000000eb, 0x000000e9, - 0x000000e7, 0x000000e5, 0x000000e3, 0x000000e1, - 0x0000006f, 0x0000006d, 0x0000006b, 0x00000069, - 0x00000067, 0x00000065, 0x00000063, 0x00000061, - 0x0000002f, 0x0000002d, 0x0000002b, 0x00000029, - 0x00000009, 0x00000007, 0x00000002, 0x00000000, - 0x00000001, 0x00000006, 0x00000008, 0x00000028, - 0x0000002a, 0x0000002c, 0x0000002e, 0x00000060, - 0x00000062, 0x00000064, 0x00000066, 0x00000068, - 0x0000006a, 0x0000006c, 0x0000006e, 0x000000e0, - 0x000000e2, 0x000000e4, 0x000000e6, 0x000000e8, - 0x000000ea, 0x000000ec, 0x000000ee, 0x000000f0, - 0x000000f2, 0x000000f4, 0x000000f6, 0x000000f8, - 0x000000fa, 0x000000fc, 0x000000fe, -}; - -static const ogg_uint32_t MvBits[(MAX_MV_EXTENT * 2) + 1] = { - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 7, 7, 7, 7, 7, - 6, 6, 6, 6, 4, 4, 3, 3, - 3, 4, 4, 6, 6, 6, 6, 7, - 7, 7, 7, 7, 7, 7, 7, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, -}; - -static const ogg_uint32_t MvPattern2[(MAX_MV_EXTENT * 2) + 1] = { - 0x0000003f, 0x0000003d, 0x0000003b, 0x00000039, - 0x00000037, 0x00000035, 0x00000033, 0x00000031, - 0x0000002f, 0x0000002d, 0x0000002b, 0x00000029, - 0x00000027, 0x00000025, 0x00000023, 0x00000021, - 0x0000001f, 0x0000001d, 0x0000001b, 0x00000019, - 0x00000017, 0x00000015, 0x00000013, 0x00000011, - 0x0000000f, 0x0000000d, 0x0000000b, 0x00000009, - 0x00000007, 0x00000005, 0x00000003, 0x00000000, - 0x00000002, 0x00000004, 0x00000006, 0x00000008, - 0x0000000a, 0x0000000c, 0x0000000e, 0x00000010, - 0x00000012, 0x00000014, 0x00000016, 0x00000018, - 0x0000001a, 0x0000001c, 0x0000001e, 0x00000020, - 0x00000022, 0x00000024, 0x00000026, 0x00000028, - 0x0000002a, 0x0000002c, 0x0000002e, 0x00000030, - 0x00000032, 0x00000034, 0x00000036, 0x00000038, - 0x0000003a, 0x0000003c, 0x0000003e, -}; - -static const ogg_uint32_t MvBits2[(MAX_MV_EXTENT * 2) + 1] = { - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, -}; - -static const ogg_uint32_t ModeBitPatterns[MAX_MODES] = { - 0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0x7E, 0x7F }; - -static const ogg_int32_t ModeBitLengths[MAX_MODES] = { - 1, 2, 3, 4, 5, 6, 7, 7 }; - -static const unsigned char ModeSchemes[MODE_METHODS-2][MAX_MODES] = { - /* Last Mv dominates */ - { 3, 4, 2, 0, 1, 5, 6, 7 }, /* L P M N I G GM 4 */ - { 2, 4, 3, 0, 1, 5, 6, 7 }, /* L P N M I G GM 4 */ - { 3, 4, 1, 0, 2, 5, 6, 7 }, /* L M P N I G GM 4 */ - { 2, 4, 1, 0, 3, 5, 6, 7 }, /* L M N P I G GM 4 */ - - /* No MV dominates */ - { 0, 4, 3, 1, 2, 5, 6, 7 }, /* N L P M I G GM 4 */ - { 0, 5, 4, 2, 3, 1, 6, 7 }, /* N G L P M I GM 4 */ - -}; - - -static const ogg_uint32_t MvThreshTable[Q_TABLE_SIZE] = { - 65, 65, 65, 65, 50, 50, 50, 50, - 40, 40, 40, 40, 40, 40, 40, 40, - 30, 30, 30, 30, 30, 30, 30, 30, - 20, 20, 20, 20, 20, 20, 20, 20, - 15, 15, 15, 15, 15, 15, 15, 15, - 10, 10, 10, 10, 10, 10, 10, 10, - 5, 5, 5, 5, 5, 5, 5, 5, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const ogg_uint32_t MVChangeFactorTable[Q_TABLE_SIZE] = { - 11, 11, 11, 11, 12, 12, 12, 12, - 13, 13, 13, 13, 13, 13, 13, 13, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15 -}; diff --git a/Engine/lib/libtheora/lib/enc/encoder_quant.c b/Engine/lib/libtheora/lib/enc/encoder_quant.c deleted file mode 100644 index a5639a233..000000000 --- a/Engine/lib/libtheora/lib/enc/encoder_quant.c +++ /dev/null @@ -1,558 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2005 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: encoder_quant.c 15153 2008-08-04 18:37:55Z tterribe $ - - ********************************************************************/ - -#include -#include -#include "codec_internal.h" -#include "quant_lookup.h" - -#define OC_QUANT_MAX (1024<<2) -static const unsigned DC_QUANT_MIN[2]={4<<2,8<<2}; -static const unsigned AC_QUANT_MIN[2]={2<<2,4<<2}; -#define OC_MAXI(_a,_b) ((_a)<(_b)?(_b):(_a)) -#define OC_MINI(_a,_b) ((_a)>(_b)?(_b):(_a)) -#define OC_CLAMPI(_a,_b,_c) (OC_MAXI(_a,OC_MINI(_b,_c))) - -static int ilog(unsigned _v){ - int ret; - for(ret=0;_v;ret++)_v>>=1; - return ret; -} - - -void WriteQTables(PB_INSTANCE *pbi,oggpack_buffer* _opb) { - - th_quant_info *_qinfo = &pbi->quant_info; - - const th_quant_ranges *qranges; - const th_quant_base *base_mats[2*3*64]; - int indices[2][3][64]; - int nbase_mats; - int nbits; - int ci; - int qi; - int qri; - int qti; - int pli; - int qtj; - int plj; - int bmi; - int i; - - /*Unlike the scale tables, we can't assume the maximum value will be in - index 0, so search for it here.*/ - i=_qinfo->loop_filter_limits[0]; - for(qi=1;qi<64;qi++)i=OC_MAXI(i,_qinfo->loop_filter_limits[qi]); - nbits=ilog(i); - oggpackB_write(_opb,nbits,3); - for(qi=0;qi<64;qi++){ - oggpackB_write(_opb,_qinfo->loop_filter_limits[qi],nbits); - } - /* 580 bits for VP3.*/ - nbits=OC_MAXI(ilog(_qinfo->ac_scale[0]),1); - oggpackB_write(_opb,nbits-1,4); - for(qi=0;qi<64;qi++)oggpackB_write(_opb,_qinfo->ac_scale[qi],nbits); - /* 516 bits for VP3.*/ - nbits=OC_MAXI(ilog(_qinfo->dc_scale[0]),1); - oggpackB_write(_opb,nbits-1,4); - for(qi=0;qi<64;qi++)oggpackB_write(_opb,_qinfo->dc_scale[qi],nbits); - /*Consolidate any duplicate base matrices.*/ - nbase_mats=0; - for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){ - qranges=_qinfo->qi_ranges[qti]+pli; - for(qri=0;qri<=qranges->nranges;qri++){ - for(bmi=0;;bmi++){ - if(bmi>=nbase_mats){ - base_mats[bmi]=qranges->base_matrices+qri; - indices[qti][pli][qri]=nbase_mats++; - break; - } - else if(memcmp(base_mats[bmi][0],qranges->base_matrices[qri], - sizeof(base_mats[bmi][0]))==0){ - indices[qti][pli][qri]=bmi; - break; - } - } - } - } - /*Write out the list of unique base matrices. - 1545 bits for VP3 matrices.*/ - oggpackB_write(_opb,nbase_mats-1,9); - for(bmi=0;bmiqi_ranges[qti]+pli; - if(i>0){ - if(qti>0){ - if(qranges->nranges==_qinfo->qi_ranges[qti-1][pli].nranges&& - memcmp(qranges->sizes,_qinfo->qi_ranges[qti-1][pli].sizes, - qranges->nranges*sizeof(qranges->sizes[0]))==0&& - memcmp(indices[qti][pli],indices[qti-1][pli], - (qranges->nranges+1)*sizeof(indices[qti][pli][0]))==0){ - oggpackB_write(_opb,1,2); - continue; - } - } - qtj=(i-1)/3; - plj=(i-1)%3; - if(qranges->nranges==_qinfo->qi_ranges[qtj][plj].nranges&& - memcmp(qranges->sizes,_qinfo->qi_ranges[qtj][plj].sizes, - qranges->nranges*sizeof(qranges->sizes[0]))==0&& - memcmp(indices[qti][pli],indices[qtj][plj], - (qranges->nranges+1)*sizeof(indices[qti][pli][0]))==0){ - oggpackB_write(_opb,0,1+(qti>0)); - continue; - } - oggpackB_write(_opb,1,1); - } - oggpackB_write(_opb,indices[qti][pli][0],nbits); - for(qi=qri=0;qi<63;qri++){ - oggpackB_write(_opb,qranges->sizes[qri]-1,ilog(62-qi)); - qi+=qranges->sizes[qri]; - oggpackB_write(_opb,indices[qti][pli][qri+1],nbits); - } - } -} - -/* a copied/reconciled version of derf's theora-exp code; redundancy - should be eliminated at some point */ -void InitQTables( PB_INSTANCE *pbi ){ - int qti; /* coding mode: intra or inter */ - int pli; /* Y U V */ - th_quant_info *qinfo = &pbi->quant_info; - - pbi->QThreshTable = pbi->quant_info.ac_scale; - - for(qti=0;qti<2;qti++){ - for(pli=0;pli<3;pli++){ - int qi; /* quality index */ - int qri; /* range iterator */ - - for(qi=0,qri=0; qri<=qinfo->qi_ranges[qti][pli].nranges; qri++){ - th_quant_base base; - - ogg_uint32_t q; - int qi_start; - int qi_end; - int ci; - memcpy(base,qinfo->qi_ranges[qti][pli].base_matrices[qri], - sizeof(base)); - - qi_start=qi; - if(qri==qinfo->qi_ranges[qti][pli].nranges) - qi_end=qi+1; - else - qi_end=qi+qinfo->qi_ranges[qti][pli].sizes[qri]; - - /* Iterate over quality indicies in this range */ - for(;;){ - - /*Scale DC the coefficient from the proper table.*/ - q=((ogg_uint32_t)qinfo->dc_scale[qi]*base[0]/100)<<2; - q=OC_CLAMPI(DC_QUANT_MIN[qti],q,OC_QUANT_MAX); - pbi->quant_tables[qti][pli][qi][0]=(ogg_uint16_t)q; - - /*Now scale AC coefficients from the proper table.*/ - for(ci=1;ci<64;ci++){ - q=((ogg_uint32_t)qinfo->ac_scale[qi]*base[ci]/100)<<2; - q=OC_CLAMPI(AC_QUANT_MIN[qti],q,OC_QUANT_MAX); - pbi->quant_tables[qti][pli][qi][ci]=(ogg_uint16_t)q; - } - - if(++qi>=qi_end)break; - - /*Interpolate the next base matrix.*/ - for(ci=0;ci<64;ci++){ - base[ci]=(unsigned char) - ((2*((qi_end-qi)*qinfo->qi_ranges[qti][pli].base_matrices[qri][ci]+ - (qi-qi_start)*qinfo->qi_ranges[qti][pli].base_matrices[qri+1][ci]) - +qinfo->qi_ranges[qti][pli].sizes[qri])/ - (2*qinfo->qi_ranges[qti][pli].sizes[qri])); - } - } - } - } - } -} - -static void BuildZigZagIndex(PB_INSTANCE *pbi){ - ogg_int32_t i,j; - - /* invert the row to zigzag coeffient order lookup table */ - for ( i = 0; i < BLOCK_SIZE; i++ ){ - j = dezigzag_index[i]; - pbi->zigzag_index[j] = i; - } -} - -static void init_quantizer ( CP_INSTANCE *cpi, - unsigned char QIndex ){ - int i; - double ZBinFactor; - double RoundingFactor; - - double temp_fp_quant_coeffs; - double temp_fp_quant_round; - double temp_fp_ZeroBinSize; - PB_INSTANCE *pbi = &cpi->pb; - - - const ogg_uint16_t * temp_Y_coeffs; - const ogg_uint16_t * temp_U_coeffs; - const ogg_uint16_t * temp_V_coeffs; - const ogg_uint16_t * temp_Inter_Y_coeffs; - const ogg_uint16_t * temp_Inter_U_coeffs; - const ogg_uint16_t * temp_Inter_V_coeffs; - ogg_uint16_t scale_factor = cpi->pb.quant_info.ac_scale[QIndex]; - - /* Notes on setup of quantisers. The initial multiplication by - the scale factor is done in the ogg_int32_t domain to insure that the - precision in the quantiser is the same as in the inverse - quantiser where all calculations are integer. The "<< 2" is a - normalisation factor for the forward DCT transform. */ - - temp_Y_coeffs = pbi->quant_tables[0][0][QIndex]; - temp_U_coeffs = pbi->quant_tables[0][1][QIndex]; - temp_V_coeffs = pbi->quant_tables[0][2][QIndex]; - temp_Inter_Y_coeffs = pbi->quant_tables[1][0][QIndex]; - temp_Inter_U_coeffs = pbi->quant_tables[1][1][QIndex]; - temp_Inter_V_coeffs = pbi->quant_tables[1][2][QIndex]; - - ZBinFactor = 0.9; - - switch(cpi->pb.info.sharpness){ - case 0: - ZBinFactor = 0.65; - if ( scale_factor <= 50 ) - RoundingFactor = 0.499; - else - RoundingFactor = 0.46; - break; - case 1: - ZBinFactor = 0.75; - if ( scale_factor <= 50 ) - RoundingFactor = 0.476; - else - RoundingFactor = 0.400; - break; - - default: - ZBinFactor = 0.9; - if ( scale_factor <= 50 ) - RoundingFactor = 0.476; - else - RoundingFactor = 0.333; - break; - } - - /* Use fixed multiplier for intra Y DC */ - temp_fp_quant_coeffs = temp_Y_coeffs[0]; - temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; - pbi->fp_quant_Y_round[0] = (ogg_int32_t) (0.5 + temp_fp_quant_round); - temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; - pbi->fp_ZeroBinSize_Y[0] = (ogg_int32_t) (0.5 + temp_fp_ZeroBinSize); - temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs; - pbi->fp_quant_Y_coeffs[0] = (0.5 + SHIFT16 * temp_fp_quant_coeffs); - - /* Intra U */ - temp_fp_quant_coeffs = temp_U_coeffs[0]; - temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; - pbi->fp_quant_U_round[0] = (0.5 + temp_fp_quant_round); - temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; - pbi->fp_ZeroBinSize_U[0] = (0.5 + temp_fp_ZeroBinSize); - temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs; - pbi->fp_quant_U_coeffs[0]= (0.5 + SHIFT16 * temp_fp_quant_coeffs); - - /* Intra V */ - temp_fp_quant_coeffs = temp_V_coeffs[0]; - temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; - pbi->fp_quant_V_round[0] = (0.5 + temp_fp_quant_round); - temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; - pbi->fp_ZeroBinSize_V[0] = (0.5 + temp_fp_ZeroBinSize); - temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs; - pbi->fp_quant_V_coeffs[0]= (0.5 + SHIFT16 * temp_fp_quant_coeffs); - - - /* Inter Y */ - temp_fp_quant_coeffs = temp_Inter_Y_coeffs[0]; - temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; - pbi->fp_quant_Inter_Y_round[0]= (0.5 + temp_fp_quant_round); - temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; - pbi->fp_ZeroBinSize_Inter_Y[0]= (0.5 + temp_fp_ZeroBinSize); - temp_fp_quant_coeffs= 1.0 / temp_fp_quant_coeffs; - pbi->fp_quant_Inter_Y_coeffs[0]= (0.5 + SHIFT16 * temp_fp_quant_coeffs); - - /* Inter U */ - temp_fp_quant_coeffs = temp_Inter_U_coeffs[0]; - temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; - pbi->fp_quant_Inter_U_round[0]= (0.5 + temp_fp_quant_round); - temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; - pbi->fp_ZeroBinSize_Inter_U[0]= (0.5 + temp_fp_ZeroBinSize); - temp_fp_quant_coeffs= 1.0 / temp_fp_quant_coeffs; - pbi->fp_quant_Inter_U_coeffs[0]= (0.5 + SHIFT16 * temp_fp_quant_coeffs); - - /* Inter V */ - temp_fp_quant_coeffs = temp_Inter_V_coeffs[0]; - temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; - pbi->fp_quant_Inter_V_round[0]= (0.5 + temp_fp_quant_round); - temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; - pbi->fp_ZeroBinSize_Inter_V[0]= (0.5 + temp_fp_ZeroBinSize); - temp_fp_quant_coeffs= 1.0 / temp_fp_quant_coeffs; - pbi->fp_quant_Inter_V_coeffs[0]= (0.5 + SHIFT16 * temp_fp_quant_coeffs); - - - for ( i = 1; i < 64; i++ ){ - /* Intra Y */ - temp_fp_quant_coeffs = temp_Y_coeffs[i]; - temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; - pbi->fp_quant_Y_round[i] = (0.5 + temp_fp_quant_round); - temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; - pbi->fp_ZeroBinSize_Y[i] = (0.5 + temp_fp_ZeroBinSize); - temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs; - pbi->fp_quant_Y_coeffs[i] = (0.5 + SHIFT16 * temp_fp_quant_coeffs); - - /* Intra U */ - temp_fp_quant_coeffs = temp_U_coeffs[i]; - temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; - pbi->fp_quant_U_round[i] = (0.5 + temp_fp_quant_round); - temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; - pbi->fp_ZeroBinSize_U[i] = (0.5 + temp_fp_ZeroBinSize); - temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs; - pbi->fp_quant_U_coeffs[i]= (0.5 + SHIFT16 * temp_fp_quant_coeffs); - - /* Intra V */ - temp_fp_quant_coeffs = temp_V_coeffs[i]; - temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; - pbi->fp_quant_V_round[i] = (0.5 + temp_fp_quant_round); - temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; - pbi->fp_ZeroBinSize_V[i] = (0.5 + temp_fp_ZeroBinSize); - temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs; - pbi->fp_quant_V_coeffs[i]= (0.5 + SHIFT16 * temp_fp_quant_coeffs); - - /* Inter Y */ - temp_fp_quant_coeffs = temp_Inter_Y_coeffs[i]; - temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; - pbi->fp_quant_Inter_Y_round[i]= (0.5 + temp_fp_quant_round); - temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; - pbi->fp_ZeroBinSize_Inter_Y[i]= (0.5 + temp_fp_ZeroBinSize); - temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs; - pbi->fp_quant_Inter_Y_coeffs[i]= (0.5 + SHIFT16 * temp_fp_quant_coeffs); - - /* Inter U */ - temp_fp_quant_coeffs = temp_Inter_U_coeffs[i]; - temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; - pbi->fp_quant_Inter_U_round[i]= (0.5 + temp_fp_quant_round); - temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; - pbi->fp_ZeroBinSize_Inter_U[i]= (0.5 + temp_fp_ZeroBinSize); - temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs; - pbi->fp_quant_Inter_U_coeffs[i]= (0.5 + SHIFT16 * temp_fp_quant_coeffs); - - /* Inter V */ - temp_fp_quant_coeffs = temp_Inter_V_coeffs[i]; - temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor; - pbi->fp_quant_Inter_V_round[i]= (0.5 + temp_fp_quant_round); - temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor; - pbi->fp_ZeroBinSize_Inter_V[i]= (0.5 + temp_fp_ZeroBinSize); - temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs; - pbi->fp_quant_Inter_V_coeffs[i]= (0.5 + SHIFT16 * temp_fp_quant_coeffs); - - - } - - pbi->fquant_coeffs = pbi->fp_quant_Y_coeffs; - -} - -void select_quantiser(PB_INSTANCE *pbi, int type) { - /* select a quantiser according to what plane has to be coded in what - * mode. Could be extended to a more sophisticated scheme. */ - - switch(type) { - case BLOCK_Y: - pbi->fquant_coeffs = pbi->fp_quant_Y_coeffs; - pbi->fquant_round = pbi->fp_quant_Y_round; - pbi->fquant_ZbSize = pbi->fp_ZeroBinSize_Y; - break; - case BLOCK_U: - pbi->fquant_coeffs = pbi->fp_quant_U_coeffs; - pbi->fquant_round = pbi->fp_quant_U_round; - pbi->fquant_ZbSize = pbi->fp_ZeroBinSize_U; - break; - case BLOCK_V: - pbi->fquant_coeffs = pbi->fp_quant_V_coeffs; - pbi->fquant_round = pbi->fp_quant_V_round; - pbi->fquant_ZbSize = pbi->fp_ZeroBinSize_V; - break; - case BLOCK_INTER_Y: - pbi->fquant_coeffs = pbi->fp_quant_Inter_Y_coeffs; - pbi->fquant_round = pbi->fp_quant_Inter_Y_round; - pbi->fquant_ZbSize = pbi->fp_ZeroBinSize_Inter_Y; - break; - case BLOCK_INTER_U: - pbi->fquant_coeffs = pbi->fp_quant_Inter_U_coeffs; - pbi->fquant_round = pbi->fp_quant_Inter_U_round; - pbi->fquant_ZbSize = pbi->fp_ZeroBinSize_Inter_U; - break; - case BLOCK_INTER_V: - pbi->fquant_coeffs = pbi->fp_quant_Inter_V_coeffs; - pbi->fquant_round = pbi->fp_quant_Inter_V_round; - pbi->fquant_ZbSize = pbi->fp_ZeroBinSize_Inter_V; - break; - } -} - - -void quantize( PB_INSTANCE *pbi, - ogg_int16_t * DCT_block, - Q_LIST_ENTRY * quantized_list){ - ogg_uint32_t i; /* Row index */ - Q_LIST_ENTRY val; /* Quantised value. */ - - ogg_int32_t * FquantRoundPtr = pbi->fquant_round; - ogg_int32_t * FquantCoeffsPtr = pbi->fquant_coeffs; - ogg_int32_t * FquantZBinSizePtr = pbi->fquant_ZbSize; - ogg_int16_t * DCT_blockPtr = DCT_block; - ogg_uint32_t * ZigZagPtr = (ogg_uint32_t *)pbi->zigzag_index; - ogg_int32_t temp; - - /* Set the quantized_list to default to 0 */ - memset( quantized_list, 0, 64 * sizeof(Q_LIST_ENTRY) ); - - /* Note that we add half divisor to effect rounding on positive number */ - for( i = 0; i < VFRAGPIXELS; i++) { - - int col; - /* Iterate through columns */ - for( col = 0; col < 8; col++) { - if ( DCT_blockPtr[col] >= FquantZBinSizePtr[col] ) { - temp = FquantCoeffsPtr[col] * ( DCT_blockPtr[col] + FquantRoundPtr[col] ) ; - val = (Q_LIST_ENTRY) (temp>>16); - quantized_list[ZigZagPtr[col]] = ( val > 511 ) ? 511 : val; - } else if ( DCT_blockPtr[col] <= -FquantZBinSizePtr[col] ) { - temp = FquantCoeffsPtr[col] * - ( DCT_blockPtr[col] - FquantRoundPtr[col] ) + MIN16; - val = (Q_LIST_ENTRY) (temp>>16); - quantized_list[ZigZagPtr[col]] = ( val < -511 ) ? -511 : val; - } - } - - FquantRoundPtr += 8; - FquantCoeffsPtr += 8; - FquantZBinSizePtr += 8; - DCT_blockPtr += 8; - ZigZagPtr += 8; - } -} - -static void init_dequantizer ( PB_INSTANCE *pbi, - unsigned char QIndex ){ - int i, j; - - ogg_uint16_t * InterY_coeffs; - ogg_uint16_t * InterU_coeffs; - ogg_uint16_t * InterV_coeffs; - ogg_uint16_t * Y_coeffs; - ogg_uint16_t * U_coeffs; - ogg_uint16_t * V_coeffs; - - Y_coeffs = pbi->quant_tables[0][0][QIndex]; - U_coeffs = pbi->quant_tables[0][1][QIndex]; - V_coeffs = pbi->quant_tables[0][2][QIndex]; - InterY_coeffs = pbi->quant_tables[1][0][QIndex]; - InterU_coeffs = pbi->quant_tables[1][1][QIndex]; - InterV_coeffs = pbi->quant_tables[1][2][QIndex]; - - /* invert the dequant index into the quant index - the dxer has a different order than the cxer. */ - BuildZigZagIndex(pbi); - - /* Reorder dequantisation coefficients into dct zigzag order. */ - for ( i = 0; i < BLOCK_SIZE; i++ ) { - j = pbi->zigzag_index[i]; - pbi->dequant_Y_coeffs[j] = Y_coeffs[i]; - } - for ( i = 0; i < BLOCK_SIZE; i++ ) { - j = pbi->zigzag_index[i]; - pbi->dequant_U_coeffs[j] = U_coeffs[i]; - } - for ( i = 0; i < BLOCK_SIZE; i++ ) { - j = pbi->zigzag_index[i]; - pbi->dequant_V_coeffs[j] = V_coeffs[i]; - } - for ( i = 0; i < BLOCK_SIZE; i++ ){ - j = pbi->zigzag_index[i]; - pbi->dequant_InterY_coeffs[j] = InterY_coeffs[i]; - } - for ( i = 0; i < BLOCK_SIZE; i++ ){ - j = pbi->zigzag_index[i]; - pbi->dequant_InterU_coeffs[j] = InterU_coeffs[i]; - } - for ( i = 0; i < BLOCK_SIZE; i++ ){ - j = pbi->zigzag_index[i]; - pbi->dequant_InterV_coeffs[j] = InterV_coeffs[i]; - } - - pbi->dequant_coeffs = pbi->dequant_Y_coeffs; -} - -void UpdateQ( PB_INSTANCE *pbi, int NewQIndex ){ - ogg_uint32_t qscale; - - /* clamp to legal bounds */ - if (NewQIndex >= Q_TABLE_SIZE) NewQIndex = Q_TABLE_SIZE - 1; - else if (NewQIndex < 0) NewQIndex = 0; - - pbi->FrameQIndex = NewQIndex; - - qscale = pbi->quant_info.ac_scale[NewQIndex]; - pbi->ThisFrameQualityValue = qscale; - - /* Re-initialise the Q tables for forward and reverse transforms. */ - init_dequantizer ( pbi, (unsigned char) pbi->FrameQIndex ); -} - -void UpdateQC( CP_INSTANCE *cpi, ogg_uint32_t NewQ ){ - ogg_uint32_t qscale; - PB_INSTANCE *pbi = &cpi->pb; - - /* Do bounds checking and convert to a float. */ - qscale = NewQ; - if ( qscale < pbi->quant_info.ac_scale[Q_TABLE_SIZE-1] ) - qscale = pbi->quant_info.ac_scale[Q_TABLE_SIZE-1]; - else if ( qscale > pbi->quant_info.ac_scale[0] ) - qscale = pbi->quant_info.ac_scale[0]; - - /* Set the inter/intra descision control variables. */ - pbi->FrameQIndex = Q_TABLE_SIZE - 1; - while ((ogg_int32_t) pbi->FrameQIndex >= 0 ) { - if ( (pbi->FrameQIndex == 0) || - ( pbi->quant_info.ac_scale[pbi->FrameQIndex] >= NewQ) ) - break; - pbi->FrameQIndex --; - } - - /* Re-initialise the Q tables for forward and reverse transforms. */ - init_quantizer ( cpi, pbi->FrameQIndex ); - init_dequantizer ( pbi, pbi->FrameQIndex ); -} diff --git a/Engine/lib/libtheora/lib/enc/encoder_toplevel.c b/Engine/lib/libtheora/lib/enc/encoder_toplevel.c deleted file mode 100644 index 9356bba23..000000000 --- a/Engine/lib/libtheora/lib/enc/encoder_toplevel.c +++ /dev/null @@ -1,1447 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: encoder_toplevel.c 15383 2008-10-10 14:33:46Z xiphmont $ - - ********************************************************************/ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include "toplevel_lookup.h" -#include "../internal.h" -#include "dsp.h" -#include "codec_internal.h" - -#define A_TABLE_SIZE 29 -#define DF_CANDIDATE_WINDOW 5 - -/* - * th_quant_info for VP3 - */ - -/*The default quantization parameters used by VP3.1.*/ -static const int OC_VP31_RANGE_SIZES[1]={63}; -static const th_quant_base OC_VP31_BASES_INTRA_Y[2]={ - { - 16, 11, 10, 16, 24, 40, 51, 61, - 12, 12, 14, 19, 26, 58, 60, 55, - 14, 13, 16, 24, 40, 57, 69, 56, - 14, 17, 22, 29, 51, 87, 80, 62, - 18, 22, 37, 58, 68, 109,103, 77, - 24, 35, 55, 64, 81, 104,113, 92, - 49, 64, 78, 87,103, 121,120,101, - 72, 92, 95, 98,112, 100,103, 99 - }, - { - 16, 11, 10, 16, 24, 40, 51, 61, - 12, 12, 14, 19, 26, 58, 60, 55, - 14, 13, 16, 24, 40, 57, 69, 56, - 14, 17, 22, 29, 51, 87, 80, 62, - 18, 22, 37, 58, 68, 109,103, 77, - 24, 35, 55, 64, 81, 104,113, 92, - 49, 64, 78, 87,103, 121,120,101, - 72, 92, 95, 98,112, 100,103, 99 - } -}; -static const th_quant_base OC_VP31_BASES_INTRA_C[2]={ - { - 17, 18, 24, 47, 99, 99, 99, 99, - 18, 21, 26, 66, 99, 99, 99, 99, - 24, 26, 56, 99, 99, 99, 99, 99, - 47, 66, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99 - }, - { - 17, 18, 24, 47, 99, 99, 99, 99, - 18, 21, 26, 66, 99, 99, 99, 99, - 24, 26, 56, 99, 99, 99, 99, 99, - 47, 66, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99 - } -}; -static const th_quant_base OC_VP31_BASES_INTER[2]={ - { - 16, 16, 16, 20, 24, 28, 32, 40, - 16, 16, 20, 24, 28, 32, 40, 48, - 16, 20, 24, 28, 32, 40, 48, 64, - 20, 24, 28, 32, 40, 48, 64, 64, - 24, 28, 32, 40, 48, 64, 64, 64, - 28, 32, 40, 48, 64, 64, 64, 96, - 32, 40, 48, 64, 64, 64, 96,128, - 40, 48, 64, 64, 64, 96,128,128 - }, - { - 16, 16, 16, 20, 24, 28, 32, 40, - 16, 16, 20, 24, 28, 32, 40, 48, - 16, 20, 24, 28, 32, 40, 48, 64, - 20, 24, 28, 32, 40, 48, 64, 64, - 24, 28, 32, 40, 48, 64, 64, 64, - 28, 32, 40, 48, 64, 64, 64, 96, - 32, 40, 48, 64, 64, 64, 96,128, - 40, 48, 64, 64, 64, 96,128,128 - } -}; - -const th_quant_info TH_VP31_QUANT_INFO={ - { - 220,200,190,180,170,170,160,160, - 150,150,140,140,130,130,120,120, - 110,110,100,100, 90, 90, 90, 80, - 80, 80, 70, 70, 70, 60, 60, 60, - 60, 50, 50, 50, 50, 40, 40, 40, - 40, 40, 30, 30, 30, 30, 30, 30, - 30, 20, 20, 20, 20, 20, 20, 20, - 20, 10, 10, 10, 10, 10, 10, 10 - }, - { - 500,450,400,370,340,310,285,265, - 245,225,210,195,185,180,170,160, - 150,145,135,130,125,115,110,107, - 100, 96, 93, 89, 85, 82, 75, 74, - 70, 68, 64, 60, 57, 56, 52, 50, - 49, 45, 44, 43, 40, 38, 37, 35, - 33, 32, 30, 29, 28, 25, 24, 22, - 21, 19, 18, 17, 15, 13, 12, 10 - }, - { - 30,25,20,20,15,15,14,14, - 13,13,12,12,11,11,10,10, - 9, 9, 8, 8, 7, 7, 7, 7, - 6, 6, 6, 6, 5, 5, 5, 5, - 4, 4, 4, 4, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 - }, - { - { - {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTRA_Y}, - {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTRA_C}, - {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTRA_C} - }, - { - {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTER}, - {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTER}, - {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTER} - } - } -}; - - -static void EClearFragmentInfo(CP_INSTANCE * cpi){ - if(cpi->extra_fragments) - _ogg_free(cpi->extra_fragments); - if(cpi->FragmentLastQ) - _ogg_free(cpi->FragmentLastQ); - if(cpi->FragTokens) - _ogg_free(cpi->FragTokens); - if(cpi->FragTokenCounts) - _ogg_free(cpi->FragTokenCounts); - if(cpi->RunHuffIndices) - _ogg_free(cpi->RunHuffIndices); - if(cpi->LastCodedErrorScore) - _ogg_free(cpi->LastCodedErrorScore); - if(cpi->ModeList) - _ogg_free(cpi->ModeList); - if(cpi->MVList) - _ogg_free(cpi->MVList); - if(cpi->DCT_codes ) - _ogg_free( cpi->DCT_codes ); - if(cpi->DCTDataBuffer ) - _ogg_free( cpi->DCTDataBuffer); - if(cpi->quantized_list) - _ogg_free( cpi->quantized_list); - if(cpi->OriginalDC) - _ogg_free( cpi->OriginalDC); - if(cpi->PartiallyCodedFlags) - _ogg_free(cpi->PartiallyCodedFlags); - if(cpi->PartiallyCodedMbPatterns) - _ogg_free(cpi->PartiallyCodedMbPatterns); - if(cpi->UncodedMbFlags) - _ogg_free(cpi->UncodedMbFlags); - - if(cpi->BlockCodedFlags) - _ogg_free(cpi->BlockCodedFlags); - - cpi->extra_fragments = 0; - cpi->FragmentLastQ = 0; - cpi->FragTokens = 0; - cpi->FragTokenCounts = 0; - cpi->RunHuffIndices = 0; - cpi->LastCodedErrorScore = 0; - cpi->ModeList = 0; - cpi->MVList = 0; - cpi->DCT_codes = 0; - cpi->DCTDataBuffer = 0; - cpi->quantized_list = 0; - cpi->OriginalDC = 0; - cpi->BlockCodedFlags = 0; -} - -static void EInitFragmentInfo(CP_INSTANCE * cpi){ - - /* clear any existing info */ - EClearFragmentInfo(cpi); - - /* Perform Fragment Allocations */ - cpi->extra_fragments = - _ogg_malloc(cpi->pb.UnitFragments*sizeof(unsigned char)); - - /* A note to people reading and wondering why malloc returns aren't - checked: - - lines like the following that implement a general strategy of - 'check the return of malloc; a zero pointer means we're out of - memory!'...: - - if(!cpi->extra_fragments) { EDeleteFragmentInfo(cpi); return FALSE; } - - ...are not useful. It's true that many platforms follow this - malloc behavior, but many do not. The more modern malloc - strategy is only to allocate virtual pages, which are not mapped - until the memory on that page is touched. At *that* point, if - the machine is out of heap, the page fails to be mapped and a - SEGV is generated. - - That means that if we want to deal with out of memory conditions, - we *must* be prepared to process a SEGV. If we implement the - SEGV handler, there's no reason to to check malloc return; it is - a waste of code. */ - - cpi->FragmentLastQ = - _ogg_malloc(cpi->pb.UnitFragments* - sizeof(*cpi->FragmentLastQ)); - cpi->FragTokens = - _ogg_malloc(cpi->pb.UnitFragments* - sizeof(*cpi->FragTokens)); - cpi->OriginalDC = - _ogg_malloc(cpi->pb.UnitFragments* - sizeof(*cpi->OriginalDC)); - cpi->FragTokenCounts = - _ogg_malloc(cpi->pb.UnitFragments* - sizeof(*cpi->FragTokenCounts)); - cpi->RunHuffIndices = - _ogg_malloc(cpi->pb.UnitFragments* - sizeof(*cpi->RunHuffIndices)); - cpi->LastCodedErrorScore = - _ogg_malloc(cpi->pb.UnitFragments* - sizeof(*cpi->LastCodedErrorScore)); - cpi->BlockCodedFlags = - _ogg_malloc(cpi->pb.UnitFragments* - sizeof(*cpi->BlockCodedFlags)); - cpi->ModeList = - _ogg_malloc(cpi->pb.UnitFragments* - sizeof(*cpi->ModeList)); - cpi->MVList = - _ogg_malloc(cpi->pb.UnitFragments* - sizeof(*cpi->MVList)); - cpi->DCT_codes = - _ogg_malloc(64* - sizeof(*cpi->DCT_codes)); - cpi->DCTDataBuffer = - _ogg_malloc(64* - sizeof(*cpi->DCTDataBuffer)); - cpi->quantized_list = - _ogg_malloc(64* - sizeof(*cpi->quantized_list)); - cpi->PartiallyCodedFlags = - _ogg_malloc(cpi->pb.MacroBlocks* - sizeof(*cpi->PartiallyCodedFlags)); - cpi->PartiallyCodedMbPatterns = - _ogg_malloc(cpi->pb.MacroBlocks* - sizeof(*cpi->PartiallyCodedMbPatterns)); - cpi->UncodedMbFlags = - _ogg_malloc(cpi->pb.MacroBlocks* - sizeof(*cpi->UncodedMbFlags)); - -} - -static void EClearFrameInfo(CP_INSTANCE * cpi) { - if(cpi->ConvDestBuffer ) - _ogg_free(cpi->ConvDestBuffer ); - cpi->ConvDestBuffer = 0; - - if(cpi->yuv0ptr) - _ogg_free(cpi->yuv0ptr); - cpi->yuv0ptr = 0; - - if(cpi->yuv1ptr) - _ogg_free(cpi->yuv1ptr); - cpi->yuv1ptr = 0; - - if(cpi->OptimisedTokenListEb ) - _ogg_free(cpi->OptimisedTokenListEb); - cpi->OptimisedTokenListEb = 0; - - if(cpi->OptimisedTokenList ) - _ogg_free(cpi->OptimisedTokenList); - cpi->OptimisedTokenList = 0; - - if(cpi->OptimisedTokenListHi ) - _ogg_free(cpi->OptimisedTokenListHi); - cpi->OptimisedTokenListHi = 0; - - if(cpi->OptimisedTokenListPl ) - _ogg_free(cpi->OptimisedTokenListPl); - cpi->OptimisedTokenListPl = 0; - -} - -static void EInitFrameInfo(CP_INSTANCE * cpi){ - int FrameSize = cpi->pb.ReconYPlaneSize + 2 * cpi->pb.ReconUVPlaneSize; - - /* clear any existing info */ - EClearFrameInfo(cpi); - - /* allocate frames */ - cpi->ConvDestBuffer = - _ogg_malloc(FrameSize* - sizeof(*cpi->ConvDestBuffer)); - cpi->yuv0ptr = - _ogg_malloc(FrameSize* - sizeof(*cpi->yuv0ptr)); - cpi->yuv1ptr = - _ogg_malloc(FrameSize* - sizeof(*cpi->yuv1ptr)); - cpi->OptimisedTokenListEb = - _ogg_malloc(FrameSize* - sizeof(*cpi->OptimisedTokenListEb)); - cpi->OptimisedTokenList = - _ogg_malloc(FrameSize* - sizeof(*cpi->OptimisedTokenList)); - cpi->OptimisedTokenListHi = - _ogg_malloc(FrameSize* - sizeof(*cpi->OptimisedTokenListHi)); - cpi->OptimisedTokenListPl = - _ogg_malloc(FrameSize* - sizeof(*cpi->OptimisedTokenListPl)); -} - -static void SetupKeyFrame(CP_INSTANCE *cpi) { - /* Make sure the "last frame" buffer contains the first frame data - as well. */ - memcpy ( cpi->yuv0ptr, cpi->yuv1ptr, - cpi->pb.ReconYPlaneSize + 2 * cpi->pb.ReconUVPlaneSize ); - - /* Initialise the cpi->pb.display_fragments and other fragment - structures for the first frame. */ - memset( cpi->pb.display_fragments, 1, cpi->pb.UnitFragments ); - memset( cpi->extra_fragments, 1, cpi->pb.UnitFragments ); - - /* Set up for a KEY FRAME */ - cpi->pb.FrameType = KEY_FRAME; -} - -static void AdjustKeyFrameContext(CP_INSTANCE *cpi) { - ogg_uint32_t i; - ogg_uint32_t AvKeyFrameFrequency = - (ogg_uint32_t) (cpi->CurrentFrame / cpi->KeyFrameCount); - ogg_uint32_t AvKeyFrameBytes = - (ogg_uint32_t) (cpi->TotKeyFrameBytes / cpi->KeyFrameCount); - ogg_uint32_t TotalWeight=0; - ogg_int32_t AvKeyFramesPerSecond; - ogg_int32_t MinFrameTargetRate; - - /* Update the frame carry over. */ - cpi->TotKeyFrameBytes += oggpackB_bytes(cpi->oggbuffer); - - /* reset keyframe context and calculate weighted average of last - KEY_FRAME_CONTEXT keyframes */ - for( i = 0 ; i < KEY_FRAME_CONTEXT ; i ++ ) { - if ( i < KEY_FRAME_CONTEXT -1) { - cpi->PriorKeyFrameSize[i] = cpi->PriorKeyFrameSize[i+1]; - cpi->PriorKeyFrameDistance[i] = cpi->PriorKeyFrameDistance[i+1]; - } else { - cpi->PriorKeyFrameSize[KEY_FRAME_CONTEXT - 1] = - oggpackB_bytes(cpi->oggbuffer); - cpi->PriorKeyFrameDistance[KEY_FRAME_CONTEXT - 1] = - cpi->LastKeyFrame; - } - - AvKeyFrameBytes += PriorKeyFrameWeight[i] * - cpi->PriorKeyFrameSize[i]; - AvKeyFrameFrequency += PriorKeyFrameWeight[i] * - cpi->PriorKeyFrameDistance[i]; - TotalWeight += PriorKeyFrameWeight[i]; - } - AvKeyFrameBytes /= TotalWeight; - AvKeyFrameFrequency /= TotalWeight; - AvKeyFramesPerSecond = 100 * cpi->Configuration.OutputFrameRate / - AvKeyFrameFrequency ; - - /* Calculate a new target rate per frame allowing for average key - frame frequency over newest frames . */ - if ( 100 * cpi->Configuration.TargetBandwidth > - AvKeyFrameBytes * AvKeyFramesPerSecond && - (100 * cpi->Configuration.OutputFrameRate - AvKeyFramesPerSecond )){ - cpi->frame_target_rate = - (ogg_int32_t)(100* cpi->Configuration.TargetBandwidth - - AvKeyFrameBytes * AvKeyFramesPerSecond ) / - ( (100 * cpi->Configuration.OutputFrameRate - AvKeyFramesPerSecond ) ); - } else { - /* don't let this number get too small!!! */ - cpi->frame_target_rate = 1; - } - - /* minimum allowable frame_target_rate */ - MinFrameTargetRate = (cpi->Configuration.TargetBandwidth / - cpi->Configuration.OutputFrameRate) / 3; - - if(cpi->frame_target_rate < MinFrameTargetRate ) { - cpi->frame_target_rate = MinFrameTargetRate; - } - - cpi->LastKeyFrame = 1; - cpi->LastKeyFrameSize=oggpackB_bytes(cpi->oggbuffer); - -} - -static void UpdateFrame(CP_INSTANCE *cpi){ - - double CorrectionFactor; - - /* Reset the DC predictors. */ - cpi->pb.LastIntraDC = 0; - cpi->pb.InvLastIntraDC = 0; - cpi->pb.LastInterDC = 0; - cpi->pb.InvLastInterDC = 0; - - /* Initialise bit packing mechanism. */ - oggpackB_reset(cpi->oggbuffer); - - /* mark as video frame */ - oggpackB_write(cpi->oggbuffer,0,1); - - /* Write out the frame header information including size. */ - WriteFrameHeader(cpi); - - /* Copy back any extra frags that are to be updated by the codec - as part of the background cleanup task */ - CopyBackExtraFrags(cpi); - - /* Encode the data. */ - EncodeData(cpi); - - /* Adjust drop frame trigger. */ - if ( cpi->pb.FrameType != KEY_FRAME ) { - /* Apply decay factor then add in the last frame size. */ - cpi->DropFrameTriggerBytes = - ((cpi->DropFrameTriggerBytes * (DF_CANDIDATE_WINDOW-1)) / - DF_CANDIDATE_WINDOW) + oggpackB_bytes(cpi->oggbuffer); - }else{ - /* Increase cpi->DropFrameTriggerBytes a little. Just after a key - frame may actually be a good time to drop a frame. */ - cpi->DropFrameTriggerBytes = - (cpi->DropFrameTriggerBytes * DF_CANDIDATE_WINDOW) / - (DF_CANDIDATE_WINDOW-1); - } - - /* Test for overshoot which may require a dropped frame next time - around. If we are already in a drop frame condition but the - previous frame was not dropped then the threshold for continuing - to allow dropped frames is reduced. */ - if ( cpi->DropFrameCandidate ) { - if ( cpi->DropFrameTriggerBytes > - (cpi->frame_target_rate * (DF_CANDIDATE_WINDOW+1)) ) - cpi->DropFrameCandidate = 1; - else - cpi->DropFrameCandidate = 0; - } else { - if ( cpi->DropFrameTriggerBytes > - (cpi->frame_target_rate * ((DF_CANDIDATE_WINDOW*2)-2)) ) - cpi->DropFrameCandidate = 1; - else - cpi->DropFrameCandidate = 0; - } - - /* Update the BpbCorrectionFactor variable according to whether or - not we were close enough with our selection of DCT quantiser. */ - if ( cpi->pb.FrameType != KEY_FRAME ) { - /* Work out a size correction factor. */ - CorrectionFactor = (double)oggpackB_bytes(cpi->oggbuffer) / - (double)cpi->ThisFrameTargetBytes; - - if ( (CorrectionFactor > 1.05) && - (cpi->pb.ThisFrameQualityValue < - cpi->pb.QThreshTable[cpi->Configuration.ActiveMaxQ]) ) { - CorrectionFactor = 1.0 + ((CorrectionFactor - 1.0)/2); - if ( CorrectionFactor > 1.5 ) - cpi->BpbCorrectionFactor *= 1.5; - else - cpi->BpbCorrectionFactor *= CorrectionFactor; - - /* Keep BpbCorrectionFactor within limits */ - if ( cpi->BpbCorrectionFactor > MAX_BPB_FACTOR ) - cpi->BpbCorrectionFactor = MAX_BPB_FACTOR; - } else if ( (CorrectionFactor < 0.95) && - (cpi->pb.ThisFrameQualityValue > VERY_BEST_Q) ){ - CorrectionFactor = 1.0 - ((1.0 - CorrectionFactor)/2); - if ( CorrectionFactor < 0.75 ) - cpi->BpbCorrectionFactor *= 0.75; - else - cpi->BpbCorrectionFactor *= CorrectionFactor; - - /* Keep BpbCorrectionFactor within limits */ - if ( cpi->BpbCorrectionFactor < MIN_BPB_FACTOR ) - cpi->BpbCorrectionFactor = MIN_BPB_FACTOR; - } - } - - /* Adjust carry over and or key frame context. */ - if ( cpi->pb.FrameType == KEY_FRAME ) { - /* Adjust the key frame context unless the key frame was very small */ - AdjustKeyFrameContext(cpi); - } else { - /* Update the frame carry over */ - cpi->CarryOver += ((ogg_int32_t)cpi->frame_target_rate - - (ogg_int32_t)oggpackB_bytes(cpi->oggbuffer)); - } - cpi->TotalByteCount += oggpackB_bytes(cpi->oggbuffer); -} - -static void CompressFirstFrame(CP_INSTANCE *cpi) { - ogg_uint32_t i; - - /* set up context of key frame sizes and distances for more local - datarate control */ - for( i = 0 ; i < KEY_FRAME_CONTEXT ; i ++ ) { - cpi->PriorKeyFrameSize[i] = cpi->Configuration.KeyFrameDataTarget; - cpi->PriorKeyFrameDistance[i] = cpi->pb.info.keyframe_frequency_force; - } - - /* Keep track of the total number of Key Frames Coded. */ - cpi->KeyFrameCount = 1; - cpi->LastKeyFrame = 1; - cpi->TotKeyFrameBytes = 0; - - /* A key frame is not a dropped frame there for reset the count of - consequative dropped frames. */ - cpi->DropCount = 0; - - SetupKeyFrame(cpi); - - /* Calculate a new target rate per frame allowing for average key - frame frequency and size thus far. */ - if ( cpi->Configuration.TargetBandwidth > - ((cpi->Configuration.KeyFrameDataTarget * - cpi->Configuration.OutputFrameRate)/ - cpi->pb.info.keyframe_frequency) ) { - - cpi->frame_target_rate = - (ogg_int32_t)((cpi->Configuration.TargetBandwidth - - ((cpi->Configuration.KeyFrameDataTarget * - cpi->Configuration.OutputFrameRate)/ - cpi->pb.info.keyframe_frequency)) / - cpi->Configuration.OutputFrameRate); - }else - cpi->frame_target_rate = 1; - - /* Set baseline frame target rate. */ - cpi->BaseLineFrameTargetRate = cpi->frame_target_rate; - - /* A key frame is not a dropped frame there for reset the count of - consequative dropped frames. */ - cpi->DropCount = 0; - - /* Initialise drop frame trigger to 5 frames worth of data. */ - cpi->DropFrameTriggerBytes = cpi->frame_target_rate * DF_CANDIDATE_WINDOW; - - /* Set a target size for this key frame based upon the baseline - target and frequency */ - cpi->ThisFrameTargetBytes = cpi->Configuration.KeyFrameDataTarget; - - /* Get a DCT quantizer level for the key frame. */ - cpi->MotionScore = cpi->pb.UnitFragments; - - RegulateQ(cpi, cpi->pb.UnitFragments); - - cpi->pb.LastFrameQualityValue = cpi->pb.ThisFrameQualityValue; - - /* Initialise quantizer. */ - UpdateQC(cpi, cpi->pb.ThisFrameQualityValue ); - - /* Initialise the cpi->pb.display_fragments and other fragment - structures for the first frame. */ - for ( i = 0; i < cpi->pb.UnitFragments; i ++ ) - cpi->FragmentLastQ[i] = cpi->pb.ThisFrameQualityValue; - - /* Compress and output the frist frame. */ - PickIntra( cpi, - cpi->pb.YSBRows, cpi->pb.YSBCols); - UpdateFrame(cpi); - - /* Initialise the carry over rate targeting variables. */ - cpi->CarryOver = 0; - -} - -static void CompressKeyFrame(CP_INSTANCE *cpi){ - ogg_uint32_t i; - - /* Before we compress reset the carry over to the actual frame carry over */ - cpi->CarryOver = cpi->Configuration.TargetBandwidth * cpi->CurrentFrame / - cpi->Configuration.OutputFrameRate - cpi->TotalByteCount; - - /* Keep track of the total number of Key Frames Coded */ - cpi->KeyFrameCount += 1; - - /* A key frame is not a dropped frame there for reset the count of - consequative dropped frames. */ - cpi->DropCount = 0; - - SetupKeyFrame(cpi); - - /* set a target size for this frame */ - cpi->ThisFrameTargetBytes = (ogg_int32_t) cpi->frame_target_rate + - ( (cpi->Configuration.KeyFrameDataTarget - cpi->frame_target_rate) * - cpi->LastKeyFrame / cpi->pb.info.keyframe_frequency_force ); - - if ( cpi->ThisFrameTargetBytes > cpi->Configuration.KeyFrameDataTarget ) - cpi->ThisFrameTargetBytes = cpi->Configuration.KeyFrameDataTarget; - - /* Get a DCT quantizer level for the key frame. */ - cpi->MotionScore = cpi->pb.UnitFragments; - - RegulateQ(cpi, cpi->pb.UnitFragments); - - cpi->pb.LastFrameQualityValue = cpi->pb.ThisFrameQualityValue; - - /* Initialise DCT tables. */ - UpdateQC(cpi, cpi->pb.ThisFrameQualityValue ); - - /* Initialise the cpi->pb.display_fragments and other fragment - structures for the first frame. */ - for ( i = 0; i < cpi->pb.UnitFragments; i ++ ) - cpi->FragmentLastQ[i] = cpi->pb.ThisFrameQualityValue; - - - /* Compress and output the frist frame. */ - PickIntra( cpi, - cpi->pb.YSBRows, cpi->pb.YSBCols); - UpdateFrame(cpi); - -} - -static void CompressFrame( CP_INSTANCE *cpi) { - ogg_int32_t min_blocks_per_frame; - ogg_uint32_t i; - int DropFrame = 0; - ogg_uint32_t ResidueBlocksAdded=0; - ogg_uint32_t KFIndicator = 0; - - double QModStep; - double QModifier = 1.0; - - /* Clear down the macro block level mode and MV arrays. */ - for ( i = 0; i < cpi->pb.UnitFragments; i++ ) { - cpi->pb.FragCodingMethod[i] = CODE_INTER_NO_MV; /* Default coding mode */ - cpi->pb.FragMVect[i].x = 0; - cpi->pb.FragMVect[i].y = 0; - } - - /* Default to delta frames. */ - cpi->pb.FrameType = DELTA_FRAME; - - /* Clear down the difference arrays for the current frame. */ - memset( cpi->pb.display_fragments, 0, cpi->pb.UnitFragments ); - memset( cpi->extra_fragments, 0, cpi->pb.UnitFragments ); - - /* Calculate the target bytes for this frame. */ - cpi->ThisFrameTargetBytes = cpi->frame_target_rate; - - /* Correct target to try and compensate for any overall rate error - that is developing */ - - /* Set the max allowed Q for this frame based upon carry over - history. First set baseline worst Q for this frame */ - cpi->Configuration.ActiveMaxQ = cpi->Configuration.MaxQ + 10; - if ( cpi->Configuration.ActiveMaxQ >= Q_TABLE_SIZE ) - cpi->Configuration.ActiveMaxQ = Q_TABLE_SIZE - 1; - - /* Make a further adjustment based upon the carry over and recent - history.. cpi->Configuration.ActiveMaxQ reduced by 1 for each 1/2 - seconds worth of -ve carry over up to a limit of 6. Also - cpi->Configuration.ActiveMaxQ reduced if frame is a - "DropFrameCandidate". Remember that if we are behind the bit - target carry over is -ve. */ - if ( cpi->CarryOver < 0 ) { - if ( cpi->DropFrameCandidate ) { - cpi->Configuration.ActiveMaxQ -= 4; - } - - if ( cpi->CarryOver < - -((ogg_int32_t)cpi->Configuration.TargetBandwidth*3) ) - cpi->Configuration.ActiveMaxQ -= 6; - else - cpi->Configuration.ActiveMaxQ += - (ogg_int32_t) ((cpi->CarryOver*2) / - (ogg_int32_t)cpi->Configuration.TargetBandwidth); - - /* Check that we have not dropped quality too far */ - if ( cpi->Configuration.ActiveMaxQ < cpi->Configuration.MaxQ ) - cpi->Configuration.ActiveMaxQ = cpi->Configuration.MaxQ; - } - - /* Calculate the Q Modifier step size required to cause a step down - from full target bandwidth to 40% of target between max Q and - best Q */ - QModStep = 0.5 / (double)((Q_TABLE_SIZE - 1) - - cpi->Configuration.ActiveMaxQ); - - /* Set up the cpi->QTargetModifier[] table. */ - for ( i = 0; i < cpi->Configuration.ActiveMaxQ; i++ ) { - cpi->QTargetModifier[i] = QModifier; - } - for ( i = cpi->Configuration.ActiveMaxQ; i < Q_TABLE_SIZE; i++ ) { - cpi->QTargetModifier[i] = QModifier; - QModifier -= QModStep; - } - - /* if we are allowed to drop frames and are falling behind (eg more - than x frames worth of bandwidth) */ - if ( cpi->pb.info.dropframes_p && - ( cpi->DropCount < cpi->MaxConsDroppedFrames) && - ( cpi->CarryOver < - -((ogg_int32_t)cpi->Configuration.TargetBandwidth)) && - ( cpi->DropFrameCandidate) ) { - /* (we didn't do this frame so we should have some left over for - the next frame) */ - cpi->CarryOver += cpi->frame_target_rate; - DropFrame = 1; - cpi->DropCount ++; - - /* Adjust DropFrameTriggerBytes to account for the saving achieved. */ - cpi->DropFrameTriggerBytes = - (cpi->DropFrameTriggerBytes * - (DF_CANDIDATE_WINDOW-1))/DF_CANDIDATE_WINDOW; - - /* Even if we drop a frame we should account for it when - considering key frame seperation. */ - cpi->LastKeyFrame++; - } else if ( cpi->CarryOver < - -((ogg_int32_t)cpi->Configuration.TargetBandwidth * 2) ) { - /* Reduce frame bit target by 1.75% for each 1/10th of a seconds - worth of -ve carry over down to a minimum of 65% of its - un-modified value. */ - - cpi->ThisFrameTargetBytes = - (ogg_uint32_t)(cpi->ThisFrameTargetBytes * 0.65); - } else if ( cpi->CarryOver < 0 ) { - /* Note that cpi->CarryOver is a -ve here hence 1.0 "+" ... */ - cpi->ThisFrameTargetBytes = - (ogg_uint32_t)(cpi->ThisFrameTargetBytes * - (1.0 + ( ((cpi->CarryOver * 10)/ - ((ogg_int32_t)cpi-> - Configuration.TargetBandwidth)) * 0.0175) )); - } - - if ( !DropFrame ) { - /* pick all the macroblock modes and motion vectors */ - ogg_uint32_t InterError; - ogg_uint32_t IntraError; - - - /* Set Baseline filter level. */ - ConfigurePP( &cpi->pp, cpi->pb.info.noise_sensitivity); - - /* Score / analyses the fragments. */ - cpi->MotionScore = YUVAnalyseFrame(&cpi->pp, &KFIndicator ); - - /* Get the baseline Q value */ - RegulateQ( cpi, cpi->MotionScore ); - - /* Recode blocks if the error score in last frame was high. */ - ResidueBlocksAdded = 0; - for ( i = 0; i < cpi->pb.UnitFragments; i++ ){ - if ( !cpi->pb.display_fragments[i] ){ - if ( cpi->LastCodedErrorScore[i] >= - ResidueErrorThresh[cpi->pb.FrameQIndex] ) { - cpi->pb.display_fragments[i] = 1; /* Force block update */ - cpi->extra_fragments[i] = 1; /* Insures up to date - pixel data is used. */ - ResidueBlocksAdded ++; - } - } - } - - /* Adjust the motion score to allow for residue blocks - added. These are assumed to have below average impact on - bitrate (Hence ResidueBlockFactor). */ - cpi->MotionScore = cpi->MotionScore + - (ResidueBlocksAdded / ResidueBlockFactor[cpi->pb.FrameQIndex]); - - /* Estimate the min number of blocks at best Q */ - min_blocks_per_frame = - (ogg_int32_t)(cpi->ThisFrameTargetBytes / - GetEstimatedBpb( cpi, VERY_BEST_Q )); - if ( min_blocks_per_frame == 0 ) - min_blocks_per_frame = 1; - - /* If we have less than this number then consider adding in some - extra blocks */ - if ( cpi->MotionScore < min_blocks_per_frame ) { - min_blocks_per_frame = - cpi->MotionScore + - (ogg_int32_t)(((min_blocks_per_frame - cpi->MotionScore) * 4) / 3 ); - UpRegulateDataStream( cpi, VERY_BEST_Q, min_blocks_per_frame ); - }else{ - /* Reset control variable for best quality final pass. */ - cpi->FinalPassLastPos = 0; - } - - /* Get the modified Q prediction taking into account extra blocks added. */ - RegulateQ( cpi, cpi->MotionScore ); - - /* Unless we are already well ahead (4 seconds of data) of the - projected bitrate */ - if ( cpi->CarryOver < - (ogg_int32_t)(cpi->Configuration.TargetBandwidth * 4) ){ - /* Look at the predicted Q (pbi->FrameQIndex). Adjust the - target bits for this frame based upon projected Q and - re-calculate. The idea is that if the Q is better than a - given (good enough) level then we will try and save some bits - for use in more difficult segments. */ - cpi->ThisFrameTargetBytes = - (ogg_int32_t) (cpi->ThisFrameTargetBytes * - cpi->QTargetModifier[cpi->pb.FrameQIndex]); - - /* Recalculate Q again */ - RegulateQ( cpi, cpi->MotionScore ); - } - - - /* Select modes and motion vectors for each of the blocks : return - an error score for inter and intra */ - PickModes( cpi, cpi->pb.YSBRows, cpi->pb.YSBCols, - cpi->pb.info.width, - &InterError, &IntraError ); - - /* decide whether we really should have made this frame a key frame */ - /* forcing out a keyframe if the max interval is up is done at a higher level */ - if( cpi->pb.info.keyframe_auto_p){ - if( ( 2* IntraError < 5 * InterError ) - && ( KFIndicator >= (ogg_uint32_t) - cpi->pb.info.keyframe_auto_threshold) - && ( cpi->LastKeyFrame > cpi->pb.info.keyframe_mindistance) - ){ - CompressKeyFrame(cpi); /* Code a key frame */ - return; - } - - } - - /* Increment the frames since last key frame count */ - cpi->LastKeyFrame++; - - /* Proceed with the frame update. */ - UpdateFrame(cpi); - cpi->DropCount = 0; - - if ( cpi->MotionScore > 0 ){ - /* Note the Quantizer used for each block coded. */ - for ( i = 0; i < cpi->pb.UnitFragments; i++ ){ - if ( cpi->pb.display_fragments[i] ){ - cpi->FragmentLastQ[i] = cpi->pb.ThisFrameQualityValue; - } - } - - } - }else{ - /* even if we 'drop' a frame, a placeholder must be written as we - currently assume fixed frame rate timebase as Ogg mapping - invariant */ - UpdateFrame(cpi); - } -} - -/********************** The toplevel: encode ***********************/ - -static int _ilog(unsigned int v){ - int ret=0; - while(v){ - ret++; - v>>=1; - } - return(ret); -} - -static void theora_encode_dispatch_init(CP_INSTANCE *cpi); - -int theora_encode_init(theora_state *th, theora_info *c){ - int i; - - CP_INSTANCE *cpi; - - memset(th, 0, sizeof(*th)); - /*Currently only the 4:2:0 format is supported.*/ - if(c->pixelformat!=OC_PF_420)return OC_IMPL; - th->internal_encode=cpi=_ogg_calloc(1,sizeof(*cpi)); - theora_encode_dispatch_init(cpi); - - dsp_static_init (&cpi->dsp); - memcpy (&cpi->pb.dsp, &cpi->dsp, sizeof(DspFunctions)); - - c->version_major=TH_VERSION_MAJOR; - c->version_minor=TH_VERSION_MINOR; - c->version_subminor=TH_VERSION_SUB; - - InitTmpBuffers(&cpi->pb); - InitPPInstance(&cpi->pp, &cpi->dsp); - - /* Initialise Configuration structure to legal values */ - if(c->quality>63)c->quality=63; - if(c->quality<0)c->quality=32; - if(c->target_bitrate<0)c->target_bitrate=0; - /* we clamp target_bitrate to 24 bits after setting up the encoder */ - - cpi->Configuration.BaseQ = c->quality; - cpi->Configuration.FirstFrameQ = c->quality; - cpi->Configuration.MaxQ = c->quality; - cpi->Configuration.ActiveMaxQ = c->quality; - - cpi->MVChangeFactor = 14; - cpi->FourMvChangeFactor = 8; - cpi->MinImprovementForNewMV = 25; - cpi->ExhaustiveSearchThresh = 2500; - cpi->MinImprovementForFourMV = 100; - cpi->FourMVThreshold = 10000; - cpi->BitRateCapFactor = 1.5; - cpi->InterTripOutThresh = 5000; - cpi->MVEnabled = 1; - cpi->InterCodeCount = 127; - cpi->BpbCorrectionFactor = 1.0; - cpi->GoldenFrameEnabled = 1; - cpi->InterPrediction = 1; - cpi->MotionCompensation = 1; - cpi->ThreshMapThreshold = 5; - cpi->MaxConsDroppedFrames = 1; - - /* Set encoder flags. */ - /* if not AutoKeyframing cpi->ForceKeyFrameEvery = is frequency */ - if(!c->keyframe_auto_p) - c->keyframe_frequency_force = c->keyframe_frequency; - - /* Set the frame rate variables. */ - if ( c->fps_numerator < 1 ) - c->fps_numerator = 1; - if ( c->fps_denominator < 1 ) - c->fps_denominator = 1; - - /* don't go too nuts on keyframe spacing; impose a high limit to - make certain the granulepos encoding strategy works */ - if(c->keyframe_frequency_force>32768)c->keyframe_frequency_force=32768; - if(c->keyframe_mindistance>32768)c->keyframe_mindistance=32768; - if(c->keyframe_mindistance>c->keyframe_frequency_force) - c->keyframe_mindistance=c->keyframe_frequency_force; - cpi->pb.keyframe_granule_shift=_ilog(c->keyframe_frequency_force-1); - - /* clamp the target_bitrate to a maximum of 24 bits so we get a - more meaningful value when we write this out in the header. */ - if(c->target_bitrate>(1<<24)-1)c->target_bitrate=(1<<24)-1; - - /* copy in config */ - memcpy(&cpi->pb.info,c,sizeof(*c)); - th->i=&cpi->pb.info; - th->granulepos=-1; - - /* Set up default values for QTargetModifier[Q_TABLE_SIZE] table */ - for ( i = 0; i < Q_TABLE_SIZE; i++ ) - cpi->QTargetModifier[i] = 1.0; - - /* Set up an encode buffer */ - cpi->oggbuffer = _ogg_malloc(sizeof(oggpack_buffer)); - oggpackB_writeinit(cpi->oggbuffer); - - /* Set data rate related variables. */ - cpi->Configuration.TargetBandwidth = (c->target_bitrate) / 8; - - cpi->Configuration.OutputFrameRate = - (double)( c->fps_numerator / - c->fps_denominator ); - - cpi->frame_target_rate = cpi->Configuration.TargetBandwidth / - cpi->Configuration.OutputFrameRate; - - /* Set key frame data rate target; this is nominal keyframe size */ - cpi->Configuration.KeyFrameDataTarget = (c->keyframe_data_target_bitrate * - c->fps_denominator / - c->fps_numerator ) / 8; - - /* Note the height and width in the pre-processor control structure. */ - cpi->ScanConfig.VideoFrameHeight = cpi->pb.info.height; - cpi->ScanConfig.VideoFrameWidth = cpi->pb.info.width; - - InitFrameDetails(&cpi->pb); - EInitFragmentInfo(cpi); - EInitFrameInfo(cpi); - - /* Set up pre-processor config pointers. */ - cpi->ScanConfig.Yuv0ptr = cpi->yuv0ptr; - cpi->ScanConfig.Yuv1ptr = cpi->yuv1ptr; - cpi->ScanConfig.SrfWorkSpcPtr = cpi->ConvDestBuffer; - cpi->ScanConfig.disp_fragments = cpi->pb.display_fragments; - cpi->ScanConfig.RegionIndex = cpi->pb.pixel_index_table; - - /* Initialise the pre-processor module. */ - ScanYUVInit(&cpi->pp, &(cpi->ScanConfig)); - - /* Initialise Motion compensation */ - InitMotionCompensation(cpi); - - /* Initialise the compression process. */ - /* We always start at frame 1 */ - cpi->CurrentFrame = 1; - - /* Reset the rate targeting correction factor. */ - cpi->BpbCorrectionFactor = 1.0; - - cpi->TotalByteCount = 0; - cpi->TotalMotionScore = 0; - - /* Up regulation variables. */ - cpi->FinalPassLastPos = 0; /* Used to regulate a final unrestricted pass. */ - cpi->LastEndSB = 0; /* Where we were in the loop last time. */ - cpi->ResidueLastEndSB = 0; /* Where we were in the residue update - loop last time. */ - - InitHuffmanSet(&cpi->pb); - - /* This makes sure encoder version specific tables are initialised */ - memcpy(&cpi->pb.quant_info, &TH_VP31_QUANT_INFO, sizeof(th_quant_info)); - InitQTables(&cpi->pb); - - /* Indicate that the next frame to be compressed is the first in the - current clip. */ - cpi->ThisIsFirstFrame = 1; - cpi->readyflag = 1; - - cpi->pb.HeadersWritten = 0; - /*We overload this flag to track header output.*/ - cpi->doneflag=-3; - - return 0; -} - -int theora_encode_YUVin(theora_state *t, - yuv_buffer *yuv){ - ogg_int32_t i; - unsigned char *LocalDataPtr; - unsigned char *InputDataPtr; - CP_INSTANCE *cpi=(CP_INSTANCE *)(t->internal_encode); - - if(!cpi->readyflag)return OC_EINVAL; - if(cpi->doneflag>0)return OC_EINVAL; - - /* If frame size has changed, abort out for now */ - if (yuv->y_height != (int)cpi->pb.info.height || - yuv->y_width != (int)cpi->pb.info.width ) - return(-1); - - - /* Copy over input YUV to internal YUV buffers. */ - /* we invert the image for backward compatibility with VP3 */ - /* First copy over the Y data */ - LocalDataPtr = cpi->yuv1ptr + yuv->y_width*(yuv->y_height - 1); - InputDataPtr = yuv->y; - for ( i = 0; i < yuv->y_height; i++ ){ - memcpy( LocalDataPtr, InputDataPtr, yuv->y_width ); - LocalDataPtr -= yuv->y_width; - InputDataPtr += yuv->y_stride; - } - - /* Now copy over the U data */ - LocalDataPtr = &cpi->yuv1ptr[(yuv->y_height * yuv->y_width)]; - LocalDataPtr += yuv->uv_width*(yuv->uv_height - 1); - InputDataPtr = yuv->u; - for ( i = 0; i < yuv->uv_height; i++ ){ - memcpy( LocalDataPtr, InputDataPtr, yuv->uv_width ); - LocalDataPtr -= yuv->uv_width; - InputDataPtr += yuv->uv_stride; - } - - /* Now copy over the V data */ - LocalDataPtr = - &cpi->yuv1ptr[((yuv->y_height*yuv->y_width)*5)/4]; - LocalDataPtr += yuv->uv_width*(yuv->uv_height - 1); - InputDataPtr = yuv->v; - for ( i = 0; i < yuv->uv_height; i++ ){ - memcpy( LocalDataPtr, InputDataPtr, yuv->uv_width ); - LocalDataPtr -= yuv->uv_width; - InputDataPtr += yuv->uv_stride; - } - - /* Special case for first frame */ - if ( cpi->ThisIsFirstFrame ){ - CompressFirstFrame(cpi); - cpi->ThisIsFirstFrame = 0; - cpi->ThisIsKeyFrame = 0; - } else { - - /* don't allow generating invalid files that overflow the p-frame - shift, even if keyframe_auto_p is turned off */ - if(cpi->LastKeyFrame >= (ogg_uint32_t) - cpi->pb.info.keyframe_frequency_force) - cpi->ThisIsKeyFrame = 1; - - if ( cpi->ThisIsKeyFrame ) { - CompressKeyFrame(cpi); - cpi->ThisIsKeyFrame = 0; - } else { - /* Compress the frame. */ - CompressFrame( cpi ); - } - - } - - /* Update stats variables. */ - cpi->LastFrameSize = oggpackB_bytes(cpi->oggbuffer); - cpi->CurrentFrame++; - cpi->packetflag=1; - - t->granulepos= - ((cpi->CurrentFrame - cpi->LastKeyFrame)<pb.keyframe_granule_shift)+ - cpi->LastKeyFrame - 1; - - return 0; -} - -int theora_encode_packetout( theora_state *t, int last_p, ogg_packet *op){ - CP_INSTANCE *cpi=(CP_INSTANCE *)(t->internal_encode); - long bytes=oggpackB_bytes(cpi->oggbuffer); - - if(!bytes)return(0); - if(!cpi->packetflag)return(0); - if(cpi->doneflag>0)return(-1); - - op->packet=oggpackB_get_buffer(cpi->oggbuffer); - op->bytes=bytes; - op->b_o_s=0; - op->e_o_s=last_p; - - op->packetno=cpi->CurrentFrame; - op->granulepos=t->granulepos; - - cpi->packetflag=0; - if(last_p)cpi->doneflag=1; - - return 1; -} - -static void _tp_writebuffer(oggpack_buffer *opb, const char *buf, const long len) -{ - long i; - - for (i = 0; i < len; i++) - oggpackB_write(opb, *buf++, 8); -} - -static void _tp_writelsbint(oggpack_buffer *opb, long value) -{ - oggpackB_write(opb, value&0xFF, 8); - oggpackB_write(opb, value>>8&0xFF, 8); - oggpackB_write(opb, value>>16&0xFF, 8); - oggpackB_write(opb, value>>24&0xFF, 8); -} - -/* build the initial short header for stream recognition and format */ -int theora_encode_header(theora_state *t, ogg_packet *op){ - CP_INSTANCE *cpi=(CP_INSTANCE *)(t->internal_encode); - int offset_y; - - oggpackB_reset(cpi->oggbuffer); - oggpackB_write(cpi->oggbuffer,0x80,8); - _tp_writebuffer(cpi->oggbuffer, "theora", 6); - - oggpackB_write(cpi->oggbuffer,TH_VERSION_MAJOR,8); - oggpackB_write(cpi->oggbuffer,TH_VERSION_MINOR,8); - oggpackB_write(cpi->oggbuffer,TH_VERSION_SUB,8); - - oggpackB_write(cpi->oggbuffer,cpi->pb.info.width>>4,16); - oggpackB_write(cpi->oggbuffer,cpi->pb.info.height>>4,16); - oggpackB_write(cpi->oggbuffer,cpi->pb.info.frame_width,24); - oggpackB_write(cpi->oggbuffer,cpi->pb.info.frame_height,24); - oggpackB_write(cpi->oggbuffer,cpi->pb.info.offset_x,8); - /* Applications use offset_y to mean offset from the top of the image; the - * meaning in the bitstream is the opposite (from the bottom). Transform. - */ - offset_y = cpi->pb.info.height - cpi->pb.info.frame_height - - cpi->pb.info.offset_y; - oggpackB_write(cpi->oggbuffer,offset_y,8); - - oggpackB_write(cpi->oggbuffer,cpi->pb.info.fps_numerator,32); - oggpackB_write(cpi->oggbuffer,cpi->pb.info.fps_denominator,32); - oggpackB_write(cpi->oggbuffer,cpi->pb.info.aspect_numerator,24); - oggpackB_write(cpi->oggbuffer,cpi->pb.info.aspect_denominator,24); - - oggpackB_write(cpi->oggbuffer,cpi->pb.info.colorspace,8); - oggpackB_write(cpi->oggbuffer,cpi->pb.info.target_bitrate,24); - oggpackB_write(cpi->oggbuffer,cpi->pb.info.quality,6); - - oggpackB_write(cpi->oggbuffer,cpi->pb.keyframe_granule_shift,5); - - oggpackB_write(cpi->oggbuffer,cpi->pb.info.pixelformat,2); - - oggpackB_write(cpi->oggbuffer,0,3); /* spare config bits */ - - op->packet=oggpackB_get_buffer(cpi->oggbuffer); - op->bytes=oggpackB_bytes(cpi->oggbuffer); - - op->b_o_s=1; - op->e_o_s=0; - - op->packetno=0; - - op->granulepos=0; - cpi->packetflag=0; - - return(0); -} - -/* build the comment header packet from the passed metadata */ -int theora_encode_comment(theora_comment *tc, ogg_packet *op) -{ - const char *vendor = theora_version_string(); - const int vendor_length = strlen(vendor); - oggpack_buffer *opb; - - opb = _ogg_malloc(sizeof(oggpack_buffer)); - oggpackB_writeinit(opb); - oggpackB_write(opb, 0x81, 8); - _tp_writebuffer(opb, "theora", 6); - - _tp_writelsbint(opb, vendor_length); - _tp_writebuffer(opb, vendor, vendor_length); - - _tp_writelsbint(opb, tc->comments); - if(tc->comments){ - int i; - for(i=0;icomments;i++){ - if(tc->user_comments[i]){ - _tp_writelsbint(opb,tc->comment_lengths[i]); - _tp_writebuffer(opb,tc->user_comments[i],tc->comment_lengths[i]); - }else{ - oggpackB_write(opb,0,32); - } - } - } - op->bytes=oggpack_bytes(opb); - - /* So we're expecting the application will free this? */ - op->packet=_ogg_malloc(oggpack_bytes(opb)); - memcpy(op->packet, oggpack_get_buffer(opb), oggpack_bytes(opb)); - oggpack_writeclear(opb); - - _ogg_free(opb); - - op->b_o_s=0; - op->e_o_s=0; - - op->packetno=0; - op->granulepos=0; - - return (0); -} - -/* build the final header packet with the tables required - for decode */ -int theora_encode_tables(theora_state *t, ogg_packet *op){ - CP_INSTANCE *cpi=(CP_INSTANCE *)(t->internal_encode); - - oggpackB_reset(cpi->oggbuffer); - oggpackB_write(cpi->oggbuffer,0x82,8); - _tp_writebuffer(cpi->oggbuffer,"theora",6); - - WriteQTables(&cpi->pb,cpi->oggbuffer); - WriteHuffmanTrees(cpi->pb.HuffRoot_VP3x,cpi->oggbuffer); - - op->packet=oggpackB_get_buffer(cpi->oggbuffer); - op->bytes=oggpackB_bytes(cpi->oggbuffer); - - op->b_o_s=0; - op->e_o_s=0; - - op->packetno=0; - - op->granulepos=0; - cpi->packetflag=0; - - cpi->pb.HeadersWritten = 1; - - return(0); -} - -static void theora_encode_clear (theora_state *th){ - CP_INSTANCE *cpi; - cpi=(CP_INSTANCE *)th->internal_encode; - if(cpi){ - - ClearHuffmanSet(&cpi->pb); - ClearFragmentInfo(&cpi->pb); - ClearFrameInfo(&cpi->pb); - EClearFragmentInfo(cpi); - EClearFrameInfo(cpi); - ClearTmpBuffers(&cpi->pb); - ClearPPInstance(&cpi->pp); - - oggpackB_writeclear(cpi->oggbuffer); - _ogg_free(cpi->oggbuffer); - _ogg_free(cpi); - } - - memset(th,0,sizeof(*th)); -} - - -/* returns, in seconds, absolute time of current packet in given - logical stream */ -static double theora_encode_granule_time(theora_state *th, - ogg_int64_t granulepos){ -#ifndef THEORA_DISABLE_FLOAT - CP_INSTANCE *cpi=(CP_INSTANCE *)(th->internal_encode); - PB_INSTANCE *pbi=(PB_INSTANCE *)(th->internal_decode); - - if(cpi)pbi=&cpi->pb; - - if(granulepos>=0){ - ogg_int64_t iframe=granulepos>>pbi->keyframe_granule_shift; - ogg_int64_t pframe=granulepos-(iframe<keyframe_granule_shift); - - return (iframe+pframe)* - ((double)pbi->info.fps_denominator/pbi->info.fps_numerator); - - } -#endif - - return(-1); /* negative granulepos or float calculations disabled */ -} - -/* returns frame number of current packet in given logical stream */ -static ogg_int64_t theora_encode_granule_frame(theora_state *th, - ogg_int64_t granulepos){ - CP_INSTANCE *cpi=(CP_INSTANCE *)(th->internal_encode); - PB_INSTANCE *pbi=(PB_INSTANCE *)(th->internal_decode); - - if(cpi)pbi=&cpi->pb; - - if(granulepos>=0){ - ogg_int64_t iframe=granulepos>>pbi->keyframe_granule_shift; - ogg_int64_t pframe=granulepos-(iframe<keyframe_granule_shift); - - return (iframe+pframe-1); - } - - return(-1); -} - - -static int theora_encode_control(theora_state *th,int req, - void *buf,size_t buf_sz) { - CP_INSTANCE *cpi; - PB_INSTANCE *pbi; - int value; - - if(th == NULL) - return TH_EFAULT; - - cpi = th->internal_encode; - pbi = &cpi->pb; - - switch(req) { - case TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE: - { - ogg_uint32_t keyframe_frequency_force; - if( (buf==NULL) || (buf_sz!=sizeof(ogg_uint32_t))) return TH_EINVAL; - keyframe_frequency_force=*(ogg_uint32_t *)buf; - - keyframe_frequency_force= - OC_MINI(keyframe_frequency_force, - 1U<pb.keyframe_granule_shift); - cpi->pb.info.keyframe_frequency_force= - OC_MAXI(1,keyframe_frequency_force); - *(ogg_uint32_t *)buf=cpi->pb.info.keyframe_frequency_force; - return 0; - } - case TH_ENCCTL_SET_QUANT_PARAMS: - if( ( buf==NULL&&buf_sz!=0 ) - || ( buf!=NULL&&buf_sz!=sizeof(th_quant_info) ) - || cpi->pb.HeadersWritten ){ - return TH_EINVAL; - } - - if(buf==NULL) - memcpy(&pbi->quant_info, &TH_VP31_QUANT_INFO, sizeof(th_quant_info)); - else - memcpy(&pbi->quant_info, buf, sizeof(th_quant_info)); - InitQTables(pbi); - - return 0; - case TH_ENCCTL_SET_VP3_COMPATIBLE: - if(cpi->pb.HeadersWritten) - return TH_EINVAL; - - memcpy(&pbi->quant_info, &TH_VP31_QUANT_INFO, sizeof(th_quant_info)); - InitQTables(pbi); - - return 0; - case TH_ENCCTL_SET_SPLEVEL: - if(buf == NULL || buf_sz != sizeof(int)) - return TH_EINVAL; - - memcpy(&value, buf, sizeof(int)); - - switch(value) { - case 0: - cpi->MotionCompensation = 1; - pbi->info.quick_p = 0; - break; - - case 1: - cpi->MotionCompensation = 1; - pbi->info.quick_p = 1; - break; - - case 2: - cpi->MotionCompensation = 0; - pbi->info.quick_p = 1; - break; - - default: - return TH_EINVAL; - } - - return 0; - case TH_ENCCTL_GET_SPLEVEL_MAX: - value = 2; - memcpy(buf, &value, sizeof(int)); - return 0; - default: - return TH_EIMPL; - } -} - -static void theora_encode_dispatch_init(CP_INSTANCE *cpi){ - cpi->dispatch_vtbl.clear=theora_encode_clear; - cpi->dispatch_vtbl.control=theora_encode_control; - cpi->dispatch_vtbl.granule_frame=theora_encode_granule_frame; - cpi->dispatch_vtbl.granule_time=theora_encode_granule_time; -} diff --git a/Engine/lib/libtheora/lib/enc/frarray.c b/Engine/lib/libtheora/lib/enc/frarray.c deleted file mode 100644 index 51b327206..000000000 --- a/Engine/lib/libtheora/lib/enc/frarray.c +++ /dev/null @@ -1,243 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: frarray.c 15153 2008-08-04 18:37:55Z tterribe $ - - ********************************************************************/ - -#include -#include "codec_internal.h" -#include "block_inline.h" - -/* Long run bit string coding */ -static ogg_uint32_t FrArrayCodeSBRun( CP_INSTANCE *cpi, ogg_uint32_t value){ - ogg_uint32_t CodedVal = 0; - ogg_uint32_t CodedBits = 0; - - /* Coding scheme: - Codeword RunLength - 0 1 - 10x 2-3 - 110x 4-5 - 1110xx 6-9 - 11110xxx 10-17 - 111110xxxx 18-33 - 111111xxxxxxxxxxxx 34-4129 */ - - if ( value == 1 ){ - CodedVal = 0; - CodedBits = 1; - } else if ( value <= 3 ) { - CodedVal = 0x0004 + (value - 2); - CodedBits = 3; - } else if ( value <= 5 ) { - CodedVal = 0x000C + (value - 4); - CodedBits = 4; - } else if ( value <= 9 ) { - CodedVal = 0x0038 + (value - 6); - CodedBits = 6; - } else if ( value <= 17 ) { - CodedVal = 0x00F0 + (value - 10); - CodedBits = 8; - } else if ( value <= 33 ) { - CodedVal = 0x03E0 + (value - 18); - CodedBits = 10; - } else { - CodedVal = 0x3F000 + (value - 34); - CodedBits = 18; - } - - /* Add the bits to the encode holding buffer. */ - oggpackB_write( cpi->oggbuffer, CodedVal, CodedBits ); - - return CodedBits; -} - -/* Short run bit string coding */ -static ogg_uint32_t FrArrayCodeBlockRun( CP_INSTANCE *cpi, - ogg_uint32_t value ) { - ogg_uint32_t CodedVal = 0; - ogg_uint32_t CodedBits = 0; - - /* Coding scheme: - Codeword RunLength - 0x 1-2 - 10x 3-4 - 110x 5-6 - 1110xx 7-10 - 11110xx 11-14 - 11111xxxx 15-30 */ - - if ( value <= 2 ) { - CodedVal = value - 1; - CodedBits = 2; - } else if ( value <= 4 ) { - CodedVal = 0x0004 + (value - 3); - CodedBits = 3; - - } else if ( value <= 6 ) { - CodedVal = 0x000C + (value - 5); - CodedBits = 4; - - } else if ( value <= 10 ) { - CodedVal = 0x0038 + (value - 7); - CodedBits = 6; - - } else if ( value <= 14 ) { - CodedVal = 0x0078 + (value - 11); - CodedBits = 7; - } else { - CodedVal = 0x01F0 + (value - 15); - CodedBits = 9; - } - - /* Add the bits to the encode holding buffer. */ - oggpackB_write( cpi->oggbuffer, CodedVal, CodedBits ); - - return CodedBits; -} - -void PackAndWriteDFArray( CP_INSTANCE *cpi ){ - ogg_uint32_t i; - unsigned char val; - ogg_uint32_t run_count; - - ogg_uint32_t SB, MB, B; /* Block, MB and SB loop variables */ - ogg_uint32_t BListIndex = 0; - ogg_uint32_t LastSbBIndex = 0; - ogg_int32_t DfBlockIndex; /* Block index in display_fragments */ - - /* Initialise workspaces */ - memset( cpi->pb.SBFullyFlags, 1, cpi->pb.SuperBlocks); - memset( cpi->pb.SBCodedFlags, 0, cpi->pb.SuperBlocks ); - memset( cpi->PartiallyCodedFlags, 0, cpi->pb.SuperBlocks ); - memset( cpi->BlockCodedFlags, 0, cpi->pb.UnitFragments); - - for( SB = 0; SB < cpi->pb.SuperBlocks; SB++ ) { - /* Check for coded blocks and macro-blocks */ - for ( MB=0; MB<4; MB++ ) { - /* If MB in frame */ - if ( QuadMapToMBTopLeft(cpi->pb.BlockMap,SB,MB) >= 0 ) { - for ( B=0; B<4; B++ ) { - DfBlockIndex = QuadMapToIndex1( cpi->pb.BlockMap,SB, MB, B ); - - /* Does Block lie in frame: */ - if ( DfBlockIndex >= 0 ) { - /* In Frame: If it is not coded then this SB is only - partly coded.: */ - if ( cpi->pb.display_fragments[DfBlockIndex] ) { - cpi->pb.SBCodedFlags[SB] = 1; /* SB at least partly coded */ - cpi->BlockCodedFlags[BListIndex] = 1; /* Block is coded */ - - }else{ - cpi->pb.SBFullyFlags[SB] = 0; /* SB not fully coded */ - cpi->BlockCodedFlags[BListIndex] = 0; /* Block is not coded */ - } - - BListIndex++; - } - } - } - } - - /* Is the SB fully coded or uncoded. - If so then backup BListIndex and MBListIndex */ - if ( cpi->pb.SBFullyFlags[SB] || !cpi->pb.SBCodedFlags[SB] ) { - BListIndex = LastSbBIndex; /* Reset to values from previous SB */ - }else{ - cpi->PartiallyCodedFlags[SB] = 1; /* Set up list of partially - coded SBs */ - LastSbBIndex = BListIndex; - } - } - - /* Code list of partially coded Super-Block. */ - val = cpi->PartiallyCodedFlags[0]; - oggpackB_write( cpi->oggbuffer, (ogg_uint32_t)val, 1); - - i = 0; - while ( i < cpi->pb.SuperBlocks ) { - run_count = 0; - while ( (ipb.SuperBlocks) && - (cpi->PartiallyCodedFlags[i]==val) && - run_count<4129 ) { - i++; - run_count++; - } - - /* Code the run */ - FrArrayCodeSBRun( cpi, run_count); - - if(run_count >= 4129 && i < cpi->pb.SuperBlocks ){ - val = cpi->PartiallyCodedFlags[i]; - oggpackB_write( cpi->oggbuffer, (ogg_uint32_t)val, 1); - - }else - val = ( val == 0 ) ? 1 : 0; - } - - /* RLC Super-Block fully/not coded. */ - i = 0; - - /* Skip partially coded blocks */ - while( (i < cpi->pb.SuperBlocks) && cpi->PartiallyCodedFlags[i] ) - i++; - - if ( i < cpi->pb.SuperBlocks ) { - val = cpi->pb.SBFullyFlags[i]; - oggpackB_write( cpi->oggbuffer, (ogg_uint32_t)val, 1); - - while ( i < cpi->pb.SuperBlocks ) { - run_count = 0; - while ( (i < cpi->pb.SuperBlocks) && - (cpi->pb.SBFullyFlags[i] == val) && - run_count < 4129) { - i++; - /* Skip partially coded blocks */ - while( (i < cpi->pb.SuperBlocks) && cpi->PartiallyCodedFlags[i] ) - i++; - run_count++; - } - - /* Code the run */ - FrArrayCodeSBRun( cpi, run_count ); - - if(run_count >= 4129 && i < cpi->pb.SuperBlocks ){ - val = cpi->PartiallyCodedFlags[i]; - oggpackB_write( cpi->oggbuffer, (ogg_uint32_t)val, 1); - }else - val = ( val == 0 ) ? 1 : 0; - } - } - - - /* Now code the block flags */ - if ( BListIndex > 0 ) { - /* Code the block flags start value */ - val = cpi->BlockCodedFlags[0]; - oggpackB_write( cpi->oggbuffer, (ogg_uint32_t)val, 1); - - /* Now code the block flags. */ - for ( i = 0; i < BListIndex; ) { - run_count = 0; - while ( (i < BListIndex) && (cpi->BlockCodedFlags[i] == val) ) { - i++; - run_count++; - } - - FrArrayCodeBlockRun( cpi, run_count ); - - val = ( val == 0 ) ? 1 : 0; - } - } -} diff --git a/Engine/lib/libtheora/lib/enc/frinit.c b/Engine/lib/libtheora/lib/enc/frinit.c deleted file mode 100644 index ae6bbd64f..000000000 --- a/Engine/lib/libtheora/lib/enc/frinit.c +++ /dev/null @@ -1,392 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: frinit.c 15153 2008-08-04 18:37:55Z tterribe $ - - ********************************************************************/ - -#include -#include "codec_internal.h" - - -void InitializeFragCoordinates(PB_INSTANCE *pbi){ - - ogg_uint32_t i, j; - - ogg_uint32_t HorizFrags = pbi->HFragments; - ogg_uint32_t VertFrags = pbi->VFragments; - ogg_uint32_t StartFrag = 0; - - /* Y */ - - for(i = 0; i< VertFrags; i++){ - for(j = 0; j< HorizFrags; j++){ - - ogg_uint32_t ThisFrag = i * HorizFrags + j; - pbi->FragCoordinates[ ThisFrag ].x=j * BLOCK_HEIGHT_WIDTH; - pbi->FragCoordinates[ ThisFrag ].y=i * BLOCK_HEIGHT_WIDTH; - - } - } - - /* U */ - HorizFrags >>= 1; - VertFrags >>= 1; - StartFrag = pbi->YPlaneFragments; - - for(i = 0; i< VertFrags; i++) { - for(j = 0; j< HorizFrags; j++) { - ogg_uint32_t ThisFrag = StartFrag + i * HorizFrags + j; - pbi->FragCoordinates[ ThisFrag ].x=j * BLOCK_HEIGHT_WIDTH; - pbi->FragCoordinates[ ThisFrag ].y=i * BLOCK_HEIGHT_WIDTH; - - } - } - - /* V */ - StartFrag = pbi->YPlaneFragments + pbi->UVPlaneFragments; - for(i = 0; i< VertFrags; i++) { - for(j = 0; j< HorizFrags; j++) { - ogg_uint32_t ThisFrag = StartFrag + i * HorizFrags + j; - pbi->FragCoordinates[ ThisFrag ].x=j * BLOCK_HEIGHT_WIDTH; - pbi->FragCoordinates[ ThisFrag ].y=i * BLOCK_HEIGHT_WIDTH; - - } - } -} - -static void CalcPixelIndexTable( PB_INSTANCE *pbi){ - ogg_uint32_t i; - ogg_uint32_t * PixelIndexTablePtr; - - /* Calculate the pixel index table for normal image buffers */ - PixelIndexTablePtr = pbi->pixel_index_table; - for ( i = 0; i < pbi->YPlaneFragments; i++ ) { - PixelIndexTablePtr[ i ] = - ((i / pbi->HFragments) * VFRAGPIXELS * - pbi->info.width); - PixelIndexTablePtr[ i ] += - ((i % pbi->HFragments) * HFRAGPIXELS); - } - - PixelIndexTablePtr = &pbi->pixel_index_table[pbi->YPlaneFragments]; - for ( i = 0; i < ((pbi->HFragments >> 1) * pbi->VFragments); i++ ) { - PixelIndexTablePtr[ i ] = - ((i / (pbi->HFragments / 2) ) * - (VFRAGPIXELS * - (pbi->info.width / 2)) ); - PixelIndexTablePtr[ i ] += - ((i % (pbi->HFragments / 2) ) * - HFRAGPIXELS) + pbi->YPlaneSize; - } - - /************************************************************************/ - /* Now calculate the pixel index table for image reconstruction buffers */ - PixelIndexTablePtr = pbi->recon_pixel_index_table; - for ( i = 0; i < pbi->YPlaneFragments; i++ ){ - PixelIndexTablePtr[ i ] = - ((i / pbi->HFragments) * VFRAGPIXELS * - pbi->YStride); - PixelIndexTablePtr[ i ] += - ((i % pbi->HFragments) * HFRAGPIXELS) + - pbi->ReconYDataOffset; - } - - /* U blocks */ - PixelIndexTablePtr = &pbi->recon_pixel_index_table[pbi->YPlaneFragments]; - for ( i = 0; i < pbi->UVPlaneFragments; i++ ) { - PixelIndexTablePtr[ i ] = - ((i / (pbi->HFragments / 2) ) * - (VFRAGPIXELS * (pbi->UVStride)) ); - PixelIndexTablePtr[ i ] += - ((i % (pbi->HFragments / 2) ) * - HFRAGPIXELS) + pbi->ReconUDataOffset; - } - - /* V blocks */ - PixelIndexTablePtr = - &pbi->recon_pixel_index_table[pbi->YPlaneFragments + - pbi->UVPlaneFragments]; - - for ( i = 0; i < pbi->UVPlaneFragments; i++ ) { - PixelIndexTablePtr[ i ] = - ((i / (pbi->HFragments / 2) ) * - (VFRAGPIXELS * (pbi->UVStride)) ); - PixelIndexTablePtr[ i ] += - ((i % (pbi->HFragments / 2) ) * HFRAGPIXELS) + - pbi->ReconVDataOffset; - } -} - -void ClearFragmentInfo(PB_INSTANCE * pbi){ - - /* free prior allocs if present */ - if(pbi->display_fragments) _ogg_free(pbi->display_fragments); - if(pbi->pixel_index_table) _ogg_free(pbi->pixel_index_table); - if(pbi->recon_pixel_index_table) _ogg_free(pbi->recon_pixel_index_table); - if(pbi->FragTokenCounts) _ogg_free(pbi->FragTokenCounts); - if(pbi->CodedBlockList) _ogg_free(pbi->CodedBlockList); - if(pbi->FragMVect) _ogg_free(pbi->FragMVect); - if(pbi->FragCoeffs) _ogg_free(pbi->FragCoeffs); - if(pbi->FragCoefEOB) _ogg_free(pbi->FragCoefEOB); - if(pbi->skipped_display_fragments) _ogg_free(pbi->skipped_display_fragments); - if(pbi->QFragData) _ogg_free(pbi->QFragData); - if(pbi->TokenList) _ogg_free(pbi->TokenList); - if(pbi->FragCodingMethod) _ogg_free(pbi->FragCodingMethod); - if(pbi->FragCoordinates) _ogg_free(pbi->FragCoordinates); - - if(pbi->FragQIndex) _ogg_free(pbi->FragQIndex); - if(pbi->PPCoefBuffer) _ogg_free(pbi->PPCoefBuffer); - if(pbi->FragmentVariances) _ogg_free(pbi->FragmentVariances); - - if(pbi->BlockMap) _ogg_free(pbi->BlockMap); - - if(pbi->SBCodedFlags) _ogg_free(pbi->SBCodedFlags); - if(pbi->SBFullyFlags) _ogg_free(pbi->SBFullyFlags); - if(pbi->MBFullyFlags) _ogg_free(pbi->MBFullyFlags); - if(pbi->MBCodedFlags) _ogg_free(pbi->MBCodedFlags); - - if(pbi->_Nodes) _ogg_free(pbi->_Nodes); - pbi->_Nodes = 0; - - pbi->QFragData = 0; - pbi->TokenList = 0; - pbi->skipped_display_fragments = 0; - pbi->FragCoeffs = 0; - pbi->FragCoefEOB = 0; - pbi->display_fragments = 0; - pbi->pixel_index_table = 0; - pbi->recon_pixel_index_table = 0; - pbi->FragTokenCounts = 0; - pbi->CodedBlockList = 0; - pbi->FragCodingMethod = 0; - pbi->FragMVect = 0; - pbi->MBCodedFlags = 0; - pbi->MBFullyFlags = 0; - pbi->BlockMap = 0; - - pbi->SBCodedFlags = 0; - pbi->SBFullyFlags = 0; - pbi->QFragData = 0; - pbi->TokenList = 0; - pbi->skipped_display_fragments = 0; - pbi->FragCoeffs = 0; - pbi->FragCoefEOB = 0; - pbi->display_fragments = 0; - pbi->pixel_index_table = 0; - pbi->recon_pixel_index_table = 0; - pbi->FragTokenCounts = 0; - pbi->CodedBlockList = 0; - pbi->FragCodingMethod = 0; - pbi->FragCoordinates = 0; - pbi->FragMVect = 0; - - pbi->PPCoefBuffer=0; - pbi->PPCoefBuffer=0; - pbi->FragQIndex = 0; - pbi->FragQIndex = 0; - pbi->FragmentVariances= 0; - pbi->FragmentVariances = 0 ; -} - -void InitFragmentInfo(PB_INSTANCE * pbi){ - - /* clear any existing info */ - ClearFragmentInfo(pbi); - - /* Perform Fragment Allocations */ - pbi->display_fragments = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->display_fragments)); - - pbi->pixel_index_table = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->pixel_index_table)); - - pbi->recon_pixel_index_table = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->recon_pixel_index_table)); - - pbi->FragTokenCounts = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragTokenCounts)); - - pbi->CodedBlockList = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->CodedBlockList)); - - pbi->FragMVect = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragMVect)); - - pbi->FragCoeffs = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragCoeffs)); - - pbi->FragCoefEOB = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragCoefEOB)); - - pbi->skipped_display_fragments = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->skipped_display_fragments)); - - pbi->QFragData = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->QFragData)); - - pbi->TokenList = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->TokenList)); - - pbi->FragCodingMethod = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragCodingMethod)); - - pbi->FragCoordinates = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragCoordinates)); - - pbi->FragQIndex = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragQIndex)); - - pbi->PPCoefBuffer = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->PPCoefBuffer)); - - pbi->FragmentVariances = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragmentVariances)); - - pbi->_Nodes = - _ogg_malloc(pbi->UnitFragments * sizeof(*pbi->_Nodes)); - - /* Super Block Initialization */ - pbi->SBCodedFlags = - _ogg_malloc(pbi->SuperBlocks * sizeof(*pbi->SBCodedFlags)); - - pbi->SBFullyFlags = - _ogg_malloc(pbi->SuperBlocks * sizeof(*pbi->SBFullyFlags)); - - /* Macro Block Initialization */ - pbi->MBCodedFlags = - _ogg_malloc(pbi->MacroBlocks * sizeof(*pbi->MBCodedFlags)); - - pbi->MBFullyFlags = - _ogg_malloc(pbi->MacroBlocks * sizeof(*pbi->MBFullyFlags)); - - pbi->BlockMap = - _ogg_malloc(pbi->SuperBlocks * sizeof(*pbi->BlockMap)); - -} - -void ClearFrameInfo(PB_INSTANCE * pbi){ - if(pbi->ThisFrameRecon ) - _ogg_free(pbi->ThisFrameRecon ); - if(pbi->GoldenFrame) - _ogg_free(pbi->GoldenFrame); - if(pbi->LastFrameRecon) - _ogg_free(pbi->LastFrameRecon); - if(pbi->PostProcessBuffer) - _ogg_free(pbi->PostProcessBuffer); - - - pbi->ThisFrameRecon = 0; - pbi->GoldenFrame = 0; - pbi->LastFrameRecon = 0; - pbi->PostProcessBuffer = 0; - - - pbi->ThisFrameRecon = 0; - pbi->GoldenFrame = 0; - pbi->LastFrameRecon = 0; - pbi->PostProcessBuffer = 0; - -} - -void InitFrameInfo(PB_INSTANCE * pbi, unsigned int FrameSize){ - - /* clear any existing info */ - ClearFrameInfo(pbi); - - /* allocate frames */ - pbi->ThisFrameRecon = - _ogg_malloc(FrameSize*sizeof(*pbi->ThisFrameRecon)); - - pbi->GoldenFrame = - _ogg_malloc(FrameSize*sizeof(*pbi->GoldenFrame)); - - pbi->LastFrameRecon = - _ogg_malloc(FrameSize*sizeof(*pbi->LastFrameRecon)); - - pbi->PostProcessBuffer = - _ogg_malloc(FrameSize*sizeof(*pbi->PostProcessBuffer)); - -} - -void InitFrameDetails(PB_INSTANCE *pbi){ - int FrameSize; - - /*pbi->PostProcessingLevel = 0; - pbi->PostProcessingLevel = 4; - pbi->PostProcessingLevel = 5; - pbi->PostProcessingLevel = 6;*/ - - pbi->PostProcessingLevel = 0; - - - /* Set the frame size etc. */ - - pbi->YPlaneSize = pbi->info.width * - pbi->info.height; - pbi->UVPlaneSize = pbi->YPlaneSize / 4; - pbi->HFragments = pbi->info.width / HFRAGPIXELS; - pbi->VFragments = pbi->info.height / VFRAGPIXELS; - pbi->UnitFragments = ((pbi->VFragments * pbi->HFragments)*3)/2; - pbi->YPlaneFragments = pbi->HFragments * pbi->VFragments; - pbi->UVPlaneFragments = pbi->YPlaneFragments / 4; - - pbi->YStride = (pbi->info.width + STRIDE_EXTRA); - pbi->UVStride = pbi->YStride / 2; - pbi->ReconYPlaneSize = pbi->YStride * - (pbi->info.height + STRIDE_EXTRA); - pbi->ReconUVPlaneSize = pbi->ReconYPlaneSize / 4; - FrameSize = pbi->ReconYPlaneSize + 2 * pbi->ReconUVPlaneSize; - - pbi->YDataOffset = 0; - pbi->UDataOffset = pbi->YPlaneSize; - pbi->VDataOffset = pbi->YPlaneSize + pbi->UVPlaneSize; - pbi->ReconYDataOffset = - (pbi->YStride * UMV_BORDER) + UMV_BORDER; - pbi->ReconUDataOffset = pbi->ReconYPlaneSize + - (pbi->UVStride * (UMV_BORDER/2)) + (UMV_BORDER/2); - pbi->ReconVDataOffset = pbi->ReconYPlaneSize + pbi->ReconUVPlaneSize + - (pbi->UVStride * (UMV_BORDER/2)) + (UMV_BORDER/2); - - /* Image dimensions in Super-Blocks */ - pbi->YSBRows = (pbi->info.height/32) + - ( pbi->info.height%32 ? 1 : 0 ); - pbi->YSBCols = (pbi->info.width/32) + - ( pbi->info.width%32 ? 1 : 0 ); - pbi->UVSBRows = ((pbi->info.height/2)/32) + - ( (pbi->info.height/2)%32 ? 1 : 0 ); - pbi->UVSBCols = ((pbi->info.width/2)/32) + - ( (pbi->info.width/2)%32 ? 1 : 0 ); - - /* Super-Blocks per component */ - pbi->YSuperBlocks = pbi->YSBRows * pbi->YSBCols; - pbi->UVSuperBlocks = pbi->UVSBRows * pbi->UVSBCols; - pbi->SuperBlocks = pbi->YSuperBlocks+2*pbi->UVSuperBlocks; - - /* Useful externals */ - pbi->MacroBlocks = ((pbi->VFragments+1)/2)*((pbi->HFragments+1)/2); - - InitFragmentInfo(pbi); - InitFrameInfo(pbi, FrameSize); - InitializeFragCoordinates(pbi); - - /* Configure mapping between quad-tree and fragments */ - CreateBlockMapping ( pbi->BlockMap, pbi->YSuperBlocks, - pbi->UVSuperBlocks, pbi->HFragments, pbi->VFragments); - - /* Re-initialise the pixel index table. */ - - CalcPixelIndexTable( pbi ); - -} - diff --git a/Engine/lib/libtheora/lib/enc/hufftables.h b/Engine/lib/libtheora/lib/enc/hufftables.h deleted file mode 100644 index eb4be22c2..000000000 --- a/Engine/lib/libtheora/lib/enc/hufftables.h +++ /dev/null @@ -1,1034 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: hufftables.h 13884 2007-09-22 08:38:10Z giles $ - - ********************************************************************/ - -#include "../dec/huffman.h" -#include "codec_internal.h" - -const unsigned char ExtraBitLengths_VP31[MAX_ENTROPY_TOKENS] = { - 0, 0, 0, 2, 3, 4, 12,3, 6, /* EOB and Zero-run tokens. */ - 0, 0, 0, 0, /* Very low value tokens. */ - 1, 1, 1, 1, 2, 3, 4, 5, 6, 10, /* Other value tokens */ - 1, 1, 1, 1, 1, 3, 4, /* Category 1 runs. */ - 2, 3, /* Category 2 runs. */ -}; - -#define NEW_FREQS 0 /* dbm - test new frequency tables */ - -#if NEW_FREQS -/* New baseline frequency tables for encoder version >= 2 */ -const ogg_uint32_t FrequencyCounts_VP3[NUM_HUFF_TABLES][MAX_ENTROPY_TOKENS] = { - /* DC Intra bias */ - { 272, 84, 31, 36, 10, 2, 1, 92, 1, - 701, 872, 410, 478, - 630, 502, 417, 356, 582, 824, 985, 965, 697, 606, - 125, 119, 40, 3, 9, 15, 10, - 73, 37, - }, - { 311, 107, 41, 51, 18, 4, 2, 120, 1, - 824, 1037, 468, 541, - 714, 555, 451, 374, 595, 819, 929, 817, 474, 220, - 172, 142, 27, 4, 9, 10, 2, - 98, 48, - }, - { 353, 125, 49, 66, 24, 6, 2, 124, 1, - 926, 1172, 512, 594, - 766, 581, 458, 379, 590, 789, 849, 665, 306, 80, - 204, 147, 25, 5, 12, 9, 2, - 108, 54, - }, - { 392, 141, 57, 75, 31, 7, 4, 138, 1, - 1050, 1321, 559, 649, - 806, 594, 460, 372, 568, 727, 710, 475, 155, 19, - 251, 174, 27, 7, 16, 8, 2, - 126, 62, - }, - { 455, 168, 66, 87, 39, 10, 6, 124, 2, - 1143, 1455, 592, 692, - 824, 596, 453, 361, 542, 657, 592, 329, 78, 5, - 269, 184, 27, 9, 19, 7, 2, - 127, 66, - }, - { 544, 201, 80, 102, 45, 11, 6, 99, 1, - 1236, 1587, 610, 720, - 833, 590, 444, 348, 506, 588, 487, 226, 39, 2, - 253, 178, 27, 10, 20, 7, 2, - 118, 65, - }, - { 649, 241, 98, 121, 54, 14, 8, 84, 1, - 1349, 1719, 634, 763, - 847, 583, 428, 323, 456, 492, 349, 120, 13, 1, - 231, 170, 24, 8, 19, 7, 1, - 109, 67, - }, - { 824, 304, 129, 158, 66, 19, 10, 44, 2, - 1476, 1925, 644, 794, - 838, 559, 396, 289, 392, 384, 223, 53, 3, 1, - 159, 121, 17, 6, 16, 6, 2, - 69, 53, - }, - - /* DC Inter Bias */ - { 534, 174, 71, 68, 10, 1, 1, 68, 119, - 1674, 1526, 560, 536, - 539, 331, 229, 168, 233, 262, 231, 149, 71, 51, - 629, 530, 284, 126, 182, 208, 184, - 148, 87, - }, - { 594, 195, 77, 71, 9, 1, 1, 47, 89, - 1723, 1592, 595, 570, - 574, 351, 241, 176, 243, 271, 234, 144, 65, 37, - 534, 449, 240, 117, 167, 277, 153, - 96, 54, - }, - { 642, 213, 88, 83, 12, 1, 1, 40, 80, - 1751, 1630, 621, 600, - 598, 367, 250, 183, 251, 276, 235, 143, 62, 28, - 485, 397, 212, 110, 161, 193, 141, - 84, 48, - }, - { 693, 258, 114, 131, 27, 3, 1, 44, 79, - 1794, 1644, 550, 533, - 518, 314, 213, 154, 209, 223, 174, 97, 40, 14, - 584, 463, 236, 138, 196, 249, 143, - 94, 54, - }, - { 758, 303, 144, 189, 53, 8, 1, 37, 69, - 1842, 1732, 513, 504, - 478, 287, 191, 137, 182, 186, 137, 72, 31, 6, - 589, 469, 199, 128, 177, 264, 161, - 89, 49, - }, - { 817, 344, 170, 243, 84, 18, 2, 30, 65, - 1836, 1733, 518, 511, - 477, 281, 185, 130, 169, 166, 117, 59, 25, 3, - 572, 450, 185, 121, 173, 232, 146, - 80, 43, - }, - { 865, 389, 204, 322, 139, 42, 9, 26, 51, - 1848, 1766, 531, 522, - 477, 275, 177, 122, 153, 144, 97, 50, 16, 1, - 485, 378, 167, 115, 164, 203, 128, - 74, 42, - }, - { 961, 447, 243, 407, 196, 74, 26, 12, 34, - 2003, 1942, 571, 565, - 494, 278, 173, 116, 141, 129, 85, 44, 8, 1, - 285, 223, 101, 66, 104, 120, 74, - 35, 22, - }, - - /* AC INTRA Tables */ - /* AC Intra bias group 1 tables */ - { 245, 68, 25, 28, 5, 1, 1, 359, 4, - 910, 904, 570, 571, - 766, 620, 478, 375, 554, 684, 652, 441, 182, 30, - 535, 206, 118, 77, 69, 90, 16, - 299, 100, - }, - { 302, 86, 32, 36, 8, 1, 1, 362, 3, - 974, 968, 599, 599, - 774, 635, 469, 365, 528, 628, 557, 337, 118, 14, - 577, 219, 136, 82, 69, 65, 13, - 317, 112, - }, - { 348, 102, 39, 44, 9, 2, 1, 363, 3, - 1062, 1055, 607, 609, - 787, 626, 457, 348, 494, 550, 452, 233, 60, 2, - 636, 244, 159, 92, 74, 68, 12, - 327, 119, - }, - { 400, 121, 47, 51, 11, 2, 1, 366, 3, - 1109, 1102, 620, 622, - 786, 624, 450, 331, 459, 490, 366, 163, 29, 1, - 673, 257, 175, 98, 77, 63, 14, - 344, 131, - }, - { 470, 151, 59, 67, 15, 3, 1, 354, 4, - 1198, 1189, 640, 643, - 769, 603, 410, 294, 386, 381, 240, 78, 5, 1, - 746, 282, 205, 113, 87, 64, 15, - 368, 145, - }, - { 553, 189, 77, 94, 24, 6, 1, 347, 4, - 1244, 1232, 650, 653, - 739, 551, 360, 249, 303, 261, 129, 24, 1, 1, - 828, 313, 245, 135, 108, 77, 17, - 403, 169, - }, - { 701, 253, 109, 140, 42, 12, 2, 350, 6, - 1210, 1197, 652, 647, - 673, 495, 299, 189, 211, 151, 50, 2, 1, 1, - 892, 336, 284, 162, 134, 101, 25, - 455, 205, - }, - { 924, 390, 180, 248, 85, 31, 13, 286, 14, - 1242, 1206, 601, 577, - 519, 342, 175, 100, 85, 36, 1, 1, 1, 1, - 1031, 348, 346, 204, 166, 131, 34, - 473, 197, - }, - /* AC Inter bias group 1 tables */ - { 459, 128, 50, 48, 8, 1, 1, 224, 69, - 1285, 1227, 587, 565, - 573, 406, 261, 180, 228, 213, 130, 47, 11, 3, - 1069, 540, 309, 231, 147, 279, 157, - 383, 165, - }, - { 524, 155, 62, 64, 14, 2, 1, 209, 63, - 1345, 1288, 523, 507, - 515, 358, 225, 153, 183, 160, 87, 29, 7, 2, - 1151, 591, 365, 282, 179, 308, 133, - 344, 157, - }, - { 588, 181, 75, 81, 19, 3, 1, 204, 68, - 1344, 1288, 517, 503, - 505, 346, 216, 141, 169, 139, 71, 21, 5, 1, - 1146, 584, 366, 286, 170, 298, 153, - 342, 157, - }, - { 634, 196, 82, 89, 22, 4, 1, 194, 60, - 1356, 1312, 515, 502, - 489, 331, 199, 127, 145, 111, 51, 14, 3, 1, - 1156, 589, 393, 300, 182, 285, 144, - 340, 159, - }, - { 715, 231, 98, 113, 31, 7, 1, 181, 57, - 1345, 1303, 498, 490, - 448, 291, 166, 101, 106, 75, 30, 9, 1, 1, - 1175, 584, 416, 321, 209, 333, 164, - 330, 159, - }, - { 825, 283, 125, 149, 44, 11, 2, 160, 59, - 1343, 1308, 476, 469, - 405, 247, 131, 75, 76, 47, 18, 5, 1, 1, - 1192, 579, 432, 332, 217, 327, 176, - 320, 154, - }, - { 961, 361, 170, 215, 70, 20, 5, 161, 55, - 1250, 1218, 463, 460, - 354, 204, 101, 52, 48, 28, 11, 1, 1, 1, - 1172, 570, 449, 350, 222, 332, 169, - 338, 174, - }, - { 1139, 506, 266, 387, 156, 57, 26, 114, 48, - 1192, 1170, 366, 366, - 226, 113, 47, 22, 22, 12, 1, 1, 1, 1, - 1222, 551, 462, 391, 220, 322, 156, - 290, 136, - }, - - /* AC Intra bias group 2 tables */ - { 245, 49, 15, 11, 1, 1, 1, 332, 38, - 1163, 1162, 685, 683, - 813, 623, 437, 318, 421, 424, 288, 109, 14, 1, - 729, 303, 179, 112, 87, 199, 46, - 364, 135, - }, - { 305, 67, 22, 17, 2, 1, 1, 329, 39, - 1250, 1245, 706, 705, - 801, 584, 385, 267, 330, 296, 165, 40, 3, 1, - 798, 340, 206, 131, 108, 258, 52, - 382, 154, - }, - { 356, 82, 28, 23, 3, 1, 1, 312, 42, - 1340, 1334, 701, 703, - 770, 545, 346, 227, 269, 223, 100, 17, 1, 1, - 846, 359, 222, 142, 120, 284, 55, - 379, 157, - }, - { 402, 95, 33, 30, 4, 1, 1, 300, 43, - 1379, 1371, 710, 714, - 724, 486, 289, 182, 202, 144, 47, 5, 1, 1, - 908, 394, 250, 161, 141, 350, 60, - 391, 171, - }, - { 499, 122, 44, 42, 7, 1, 1, 267, 45, - 1439, 1436, 690, 694, - 628, 385, 213, 122, 117, 62, 14, 1, 1, 1, - 992, 441, 288, 187, 167, 446, 82, - 378, 176, - }, - { 641, 168, 62, 60, 12, 1, 1, 247, 49, - 1435, 1436, 662, 669, - 527, 298, 142, 71, 55, 22, 3, 1, 1, 1, - 1036, 470, 319, 208, 193, 548, 106, - 362, 184, - }, - { 860, 274, 111, 113, 23, 4, 1, 229, 59, - 1331, 1323, 629, 645, - 419, 192, 72, 30, 19, 6, 1, 1, 1, 1, - 1022, 478, 339, 225, 213, 690, 142, - 342, 198, - }, - { 1059, 437, 218, 285, 84, 17, 2, 152, 44, - 1284, 1313, 530, 561, - 212, 66, 17, 6, 3, 1, 1, 1, 1, 1, - 1034, 485, 346, 226, 207, 819, 185, - 248, 145, - }, - /* AC Inter bias group 2 tables */ - { 407, 93, 31, 24, 2, 1, 1, 232, 108, - 1365, 1349, 581, 578, - 498, 305, 170, 100, 103, 67, 24, 5, 1, 1, - 1175, 604, 393, 268, 209, 506, 217, - 379, 193, - }, - { 521, 129, 46, 39, 4, 1, 1, 199, 116, - 1419, 1403, 543, 540, - 446, 263, 138, 78, 75, 44, 13, 2, 1, 1, - 1201, 605, 392, 267, 214, 533, 252, - 334, 167, - }, - { 575, 144, 52, 46, 6, 1, 1, 193, 124, - 1394, 1384, 528, 528, - 406, 227, 112, 59, 54, 28, 7, 1, 1, 1, - 1210, 621, 412, 284, 235, 604, 265, - 320, 167, - }, - { 673, 174, 64, 59, 9, 1, 1, 177, 128, - 1392, 1385, 499, 499, - 352, 183, 85, 42, 35, 16, 3, 1, 1, 1, - 1210, 626, 418, 289, 246, 675, 297, - 292, 158, - }, - { 804, 225, 85, 77, 12, 1, 1, 150, 129, - 1387, 1384, 455, 455, - 277, 129, 53, 23, 17, 7, 1, 1, 1, 1, - 1212, 635, 433, 306, 268, 760, 313, - 249, 137, - }, - { 975, 305, 123, 117, 20, 2, 1, 135, 140, - 1312, 1310, 401, 399, - 201, 80, 28, 11, 8, 2, 1, 1, 1, 1, - 1162, 623, 439, 314, 283, 906, 368, - 203, 121, - }, - { 1205, 452, 208, 231, 50, 6, 1, 123, 149, - 1161, 1164, 370, 370, - 137, 45, 14, 4, 2, 1, 1, 1, 1, 1, - 1047, 562, 413, 300, 277, 1020, 404, - 168, 105, - }, - { 1297, 662, 389, 574, 200, 39, 4, 55, 120, - 1069, 1076, 273, 265, - 66, 14, 2, 1, 1, 1, 1, 1, 1, 1, - 930, 475, 345, 249, 236, 1124, 376, - 91, 56, - }, - - /* AC Intra bias group 3 tables */ - { 278, 55, 17, 12, 1, 1, 1, 288, 71, - 1315, 1304, 725, 724, - 733, 506, 307, 195, 225, 175, 77, 12, 1, 1, - 904, 414, 246, 170, 126, 290, 205, - 423, 185, - }, - { 382, 80, 26, 21, 2, 1, 1, 239, 64, - 1442, 1429, 706, 701, - 664, 420, 239, 146, 152, 105, 34, 2, 1, 1, - 975, 440, 263, 185, 140, 332, 229, - 397, 169, - }, - { 451, 97, 32, 27, 4, 1, 1, 223, 75, - 1462, 1454, 682, 680, - 574, 343, 179, 101, 98, 54, 9, 1, 1, 1, - 1031, 482, 293, 210, 163, 400, 297, - 384, 181, - }, - { 551, 128, 43, 37, 5, 1, 1, 201, 78, - 1497, 1487, 642, 651, - 493, 269, 133, 70, 60, 24, 2, 1, 1, 1, - 1065, 504, 312, 228, 178, 451, 352, - 351, 174, - }, - { 693, 179, 63, 54, 8, 1, 1, 169, 78, - 1502, 1497, 580, 591, - 375, 186, 77, 35, 21, 4, 1, 1, 1, 1, - 1099, 533, 341, 253, 206, 542, 432, - 306, 164, - }, - { 867, 263, 105, 96, 16, 2, 1, 152, 81, - 1435, 1439, 521, 525, - 270, 107, 32, 8, 3, 1, 1, 1, 1, 1, - 1085, 537, 361, 277, 223, 616, 549, - 258, 156, - }, - { 1022, 385, 182, 207, 46, 7, 1, 158, 88, - 1290, 1318, 501, 502, - 184, 38, 6, 1, 1, 1, 1, 1, 1, 1, - 1023, 480, 345, 301, 232, 665, 661, - 210, 133, - }, - { 1184, 555, 307, 457, 185, 44, 6, 115, 41, - 1236, 1253, 329, 340, - 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1017, 385, 316, 370, 246, 672, 788, - 85, 23, - }, - /* AC Inter bias group 3 tables */ - { 502, 106, 33, 22, 1, 1, 1, 151, 132, - 1446, 1451, 502, 499, - 343, 181, 84, 42, 36, 16, 3, 1, 1, 1, - 1211, 661, 429, 312, 242, 637, 498, - 288, 156, - }, - { 651, 147, 48, 35, 3, 1, 1, 145, 140, - 1419, 1420, 469, 466, - 281, 132, 56, 25, 18, 6, 1, 1, 1, 1, - 1175, 656, 435, 328, 260, 715, 556, - 252, 147, - }, - { 749, 179, 59, 43, 4, 1, 1, 123, 135, - 1423, 1431, 413, 409, - 221, 95, 36, 15, 9, 2, 1, 1, 1, 1, - 1159, 658, 444, 340, 272, 782, 656, - 205, 124, - }, - { 902, 243, 86, 67, 7, 1, 1, 114, 141, - 1385, 1385, 387, 383, - 178, 67, 22, 7, 4, 1, 1, 1, 1, 1, - 1096, 632, 434, 339, 277, 813, 735, - 171, 109, - }, - { 1081, 337, 133, 112, 15, 1, 1, 92, 137, - 1350, 1349, 311, 309, - 115, 34, 8, 2, 1, 1, 1, 1, 1, 1, - 1016, 595, 418, 342, 283, 870, 883, - 114, 78, - }, - { 1253, 467, 210, 205, 34, 3, 1, 80, 130, - 1318, 1313, 258, 260, - 68, 12, 2, 1, 1, 1, 1, 1, 1, 1, - 874, 516, 378, 330, 273, 877, 1000, - 72, 53, - }, - { 1362, 626, 333, 423, 100, 10, 1, 73, 106, - 1311, 1313, 241, 231, - 31, 3, 1, 1, 1, 1, 1, 1, 1, 1, - 620, 368, 286, 302, 245, 814, 1127, - 34, 28, - }, - { 1203, 743, 460, 774, 284, 36, 1, 13, 25, - 1956, 1961, 103, 106, - 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 248, 131, 149, 272, 165, 535, 813, - 3, 3, - }, - - /* AC Intra bias group 4 tables */ - { 599, 150, 55, 50, 9, 1, 1, 181, 19, - 1487, 1487, 625, 625, - 473, 271, 138, 74, 71, 42, 11, 1, 1, 1, - 1187, 591, 356, 239, 170, 351, 137, - 395, 194, - }, - { 758, 209, 79, 74, 15, 2, 1, 147, 25, - 1514, 1514, 521, 520, - 334, 165, 74, 36, 30, 11, 1, 1, 1, 1, - 1252, 644, 409, 279, 211, 472, 203, - 318, 171, - }, - { 852, 252, 100, 98, 20, 3, 1, 130, 26, - 1493, 1498, 481, 473, - 268, 123, 51, 23, 15, 3, 1, 1, 1, 1, - 1256, 652, 426, 294, 231, 543, 242, - 278, 156, - }, - { 971, 309, 130, 136, 30, 5, 1, 113, 28, - 1458, 1467, 443, 435, - 215, 90, 31, 12, 5, 1, 1, 1, 1, 1, - 1232, 643, 426, 303, 243, 590, 300, - 235, 136, - }, - { 1100, 399, 180, 206, 53, 9, 1, 101, 29, - 1419, 1425, 375, 374, - 158, 47, 10, 1, 1, 1, 1, 1, 1, 1, - 1193, 609, 426, 319, 256, 643, 383, - 166, 103, - }, - { 1195, 505, 249, 326, 98, 20, 3, 102, 25, - 1370, 1356, 355, 347, - 104, 11, 1, 1, 1, 1, 1, 1, 1, 1, - 1100, 568, 381, 330, 261, 642, 466, - 105, 69, - }, - { 1176, 608, 345, 559, 244, 57, 6, 110, 9, - 1370, 1332, 372, 367, - 29, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 859, 427, 269, 359, 375, 608, 451, - 35, 20, - }, - { 1140, 613, 391, 797, 458, 180, 37, 2, 1, - 2037, 1697, 95, 31, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 360, 49, 23, 198, 1001, 719, 160, - 1, 1, - }, - /* AC Inter bias group 4 tables */ - { 931, 272, 105, 96, 16, 1, 1, 91, 52, - 1481, 1489, 347, 349, - 174, 74, 28, 12, 8, 3, 1, 1, 1, 1, - 1247, 719, 490, 356, 279, 706, 363, - 187, 110, - }, - { 1095, 358, 148, 143, 25, 3, 1, 74, 61, - 1439, 1457, 304, 302, - 127, 46, 15, 5, 3, 1, 1, 1, 1, 1, - 1138, 664, 469, 347, 282, 768, 487, - 139, 87, - }, - { 1192, 423, 188, 189, 36, 4, 1, 64, 61, - 1457, 1475, 284, 282, - 106, 35, 10, 3, 1, 1, 1, 1, 1, 1, - 1078, 624, 440, 329, 264, 744, 507, - 117, 73, - }, - { 1275, 496, 231, 258, 52, 6, 1, 53, 55, - 1458, 1470, 248, 245, - 77, 20, 5, 1, 1, 1, 1, 1, 1, 1, - 984, 576, 414, 323, 260, 771, 569, - 84, 54, - }, - { 1377, 603, 302, 367, 87, 11, 1, 37, 52, - 1522, 1532, 207, 204, - 47, 8, 1, 1, 1, 1, 1, 1, 1, 1, - 840, 493, 366, 291, 231, 690, 636, - 52, 32, - }, - { 1409, 708, 385, 529, 148, 24, 1, 23, 37, - 1672, 1670, 163, 162, - 22, 2, 1, 1, 1, 1, 1, 1, 1, 1, - 647, 364, 291, 262, 210, 574, 643, - 26, 14, - }, - { 1348, 778, 481, 755, 245, 53, 4, 13, 19, - 2114, 2089, 141, 139, - 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 302, 183, 162, 181, 182, 344, 437, - 8, 3, - }, - { 1560, 769, 410, 664, 243, 58, 1, 1, 1, - 3017, 2788, 17, 24, - 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 34, 16, 8, 55, 134, 105, 86, - 1, 1, - }, -}; - -#else /* Frequency tables for encoder version < 2 */ - -const ogg_uint32_t FrequencyCounts_VP3[NUM_HUFF_TABLES][MAX_ENTROPY_TOKENS] = { - /* DC Intra bias */ - { 198, 62, 22, 31, 14, 6, 6, 205, 3, - 843, 843, 415, 516, - 660, 509, 412, 347, 560, 779, 941, 930, 661, 377, - 170, 155, 39, 2, 9, 15, 11, - 128, 86, - }, - { 299, 92, 34, 39, 15, 6, 6, 132, 1, - 851, 851, 484, 485, - 666, 514, 416, 351, 567, 788, 953, 943, 670, 383, - 117, 119, 26, 4, 17, 7, 1, - 93, 56, - }, - { 367, 115, 42, 47, 16, 6, 6, 105, 1, - 896, 896, 492, 493, - 667, 510, 408, 342, 547, 760, 932, 927, 656, 379, - 114, 103, 10, 3, 6, 2, 1, - 88, 49, - }, - { 462, 158, 63, 76, 28, 9, 8, 145, 1, - 1140, 1140, 573, 574, - 754, 562, 435, 357, 555, 742, 793, 588, 274, 81, - 154, 117, 13, 6, 12, 2, 1, - 104, 62, - }, - { 558, 196, 81, 99, 36, 11, 9, 135, 1, - 1300, 1301, 606, 607, - 779, 560, 429, 349, 536, 680, 644, 405, 153, 30, - 171, 120, 12, 5, 14, 3, 1, - 104, 53, - }, - { 635, 233, 100, 122, 46, 14, 12, 113, 1, - 1414, 1415, 631, 631, - 785, 555, 432, 335, 513, 611, 521, 284, 89, 13, - 170, 113, 10, 5, 14, 3, 1, - 102, 62, - }, - { 720, 276, 119, 154, 62, 20, 16, 101, 1, - 1583, 1583, 661, 661, - 794, 556, 407, 318, 447, 472, 343, 153, 35, 1, - 172, 115, 11, 7, 14, 3, 1, - 112, 70, - }, - { 853, 326, 144, 184, 80, 27, 19, 52, 1, - 1739, 1740, 684, 685, - 800, 540, 381, 277, 364, 352, 218, 78, 13, 1, - 139, 109, 9, 6, 20, 2, 1, - 94, 50, - }, - - /* DC Inter Bias */ - { 490, 154, 57, 53, 10, 2, 1, 238, 160, - 1391, 1390, 579, 578, - 491, 273, 172, 118, 152, 156, 127, 79, 41, 39, - 712, 547, 316, 125, 183, 306, 237, - 451, 358, - }, - { 566, 184, 70, 65, 11, 2, 1, 235, 51, - 1414, 1414, 599, 598, - 510, 285, 180, 124, 157, 161, 131, 82, 42, 40, - 738, 551, 322, 138, 195, 188, 93, - 473, 365, - }, - { 711, 261, 111, 126, 27, 4, 1, 137, 52, - 1506, 1505, 645, 645, - 567, 316, 199, 136, 172, 175, 142, 88, 45, 48, - 548, 449, 255, 145, 184, 174, 121, - 260, 227, - }, - { 823, 319, 144, 175, 43, 7, 1, 53, 42, - 1648, 1648, 653, 652, - 583, 329, 205, 139, 175, 176, 139, 84, 44, 34, - 467, 389, 211, 137, 181, 186, 107, - 106, 85, - }, - { 948, 411, 201, 276, 85, 16, 2, 39, 33, - 1778, 1777, 584, 583, - 489, 265, 162, 111, 140, 140, 108, 64, 38, 23, - 428, 356, 201, 139, 186, 165, 94, - 78, 63, - }, - { 1002, 470, 248, 386, 153, 39, 6, 23, 23, - 1866, 1866, 573, 573, - 467, 249, 155, 103, 130, 128, 94, 60, 38, 14, - 323, 263, 159, 111, 156, 153, 74, - 46, 34, - }, - { 1020, 518, 291, 504, 242, 78, 18, 14, 14, - 1980, 1979, 527, 526, - 408, 219, 132, 87, 110, 104, 79, 55, 31, 7, - 265, 213, 129, 91, 131, 111, 50, - 31, 20, - }, - { 1018, 544, 320, 591, 338, 139, 47, 5, 2, - 2123, 2123, 548, 547, - 414, 212, 126, 83, 101, 96, 79, 60, 23, 1, - 120, 97, 55, 39, 60, 38, 15, - 11, 8, - }, - - /* AC INTRA Tables */ - /* AC Intra bias group 1 tables */ - { 242, 62, 22, 20, 4, 1, 1, 438, 1, - 593, 593, 489, 490, - 657, 580, 471, 374, 599, 783, 869, 770, 491, 279, - 358, 144, 82, 54, 49, 70, 5, - 289, 107, - }, - { 317, 95, 38, 41, 8, 1, 1, 479, 1, - 653, 654, 500, 501, - 682, 611, 473, 376, 582, 762, 806, 656, 358, 155, - 419, 162, 86, 58, 36, 34, 1, - 315, 126, - }, - { 382, 121, 49, 59, 15, 3, 1, 496, 1, - 674, 674, 553, 554, - 755, 636, 487, 391, 576, 718, 701, 488, 221, 72, - 448, 161, 107, 56, 37, 29, 1, - 362, 156, - }, - { 415, 138, 57, 73, 21, 5, 1, 528, 1, - 742, 741, 562, 563, - 753, 669, 492, 388, 563, 664, 589, 340, 129, 26, - 496, 184, 139, 71, 48, 33, 2, - 387, 166, - }, - { 496, 170, 73, 94, 31, 8, 2, 513, 1, - 855, 855, 604, 604, - 769, 662, 477, 356, 486, 526, 381, 183, 51, 5, - 590, 214, 160, 85, 60, 39, 3, - 427, 203, - }, - { 589, 207, 89, 116, 40, 13, 3, 491, 1, - 919, 919, 631, 631, - 769, 633, 432, 308, 408, 378, 247, 94, 17, 1, - 659, 247, 201, 105, 73, 51, 3, - 466, 242, - }, - { 727, 266, 115, 151, 49, 17, 6, 439, 1, - 977, 977, 642, 642, - 718, 572, 379, 243, 285, 251, 133, 40, 1, 1, - 756, 287, 253, 126, 94, 66, 4, - 492, 280, - }, - { 940, 392, 180, 247, 82, 30, 14, 343, 1, - 1064, 1064, 615, 616, - 596, 414, 235, 146, 149, 108, 41, 1, 1, 1, - 882, 314, 346, 172, 125, 83, 6, - 489, 291, - }, - /* AC Inter bias group 1 tables */ - { 440, 102, 33, 23, 2, 1, 1, 465, 85, - 852, 852, 744, 743, - 701, 496, 297, 193, 225, 200, 129, 58, 18, 2, - 798, 450, 269, 202, 145, 308, 154, - 646, 389, - }, - { 592, 151, 53, 43, 6, 1, 1, 409, 34, - 875, 875, 748, 747, - 723, 510, 305, 196, 229, 201, 130, 59, 18, 2, - 800, 436, 253, 185, 115, 194, 88, - 642, 368, - }, - { 759, 222, 86, 85, 17, 2, 1, 376, 46, - 888, 888, 689, 688, - 578, 408, 228, 143, 165, 141, 84, 35, 7, 1, - 878, 488, 321, 244, 147, 266, 124, - 612, 367, - }, - { 912, 298, 122, 133, 34, 7, 1, 261, 44, - 1092, 1091, 496, 496, - 409, 269, 150, 95, 106, 87, 49, 16, 1, 1, - 1102, 602, 428, 335, 193, 323, 157, - 423, 253, - }, - { 1072, 400, 180, 210, 60, 16, 3, 210, 40, - 1063, 1063, 451, 451, - 345, 221, 121, 73, 79, 64, 31, 6, 1, 1, - 1105, 608, 462, 358, 202, 330, 155, - 377, 228, - }, - { 1164, 503, 254, 330, 109, 34, 9, 167, 35, - 1038, 1037, 390, 390, - 278, 170, 89, 54, 56, 40, 13, 1, 1, 1, - 1110, 607, 492, 401, 218, 343, 141, - 323, 192, - }, - { 1173, 583, 321, 486, 196, 68, 23, 124, 23, - 1037, 1037, 347, 346, - 232, 139, 69, 40, 37, 20, 2, 1, 1, 1, - 1128, 584, 506, 410, 199, 301, 113, - 283, 159, - }, - { 1023, 591, 366, 699, 441, 228, 113, 79, 5, - 1056, 1056, 291, 291, - 173, 96, 38, 19, 8, 1, 1, 1, 1, 1, - 1187, 527, 498, 409, 147, 210, 56, - 263, 117, - }, - - /* AC Intra bias group 2 tables */ - { 311, 74, 27, 27, 5, 1, 1, 470, 24, - 665, 667, 637, 638, - 806, 687, 524, 402, 585, 679, 609, 364, 127, 20, - 448, 210, 131, 76, 52, 111, 19, - 393, 195, - }, - { 416, 104, 39, 38, 8, 1, 1, 545, 33, - 730, 731, 692, 692, - 866, 705, 501, 365, 495, 512, 387, 168, 39, 2, - 517, 240, 154, 86, 64, 127, 19, - 461, 247, - }, - { 474, 117, 43, 42, 9, 1, 1, 560, 40, - 783, 783, 759, 760, - 883, 698, 466, 318, 404, 377, 215, 66, 7, 1, - 559, 259, 176, 110, 87, 170, 22, - 520, 278, - }, - { 582, 149, 53, 53, 12, 2, 1, 473, 39, - 992, 993, 712, 713, - 792, 593, 373, 257, 299, 237, 114, 25, 1, 1, - 710, 329, 221, 143, 116, 226, 26, - 490, 259, - }, - { 744, 210, 78, 77, 16, 2, 1, 417, 37, - 1034, 1035, 728, 728, - 718, 509, 296, 175, 184, 122, 42, 3, 1, 1, - 791, 363, 255, 168, 145, 311, 35, - 492, 272, - }, - { 913, 291, 121, 128, 28, 4, 1, 334, 40, - 1083, 1084, 711, 712, - 624, 378, 191, 107, 95, 50, 7, 1, 1, 1, - 876, 414, 288, 180, 164, 382, 39, - 469, 275, - }, - { 1065, 405, 184, 216, 53, 8, 1, 236, 36, - 1134, 1134, 685, 686, - 465, 253, 113, 48, 41, 9, 1, 1, 1, 1, - 965, 451, 309, 179, 166, 429, 53, - 414, 249, - }, - { 1148, 548, 301, 438, 160, 42, 6, 84, 17, - 1222, 1223, 574, 575, - 272, 111, 23, 6, 2, 1, 1, 1, 1, 1, - 1060, 502, 328, 159, 144, 501, 54, - 302, 183, - }, - /* AC Inter bias group 2 tables */ - { 403, 80, 24, 17, 1, 1, 1, 480, 90, - 899, 899, 820, 819, - 667, 413, 228, 133, 139, 98, 42, 10, 1, 1, - 865, 470, 316, 222, 171, 419, 213, - 645, 400, - }, - { 698, 169, 59, 49, 6, 1, 1, 414, 101, - 894, 893, 761, 761, - 561, 338, 171, 96, 97, 64, 26, 6, 1, 1, - 896, 494, 343, 239, 192, 493, 215, - 583, 366, - }, - { 914, 255, 94, 80, 10, 1, 1, 345, 128, - 935, 935, 670, 671, - 415, 222, 105, 55, 51, 30, 10, 1, 1, 1, - 954, 530, 377, 274, 232, 641, 295, - 456, 298, - }, - { 1103, 359, 146, 135, 20, 1, 1, 235, 119, - 1042, 1042, 508, 507, - 293, 146, 65, 33, 30, 16, 4, 1, 1, 1, - 1031, 561, 407, 296, 265, 813, 317, - 301, 192, - }, - { 1255, 504, 238, 265, 51, 5, 1, 185, 113, - 1013, 1013, 437, 438, - 212, 92, 41, 18, 15, 6, 1, 1, 1, 1, - 976, 530, 386, 276, 260, 927, 357, - 224, 148, - }, - { 1292, 610, 332, 460, 127, 16, 1, 136, 99, - 1014, 1015, 384, 384, - 153, 65, 25, 11, 6, 1, 1, 1, 1, 1, - 942, 487, 343, 241, 238, 970, 358, - 174, 103, - }, - { 1219, 655, 407, 700, 280, 55, 2, 100, 60, - 1029, 1029, 337, 336, - 119, 43, 11, 3, 2, 1, 1, 1, 1, 1, - 894, 448, 305, 199, 213, 1005, 320, - 136, 77, - }, - { 1099, 675, 435, 971, 581, 168, 12, 37, 16, - 1181, 1081, 319, 318, - 66, 11, 6, 1, 1, 1, 1, 1, 1, 1, - 914, 370, 235, 138, 145, 949, 128, - 94, 41, - }, - - /* AC Intra bias group 3 tables */ - { 486, 112, 39, 34, 6, 1, 1, 541, 67, - 819, 818, 762, 763, - 813, 643, 403, 280, 332, 295, 164, 53, 6, 1, - 632, 294, 180, 131, 105, 208, 109, - 594, 295, - }, - { 723, 191, 69, 65, 12, 1, 1, 445, 79, - 865, 865, 816, 816, - 750, 515, 290, 172, 184, 122, 46, 5, 1, 1, - 740, 340, 213, 165, 129, 270, 168, - 603, 326, - }, - { 884, 264, 102, 103, 21, 3, 1, 382, 68, - 897, 897, 836, 836, - 684, 427, 227, 119, 119, 70, 16, 1, 1, 1, - 771, 367, 234, 184, 143, 272, 178, - 555, 326, - }, - { 1028, 347, 153, 161, 36, 8, 1, 251, 44, - 1083, 1084, 735, 735, - 541, 289, 144, 77, 57, 23, 3, 1, 1, 1, - 926, 422, 270, 215, 176, 301, 183, - 443, 248, - }, - { 1155, 465, 224, 264, 71, 14, 3, 174, 27, - 1110, 1111, 730, 731, - 429, 206, 79, 30, 19, 4, 1, 1, 1, 1, - 929, 443, 279, 225, 194, 298, 196, - 354, 223, - }, - { 1191, 576, 296, 415, 144, 36, 8, 114, 16, - 1162, 1162, 749, 749, - 338, 108, 29, 8, 5, 1, 1, 1, 1, 1, - 947, 458, 273, 207, 194, 248, 145, - 258, 152, - }, - { 1169, 619, 366, 603, 247, 92, 23, 46, 1, - 1236, 1236, 774, 775, - 191, 35, 14, 1, 1, 1, 1, 1, 1, 1, - 913, 449, 260, 214, 194, 180, 82, - 174, 98, - }, - { 1006, 537, 381, 897, 504, 266, 101, 39, 1, - 1307, 1307, 668, 667, - 116, 3, 1, 1, 1, 1, 1, 1, 1, 1, - 1175, 261, 295, 70, 164, 107, 31, - 10, 76, - }, - /* AC Inter bias group 3 tables */ - { 652, 156, 53, 43, 5, 1, 1, 368, 128, - 983, 984, 825, 825, - 583, 331, 163, 88, 84, 48, 15, 1, 1, 1, - 870, 480, 316, 228, 179, 421, 244, - 562, 349, - }, - { 988, 280, 104, 87, 12, 1, 1, 282, 194, - 980, 981, 738, 739, - 395, 189, 80, 37, 31, 12, 2, 1, 1, 1, - 862, 489, 333, 262, 214, 600, 446, - 390, 260, - }, - { 1176, 399, 165, 154, 24, 2, 1, 218, 224, - 1017, 1018, 651, 651, - 280, 111, 42, 16, 9, 3, 1, 1, 1, 1, - 787, 469, 324, 269, 229, 686, 603, - 267, 194, - }, - { 1319, 530, 255, 268, 47, 4, 1, 113, 183, - 1149, 1150, 461, 461, - 173, 58, 17, 5, 3, 1, 1, 1, 1, 1, - 768, 450, 305, 261, 221, 716, 835, - 136, 97, - }, - { 1362, 669, 355, 465, 104, 9, 1, 76, 153, - 1253, 1253, 398, 397, - 102, 21, 5, 1, 1, 1, 1, 1, 1, 1, - 596, 371, 238, 228, 196, 660, 954, - 68, 53, - }, - { 1354, 741, 446, 702, 174, 15, 1, 38, 87, - 1498, 1498, 294, 294, - 43, 7, 1, 1, 1, 1, 1, 1, 1, 1, - 381, 283, 165, 181, 155, 544, 1039, - 25, 21, - }, - { 1262, 885, 546, 947, 263, 18, 1, 18, 27, - 1908, 1908, 163, 162, - 14, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 195, 152, 83, 125, 109, 361, 827, - 7, 5, - }, - { 2539, 951, 369, 554, 212, 18, 1, 1, 1, - 2290, 2289, 64, 64, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 18, 18, 9, 55, 36, 184, 323, - 1, 1, - }, - - - /* AC Intra bias group 4 tables */ - { 921, 264, 101, 100, 19, 2, 1, 331, 98, - 1015, 1016, 799, 799, - 512, 269, 119, 60, 50, 17, 1, 1, 1, 1, - 841, 442, 307, 222, 182, 493, 256, - 438, 310, - }, - { 1147, 412, 184, 206, 50, 6, 1, 242, 141, - 977, 976, 808, 807, - 377, 135, 40, 10, 7, 1, 1, 1, 1, 1, - 788, 402, 308, 223, 205, 584, 406, - 316, 227, - }, - { 1243, 504, 238, 310, 79, 11, 1, 184, 150, - 983, 984, 814, 813, - 285, 56, 10, 1, 1, 1, 1, 1, 1, 1, - 713, 377, 287, 217, 180, 615, 558, - 208, 164, - }, - { 1266, 606, 329, 484, 161, 27, 1, 79, 92, - 1187, 1188, 589, 588, - 103, 10, 1, 1, 1, 1, 1, 1, 1, 1, - 680, 371, 278, 221, 244, 614, 728, - 80, 62, - }, - { 1126, 828, 435, 705, 443, 90, 8, 10, 55, - 1220, 1219, 350, 350, - 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 602, 330, 222, 168, 158, 612, 919, - 104, 5, - }, - { 1210, 506, 1014, 926, 474, 240, 4, 1, 44, - 1801, 1801, 171, 171, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 900, 132, 36, 11, 47, 191, 316, - 2, 1, - }, - { 1210, 506, 1014, 926, 474, 240, 4, 1, 44, - 1801, 1801, 171, 171, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 900, 132, 36, 11, 47, 191, 316, - 2, 1, - }, - { 1210, 506, 1014, 926, 474, 240, 4, 1, 44, - 1801, 1801, 171, 171, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 900, 132, 36, 11, 47, 191, 316, - 2, 1, - }, - /* AC Inter bias group 4 tables */ - { 1064, 325, 129, 117, 20, 2, 1, 266, 121, - 1000, 1000, 706, 706, - 348, 162, 67, 32, 25, 11, 1, 1, 1, 1, - 876, 513, 363, 274, 225, 627, 384, - 370, 251, - }, - { 1311, 517, 238, 254, 45, 3, 1, 188, 160, - 1070, 1070, 635, 635, - 239, 85, 30, 11, 6, 1, 1, 1, 1, 1, - 744, 420, 313, 239, 206, 649, 541, - 221, 155, - }, - { 1394, 632, 322, 385, 78, 7, 1, 134, 152, - 1163, 1164, 607, 607, - 185, 51, 12, 3, 1, 1, 1, 1, 1, 1, - 631, 331, 275, 203, 182, 604, 620, - 146, 98, - }, - { 1410, 727, 407, 546, 146, 19, 1, 67, 88, - 1485, 1486, 419, 418, - 103, 18, 3, 1, 1, 1, 1, 1, 1, 1, - 555, 261, 234, 164, 148, 522, 654, - 67, 39, - }, - { 1423, 822, 492, 719, 216, 22, 1, 28, 59, - 1793, 1793, 323, 324, - 37, 2, 1, 1, 1, 1, 1, 1, 1, 1, - 376, 138, 158, 102, 119, 400, 604, - 28, 9, - }, - { 1585, 923, 563, 918, 207, 25, 1, 5, 20, - 2229, 2230, 172, 172, - 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 191, 40, 56, 22, 65, 243, 312, - 2, 1, - }, - { 2225, 1100, 408, 608, 133, 8, 1, 1, 1, - 2658, 2658, 25, 24, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 8, 1, 1, 1, 1, 125, 16, - 1, 1, - }, - { 2539, 951, 369, 554, 212, 18, 1, 1, 1, - 2290, 2289, 64, 64, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 18, 18, 9, 55, 36, 184, 323, - 1, 1, - }, -}; - -#endif /* NEW_FREQS */ diff --git a/Engine/lib/libtheora/lib/enc/mcomp.c b/Engine/lib/libtheora/lib/enc/mcomp.c deleted file mode 100644 index 3b6b4ac28..000000000 --- a/Engine/lib/libtheora/lib/enc/mcomp.c +++ /dev/null @@ -1,767 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: mcomp.c 15153 2008-08-04 18:37:55Z tterribe $ - - ********************************************************************/ - -#include -#include -#include "codec_internal.h" - -/* Initialises motion compentsation. */ -void InitMotionCompensation ( CP_INSTANCE *cpi ){ - int i; - int SearchSite=0; - int Len; - int LineStepY = (ogg_int32_t)cpi->pb.YStride; - - Len=((MAX_MV_EXTENT/2)+1)/2; - - - /* How many search stages are there. */ - cpi->MVSearchSteps = 0; - - /* Set up offsets arrays used in half pixel correction. */ - cpi->HalfPixelRef2Offset[0] = -LineStepY - 1; - cpi->HalfPixelRef2Offset[1] = -LineStepY; - cpi->HalfPixelRef2Offset[2] = -LineStepY + 1; - cpi->HalfPixelRef2Offset[3] = - 1; - cpi->HalfPixelRef2Offset[4] = 0; - cpi->HalfPixelRef2Offset[5] = 1; - cpi->HalfPixelRef2Offset[6] = LineStepY - 1; - cpi->HalfPixelRef2Offset[7] = LineStepY; - cpi->HalfPixelRef2Offset[8] = LineStepY + 1; - - cpi->HalfPixelXOffset[0] = -1; - cpi->HalfPixelXOffset[1] = 0; - cpi->HalfPixelXOffset[2] = 1; - cpi->HalfPixelXOffset[3] = -1; - cpi->HalfPixelXOffset[4] = 0; - cpi->HalfPixelXOffset[5] = 1; - cpi->HalfPixelXOffset[6] = -1; - cpi->HalfPixelXOffset[7] = 0; - cpi->HalfPixelXOffset[8] = 1; - - cpi->HalfPixelYOffset[0] = -1; - cpi->HalfPixelYOffset[1] = -1; - cpi->HalfPixelYOffset[2] = -1; - cpi->HalfPixelYOffset[3] = 0; - cpi->HalfPixelYOffset[4] = 0; - cpi->HalfPixelYOffset[5] = 0; - cpi->HalfPixelYOffset[6] = 1; - cpi->HalfPixelYOffset[7] = 1; - cpi->HalfPixelYOffset[8] = 1; - - - /* Generate offsets for 8 search sites per step. */ - while ( Len>0 ) { - /* Another step. */ - cpi->MVSearchSteps += 1; - - /* Compute offsets for search sites. */ - cpi->MVOffsetX[SearchSite] = -Len; - cpi->MVOffsetY[SearchSite++] = -Len; - cpi->MVOffsetX[SearchSite] = 0; - cpi->MVOffsetY[SearchSite++] = -Len; - cpi->MVOffsetX[SearchSite] = Len; - cpi->MVOffsetY[SearchSite++] = -Len; - cpi->MVOffsetX[SearchSite] = -Len; - cpi->MVOffsetY[SearchSite++] = 0; - cpi->MVOffsetX[SearchSite] = Len; - cpi->MVOffsetY[SearchSite++] = 0; - cpi->MVOffsetX[SearchSite] = -Len; - cpi->MVOffsetY[SearchSite++] = Len; - cpi->MVOffsetX[SearchSite] = 0; - cpi->MVOffsetY[SearchSite++] = Len; - cpi->MVOffsetX[SearchSite] = Len; - cpi->MVOffsetY[SearchSite++] = Len; - - /* Contract. */ - Len /= 2; - } - - /* Compute pixel index offsets. */ - for ( i=SearchSite-1; i>=0; i-- ) - cpi->MVPixelOffsetY[i] = (cpi->MVOffsetY[i]*LineStepY) + cpi->MVOffsetX[i]; -} - -static ogg_uint32_t GetInterErr (CP_INSTANCE *cpi, unsigned char * NewDataPtr, - unsigned char * RefDataPtr1, - unsigned char * RefDataPtr2, - ogg_uint32_t PixelsPerLine ) { - ogg_int32_t DiffVal; - ogg_int32_t RefOffset = (int)(RefDataPtr1 - RefDataPtr2); - ogg_uint32_t RefPixelsPerLine = PixelsPerLine + STRIDE_EXTRA; - - /* Mode of interpolation chosen based upon on the offset of the - second reference pointer */ - if ( RefOffset == 0 ) { - DiffVal = dsp_inter8x8_err (cpi->dsp, NewDataPtr, PixelsPerLine, - RefDataPtr1, RefPixelsPerLine); - }else{ - DiffVal = dsp_inter8x8_err_xy2 (cpi->dsp, NewDataPtr, PixelsPerLine, - RefDataPtr1, - RefDataPtr2, RefPixelsPerLine); - } - - /* Compute and return population variance as mis-match metric. */ - return DiffVal; -} - -static ogg_uint32_t GetHalfPixelSumAbsDiffs (CP_INSTANCE *cpi, - unsigned char * SrcData, - unsigned char * RefDataPtr1, - unsigned char * RefDataPtr2, - ogg_uint32_t PixelsPerLine, - ogg_uint32_t ErrorSoFar, - ogg_uint32_t BestSoFar ) { - - ogg_uint32_t DiffVal = ErrorSoFar; - ogg_int32_t RefOffset = (int)(RefDataPtr1 - RefDataPtr2); - ogg_uint32_t RefPixelsPerLine = PixelsPerLine + STRIDE_EXTRA; - - if ( RefOffset == 0 ) { - /* Simple case as for non 0.5 pixel */ - DiffVal += dsp_sad8x8 (cpi->dsp, SrcData, PixelsPerLine, - RefDataPtr1, RefPixelsPerLine); - } else { - DiffVal += dsp_sad8x8_xy2_thres (cpi->dsp, SrcData, PixelsPerLine, - RefDataPtr1, - RefDataPtr2, RefPixelsPerLine, BestSoFar); - } - - return DiffVal; -} - -ogg_uint32_t GetMBIntraError (CP_INSTANCE *cpi, ogg_uint32_t FragIndex, - ogg_uint32_t PixelsPerLine ) { - ogg_uint32_t LocalFragIndex = FragIndex; - ogg_uint32_t IntraError = 0; - - dsp_save_fpu (cpi->dsp); - - /* Add together the intra errors for those blocks in the macro block - that are coded (Y only) */ - if ( cpi->pb.display_fragments[LocalFragIndex] ) - IntraError += - dsp_intra8x8_err (cpi->dsp, &cpi-> - ConvDestBuffer[cpi->pb.pixel_index_table[LocalFragIndex]], - PixelsPerLine); - - LocalFragIndex++; - if ( cpi->pb.display_fragments[LocalFragIndex] ) - IntraError += - dsp_intra8x8_err (cpi->dsp, &cpi-> - ConvDestBuffer[cpi->pb.pixel_index_table[LocalFragIndex]], - PixelsPerLine); - - LocalFragIndex = FragIndex + cpi->pb.HFragments; - if ( cpi->pb.display_fragments[LocalFragIndex] ) - IntraError += - dsp_intra8x8_err (cpi->dsp, &cpi-> - ConvDestBuffer[cpi->pb.pixel_index_table[LocalFragIndex]], - PixelsPerLine); - - LocalFragIndex++; - if ( cpi->pb.display_fragments[LocalFragIndex] ) - IntraError += - dsp_intra8x8_err (cpi->dsp, &cpi-> - ConvDestBuffer[cpi->pb.pixel_index_table[LocalFragIndex]], - PixelsPerLine); - - dsp_restore_fpu (cpi->dsp); - - return IntraError; -} - -ogg_uint32_t GetMBInterError (CP_INSTANCE *cpi, - unsigned char * SrcPtr, - unsigned char * RefPtr, - ogg_uint32_t FragIndex, - ogg_int32_t LastXMV, - ogg_int32_t LastYMV, - ogg_uint32_t PixelsPerLine ) { - ogg_uint32_t RefPixelsPerLine = cpi->pb.YStride; - ogg_uint32_t LocalFragIndex = FragIndex; - ogg_int32_t PixelIndex; - ogg_int32_t RefPixelIndex; - ogg_int32_t RefPixelOffset; - ogg_int32_t RefPtr2Offset; - - ogg_uint32_t InterError = 0; - - unsigned char * SrcPtr1; - unsigned char * RefPtr1; - - dsp_save_fpu (cpi->dsp); - - /* Work out pixel offset into source buffer. */ - PixelIndex = cpi->pb.pixel_index_table[LocalFragIndex]; - - /* Work out the pixel offset in reference buffer for the default - motion vector */ - RefPixelIndex = cpi->pb.recon_pixel_index_table[LocalFragIndex]; - RefPixelOffset = ((LastYMV/2) * RefPixelsPerLine) + (LastXMV/2); - - /* Work out the second reference pointer offset. */ - RefPtr2Offset = 0; - if ( LastXMV % 2 ) { - if ( LastXMV > 0 ) - RefPtr2Offset += 1; - else - RefPtr2Offset -= 1; - } - if ( LastYMV % 2 ) { - if ( LastYMV > 0 ) - RefPtr2Offset += RefPixelsPerLine; - else - RefPtr2Offset -= RefPixelsPerLine; - } - - /* Add together the errors for those blocks in the macro block that - are coded (Y only) */ - if ( cpi->pb.display_fragments[LocalFragIndex] ) { - SrcPtr1 = &SrcPtr[PixelIndex]; - RefPtr1 = &RefPtr[RefPixelIndex + RefPixelOffset]; - InterError += GetInterErr(cpi, SrcPtr1, RefPtr1, - &RefPtr1[RefPtr2Offset], PixelsPerLine ); - } - - LocalFragIndex++; - if ( cpi->pb.display_fragments[LocalFragIndex] ) { - PixelIndex = cpi->pb.pixel_index_table[LocalFragIndex]; - RefPixelIndex = cpi->pb.recon_pixel_index_table[LocalFragIndex]; - SrcPtr1 = &SrcPtr[PixelIndex]; - RefPtr1 = &RefPtr[RefPixelIndex + RefPixelOffset]; - InterError += GetInterErr(cpi, SrcPtr1, RefPtr1, - &RefPtr1[RefPtr2Offset], PixelsPerLine ); - - } - - LocalFragIndex = FragIndex + cpi->pb.HFragments; - if ( cpi->pb.display_fragments[LocalFragIndex] ) { - PixelIndex = cpi->pb.pixel_index_table[LocalFragIndex]; - RefPixelIndex = cpi->pb.recon_pixel_index_table[LocalFragIndex]; - SrcPtr1 = &SrcPtr[PixelIndex]; - RefPtr1 = &RefPtr[RefPixelIndex + RefPixelOffset]; - InterError += GetInterErr(cpi, SrcPtr1, RefPtr1, - &RefPtr1[RefPtr2Offset], PixelsPerLine ); - } - - LocalFragIndex++; - if ( cpi->pb.display_fragments[LocalFragIndex] ) { - PixelIndex = cpi->pb.pixel_index_table[LocalFragIndex]; - RefPixelIndex = cpi->pb.recon_pixel_index_table[LocalFragIndex]; - SrcPtr1 = &SrcPtr[PixelIndex]; - RefPtr1 = &RefPtr[RefPixelIndex + RefPixelOffset]; - InterError += GetInterErr(cpi, SrcPtr1, RefPtr1, - &RefPtr1[RefPtr2Offset], PixelsPerLine ); - } - - dsp_restore_fpu (cpi->dsp); - - return InterError; -} - -ogg_uint32_t GetMBMVInterError (CP_INSTANCE *cpi, - unsigned char * RefFramePtr, - ogg_uint32_t FragIndex, - ogg_uint32_t PixelsPerLine, - ogg_int32_t *MVPixelOffset, - MOTION_VECTOR *MV ) { - ogg_uint32_t Error = 0; - ogg_uint32_t MinError; - ogg_uint32_t InterMVError = 0; - - ogg_int32_t i; - ogg_int32_t x=0, y=0; - ogg_int32_t step; - ogg_int32_t SearchSite=0; - - unsigned char *SrcPtr[4] = {NULL,NULL,NULL,NULL}; - unsigned char *RefPtr=NULL; - unsigned char *CandidateBlockPtr=NULL; - unsigned char *BestBlockPtr=NULL; - - ogg_uint32_t RefRow2Offset = cpi->pb.YStride * 8; - - int MBlockDispFrags[4]; - - /* Half pixel variables */ - ogg_int32_t HalfPixelError; - ogg_int32_t BestHalfPixelError; - unsigned char BestHalfOffset; - unsigned char * RefDataPtr1; - unsigned char * RefDataPtr2; - - dsp_save_fpu (cpi->dsp); - - /* Note which of the four blocks in the macro block are to be - included in the search. */ - MBlockDispFrags[0] = - cpi->pb.display_fragments[FragIndex]; - MBlockDispFrags[1] = - cpi->pb.display_fragments[FragIndex + 1]; - MBlockDispFrags[2] = - cpi->pb.display_fragments[FragIndex + cpi->pb.HFragments]; - MBlockDispFrags[3] = - cpi->pb.display_fragments[FragIndex + cpi->pb.HFragments + 1]; - - /* Set up the source pointers for the four source blocks. */ - SrcPtr[0] = &cpi->ConvDestBuffer[cpi->pb.pixel_index_table[FragIndex]]; - SrcPtr[1] = SrcPtr[0] + 8; - SrcPtr[2] = SrcPtr[0] + (PixelsPerLine * 8); - SrcPtr[3] = SrcPtr[2] + 8; - - /* Set starting reference point for search. */ - RefPtr = &RefFramePtr[cpi->pb.recon_pixel_index_table[FragIndex]]; - - /* Check the 0,0 candidate. */ - if ( MBlockDispFrags[0] ) { - Error += dsp_sad8x8 (cpi->dsp, SrcPtr[0], PixelsPerLine, RefPtr, - PixelsPerLine + STRIDE_EXTRA); - } - if ( MBlockDispFrags[1] ) { - Error += dsp_sad8x8 (cpi->dsp, SrcPtr[1], PixelsPerLine, RefPtr + 8, - PixelsPerLine + STRIDE_EXTRA); - } - if ( MBlockDispFrags[2] ) { - Error += dsp_sad8x8 (cpi->dsp, SrcPtr[2], PixelsPerLine, RefPtr + RefRow2Offset, - PixelsPerLine + STRIDE_EXTRA); - } - if ( MBlockDispFrags[3] ) { - Error += dsp_sad8x8 (cpi->dsp, SrcPtr[3], PixelsPerLine, RefPtr + RefRow2Offset + 8, - PixelsPerLine + STRIDE_EXTRA); - } - - /* Set starting values to results of 0, 0 vector. */ - MinError = Error; - BestBlockPtr = RefPtr; - x = 0; - y = 0; - MV->x = 0; - MV->y = 0; - - /* Proceed through N-steps. */ - for ( step=0; stepMVSearchSteps; step++ ) { - /* Search the 8-neighbours at distance pertinent to current step.*/ - for ( i=0; i<8; i++ ) { - /* Set pointer to next candidate matching block. */ - CandidateBlockPtr = RefPtr + MVPixelOffset[SearchSite]; - - /* Reset error */ - Error = 0; - - /* Get the score for the current offset */ - if ( MBlockDispFrags[0] ) { - Error += dsp_sad8x8 (cpi->dsp, SrcPtr[0], PixelsPerLine, CandidateBlockPtr, - PixelsPerLine + STRIDE_EXTRA); - } - - if ( MBlockDispFrags[1] && (Error < MinError) ) { - Error += dsp_sad8x8_thres (cpi->dsp, SrcPtr[1], PixelsPerLine, CandidateBlockPtr + 8, - PixelsPerLine + STRIDE_EXTRA, MinError); - } - - if ( MBlockDispFrags[2] && (Error < MinError) ) { - Error += dsp_sad8x8_thres (cpi->dsp, SrcPtr[2], PixelsPerLine, CandidateBlockPtr + RefRow2Offset, - PixelsPerLine + STRIDE_EXTRA, MinError); - } - - if ( MBlockDispFrags[3] && (Error < MinError) ) { - Error += dsp_sad8x8_thres (cpi->dsp, SrcPtr[3], PixelsPerLine, CandidateBlockPtr + RefRow2Offset + 8, - PixelsPerLine + STRIDE_EXTRA, MinError); - } - - if ( Error < MinError ) { - /* Remember best match. */ - MinError = Error; - BestBlockPtr = CandidateBlockPtr; - - /* Where is it. */ - x = MV->x + cpi->MVOffsetX[SearchSite]; - y = MV->y + cpi->MVOffsetY[SearchSite]; - } - - /* Move to next search location. */ - SearchSite += 1; - } - - /* Move to best location this step. */ - RefPtr = BestBlockPtr; - MV->x = x; - MV->y = y; - } - - /* Factor vectors to 1/2 pixel resoultion. */ - MV->x = (MV->x * 2); - MV->y = (MV->y * 2); - - /* Now do the half pixel pass */ - BestHalfOffset = 4; /* Default to the no offset case. */ - BestHalfPixelError = MinError; - - /* Get the half pixel error for each half pixel offset */ - for ( i=0; i < 9; i++ ) { - HalfPixelError = 0; - - if ( MBlockDispFrags[0] ) { - RefDataPtr1 = BestBlockPtr; - RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i]; - HalfPixelError = - GetHalfPixelSumAbsDiffs(cpi, SrcPtr[0], RefDataPtr1, RefDataPtr2, - PixelsPerLine, HalfPixelError, BestHalfPixelError ); - } - - if ( MBlockDispFrags[1] && (HalfPixelError < BestHalfPixelError) ) { - RefDataPtr1 = BestBlockPtr + 8; - RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i]; - HalfPixelError = - GetHalfPixelSumAbsDiffs(cpi, SrcPtr[1], RefDataPtr1, RefDataPtr2, - PixelsPerLine, HalfPixelError, BestHalfPixelError ); - } - - if ( MBlockDispFrags[2] && (HalfPixelError < BestHalfPixelError) ) { - RefDataPtr1 = BestBlockPtr + RefRow2Offset; - RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i]; - HalfPixelError = - GetHalfPixelSumAbsDiffs(cpi, SrcPtr[2], RefDataPtr1, RefDataPtr2, - PixelsPerLine, HalfPixelError, BestHalfPixelError ); - } - - if ( MBlockDispFrags[3] && (HalfPixelError < BestHalfPixelError) ) { - RefDataPtr1 = BestBlockPtr + RefRow2Offset + 8; - RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i]; - HalfPixelError = - GetHalfPixelSumAbsDiffs(cpi, SrcPtr[3], RefDataPtr1, RefDataPtr2, - PixelsPerLine, HalfPixelError, BestHalfPixelError ); - } - - if ( HalfPixelError < BestHalfPixelError ) { - BestHalfOffset = (unsigned char)i; - BestHalfPixelError = HalfPixelError; - } - } - - /* Half pixel adjust the MV */ - MV->x += cpi->HalfPixelXOffset[BestHalfOffset]; - MV->y += cpi->HalfPixelYOffset[BestHalfOffset]; - - /* Get the error score for the chosen 1/2 pixel offset as a variance. */ - InterMVError = GetMBInterError( cpi, cpi->ConvDestBuffer, RefFramePtr, - FragIndex, MV->x, MV->y, PixelsPerLine ); - - dsp_restore_fpu (cpi->dsp); - - /* Return score of best matching block. */ - return InterMVError; -} - -ogg_uint32_t GetMBMVExhaustiveSearch (CP_INSTANCE *cpi, - unsigned char * RefFramePtr, - ogg_uint32_t FragIndex, - ogg_uint32_t PixelsPerLine, - MOTION_VECTOR *MV ) { - ogg_uint32_t Error = 0; - ogg_uint32_t MinError = HUGE_ERROR; - ogg_uint32_t InterMVError = 0; - - ogg_int32_t i, j; - ogg_int32_t x=0, y=0; - - unsigned char *SrcPtr[4] = {NULL,NULL,NULL,NULL}; - unsigned char *RefPtr; - unsigned char *CandidateBlockPtr=NULL; - unsigned char *BestBlockPtr=NULL; - - ogg_uint32_t RefRow2Offset = cpi->pb.YStride * 8; - - int MBlockDispFrags[4]; - - /* Half pixel variables */ - ogg_int32_t HalfPixelError; - ogg_int32_t BestHalfPixelError; - unsigned char BestHalfOffset; - unsigned char * RefDataPtr1; - unsigned char * RefDataPtr2; - - dsp_save_fpu (cpi->dsp); - - /* Note which of the four blocks in the macro block are to be - included in the search. */ - MBlockDispFrags[0] = cpi-> - pb.display_fragments[FragIndex]; - MBlockDispFrags[1] = cpi-> - pb.display_fragments[FragIndex + 1]; - MBlockDispFrags[2] = cpi-> - pb.display_fragments[FragIndex + cpi->pb.HFragments]; - MBlockDispFrags[3] = cpi-> - pb.display_fragments[FragIndex + cpi->pb.HFragments + 1]; - - /* Set up the source pointers for the four source blocks. */ - SrcPtr[0] = &cpi-> - ConvDestBuffer[cpi->pb.pixel_index_table[FragIndex]]; - SrcPtr[1] = SrcPtr[0] + 8; - SrcPtr[2] = SrcPtr[0] + (PixelsPerLine * 8); - SrcPtr[3] = SrcPtr[2] + 8; - - RefPtr = &RefFramePtr[cpi->pb.recon_pixel_index_table[FragIndex]]; - RefPtr = RefPtr - ((MAX_MV_EXTENT/2) * cpi-> - pb.YStride) - (MAX_MV_EXTENT/2); - - /* Search each pixel alligned site */ - for ( i = 0; i < (ogg_int32_t)MAX_MV_EXTENT; i ++ ) { - /* Starting position in row */ - CandidateBlockPtr = RefPtr; - - for ( j = 0; j < (ogg_int32_t)MAX_MV_EXTENT; j++ ) { - /* Reset error */ - Error = 0; - - /* Summ errors for each block. */ - if ( MBlockDispFrags[0] ) { - Error += dsp_sad8x8 (cpi->dsp, SrcPtr[0], PixelsPerLine, CandidateBlockPtr, - PixelsPerLine + STRIDE_EXTRA); - } - if ( MBlockDispFrags[1] ){ - Error += dsp_sad8x8 (cpi->dsp, SrcPtr[1], PixelsPerLine, CandidateBlockPtr + 8, - PixelsPerLine + STRIDE_EXTRA); - } - if ( MBlockDispFrags[2] ){ - Error += dsp_sad8x8 (cpi->dsp, SrcPtr[2], PixelsPerLine, CandidateBlockPtr + RefRow2Offset, - PixelsPerLine + STRIDE_EXTRA); - } - if ( MBlockDispFrags[3] ){ - Error += dsp_sad8x8 (cpi->dsp, SrcPtr[3], PixelsPerLine, CandidateBlockPtr + RefRow2Offset + 8, - PixelsPerLine + STRIDE_EXTRA); - } - - /* Was this the best so far */ - if ( Error < MinError ) { - MinError = Error; - BestBlockPtr = CandidateBlockPtr; - x = 16 + j - MAX_MV_EXTENT; - y = 16 + i - MAX_MV_EXTENT; - } - - /* Move the the next site */ - CandidateBlockPtr ++; - } - - /* Move on to the next row. */ - RefPtr += cpi->pb.YStride; - - } - - /* Factor vectors to 1/2 pixel resoultion. */ - MV->x = (x * 2); - MV->y = (y * 2); - - /* Now do the half pixel pass */ - BestHalfOffset = 4; /* Default to the no offset case. */ - BestHalfPixelError = MinError; - - /* Get the half pixel error for each half pixel offset */ - for ( i=0; i < 9; i++ ) { - HalfPixelError = 0; - - if ( MBlockDispFrags[0] ) { - RefDataPtr1 = BestBlockPtr; - RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i]; - HalfPixelError = - GetHalfPixelSumAbsDiffs(cpi, SrcPtr[0], RefDataPtr1, RefDataPtr2, - PixelsPerLine, HalfPixelError, BestHalfPixelError ); - } - - if ( MBlockDispFrags[1] && (HalfPixelError < BestHalfPixelError) ) { - RefDataPtr1 = BestBlockPtr + 8; - RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i]; - HalfPixelError = - GetHalfPixelSumAbsDiffs(cpi, SrcPtr[1], RefDataPtr1, RefDataPtr2, - PixelsPerLine, HalfPixelError, BestHalfPixelError ); - } - - if ( MBlockDispFrags[2] && (HalfPixelError < BestHalfPixelError) ) { - RefDataPtr1 = BestBlockPtr + RefRow2Offset; - RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i]; - HalfPixelError = - GetHalfPixelSumAbsDiffs(cpi, SrcPtr[2], RefDataPtr1, RefDataPtr2, - PixelsPerLine, HalfPixelError, BestHalfPixelError ); - } - - if ( MBlockDispFrags[3] && (HalfPixelError < BestHalfPixelError) ) { - RefDataPtr1 = BestBlockPtr + RefRow2Offset + 8; - RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i]; - HalfPixelError = - GetHalfPixelSumAbsDiffs(cpi, SrcPtr[3], RefDataPtr1, RefDataPtr2, - PixelsPerLine, HalfPixelError, BestHalfPixelError ); - } - - if ( HalfPixelError < BestHalfPixelError ){ - BestHalfOffset = (unsigned char)i; - BestHalfPixelError = HalfPixelError; - } - } - - /* Half pixel adjust the MV */ - MV->x += cpi->HalfPixelXOffset[BestHalfOffset]; - MV->y += cpi->HalfPixelYOffset[BestHalfOffset]; - - /* Get the error score for the chosen 1/2 pixel offset as a variance. */ - InterMVError = GetMBInterError( cpi, cpi->ConvDestBuffer, RefFramePtr, - FragIndex, MV->x, MV->y, PixelsPerLine ); - - dsp_restore_fpu (cpi->dsp); - - /* Return score of best matching block. */ - return InterMVError; -} - -static ogg_uint32_t GetBMVExhaustiveSearch (CP_INSTANCE *cpi, - unsigned char * RefFramePtr, - ogg_uint32_t FragIndex, - ogg_uint32_t PixelsPerLine, - MOTION_VECTOR *MV ) { - ogg_uint32_t Error = 0; - ogg_uint32_t MinError = HUGE_ERROR; - ogg_uint32_t InterMVError = 0; - - ogg_int32_t i, j; - ogg_int32_t x=0, y=0; - - unsigned char *SrcPtr = NULL; - unsigned char *RefPtr; - unsigned char *CandidateBlockPtr=NULL; - unsigned char *BestBlockPtr=NULL; - - /* Half pixel variables */ - ogg_int32_t HalfPixelError; - ogg_int32_t BestHalfPixelError; - unsigned char BestHalfOffset; - unsigned char * RefDataPtr2; - - /* Set up the source pointer for the block. */ - SrcPtr = &cpi-> - ConvDestBuffer[cpi->pb.pixel_index_table[FragIndex]]; - - RefPtr = &RefFramePtr[cpi->pb.recon_pixel_index_table[FragIndex]]; - RefPtr = RefPtr - ((MAX_MV_EXTENT/2) * - cpi->pb.YStride) - (MAX_MV_EXTENT/2); - - /* Search each pixel alligned site */ - for ( i = 0; i < (ogg_int32_t)MAX_MV_EXTENT; i ++ ) { - /* Starting position in row */ - CandidateBlockPtr = RefPtr; - - for ( j = 0; j < (ogg_int32_t)MAX_MV_EXTENT; j++ ){ - /* Get the block error score. */ - Error = dsp_sad8x8 (cpi->dsp, SrcPtr, PixelsPerLine, CandidateBlockPtr, - PixelsPerLine + STRIDE_EXTRA); - - /* Was this the best so far */ - if ( Error < MinError ) { - MinError = Error; - BestBlockPtr = CandidateBlockPtr; - x = 16 + j - MAX_MV_EXTENT; - y = 16 + i - MAX_MV_EXTENT; - } - - /* Move the the next site */ - CandidateBlockPtr ++; - } - - /* Move on to the next row. */ - RefPtr += cpi->pb.YStride; - } - - /* Factor vectors to 1/2 pixel resoultion. */ - MV->x = (x * 2); - MV->y = (y * 2); - - /* Now do the half pixel pass */ - BestHalfOffset = 4; /* Default to the no offset case. */ - BestHalfPixelError = MinError; - - /* Get the half pixel error for each half pixel offset */ - for ( i=0; i < 9; i++ ) { - RefDataPtr2 = BestBlockPtr + cpi->HalfPixelRef2Offset[i]; - HalfPixelError = - GetHalfPixelSumAbsDiffs(cpi, SrcPtr, BestBlockPtr, RefDataPtr2, - PixelsPerLine, 0, BestHalfPixelError ); - - if ( HalfPixelError < BestHalfPixelError ){ - BestHalfOffset = (unsigned char)i; - BestHalfPixelError = HalfPixelError; - } - } - - /* Half pixel adjust the MV */ - MV->x += cpi->HalfPixelXOffset[BestHalfOffset]; - MV->y += cpi->HalfPixelYOffset[BestHalfOffset]; - - /* Get the variance score at the chosen offset */ - RefDataPtr2 = BestBlockPtr + cpi->HalfPixelRef2Offset[BestHalfOffset]; - - InterMVError = - GetInterErr(cpi, SrcPtr, BestBlockPtr, RefDataPtr2, PixelsPerLine ); - - /* Return score of best matching block. */ - return InterMVError; -} - -ogg_uint32_t GetFOURMVExhaustiveSearch (CP_INSTANCE *cpi, - unsigned char * RefFramePtr, - ogg_uint32_t FragIndex, - ogg_uint32_t PixelsPerLine, - MOTION_VECTOR *MV ) { - ogg_uint32_t InterMVError; - - dsp_save_fpu (cpi->dsp); - - /* For the moment the 4MV mode is only deemed to be valid - if all four Y blocks are to be updated */ - /* This may be adapted later. */ - if ( cpi->pb.display_fragments[FragIndex] && - cpi->pb.display_fragments[FragIndex + 1] && - cpi->pb.display_fragments[FragIndex + cpi->pb.HFragments] && - cpi->pb.display_fragments[FragIndex + cpi->pb.HFragments + 1] ) { - - /* Reset the error score. */ - InterMVError = 0; - - /* Get the error component from each coded block */ - InterMVError += - GetBMVExhaustiveSearch(cpi, RefFramePtr, FragIndex, - PixelsPerLine, &(MV[0]) ); - InterMVError += - GetBMVExhaustiveSearch(cpi, RefFramePtr, (FragIndex + 1), - PixelsPerLine, &(MV[1]) ); - InterMVError += - GetBMVExhaustiveSearch(cpi, RefFramePtr, - (FragIndex + cpi->pb.HFragments), - PixelsPerLine, &(MV[2]) ); - InterMVError += - GetBMVExhaustiveSearch(cpi, RefFramePtr, - (FragIndex + cpi->pb.HFragments + 1), - PixelsPerLine, &(MV[3]) ); - }else{ - InterMVError = HUGE_ERROR; - } - - dsp_restore_fpu (cpi->dsp); - - /* Return score of best matching block. */ - return InterMVError; -} - diff --git a/Engine/lib/libtheora/lib/enc/misc_common.c b/Engine/lib/libtheora/lib/enc/misc_common.c deleted file mode 100644 index 1536a494a..000000000 --- a/Engine/lib/libtheora/lib/enc/misc_common.c +++ /dev/null @@ -1,339 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: misc_common.c 15323 2008-09-19 19:43:59Z giles $ - - ********************************************************************/ - -#include -#include "codec_internal.h" -#include "block_inline.h" - -#define FIXED_Q 150 -#define MAX_UP_REG_LOOPS 2 - -/* Gives the initial bytes per block estimate for each Q value */ -static const double BpbTable[Q_TABLE_SIZE] = { - 0.42, 0.45, 0.46, 0.49, 0.51, 0.53, 0.56, 0.58, - 0.61, 0.64, 0.68, 0.71, 0.74, 0.77, 0.80, 0.84, - 0.89, 0.92, 0.98, 1.01, 1.04, 1.13, 1.17, 1.23, - 1.28, 1.34, 1.41, 1.45, 1.51, 1.59, 1.69, 1.80, - 1.84, 1.94, 2.02, 2.15, 2.23, 2.34, 2.44, 2.50, - 2.69, 2.80, 2.87, 3.04, 3.16, 3.29, 3.59, 3.66, - 3.86, 3.94, 4.22, 4.50, 4.64, 4.70, 5.24, 5.34, - 5.61, 5.87, 6.11, 6.41, 6.71, 6.99, 7.36, 7.69 -}; - -static const double KfBpbTable[Q_TABLE_SIZE] = { - 0.74, 0.81, 0.88, 0.94, 1.00, 1.06, 1.14, 1.19, - 1.27, 1.34, 1.42, 1.49, 1.54, 1.59, 1.66, 1.73, - 1.80, 1.87, 1.97, 2.01, 2.08, 2.21, 2.25, 2.36, - 2.39, 2.50, 2.55, 2.65, 2.71, 2.82, 2.95, 3.01, - 3.11, 3.19, 3.31, 3.42, 3.58, 3.66, 3.78, 3.89, - 4.11, 4.26, 4.36, 4.39, 4.63, 4.76, 4.85, 5.04, - 5.26, 5.29, 5.47, 5.64, 5.76, 6.05, 6.35, 6.67, - 6.91, 7.17, 7.40, 7.56, 8.02, 8.45, 8.86, 9.38 -}; - -double GetEstimatedBpb( CP_INSTANCE *cpi, ogg_uint32_t TargetQ ){ - ogg_uint32_t i; - ogg_int32_t ThreshTableIndex = Q_TABLE_SIZE - 1; - double BytesPerBlock; - - /* Search for the Q table index that matches the given Q. */ - for ( i = 0; i < Q_TABLE_SIZE; i++ ) { - if ( TargetQ >= cpi->pb.QThreshTable[i] ) { - ThreshTableIndex = i; - break; - } - } - - /* Adjust according to Q shift and type of frame */ - if ( cpi->pb.FrameType == KEY_FRAME ) { - /* Get primary prediction */ - BytesPerBlock = KfBpbTable[ThreshTableIndex]; - } else { - /* Get primary prediction */ - BytesPerBlock = BpbTable[ThreshTableIndex]; - BytesPerBlock = BytesPerBlock * cpi->BpbCorrectionFactor; - } - - return BytesPerBlock; -} - -static void UpRegulateMB( CP_INSTANCE *cpi, ogg_uint32_t RegulationQ, - ogg_uint32_t SB, ogg_uint32_t MB, int NoCheck ) { - ogg_int32_t FragIndex; - ogg_uint32_t B; - - /* Variables used in calculating corresponding row,col and index in - UV planes */ - ogg_uint32_t UVRow; - ogg_uint32_t UVColumn; - ogg_uint32_t UVFragOffset; - - /* There may be MB's lying out of frame which must be ignored. For - these MB's Top left block will have a negative Fragment Index. */ - if ( QuadMapToMBTopLeft(cpi->pb.BlockMap, SB, MB ) >= 0 ) { - /* Up regulate the component blocks Y then UV. */ - for ( B=0; B<4; B++ ){ - FragIndex = QuadMapToIndex1( cpi->pb.BlockMap, SB, MB, B ); - - if ( ( !cpi->pb.display_fragments[FragIndex] ) && - ( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ){ - cpi->pb.display_fragments[FragIndex] = 1; - cpi->extra_fragments[FragIndex] = 1; - cpi->FragmentLastQ[FragIndex] = RegulationQ; - cpi->MotionScore++; - } - } - - /* Check the two UV blocks */ - FragIndex = QuadMapToMBTopLeft(cpi->pb.BlockMap, SB, MB ); - - UVRow = (FragIndex / (cpi->pb.HFragments * 2)); - UVColumn = (FragIndex % cpi->pb.HFragments) / 2; - UVFragOffset = (UVRow * (cpi->pb.HFragments / 2)) + UVColumn; - - FragIndex = cpi->pb.YPlaneFragments + UVFragOffset; - if ( ( !cpi->pb.display_fragments[FragIndex] ) && - ( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ) { - cpi->pb.display_fragments[FragIndex] = 1; - cpi->extra_fragments[FragIndex] = 1; - cpi->FragmentLastQ[FragIndex] = RegulationQ; - cpi->MotionScore++; - } - - FragIndex += cpi->pb.UVPlaneFragments; - if ( ( !cpi->pb.display_fragments[FragIndex] ) && - ( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ) { - cpi->pb.display_fragments[FragIndex] = 1; - cpi->extra_fragments[FragIndex] = 1; - cpi->FragmentLastQ[FragIndex] = RegulationQ; - cpi->MotionScore++; - } - } -} - -static void UpRegulateBlocks (CP_INSTANCE *cpi, ogg_uint32_t RegulationQ, - ogg_int32_t RecoveryBlocks, - ogg_uint32_t * LastSB, ogg_uint32_t * LastMB ) { - - ogg_uint32_t LoopTimesRound = 0; - ogg_uint32_t MaxSB = cpi->pb.YSBRows * - cpi->pb.YSBCols; /* Tot super blocks in image */ - ogg_uint32_t SB, MB; /* Super-Block and macro block indices. */ - - /* First scan for blocks for which a residue update is outstanding. */ - while ( (cpi->MotionScore < RecoveryBlocks) && - (LoopTimesRound < MAX_UP_REG_LOOPS) ) { - LoopTimesRound++; - - for ( SB = (*LastSB); SB < MaxSB; SB++ ) { - /* Check its four Macro-Blocks */ - for ( MB=(*LastMB); MB<4; MB++ ) { - /* Mark relevant blocks for update */ - UpRegulateMB( cpi, RegulationQ, SB, MB, 0 ); - - /* Keep track of the last refresh MB. */ - (*LastMB) += 1; - if ( (*LastMB) == 4 ) - (*LastMB) = 0; - - /* Termination clause */ - if (cpi->MotionScore >= RecoveryBlocks) { - /* Make sure we don't stall at SB level */ - if ( *LastMB == 0 ) - SB++; - break; - } - } - - /* Termination clause */ - if (cpi->MotionScore >= RecoveryBlocks) - break; - } - - /* Update super block start index */ - if ( SB >= MaxSB){ - (*LastSB) = 0; - }else{ - (*LastSB) = SB; - } - } -} - -void UpRegulateDataStream (CP_INSTANCE *cpi, ogg_uint32_t RegulationQ, - ogg_int32_t RecoveryBlocks ) { - ogg_uint32_t LastPassMBPos = 0; - ogg_uint32_t StdLastMBPos = 0; - - ogg_uint32_t MaxSB = cpi->pb.YSBRows * - cpi->pb.YSBCols; /* Tot super blocks in image */ - - ogg_uint32_t SB=0; /* Super-Block index */ - ogg_uint32_t MB; /* Macro-Block index */ - - /* Decduct the number of blocks in an MB / 2 from the recover block count. - This will compensate for the fact that once we start checking an MB - we test every block in that macro block */ - if ( RecoveryBlocks > 3 ) - RecoveryBlocks -= 3; - - /* Up regulate blocks last coded at higher Q */ - UpRegulateBlocks( cpi, RegulationQ, RecoveryBlocks, - &cpi->LastEndSB, &StdLastMBPos ); - - /* If we have still not used up the minimum number of blocks and are - at the minimum Q then run through a final pass of the data to - insure that each block gets a final refresh. */ - if ( (RegulationQ == VERY_BEST_Q) && - (cpi->MotionScore < RecoveryBlocks) ) { - if ( cpi->FinalPassLastPos < MaxSB ) { - for ( SB = cpi->FinalPassLastPos; SB < MaxSB; SB++ ) { - /* Check its four Macro-Blocks */ - for ( MB=LastPassMBPos; MB<4; MB++ ) { - /* Mark relevant blocks for update */ - UpRegulateMB( cpi, RegulationQ, SB, MB, 1 ); - - /* Keep track of the last refresh MB. */ - LastPassMBPos += 1; - if ( LastPassMBPos == 4 ) { - LastPassMBPos = 0; - - /* Increment SB index */ - cpi->FinalPassLastPos += 1; - } - - /* Termination clause */ - if (cpi->MotionScore >= RecoveryBlocks) - break; - } - - /* Termination clause */ - if (cpi->MotionScore >= RecoveryBlocks) - break; - - } - } - } -} - -void RegulateQ( CP_INSTANCE *cpi, ogg_int32_t UpdateScore ) { - double PredUnitScoreBytes; - ogg_uint32_t QIndex = Q_TABLE_SIZE - 1; - ogg_uint32_t i; - - if ( UpdateScore > 0 ) { - double TargetUnitScoreBytes = (double)cpi->ThisFrameTargetBytes / - (double)UpdateScore; - double LastBitError = 10000.0; /* Silly high number */ - /* Search for the best Q for the target bitrate. */ - for ( i = 0; i < Q_TABLE_SIZE; i++ ) { - PredUnitScoreBytes = GetEstimatedBpb( cpi, cpi->pb.QThreshTable[i] ); - if ( PredUnitScoreBytes > TargetUnitScoreBytes ) { - if ( (PredUnitScoreBytes - TargetUnitScoreBytes) <= LastBitError ) { - QIndex = i; - } else { - QIndex = i - 1; - } - break; - } else { - LastBitError = TargetUnitScoreBytes - PredUnitScoreBytes; - } - } - } - - /* QIndex should now indicate the optimal Q. */ - cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[QIndex]; - - /* Apply range restrictions for key frames. */ - if ( cpi->pb.FrameType == KEY_FRAME ) { - if ( cpi->pb.ThisFrameQualityValue > cpi->pb.QThreshTable[20] ) - cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[20]; - else if ( cpi->pb.ThisFrameQualityValue < cpi->pb.QThreshTable[50] ) - cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[50]; - } - - /* Limit the Q value to the maximum available value */ - if (cpi->pb.ThisFrameQualityValue > - cpi->pb.QThreshTable[cpi->Configuration.ActiveMaxQ]) { - cpi->pb.ThisFrameQualityValue = - (ogg_uint32_t)cpi->pb.QThreshTable[cpi->Configuration.ActiveMaxQ]; - } - - if(cpi->FixedQ) { - if ( cpi->pb.FrameType == KEY_FRAME ) { - cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[43]; - cpi->pb.ThisFrameQualityValue = cpi->FixedQ; - } else { - cpi->pb.ThisFrameQualityValue = cpi->FixedQ; - } - } - - /* If the quantizer value has changed then re-initialise it */ - if ( cpi->pb.ThisFrameQualityValue != cpi->pb.LastFrameQualityValue ) { - /* Initialise quality tables. */ - UpdateQC( cpi, cpi->pb.ThisFrameQualityValue ); - cpi->pb.LastFrameQualityValue = cpi->pb.ThisFrameQualityValue; - } -} - -void CopyBackExtraFrags(CP_INSTANCE *cpi){ - ogg_uint32_t i,j; - unsigned char * SrcPtr; - unsigned char * DestPtr; - ogg_uint32_t PlaneLineStep; - ogg_uint32_t PixelIndex; - - /* Copy back for Y plane. */ - PlaneLineStep = cpi->pb.info.width; - for ( i = 0; i < cpi->pb.YPlaneFragments; i++ ) { - /* We are only interested in updated fragments. */ - if ( cpi->extra_fragments[i] ) { - /* Get the start index for the fragment. */ - PixelIndex = cpi->pb.pixel_index_table[i]; - SrcPtr = &cpi->yuv1ptr[PixelIndex]; - DestPtr = &cpi->ConvDestBuffer[PixelIndex]; - - for ( j = 0; j < VFRAGPIXELS; j++ ) { - memcpy( DestPtr, SrcPtr, HFRAGPIXELS); - - SrcPtr += PlaneLineStep; - DestPtr += PlaneLineStep; - } - } - } - - /* Now the U and V planes */ - PlaneLineStep = cpi->pb.info.width / 2; - for ( i = cpi->pb.YPlaneFragments; - i < (cpi->pb.YPlaneFragments + (2 * cpi->pb.UVPlaneFragments)) ; - i++ ) { - - /* We are only interested in updated fragments. */ - if ( cpi->extra_fragments[i] ) { - /* Get the start index for the fragment. */ - PixelIndex = cpi->pb.pixel_index_table[i]; - SrcPtr = &cpi->yuv1ptr[PixelIndex]; - DestPtr = &cpi->ConvDestBuffer[PixelIndex]; - - for ( j = 0; j < VFRAGPIXELS; j++ ) { - memcpy( DestPtr, SrcPtr, HFRAGPIXELS); - SrcPtr += PlaneLineStep; - DestPtr += PlaneLineStep; - } - } - } -} - diff --git a/Engine/lib/libtheora/lib/enc/pb.c b/Engine/lib/libtheora/lib/enc/pb.c deleted file mode 100644 index 42047249a..000000000 --- a/Engine/lib/libtheora/lib/enc/pb.c +++ /dev/null @@ -1,89 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: pb.c 14372 2008-01-05 23:52:28Z giles $ - - ********************************************************************/ - -#include -#include -#include "codec_internal.h" - -void ClearTmpBuffers(PB_INSTANCE * pbi){ - - if(pbi->ReconDataBuffer) - _ogg_free(pbi->ReconDataBuffer); - if(pbi->DequantBuffer) - _ogg_free(pbi->DequantBuffer); - if(pbi->TmpDataBuffer) - _ogg_free(pbi->TmpDataBuffer); - if(pbi->TmpReconBuffer) - _ogg_free(pbi->TmpReconBuffer); - - - pbi->ReconDataBuffer=0; - pbi->DequantBuffer = 0; - pbi->TmpDataBuffer = 0; - pbi->TmpReconBuffer = 0; - -} - -void InitTmpBuffers(PB_INSTANCE * pbi){ - - /* clear any existing info */ - ClearTmpBuffers(pbi); - - /* Adjust the position of all of our temporary */ - pbi->ReconDataBuffer = - _ogg_malloc(64*sizeof(*pbi->ReconDataBuffer)); - - pbi->DequantBuffer = - _ogg_malloc(64 * sizeof(*pbi->DequantBuffer)); - - pbi->TmpDataBuffer = - _ogg_malloc(64 * sizeof(*pbi->TmpDataBuffer)); - - pbi->TmpReconBuffer = - _ogg_malloc(64 * sizeof(*pbi->TmpReconBuffer)); - -} - -void ClearPBInstance(PB_INSTANCE *pbi){ - if(pbi){ - ClearTmpBuffers(pbi); - if (pbi->opb) { - _ogg_free(pbi->opb); - } - } -} - -void InitPBInstance(PB_INSTANCE *pbi){ - /* initialize whole structure to 0 */ - memset(pbi, 0, sizeof(*pbi)); - - InitTmpBuffers(pbi); - - /* allocate memory for the oggpack_buffer */ - pbi->opb = _ogg_malloc(sizeof(oggpack_buffer)); - - /* variables needing initialization (not being set to 0) */ - - pbi->ModifierPointer[0] = &pbi->Modifier[0][255]; - pbi->ModifierPointer[1] = &pbi->Modifier[1][255]; - pbi->ModifierPointer[2] = &pbi->Modifier[2][255]; - pbi->ModifierPointer[3] = &pbi->Modifier[3][255]; - - pbi->DecoderErrorCode = 0; - pbi->KeyFrameType = DCT_KEY_FRAME; - pbi->FramesHaveBeenSkipped = 0; -} diff --git a/Engine/lib/libtheora/lib/enc/pp.c b/Engine/lib/libtheora/lib/enc/pp.c deleted file mode 100644 index c45289703..000000000 --- a/Engine/lib/libtheora/lib/enc/pp.c +++ /dev/null @@ -1,951 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: pp.c 15057 2008-06-22 21:07:32Z xiphmont $ - - ********************************************************************/ - -#include -#include -#include "codec_internal.h" -#include "pp.h" -#include "dsp.h" - -#define MAX(a, b) ((a>b)?a:b) -#define MIN(a, b) ((aScanPixelIndexTable) _ogg_free(ppi->ScanPixelIndexTable); - ppi->ScanPixelIndexTable=0; - - if(ppi->ScanDisplayFragments) _ogg_free(ppi->ScanDisplayFragments); - ppi->ScanDisplayFragments=0; - - for(i = 0 ; i < MAX_PREV_FRAMES ; i ++) - if(ppi->PrevFragments[i]){ - _ogg_free(ppi->PrevFragments[i]); - ppi->PrevFragments[i]=0; - } - - if(ppi->FragScores) _ogg_free(ppi->FragScores); - ppi->FragScores=0; - - if(ppi->SameGreyDirPixels) _ogg_free(ppi->SameGreyDirPixels); - ppi->SameGreyDirPixels=0; - - if(ppi->FragDiffPixels) _ogg_free(ppi->FragDiffPixels); - ppi->FragDiffPixels=0; - - if(ppi->BarBlockMap) _ogg_free(ppi->BarBlockMap); - ppi->BarBlockMap=0; - - if(ppi->TmpCodedMap) _ogg_free(ppi->TmpCodedMap); - ppi->TmpCodedMap=0; - - if(ppi->RowChangedPixels) _ogg_free(ppi->RowChangedPixels); - ppi->RowChangedPixels=0; - - if(ppi->PixelScores) _ogg_free(ppi->PixelScores); - ppi->PixelScores=0; - - if(ppi->PixelChangedMap) _ogg_free(ppi->PixelChangedMap); - ppi->PixelChangedMap=0; - - if(ppi->ChLocals) _ogg_free(ppi->ChLocals); - ppi->ChLocals=0; - - if(ppi->yuv_differences) _ogg_free(ppi->yuv_differences); - ppi->yuv_differences=0; - -} - -void PInitFrameInfo(PP_INSTANCE * ppi){ - int i; - PClearFrameInfo(ppi); - - ppi->ScanPixelIndexTable = - _ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->ScanPixelIndexTable)); - - ppi->ScanDisplayFragments = - _ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->ScanDisplayFragments)); - - for(i = 0 ; i < MAX_PREV_FRAMES ; i ++) - ppi->PrevFragments[i] = - _ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->PrevFragments)); - - ppi->FragScores = - _ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->FragScores)); - - ppi->SameGreyDirPixels = - _ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->SameGreyDirPixels)); - - ppi->FragDiffPixels = - _ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->FragScores)); - - ppi->BarBlockMap= - _ogg_malloc(3 * ppi->ScanHFragments*sizeof(*ppi->BarBlockMap)); - - ppi->TmpCodedMap = - _ogg_malloc(ppi->ScanHFragments*sizeof(*ppi->TmpCodedMap)); - - ppi->RowChangedPixels = - _ogg_malloc(3 * ppi->ScanConfig.VideoFrameHeight* - sizeof(*ppi->RowChangedPixels)); - - ppi->PixelScores = - _ogg_malloc(ppi->ScanConfig.VideoFrameWidth* - sizeof(*ppi->PixelScores) * PSCORE_CB_ROWS); - - ppi->PixelChangedMap = - _ogg_malloc(ppi->ScanConfig.VideoFrameWidth* - sizeof(*ppi->PixelChangedMap) * PMAP_CB_ROWS); - - ppi->ChLocals = - _ogg_malloc(ppi->ScanConfig.VideoFrameWidth* - sizeof(*ppi->ChLocals) * CHLOCALS_CB_ROWS); - - ppi->yuv_differences = - _ogg_malloc(ppi->ScanConfig.VideoFrameWidth* - sizeof(*ppi->yuv_differences) * YDIFF_CB_ROWS); -} - -void ClearPPInstance(PP_INSTANCE *ppi){ - PClearFrameInfo(ppi); -} - - -void InitPPInstance(PP_INSTANCE *ppi, DspFunctions *funcs){ - - memset(ppi,0,sizeof(*ppi)); - - memcpy(&ppi->dsp, funcs, sizeof(DspFunctions)); - - /* Initializations */ - ppi->PrevFrameLimit = 3; /* Must not exceed MAX_PREV_FRAMES (Note - that this number includes the current - frame so "1 = no effect") */ - - /* Scan control variables. */ - ppi->HFragPixels = 8; - ppi->VFragPixels = 8; - - ppi->SRFGreyThresh = 4; - ppi->SRFColThresh = 5; - ppi->NoiseSupLevel = 3; - ppi->SgcLevelThresh = 3; - ppi->SuvcLevelThresh = 4; - - /* Variables controlling S.A.D. breakouts. */ - ppi->GrpLowSadThresh = 10; - ppi->GrpHighSadThresh = 64; - ppi->PrimaryBlockThreshold = 5; - ppi->SgcThresh = 16; /* (Default values for 8x8 blocks). */ - - ppi->UVBlockThreshCorrection = 1.25; - ppi->UVSgcCorrection = 1.5; - - ppi->MaxLineSearchLen = MAX_SEARCH_LINE_LEN; -} - -static void DeringBlockStrong(unsigned char *SrcPtr, - unsigned char *DstPtr, - ogg_int32_t Pitch, - ogg_uint32_t FragQIndex, - const ogg_uint32_t *QuantScale){ - - ogg_int16_t UDMod[72]; - ogg_int16_t LRMod[72]; - unsigned int j,k,l; - const unsigned char * Src; - unsigned int QValue = QuantScale[FragQIndex]; - - unsigned char p; - unsigned char pl; - unsigned char pr; - unsigned char pu; - unsigned char pd; - - int al; - int ar; - int au; - int ad; - - int atot; - int B; - int newVal; - - const unsigned char *curRow = SrcPtr - 1; /* avoid negative array indexes */ - unsigned char *dstRow = DstPtr; - const unsigned char *lastRow = SrcPtr-Pitch; - const unsigned char *nextRow = SrcPtr+Pitch; - - unsigned int rowOffset = 0; - unsigned int round = (1<<6); - - int High; - int Low; - int TmpMod; - - int Sharpen = SharpenModifier[FragQIndex]; - High = 3 * QValue; - if(High>32)High=32; - Low = 0; - - - /* Initialize the Mod Data */ - Src = SrcPtr-Pitch; - for(k=0;k<9;k++){ - for(j=0;j<8;j++){ - - TmpMod = 32 + QValue - (abs(Src[j+Pitch]-Src[j])); - - if(TmpMod< -64) - TmpMod = Sharpen; - - else if(TmpModHigh) - TmpMod = High; - - UDMod[k*8+j] = (ogg_int16_t)TmpMod; - } - Src +=Pitch; - } - - Src = SrcPtr-1; - - for(k=0;k<8;k++){ - for(j=0;j<9;j++){ - TmpMod = 32 + QValue - (abs(Src[j+1]-Src[j])); - - if(TmpMod< -64 ) - TmpMod = Sharpen; - - else if(TmpMod<0) - TmpMod = Low; - - else if(TmpMod>High) - TmpMod = High; - - LRMod[k*9+j] = (ogg_int16_t)TmpMod; - } - Src+=Pitch; - } - - for(k=0;k<8;k++){ - /* In the case that this function called with same buffer for - source and destination, To keep the c and the mmx version to have - consistant results, intermediate buffer is used to store the - eight pixel value before writing them to destination - (i.e. Overwriting souce for the speical case) */ - for(l=0;l<8;l++){ - - atot = 128; - B = round; - p = curRow[ rowOffset +l +1]; - - pl = curRow[ rowOffset +l]; - al = LRMod[k*9+l]; - atot -= al; - B += al * pl; - - pu = lastRow[ rowOffset +l]; - au = UDMod[k*8+l]; - atot -= au; - B += au * pu; - - pd = nextRow[ rowOffset +l]; - ad = UDMod[(k+1)*8+l]; - atot -= ad; - B += ad * pd; - - pr = curRow[ rowOffset +l+2]; - ar = LRMod[k*9+l+1]; - atot -= ar; - B += ar * pr; - - newVal = ( atot * p + B) >> 7; - - dstRow[ rowOffset +l]= clamp255( newVal ); - } - rowOffset += Pitch; - } -} - -static void DeringBlockWeak(unsigned char *SrcPtr, - unsigned char *DstPtr, - ogg_int32_t Pitch, - ogg_uint32_t FragQIndex, - const ogg_uint32_t *QuantScale){ - - ogg_int16_t UDMod[72]; - ogg_int16_t LRMod[72]; - unsigned int j,k; - const unsigned char * Src; - unsigned int QValue = QuantScale[FragQIndex]; - - unsigned char p; - unsigned char pl; - unsigned char pr; - unsigned char pu; - unsigned char pd; - - int al; - int ar; - int au; - int ad; - - int atot; - int B; - int newVal; - - const unsigned char *curRow = SrcPtr-1; - unsigned char *dstRow = DstPtr; - const unsigned char *lastRow = SrcPtr-Pitch; - const unsigned char *nextRow = SrcPtr+Pitch; - - unsigned int rowOffset = 0; - unsigned int round = (1<<6); - - int High; - int Low; - int TmpMod; - int Sharpen = SharpenModifier[FragQIndex]; - - High = 3 * QValue; - if(High>24) - High=24; - Low = 0 ; - - /* Initialize the Mod Data */ - Src=SrcPtr-Pitch; - for(k=0;k<9;k++) { - for(j=0;j<8;j++) { - - TmpMod = 32 + QValue - 2*(abs(Src[j+Pitch]-Src[j])); - - if(TmpMod< -64) - TmpMod = Sharpen; - - else if(TmpModHigh) - TmpMod = High; - - UDMod[k*8+j] = (ogg_int16_t)TmpMod; - } - Src +=Pitch; - } - - Src = SrcPtr-1; - - for(k=0;k<8;k++){ - for(j=0;j<9;j++){ - TmpMod = 32 + QValue - 2*(abs(Src[j+1]-Src[j])); - - if(TmpMod< -64 ) - TmpMod = Sharpen; - - else if(TmpModHigh) - TmpMod = High; - - LRMod[k*9+j] = (ogg_int16_t)TmpMod; - } - Src+=Pitch; - } - - for(k=0;k<8;k++) { - for(j=0;j<8;j++){ - atot = 128; - B = round; - p = curRow[ rowOffset +j+1]; - - pl = curRow[ rowOffset +j]; - al = LRMod[k*9+j]; - atot -= al; - B += al * pl; - - pu = lastRow[ rowOffset +j]; - au = UDMod[k*8+j]; - atot -= au; - B += au * pu; - - pd = nextRow[ rowOffset +j]; - ad = UDMod[(k+1)*8+j]; - atot -= ad; - B += ad * pd; - - pr = curRow[ rowOffset +j+2]; - ar = LRMod[k*9+j+1]; - atot -= ar; - B += ar * pr; - - newVal = ( atot * p + B) >> 7; - - dstRow[ rowOffset +j] = clamp255( newVal ); - } - - rowOffset += Pitch; - } -} - -static void DeringFrame(PB_INSTANCE *pbi, - unsigned char *Src, unsigned char *Dst){ - ogg_uint32_t col,row; - unsigned char *SrcPtr; - unsigned char *DestPtr; - ogg_uint32_t BlocksAcross,BlocksDown; - const ogg_uint32_t *QuantScale; - ogg_uint32_t Block; - ogg_uint32_t LineLength; - - ogg_int32_t Thresh1,Thresh2,Thresh3,Thresh4; - - Thresh1 = 384; - Thresh2 = 4 * Thresh1; - Thresh3 = 5 * Thresh2/4; - Thresh4 = 5 * Thresh2/2; - - QuantScale = DeringModifierV1; - - BlocksAcross = pbi->HFragments; - BlocksDown = pbi->VFragments; - - SrcPtr = Src + pbi->ReconYDataOffset; - DestPtr = Dst + pbi->ReconYDataOffset; - LineLength = pbi->YStride; - - Block = 0; - - for ( row = 0 ; row < BlocksDown; row ++){ - for (col = 0; col < BlocksAcross; col ++){ - ogg_uint32_t Quality = pbi->FragQIndex[Block]; - ogg_int32_t Variance = pbi->FragmentVariances[Block]; - - if( pbi->PostProcessingLevel >5 && Variance > Thresh3 ){ - DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col, - LineLength,Quality,QuantScale); - - if( (col > 0 && - pbi->FragmentVariances[Block-1] > Thresh4 ) || - (col + 1 < BlocksAcross && - pbi->FragmentVariances[Block+1] > Thresh4 ) || - (row + 1 < BlocksDown && - pbi->FragmentVariances[Block+BlocksAcross] > Thresh4) || - (row > 0 && - pbi->FragmentVariances[Block-BlocksAcross] > Thresh4) ){ - - DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col, - LineLength,Quality,QuantScale); - DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col, - LineLength,Quality,QuantScale); - } - } else if(Variance > Thresh2 ) { - - DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col, - LineLength,Quality,QuantScale); - } else if(Variance > Thresh1 ) { - - DeringBlockWeak(SrcPtr + 8 * col, DestPtr + 8 * col, - LineLength,Quality,QuantScale); - - } else { - - dsp_copy8x8(pbi->dsp, SrcPtr + 8 * col, DestPtr + 8 * col, LineLength); - - } - - ++Block; - - } - SrcPtr += 8 * LineLength; - DestPtr += 8 * LineLength; - } - - /* Then U */ - - BlocksAcross /= 2; - BlocksDown /= 2; - LineLength /= 2; - - SrcPtr = Src + pbi->ReconUDataOffset; - DestPtr = Dst + pbi->ReconUDataOffset; - for ( row = 0 ; row < BlocksDown; row ++) { - for (col = 0; col < BlocksAcross; col ++) { - ogg_uint32_t Quality = pbi->FragQIndex[Block]; - ogg_int32_t Variance = pbi->FragmentVariances[Block]; - - if( pbi->PostProcessingLevel >5 && Variance > Thresh4 ) { - DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col, - LineLength,Quality,QuantScale); - DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col, - LineLength,Quality,QuantScale); - DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col, - LineLength,Quality,QuantScale); - - }else if(Variance > Thresh2 ){ - DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col, - LineLength,Quality,QuantScale); - }else if(Variance > Thresh1 ){ - DeringBlockWeak(SrcPtr + 8 * col, DestPtr + 8 * col, - LineLength,Quality,QuantScale); - }else{ - dsp_copy8x8(pbi->dsp, SrcPtr + 8 * col, DestPtr + 8 * col, LineLength); - } - - ++Block; - - } - SrcPtr += 8 * LineLength; - DestPtr += 8 * LineLength; - } - - /* Then V */ - SrcPtr = Src + pbi->ReconVDataOffset; - DestPtr = Dst + pbi->ReconVDataOffset; - - for ( row = 0 ; row < BlocksDown; row ++){ - for (col = 0; col < BlocksAcross; col ++){ - - ogg_uint32_t Quality = pbi->FragQIndex[Block]; - ogg_int32_t Variance = pbi->FragmentVariances[Block]; - - - if( pbi->PostProcessingLevel >5 && Variance > Thresh4 ) { - DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col, - LineLength,Quality,QuantScale); - DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col, - LineLength,Quality,QuantScale); - DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col, - LineLength,Quality,QuantScale); - - }else if(Variance > Thresh2 ){ - DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col, - LineLength,Quality,QuantScale); - }else if(Variance > Thresh1 ){ - DeringBlockWeak(SrcPtr + 8 * col, DestPtr + 8 * col, - LineLength,Quality,QuantScale); - }else{ - dsp_copy8x8(pbi->dsp, SrcPtr + 8 * col, DestPtr + 8 * col, LineLength); - } - - ++Block; - - } - SrcPtr += 8 * LineLength; - DestPtr += 8 * LineLength; - - } - -} - -void UpdateFragQIndex(PB_INSTANCE *pbi){ - - ogg_uint32_t ThisFrameQIndex; - ogg_uint32_t i; - - /* Check this frame quality index */ - ThisFrameQIndex = pbi->FrameQIndex; - - - /* It is not a key frame, so only reset those are coded */ - for( i = 0; i < pbi->UnitFragments; i++ ) - if( pbi->display_fragments[i]) - pbi->FragQIndex[i] = ThisFrameQIndex; - -} - -static void DeblockLoopFilteredBand(PB_INSTANCE *pbi, - unsigned char *SrcPtr, - unsigned char *DesPtr, - ogg_uint32_t PlaneLineStep, - ogg_uint32_t FragsAcross, - ogg_uint32_t StartFrag, - const ogg_uint32_t *QuantScale){ - ogg_uint32_t j,k; - ogg_uint32_t CurrentFrag=StartFrag; - ogg_int32_t QStep; - ogg_int32_t FLimit; - unsigned char *Src, *Des; - ogg_int32_t x[10]; - ogg_int32_t Sum1, Sum2; - - while(CurrentFrag < StartFrag + FragsAcross){ - - Src=SrcPtr+8*(CurrentFrag-StartFrag)-PlaneLineStep*5; - Des=DesPtr+8*(CurrentFrag-StartFrag)-PlaneLineStep*4; - - QStep = QuantScale[pbi->FragQIndex[CurrentFrag+FragsAcross]]; - FLimit = ( QStep * 3 ) >> 2; - - for( j=0; j<8 ; j++){ - x[0] = Src[0]; - x[1] = Src[PlaneLineStep]; - x[2] = Src[PlaneLineStep*2]; - x[3] = Src[PlaneLineStep*3]; - x[4] = Src[PlaneLineStep*4]; - x[5] = Src[PlaneLineStep*5]; - x[6] = Src[PlaneLineStep*6]; - x[7] = Src[PlaneLineStep*7]; - x[8] = Src[PlaneLineStep*8]; - x[9] = Src[PlaneLineStep*9]; - - Sum1=Sum2=0; - - for(k=1;k<=4;k++){ - Sum1 += abs(x[k]-x[k-1]); - Sum2 += abs(x[k+4]-x[k+5]); - } - - pbi->FragmentVariances[CurrentFrag] +=((Sum1>255)?255:Sum1); - pbi->FragmentVariances[CurrentFrag + FragsAcross] += ((Sum2>255)?255:Sum2); - - if( Sum1 < FLimit && - Sum2 < FLimit && - (x[5] - x[4]) < QStep && - (x[4] - x[5]) < QStep ){ - - /* low pass filtering (LPF7: 1 1 1 2 1 1 1) */ - Des[0 ] = (x[0] + x[0] +x[0] + x[1] * 2 + - x[2] + x[3] +x[4] + 4) >> 3; - Des[PlaneLineStep ] = (x[0] + x[0] +x[1] + x[2] * 2 + - x[3] + x[4] +x[5] + 4) >> 3; - Des[PlaneLineStep*2] = (x[0] + x[1] +x[2] + x[3] * 2 + - x[4] + x[5] +x[6] + 4) >> 3; - Des[PlaneLineStep*3] = (x[1] + x[2] +x[3] + x[4] * 2 + - x[5] + x[6] +x[7] + 4) >> 3; - Des[PlaneLineStep*4] = (x[2] + x[3] +x[4] + x[5] * 2 + - x[6] + x[7] +x[8] + 4) >> 3; - Des[PlaneLineStep*5] = (x[3] + x[4] +x[5] + x[6] * 2 + - x[7] + x[8] +x[9] + 4) >> 3; - Des[PlaneLineStep*6] = (x[4] + x[5] +x[6] + x[7] * 2 + - x[8] + x[9] +x[9] + 4) >> 3; - Des[PlaneLineStep*7] = (x[5] + x[6] +x[7] + x[8] * 2 + - x[9] + x[9] +x[9] + 4) >> 3; - - }else { - /* copy the pixels to destination */ - Des[0 ]= (unsigned char)x[1]; - Des[PlaneLineStep ]= (unsigned char)x[2]; - Des[PlaneLineStep*2]= (unsigned char)x[3]; - Des[PlaneLineStep*3]= (unsigned char)x[4]; - Des[PlaneLineStep*4]= (unsigned char)x[5]; - Des[PlaneLineStep*5]= (unsigned char)x[6]; - Des[PlaneLineStep*6]= (unsigned char)x[7]; - Des[PlaneLineStep*7]= (unsigned char)x[8]; - } - Src ++; - Des ++; - } - - - /* done with filtering the horizontal edge, now let's do the - vertical one */ - /* skip the first one */ - if(CurrentFrag==StartFrag) - CurrentFrag++; - else{ - Des=DesPtr-8*PlaneLineStep+8*(CurrentFrag-StartFrag); - Src=Des-5; - Des-=4; - - QStep = QuantScale[pbi->FragQIndex[CurrentFrag]]; - FLimit = ( QStep * 3 ) >> 2; - - for( j=0; j<8 ; j++){ - x[0] = Src[0]; - x[1] = Src[1]; - x[2] = Src[2]; - x[3] = Src[3]; - x[4] = Src[4]; - x[5] = Src[5]; - x[6] = Src[6]; - x[7] = Src[7]; - x[8] = Src[8]; - x[9] = Src[9]; - - Sum1=Sum2=0; - - for(k=1;k<=4;k++){ - Sum1 += abs(x[k]-x[k-1]); - Sum2 += abs(x[k+4]-x[k+5]); - } - - pbi->FragmentVariances[CurrentFrag-1] += ((Sum1>255)?255:Sum1); - pbi->FragmentVariances[CurrentFrag] += ((Sum2>255)?255:Sum2); - - if( Sum1 < FLimit && - Sum2 < FLimit && - (x[5] - x[4]) < QStep && - (x[4] - x[5]) < QStep ){ - - /* low pass filtering (LPF7: 1 1 1 2 1 1 1) */ - Des[0] = (x[0] + x[0] +x[0] + x[1] * 2 + x[2] + x[3] +x[4] + 4) >> 3; - Des[1] = (x[0] + x[0] +x[1] + x[2] * 2 + x[3] + x[4] +x[5] + 4) >> 3; - Des[2] = (x[0] + x[1] +x[2] + x[3] * 2 + x[4] + x[5] +x[6] + 4) >> 3; - Des[3] = (x[1] + x[2] +x[3] + x[4] * 2 + x[5] + x[6] +x[7] + 4) >> 3; - Des[4] = (x[2] + x[3] +x[4] + x[5] * 2 + x[6] + x[7] +x[8] + 4) >> 3; - Des[5] = (x[3] + x[4] +x[5] + x[6] * 2 + x[7] + x[8] +x[9] + 4) >> 3; - Des[6] = (x[4] + x[5] +x[6] + x[7] * 2 + x[8] + x[9] +x[9] + 4) >> 3; - Des[7] = (x[5] + x[6] +x[7] + x[8] * 2 + x[9] + x[9] +x[9] + 4) >> 3; - } - - Src += PlaneLineStep; - Des += PlaneLineStep; - } - CurrentFrag ++; - } - } -} - -static void DeblockVerticalEdgesInLoopFilteredBand(PB_INSTANCE *pbi, - unsigned char *SrcPtr, - unsigned char *DesPtr, - ogg_uint32_t PlaneLineStep, - ogg_uint32_t FragsAcross, - ogg_uint32_t StartFrag, - const ogg_uint32_t *QuantScale){ - ogg_uint32_t j,k; - ogg_uint32_t CurrentFrag=StartFrag; - ogg_int32_t QStep; - ogg_int32_t FLimit; - unsigned char *Src, *Des; - ogg_int32_t x[10]; - ogg_int32_t Sum1, Sum2; - - while(CurrentFrag < StartFrag + FragsAcross-1) { - - Src=SrcPtr+8*(CurrentFrag-StartFrag+1)-5; - Des=DesPtr+8*(CurrentFrag-StartFrag+1)-4; - - QStep = QuantScale[pbi->FragQIndex[CurrentFrag+1]]; - FLimit = ( QStep * 3)>>2 ; - - for( j=0; j<8 ; j++){ - x[0] = Src[0]; - x[1] = Src[1]; - x[2] = Src[2]; - x[3] = Src[3]; - x[4] = Src[4]; - x[5] = Src[5]; - x[6] = Src[6]; - x[7] = Src[7]; - x[8] = Src[8]; - x[9] = Src[9]; - - Sum1=Sum2=0; - - for(k=1;k<=4;k++){ - Sum1 += abs(x[k]-x[k-1]); - Sum2 += abs(x[k+4]-x[k+5]); - } - - pbi->FragmentVariances[CurrentFrag] += ((Sum1>255)?255:Sum1); - pbi->FragmentVariances[CurrentFrag+1] += ((Sum2>255)?255:Sum2); - - - if( Sum1 < FLimit && - Sum2 < FLimit && - (x[5] - x[4]) < QStep && - (x[4] - x[5]) < QStep ){ - - /* low pass filtering (LPF7: 1 1 1 2 1 1 1) */ - Des[0] = (x[0] + x[0] +x[0] + x[1] * 2 + x[2] + x[3] +x[4] + 4) >> 3; - Des[1] = (x[0] + x[0] +x[1] + x[2] * 2 + x[3] + x[4] +x[5] + 4) >> 3; - Des[2] = (x[0] + x[1] +x[2] + x[3] * 2 + x[4] + x[5] +x[6] + 4) >> 3; - Des[3] = (x[1] + x[2] +x[3] + x[4] * 2 + x[5] + x[6] +x[7] + 4) >> 3; - Des[4] = (x[2] + x[3] +x[4] + x[5] * 2 + x[6] + x[7] +x[8] + 4) >> 3; - Des[5] = (x[3] + x[4] +x[5] + x[6] * 2 + x[7] + x[8] +x[9] + 4) >> 3; - Des[6] = (x[4] + x[5] +x[6] + x[7] * 2 + x[8] + x[9] +x[9] + 4) >> 3; - Des[7] = (x[5] + x[6] +x[7] + x[8] * 2 + x[9] + x[9] +x[9] + 4) >> 3; - } - Src +=PlaneLineStep; - Des +=PlaneLineStep; - - } - CurrentFrag ++; - } -} - -static void DeblockPlane(PB_INSTANCE *pbi, - unsigned char *SourceBuffer, - unsigned char *DestinationBuffer, - ogg_uint32_t Channel ){ - - ogg_uint32_t i,k; - ogg_uint32_t PlaneLineStep=0; - ogg_uint32_t StartFrag =0; - ogg_uint32_t PixelIndex=0; - unsigned char * SrcPtr=0, * DesPtr=0; - ogg_uint32_t FragsAcross=0; - ogg_uint32_t FragsDown=0; - const ogg_uint32_t *QuantScale=0; - - switch( Channel ){ - case 0: - /* Get the parameters */ - PlaneLineStep = pbi->YStride; - FragsAcross = pbi->HFragments; - FragsDown = pbi->VFragments; - StartFrag = 0; - PixelIndex = pbi->ReconYDataOffset; - SrcPtr = & SourceBuffer[PixelIndex]; - DesPtr = & DestinationBuffer[PixelIndex]; - break; - - case 1: - /* Get the parameters */ - PlaneLineStep = pbi->UVStride; - FragsAcross = pbi->HFragments / 2; - FragsDown = pbi->VFragments / 2; - StartFrag = pbi->YPlaneFragments; - - PixelIndex = pbi->ReconUDataOffset; - SrcPtr = & SourceBuffer[PixelIndex]; - DesPtr = & DestinationBuffer[PixelIndex]; - break; - - default: - /* Get the parameters */ - PlaneLineStep = pbi->UVStride; - FragsAcross = pbi->HFragments / 2; - FragsDown = pbi->VFragments / 2; - StartFrag = pbi->YPlaneFragments + pbi->UVPlaneFragments; - - PixelIndex = pbi->ReconVDataOffset; - SrcPtr = & SourceBuffer[PixelIndex]; - DesPtr = & DestinationBuffer[PixelIndex]; - break; - } - - QuantScale = DcQuantScaleV1; - - for(i=0;i<4;i++) - memcpy(DesPtr+i*PlaneLineStep, SrcPtr+i*PlaneLineStep, PlaneLineStep); - - k = 1; - - while( k < FragsDown ){ - - SrcPtr += 8*PlaneLineStep; - DesPtr += 8*PlaneLineStep; - - /* Filter both the horizontal and vertical block edges inside the band */ - DeblockLoopFilteredBand(pbi, SrcPtr, DesPtr, PlaneLineStep, - FragsAcross, StartFrag, QuantScale); - - /* Move Pointers */ - StartFrag += FragsAcross; - - k ++; - } - - /* The Last band */ - for(i=0;i<4;i++) - memcpy(DesPtr+(i+4)*PlaneLineStep, - SrcPtr+(i+4)*PlaneLineStep, - PlaneLineStep); - - DeblockVerticalEdgesInLoopFilteredBand(pbi,SrcPtr,DesPtr,PlaneLineStep, - FragsAcross,StartFrag,QuantScale); - -} - -static void DeblockFrame(PB_INSTANCE *pbi, unsigned char *SourceBuffer, - unsigned char *DestinationBuffer){ - - memset(pbi->FragmentVariances, 0 , sizeof(ogg_int32_t) * pbi->UnitFragments); - - - UpdateFragQIndex(pbi); - - /* Y */ - DeblockPlane( pbi, SourceBuffer, DestinationBuffer, 0); - - /* U */ - DeblockPlane( pbi, SourceBuffer, DestinationBuffer, 1); - - /* V */ - DeblockPlane( pbi, SourceBuffer, DestinationBuffer, 2); - -} - -void PostProcess(PB_INSTANCE *pbi){ - - switch (pbi->PostProcessingLevel){ - case 8: - /* on a slow machine, use a simpler and faster deblocking filter */ - DeblockFrame(pbi, pbi->LastFrameRecon,pbi->PostProcessBuffer); - break; - - case 6: - DeblockFrame(pbi, pbi->LastFrameRecon,pbi->PostProcessBuffer); - UpdateUMVBorder(pbi, pbi->PostProcessBuffer ); - DeringFrame(pbi, pbi->PostProcessBuffer, pbi->PostProcessBuffer); - break; - - case 5: - DeblockFrame(pbi, pbi->LastFrameRecon,pbi->PostProcessBuffer); - UpdateUMVBorder(pbi, pbi->PostProcessBuffer ); - DeringFrame(pbi, pbi->PostProcessBuffer, pbi->PostProcessBuffer); - break; - case 4: - DeblockFrame(pbi, pbi->LastFrameRecon, pbi->PostProcessBuffer); - break; - case 1: - UpdateFragQIndex(pbi); - break; - - case 0: - break; - - default: - DeblockFrame(pbi, pbi->LastFrameRecon, pbi->PostProcessBuffer); - UpdateUMVBorder(pbi, pbi->PostProcessBuffer ); - DeringFrame(pbi, pbi->PostProcessBuffer, pbi->PostProcessBuffer); - break; - } -} - diff --git a/Engine/lib/libtheora/lib/enc/pp.h b/Engine/lib/libtheora/lib/enc/pp.h deleted file mode 100644 index 6eb3a7604..000000000 --- a/Engine/lib/libtheora/lib/enc/pp.h +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: pp.h 13884 2007-09-22 08:38:10Z giles $ - - ********************************************************************/ - -/* Constants. */ -#define INTERNAL_BLOCK_HEIGHT 8 -#define INTERNAL_BLOCK_WIDTH 8 - - -/* NEW Line search values. */ -#define UP 0 -#define DOWN 1 -#define LEFT 2 -#define RIGHT 3 - -#define FIRST_ROW 0 -#define NOT_EDGE_ROW 1 -#define LAST_ROW 2 - -#define YDIFF_CB_ROWS (INTERNAL_BLOCK_HEIGHT * 3) -#define CHLOCALS_CB_ROWS (INTERNAL_BLOCK_HEIGHT * 3) -#define PMAP_CB_ROWS (INTERNAL_BLOCK_HEIGHT * 3) -#define PSCORE_CB_ROWS (INTERNAL_BLOCK_HEIGHT * 4) - -/* Status values in block coding map */ -#define CANDIDATE_BLOCK_LOW -2 -#define CANDIDATE_BLOCK -1 -#define BLOCK_NOT_CODED 0 -#define BLOCK_CODED_BAR 3 -#define BLOCK_CODED_SGC 4 -#define BLOCK_CODED_LOW 4 -#define BLOCK_CODED 5 - -#define MAX_PREV_FRAMES 16 -#define MAX_SEARCH_LINE_LEN 7 diff --git a/Engine/lib/libtheora/lib/enc/quant_lookup.h b/Engine/lib/libtheora/lib/enc/quant_lookup.h deleted file mode 100644 index 04bbce910..000000000 --- a/Engine/lib/libtheora/lib/enc/quant_lookup.h +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: quant_lookup.h 13884 2007-09-22 08:38:10Z giles $ - - ********************************************************************/ - -#include "codec_internal.h" - -#define MIN16 ((1<<16)-1) -#define SHIFT16 (1<<16) - -#define MIN_LEGAL_QUANT_ENTRY 8 -#define MIN_DEQUANT_VAL 2 -#define IDCT_SCALE_FACTOR 2 /* Shift left bits to improve IDCT precision */ -#define OLD_SCHEME 1 - - -/****************************** - * lookup table for DCT coefficient zig-zag ordering - * ****************************/ - -static const ogg_uint32_t dezigzag_index[64] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63 -}; - diff --git a/Engine/lib/libtheora/lib/enc/reconstruct.c b/Engine/lib/libtheora/lib/enc/reconstruct.c deleted file mode 100644 index 5602884af..000000000 --- a/Engine/lib/libtheora/lib/enc/reconstruct.c +++ /dev/null @@ -1,110 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: reconstruct.c 13884 2007-09-22 08:38:10Z giles $ - - ********************************************************************/ - -#include "codec_internal.h" - -static void copy8x8__c (unsigned char *src, - unsigned char *dest, - unsigned int stride) -{ - int j; - for ( j = 0; j < 8; j++ ){ - ((ogg_uint32_t*)dest)[0] = ((ogg_uint32_t*)src)[0]; - ((ogg_uint32_t*)dest)[1] = ((ogg_uint32_t*)src)[1]; - src+=stride; - dest+=stride; - } -} - -static void recon_intra8x8__c (unsigned char *ReconPtr, ogg_int16_t *ChangePtr, - ogg_uint32_t LineStep) -{ - ogg_uint32_t i; - - for (i = 8; i; i--){ - /* Convert the data back to 8 bit unsigned */ - /* Saturate the output to unsigend 8 bit values */ - ReconPtr[0] = clamp255( ChangePtr[0] + 128 ); - ReconPtr[1] = clamp255( ChangePtr[1] + 128 ); - ReconPtr[2] = clamp255( ChangePtr[2] + 128 ); - ReconPtr[3] = clamp255( ChangePtr[3] + 128 ); - ReconPtr[4] = clamp255( ChangePtr[4] + 128 ); - ReconPtr[5] = clamp255( ChangePtr[5] + 128 ); - ReconPtr[6] = clamp255( ChangePtr[6] + 128 ); - ReconPtr[7] = clamp255( ChangePtr[7] + 128 ); - - ReconPtr += LineStep; - ChangePtr += 8; - } -} - -static void recon_inter8x8__c (unsigned char *ReconPtr, unsigned char *RefPtr, - ogg_int16_t *ChangePtr, ogg_uint32_t LineStep) -{ - ogg_uint32_t i; - - for (i = 8; i; i--){ - ReconPtr[0] = clamp255(RefPtr[0] + ChangePtr[0]); - ReconPtr[1] = clamp255(RefPtr[1] + ChangePtr[1]); - ReconPtr[2] = clamp255(RefPtr[2] + ChangePtr[2]); - ReconPtr[3] = clamp255(RefPtr[3] + ChangePtr[3]); - ReconPtr[4] = clamp255(RefPtr[4] + ChangePtr[4]); - ReconPtr[5] = clamp255(RefPtr[5] + ChangePtr[5]); - ReconPtr[6] = clamp255(RefPtr[6] + ChangePtr[6]); - ReconPtr[7] = clamp255(RefPtr[7] + ChangePtr[7]); - - ChangePtr += 8; - ReconPtr += LineStep; - RefPtr += LineStep; - } -} - -static void recon_inter8x8_half__c (unsigned char *ReconPtr, unsigned char *RefPtr1, - unsigned char *RefPtr2, ogg_int16_t *ChangePtr, - ogg_uint32_t LineStep) -{ - ogg_uint32_t i; - - for (i = 8; i; i--){ - ReconPtr[0] = clamp255((((int)RefPtr1[0] + (int)RefPtr2[0]) >> 1) + ChangePtr[0] ); - ReconPtr[1] = clamp255((((int)RefPtr1[1] + (int)RefPtr2[1]) >> 1) + ChangePtr[1] ); - ReconPtr[2] = clamp255((((int)RefPtr1[2] + (int)RefPtr2[2]) >> 1) + ChangePtr[2] ); - ReconPtr[3] = clamp255((((int)RefPtr1[3] + (int)RefPtr2[3]) >> 1) + ChangePtr[3] ); - ReconPtr[4] = clamp255((((int)RefPtr1[4] + (int)RefPtr2[4]) >> 1) + ChangePtr[4] ); - ReconPtr[5] = clamp255((((int)RefPtr1[5] + (int)RefPtr2[5]) >> 1) + ChangePtr[5] ); - ReconPtr[6] = clamp255((((int)RefPtr1[6] + (int)RefPtr2[6]) >> 1) + ChangePtr[6] ); - ReconPtr[7] = clamp255((((int)RefPtr1[7] + (int)RefPtr2[7]) >> 1) + ChangePtr[7] ); - - ChangePtr += 8; - ReconPtr += LineStep; - RefPtr1 += LineStep; - RefPtr2 += LineStep; - } -} - -void dsp_recon_init (DspFunctions *funcs, ogg_uint32_t cpu_flags) -{ - funcs->copy8x8 = copy8x8__c; - funcs->recon_intra8x8 = recon_intra8x8__c; - funcs->recon_inter8x8 = recon_inter8x8__c; - funcs->recon_inter8x8_half = recon_inter8x8_half__c; -#if defined(USE_ASM) - if (cpu_flags & OC_CPU_X86_MMX) { - dsp_mmx_recon_init(funcs); - } -#endif -} diff --git a/Engine/lib/libtheora/lib/enc/scan.c b/Engine/lib/libtheora/lib/enc/scan.c deleted file mode 100644 index 5466ca438..000000000 --- a/Engine/lib/libtheora/lib/enc/scan.c +++ /dev/null @@ -1,2301 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: scan.c 13884 2007-09-22 08:38:10Z giles $ - - ********************************************************************/ - -#include -#include -#include -#include "codec_internal.h" -#include "dsp.h" - -#define MAX_SEARCH_LINE_LEN 7 - -#define SET8_0(ptr) \ - ((ogg_uint32_t *)ptr)[0] = 0x00000000; \ - ((ogg_uint32_t *)ptr)[1] = 0x00000000; -#define SET8_1(ptr) \ - ((ogg_uint32_t *)ptr)[0] = 0x01010101; \ - ((ogg_uint32_t *)ptr)[1] = 0x01010101; -#define SET8_8(ptr) \ - ((ogg_uint32_t *)ptr)[0] = 0x08080808; \ - ((ogg_uint32_t *)ptr)[1] = 0x08080808; - -static ogg_uint32_t LineLengthScores[ MAX_SEARCH_LINE_LEN + 1 ] = { - 0, 0, 0, 0, 2, 4, 12, 24 -}; - -static ogg_uint32_t BodyNeighbourScore = 8; -static double DiffDevisor = 0.0625; -#define HISTORY_BLOCK_FACTOR 2 -#define MIN_STEP_THRESH 6 -#define SCORE_MULT_LOW 0.5 -#define SCORE_MULT_HIGH 4 - -#define UP 0 -#define DOWN 1 -#define LEFT 2 -#define RIGHT 3 - -#define INTERNAL_BLOCK_HEIGHT 8 -#define INTERNAL_BLOCK_WIDTH 8 - -#define BLOCK_NOT_CODED 0 -#define BLOCK_CODED_BAR 3 -#define BLOCK_CODED_SGC 4 -#define BLOCK_CODED_LOW 4 -#define BLOCK_CODED 5 - -#define CANDIDATE_BLOCK_LOW -2 -#define CANDIDATE_BLOCK -1 - -#define FIRST_ROW 0 -#define NOT_EDGE_ROW 1 -#define LAST_ROW 2 - -#define YDIFF_CB_ROWS (INTERNAL_BLOCK_HEIGHT * 3) -#define CHLOCALS_CB_ROWS (INTERNAL_BLOCK_HEIGHT * 3) -#define PMAP_CB_ROWS (INTERNAL_BLOCK_HEIGHT * 3) - -void ConfigurePP( PP_INSTANCE *ppi, int Level ) { - switch ( Level ){ - case 0: - ppi->SRFGreyThresh = 1; - ppi->SRFColThresh = 1; - ppi->NoiseSupLevel = 2; - ppi->SgcLevelThresh = 1; - ppi->SuvcLevelThresh = 1; - ppi->GrpLowSadThresh = 6; - ppi->GrpHighSadThresh = 24; - ppi->PrimaryBlockThreshold = 2; - ppi->SgcThresh = 10; - - ppi->PAKEnabled = 0; - break; - - case 1: - ppi->SRFGreyThresh = 2; - ppi->SRFColThresh = 2; - ppi->NoiseSupLevel = 2; - ppi->SgcLevelThresh = 2; - ppi->SuvcLevelThresh = 2; - ppi->GrpLowSadThresh = 8; - ppi->GrpHighSadThresh = 32; - ppi->PrimaryBlockThreshold = 5; - ppi->SgcThresh = 12; - - ppi->PAKEnabled = 1; - break; - - case 2: /* Default VP3 settings */ - ppi->SRFGreyThresh = 3; - ppi->SRFColThresh = 3; - ppi->NoiseSupLevel = 2; - ppi->SgcLevelThresh = 2; - ppi->SuvcLevelThresh = 2; - ppi->GrpLowSadThresh = 8; - ppi->GrpHighSadThresh = 32; - ppi->PrimaryBlockThreshold = 5; - ppi->SgcThresh = 16; - - ppi->PAKEnabled = 1; - break; - - case 3: - ppi->SRFGreyThresh = 4; - ppi->SRFColThresh = 4; - ppi->NoiseSupLevel = 3; - ppi->SgcLevelThresh = 3; - ppi->SuvcLevelThresh = 3; - ppi->GrpLowSadThresh = 10; - ppi->GrpHighSadThresh = 48; - ppi->PrimaryBlockThreshold = 5; - ppi->SgcThresh = 18; - - ppi->PAKEnabled = 1; - break; - - case 4: - ppi->SRFGreyThresh = 5; - ppi->SRFColThresh = 5; - ppi->NoiseSupLevel = 3; - ppi->SgcLevelThresh = 4; - ppi->SuvcLevelThresh = 4; - ppi->GrpLowSadThresh = 12; - ppi->GrpHighSadThresh = 48; - ppi->PrimaryBlockThreshold = 5; - ppi->SgcThresh = 20; - - ppi->PAKEnabled = 1; - break; - - case 5: - ppi->SRFGreyThresh = 6; - ppi->SRFColThresh = 6; - ppi->NoiseSupLevel = 3; - ppi->SgcLevelThresh = 4; - ppi->SuvcLevelThresh = 4; - ppi->GrpLowSadThresh = 12; - ppi->GrpHighSadThresh = 64; - ppi->PrimaryBlockThreshold = 10; - ppi->SgcThresh = 24; - - ppi->PAKEnabled = 1; - break; - - case 6: - ppi->SRFGreyThresh = 6; - ppi->SRFColThresh = 7; - ppi->NoiseSupLevel = 3; - ppi->SgcLevelThresh = 4; - ppi->SuvcLevelThresh = 4; - ppi->GrpLowSadThresh = 12; - ppi->GrpHighSadThresh = 64; - ppi->PrimaryBlockThreshold = 10; - ppi->SgcThresh = 24; - - ppi->PAKEnabled = 1; - break; - - default: - ppi->SRFGreyThresh = 3; - ppi->SRFColThresh = 3; - ppi->NoiseSupLevel = 2; - ppi->SgcLevelThresh = 2; - ppi->SuvcLevelThresh = 2; - ppi->GrpLowSadThresh = 10; - ppi->GrpHighSadThresh = 32; - ppi->PrimaryBlockThreshold = 5; - ppi->SgcThresh = 16; - ppi->PAKEnabled = 1; - break; - } -} - -static void ScanCalcPixelIndexTable(PP_INSTANCE *ppi){ - ogg_uint32_t i; - ogg_uint32_t * PixelIndexTablePtr = ppi->ScanPixelIndexTable; - - /* If appropriate add on extra inices for U and V planes. */ - for ( i = 0; i < (ppi->ScanYPlaneFragments); i++ ) { - PixelIndexTablePtr[ i ] = - ((i / ppi->ScanHFragments) * - VFRAGPIXELS * ppi->ScanConfig.VideoFrameWidth); - PixelIndexTablePtr[ i ] += - ((i % ppi->ScanHFragments) * HFRAGPIXELS); - } - - PixelIndexTablePtr = &ppi->ScanPixelIndexTable[ppi->ScanYPlaneFragments]; - - for ( i = 0; i < (ppi->ScanUVPlaneFragments * 2); i++ ){ - PixelIndexTablePtr[ i ] = - ((i / (ppi->ScanHFragments >> 1) ) * - (VFRAGPIXELS * (ppi->ScanConfig.VideoFrameWidth >> 1)) ); - PixelIndexTablePtr[ i ] += - ((i % (ppi->ScanHFragments >> 1) ) * - HFRAGPIXELS) + ppi->YFramePixels; - } -} - -static void InitScanMapArrays(PP_INSTANCE *ppi){ - int i; - unsigned char StepThresh; - - /* Clear down the fragment level map arrays for the current frame. */ - memset( ppi->FragScores, 0, - ppi->ScanFrameFragments * sizeof(*ppi->FragScores) ); - memset( ppi->SameGreyDirPixels, 0, - ppi->ScanFrameFragments ); - memset( ppi->FragDiffPixels, 0, - ppi->ScanFrameFragments ); - memset( ppi->RowChangedPixels, 0, - 3* ppi->ScanConfig.VideoFrameHeight*sizeof(*ppi->RowChangedPixels)); - - memset( ppi->ScanDisplayFragments, BLOCK_NOT_CODED, ppi->ScanFrameFragments); - - /* Threshold used in setting up ppi->NoiseScoreBoostTable[] */ - StepThresh = (unsigned int)(ppi->SRFGreyThresh >> 1); - if ( StepThresh < MIN_STEP_THRESH ) - StepThresh = MIN_STEP_THRESH; - ppi->SrfThresh = (int)ppi->SRFGreyThresh; - - /* Set up various tables used to tweak pixel score values and - scoring rules based upon absolute value of a pixel change */ - for ( i = 0; i < 256; i++ ){ - /* Score multiplier table indexed by absolute difference. */ - ppi->AbsDiff_ScoreMultiplierTable[i] = (double)i * DiffDevisor; - if ( ppi->AbsDiff_ScoreMultiplierTable[i] < SCORE_MULT_LOW ) - ppi->AbsDiff_ScoreMultiplierTable[i] = SCORE_MULT_LOW; - else if ( ppi->AbsDiff_ScoreMultiplierTable[i] > SCORE_MULT_HIGH) - ppi->AbsDiff_ScoreMultiplierTable[i] = SCORE_MULT_HIGH; - - /* Table that facilitates a relaxation of the changed locals rules - in NoiseScoreRow() for pixels that have changed by a large - amount. */ - if ( i < (ppi->SrfThresh + StepThresh) ) - ppi->NoiseScoreBoostTable[i] = 0; - else if ( i < (ppi->SrfThresh + (StepThresh * 4)) ) - ppi->NoiseScoreBoostTable[i] = 1; - else if ( i < (ppi->SrfThresh + (StepThresh * 6)) ) - ppi->NoiseScoreBoostTable[i] = 2; - else - ppi->NoiseScoreBoostTable[i] = 3; - - } - - /* Set various other threshold parameters. */ - - /* Set variables that control access to the line search algorithms. */ - ppi->LineSearchTripTresh = 16; - if ( ppi->LineSearchTripTresh > ppi->PrimaryBlockThreshold ) - ppi->LineSearchTripTresh = (unsigned int)(ppi->PrimaryBlockThreshold + 1); - - /* Adjust line search length if block threshold low */ - ppi->MaxLineSearchLen = MAX_SEARCH_LINE_LEN; - while ( (ppi->MaxLineSearchLen > 0) && - (LineLengthScores[ppi->MaxLineSearchLen-1] > - ppi->PrimaryBlockThreshold) ) - ppi->MaxLineSearchLen -= 1; - -} - -void ScanYUVInit( PP_INSTANCE * ppi, SCAN_CONFIG_DATA * ScanConfigPtr){ - int i; - - /* Set up the various imported data structure pointers. */ - ppi->ScanConfig.Yuv0ptr = ScanConfigPtr->Yuv0ptr; - ppi->ScanConfig.Yuv1ptr = ScanConfigPtr->Yuv1ptr; - ppi->ScanConfig.SrfWorkSpcPtr = ScanConfigPtr->SrfWorkSpcPtr; - ppi->ScanConfig.disp_fragments = ScanConfigPtr->disp_fragments; - - ppi->ScanConfig.RegionIndex = ScanConfigPtr->RegionIndex; - - ppi->ScanConfig.VideoFrameWidth = ScanConfigPtr->VideoFrameWidth; - ppi->ScanConfig.VideoFrameHeight = ScanConfigPtr->VideoFrameHeight; - - /* UV plane sizes. */ - ppi->VideoUVPlaneWidth = ScanConfigPtr->VideoFrameWidth / 2; - ppi->VideoUVPlaneHeight = ScanConfigPtr->VideoFrameHeight / 2; - - /* Note the size of each plane in pixels. */ - ppi->YFramePixels = ppi->ScanConfig.VideoFrameWidth * - ppi->ScanConfig.VideoFrameHeight; - ppi->UVFramePixels = ppi->VideoUVPlaneWidth * ppi->VideoUVPlaneHeight; - - /* Work out various fragment related values. */ - ppi->ScanYPlaneFragments = ppi->YFramePixels / - (HFRAGPIXELS * VFRAGPIXELS); - ppi->ScanUVPlaneFragments = ppi->UVFramePixels / - (HFRAGPIXELS * VFRAGPIXELS);; - ppi->ScanHFragments = ppi->ScanConfig.VideoFrameWidth / HFRAGPIXELS; - ppi->ScanVFragments = ppi->ScanConfig.VideoFrameHeight / VFRAGPIXELS; - ppi->ScanFrameFragments = ppi->ScanYPlaneFragments + - (2 * ppi->ScanUVPlaneFragments); - - PInitFrameInfo(ppi); - - /* Set up the scan pixel index table. */ - ScanCalcPixelIndexTable(ppi); - - /* Initialise the previous frame block history lists */ - for ( i = 0; i < MAX_PREV_FRAMES; i++ ) - memset( ppi->PrevFragments[i], BLOCK_NOT_CODED, ppi->ScanFrameFragments); - - /* YUVAnalyseFrame() is not called for the first frame in a sequence - (a key frame obviously). This memset insures that for the second - frame all blocks are marked for coding in line with the behaviour - for other key frames. */ - memset( ppi->PrevFragments[ppi->PrevFrameLimit-1], - BLOCK_CODED, ppi->ScanFrameFragments ); - - /* Initialise scan arrays */ - InitScanMapArrays(ppi); -} - -static void SetFromPrevious(PP_INSTANCE *ppi) { - unsigned int i,j; - - /* We buld up the list of previously updated blocks in the zero - index list of PrevFragments[] so we must start by reseting its - contents */ - memset( ppi->PrevFragments[0], BLOCK_NOT_CODED, ppi->ScanFrameFragments ); - - if ( ppi->PrevFrameLimit > 1 ){ - /* Now build up PrevFragments[0] from PrevFragments[1 to PrevFrameLimit] */ - for ( i = 0; i < ppi->ScanFrameFragments; i++ ){ - for ( j = 1; j < ppi->PrevFrameLimit; j++ ){ - if ( ppi->PrevFragments[j][i] > BLOCK_CODED_BAR ){ - ppi->PrevFragments[0][i] = BLOCK_CODED; - break; - } - } - } - } -} - -static void UpdatePreviousBlockLists(PP_INSTANCE *ppi) { - int i; - - /* Shift previous frame block lists along. */ - for ( i = ppi->PrevFrameLimit; i > 1; i-- ){ - memcpy( ppi->PrevFragments[i], ppi->PrevFragments[i-1], - ppi->ScanFrameFragments ); - } - - /* Now copy in this frames block list */ - memcpy( ppi->PrevFragments[1], ppi->ScanDisplayFragments, - ppi->ScanFrameFragments ); -} - -static void CreateOutputDisplayMap( PP_INSTANCE *ppi, - signed char *InternalFragmentsPtr, - signed char *RecentHistoryPtr, - unsigned char *ExternalFragmentsPtr ) { - ogg_uint32_t i; - ogg_uint32_t HistoryBlocksAdded = 0; - ogg_uint32_t YBand = (ppi->ScanYPlaneFragments/8); /* 1/8th of Y image. */ - - ppi->OutputBlocksUpdated = 0; - for ( i = 0; i < ppi->ScanFrameFragments; i++ ) { - if ( InternalFragmentsPtr[i] > BLOCK_NOT_CODED ) { - ppi->OutputBlocksUpdated ++; - ExternalFragmentsPtr[i] = 1; - }else if ( RecentHistoryPtr[i] == BLOCK_CODED ){ - HistoryBlocksAdded ++; - ExternalFragmentsPtr[i] = 1; - }else{ - ExternalFragmentsPtr[i] = 0; - } - } - - /* Add in a weighting for the history blocks that have been added */ - ppi->OutputBlocksUpdated += (HistoryBlocksAdded / HISTORY_BLOCK_FACTOR); - - /* Now calculate a key frame candidate indicator. This is based - upon Y data only and ignores the top and bottom 1/8 of the - image. Also ignore history blocks and BAR blocks. */ - ppi->KFIndicator = 0; - for ( i = YBand; i < (ppi->ScanYPlaneFragments - YBand); i++ ) - if ( InternalFragmentsPtr[i] > BLOCK_CODED_BAR ) - ppi->KFIndicator ++; - - /* Convert the KF score to a range 0-100 */ - ppi->KFIndicator = ((ppi->KFIndicator*100)/((ppi->ScanYPlaneFragments*3)/4)); -} - -static int RowSadScan( PP_INSTANCE *ppi, - unsigned char * YuvPtr1, - unsigned char * YuvPtr2, - signed char * DispFragPtr){ - ogg_int32_t i, j; - ogg_uint32_t GrpSad; - ogg_uint32_t LocalGrpLowSadThresh = ppi->ModifiedGrpLowSadThresh; - ogg_uint32_t LocalGrpHighSadThresh = ppi->ModifiedGrpHighSadThresh; - signed char *LocalDispFragPtr; - unsigned char *LocalYuvPtr1; - unsigned char *LocalYuvPtr2; - - int InterestingBlocksInRow = 0; - - /* For each row of pixels in the row of blocks */ - for ( j = 0; j < VFRAGPIXELS; j++ ){ - /* Set local block map pointer. */ - LocalDispFragPtr = DispFragPtr; - - /* Set the local pixel data pointers for this row.*/ - LocalYuvPtr1 = YuvPtr1; - LocalYuvPtr2 = YuvPtr2; - - /* Scan along the row of pixels If the block to which a group of - pixels belongs is already marked for update then do nothing. */ - for ( i = 0; i < ppi->PlaneHFragments; i ++ ){ - if ( *LocalDispFragPtr <= BLOCK_NOT_CODED ){ - /* Calculate the SAD score for the block row */ - GrpSad = dsp_row_sad8(ppi->dsp, LocalYuvPtr1,LocalYuvPtr2); - - /* Now test the group SAD score */ - if ( GrpSad > LocalGrpLowSadThresh ){ - /* If SAD very high we must update else we have candidate block */ - if ( GrpSad > LocalGrpHighSadThresh ){ - /* Force update */ - *LocalDispFragPtr = BLOCK_CODED; - }else{ - /* Possible Update required */ - *LocalDispFragPtr = CANDIDATE_BLOCK; - } - InterestingBlocksInRow = 1; - } - } - LocalDispFragPtr++; - - LocalYuvPtr1 += 8; - LocalYuvPtr2 += 8; - } - - /* Increment the base data pointers to the start of the next line. */ - YuvPtr1 += ppi->PlaneStride; - YuvPtr2 += ppi->PlaneStride; - } - - return InterestingBlocksInRow; - -} - -static int ColSadScan( PP_INSTANCE *ppi, - unsigned char * YuvPtr1, - unsigned char * YuvPtr2, - signed char * DispFragPtr ){ - ogg_int32_t i; - ogg_uint32_t MaxSad; - ogg_uint32_t LocalGrpLowSadThresh = ppi->ModifiedGrpLowSadThresh; - ogg_uint32_t LocalGrpHighSadThresh = ppi->ModifiedGrpHighSadThresh; - signed char * LocalDispFragPtr; - - unsigned char * LocalYuvPtr1; - unsigned char * LocalYuvPtr2; - - int InterestingBlocksInRow = 0; - - /* Set the local pixel data pointers for this row. */ - LocalYuvPtr1 = YuvPtr1; - LocalYuvPtr2 = YuvPtr2; - - /* Set local block map pointer. */ - LocalDispFragPtr = DispFragPtr; - - /* Scan along the row of blocks */ - for ( i = 0; i < ppi->PlaneHFragments; i ++ ){ - /* Skip if block already marked to be coded. */ - if ( *LocalDispFragPtr <= BLOCK_NOT_CODED ){ - /* Calculate the SAD score for the block column */ - MaxSad = dsp_col_sad8x8(ppi->dsp, LocalYuvPtr1, LocalYuvPtr2, ppi->PlaneStride ); - - /* Now test the group SAD score */ - if ( MaxSad > LocalGrpLowSadThresh ){ - /* If SAD very high we must update else we have candidate block */ - if ( MaxSad > LocalGrpHighSadThresh ){ - /* Force update */ - *LocalDispFragPtr = BLOCK_CODED; - }else{ - /* Possible Update required */ - *LocalDispFragPtr = CANDIDATE_BLOCK; - } - InterestingBlocksInRow = 1; - } - } - - /* Increment the block map pointer. */ - LocalDispFragPtr++; - - /* Step data pointers on ready for next block */ - LocalYuvPtr1 += HFRAGPIXELS; - LocalYuvPtr2 += HFRAGPIXELS; - } - - return InterestingBlocksInRow; -} - -static void SadPass2( PP_INSTANCE *ppi, - ogg_int32_t RowNumber, - signed char * DispFragPtr ){ - ogg_int32_t i; - - /* First row */ - if ( RowNumber == 0 ) { - /* First block in row. */ - if ( DispFragPtr[0] == CANDIDATE_BLOCK ){ - if ( (DispFragPtr[1] == BLOCK_CODED) || - (DispFragPtr[ppi->PlaneHFragments] == BLOCK_CODED) || - (DispFragPtr[ppi->PlaneHFragments+1] == BLOCK_CODED) ){ - ppi->TmpCodedMap[0] = BLOCK_CODED_LOW; - }else{ - ppi->TmpCodedMap[0] = DispFragPtr[0]; - } - }else{ - ppi->TmpCodedMap[0] = DispFragPtr[0]; - } - - /* All but first and last in row */ - for ( i = 1; (i < ppi->PlaneHFragments-1); i++ ){ - if ( DispFragPtr[i] == CANDIDATE_BLOCK ){ - if ( (DispFragPtr[i-1] == BLOCK_CODED) || - (DispFragPtr[i+1] == BLOCK_CODED) || - (DispFragPtr[i+ppi->PlaneHFragments] == BLOCK_CODED) || - (DispFragPtr[i+ppi->PlaneHFragments-1] == BLOCK_CODED) || - (DispFragPtr[i+ppi->PlaneHFragments+1] == BLOCK_CODED) ){ - ppi->TmpCodedMap[i] = BLOCK_CODED_LOW; - }else{ - ppi->TmpCodedMap[i] = DispFragPtr[i]; - } - }else{ - ppi->TmpCodedMap[i] = DispFragPtr[i]; - } - } - - /* Last block in row. */ - i = ppi->PlaneHFragments-1; - if ( DispFragPtr[i] == CANDIDATE_BLOCK ){ - if ( (DispFragPtr[i-1] == BLOCK_CODED) || - (DispFragPtr[i+ppi->PlaneHFragments] == BLOCK_CODED) || - (DispFragPtr[i+ppi->PlaneHFragments-1] == BLOCK_CODED) ){ - ppi->TmpCodedMap[i] = BLOCK_CODED_LOW; - }else{ - ppi->TmpCodedMap[i] = DispFragPtr[i]; - } - }else{ - ppi->TmpCodedMap[i] = DispFragPtr[i]; - } - }else if ( RowNumber < (ppi->PlaneVFragments - 1) ){ - /* General case */ - /* First block in row. */ - if ( DispFragPtr[0] == CANDIDATE_BLOCK ){ - if ( (DispFragPtr[1] == BLOCK_CODED) || - (DispFragPtr[(-ppi->PlaneHFragments)] == BLOCK_CODED) || - (DispFragPtr[(-ppi->PlaneHFragments)+1] == BLOCK_CODED) || - (DispFragPtr[ppi->PlaneHFragments] == BLOCK_CODED) || - (DispFragPtr[ppi->PlaneHFragments+1] == BLOCK_CODED) ){ - ppi->TmpCodedMap[0] = BLOCK_CODED_LOW; - }else{ - ppi->TmpCodedMap[0] = DispFragPtr[0]; - } - }else{ - ppi->TmpCodedMap[0] = DispFragPtr[0]; - } - - /* All but first and last in row */ - for ( i = 1; (i < ppi->PlaneHFragments-1); i++ ){ - if ( DispFragPtr[i] == CANDIDATE_BLOCK ){ - if ( (DispFragPtr[i-1] == BLOCK_CODED) || - (DispFragPtr[i+1] == BLOCK_CODED) || - (DispFragPtr[i-ppi->PlaneHFragments] == BLOCK_CODED) || - (DispFragPtr[i-ppi->PlaneHFragments-1] == BLOCK_CODED) || - (DispFragPtr[i-ppi->PlaneHFragments+1] == BLOCK_CODED) || - (DispFragPtr[i+ppi->PlaneHFragments] == BLOCK_CODED) || - (DispFragPtr[i+ppi->PlaneHFragments-1] == BLOCK_CODED) || - (DispFragPtr[i+ppi->PlaneHFragments+1] == BLOCK_CODED) ){ - ppi->TmpCodedMap[i] = BLOCK_CODED_LOW; - }else{ - ppi->TmpCodedMap[i] = DispFragPtr[i]; - } - }else{ - ppi->TmpCodedMap[i] = DispFragPtr[i]; - } - } - - /* Last block in row. */ - i = ppi->PlaneHFragments-1; - if ( DispFragPtr[i] == CANDIDATE_BLOCK ){ - if ( (DispFragPtr[i-1] == BLOCK_CODED) || - (DispFragPtr[i-ppi->PlaneHFragments] == BLOCK_CODED) || - (DispFragPtr[i-ppi->PlaneHFragments-1] == BLOCK_CODED) || - (DispFragPtr[i+ppi->PlaneHFragments] == BLOCK_CODED) || - (DispFragPtr[i+ppi->PlaneHFragments-1] == BLOCK_CODED) ){ - ppi->TmpCodedMap[i] = BLOCK_CODED_LOW; - }else{ - ppi->TmpCodedMap[i] = DispFragPtr[i]; - } - }else{ - ppi->TmpCodedMap[i] = DispFragPtr[i]; - } - }else{ - /* Last row */ - /* First block in row. */ - if ( DispFragPtr[0] == CANDIDATE_BLOCK ){ - if ( (DispFragPtr[1] == BLOCK_CODED) || - (DispFragPtr[(-ppi->PlaneHFragments)] == BLOCK_CODED) || - (DispFragPtr[(-ppi->PlaneHFragments)+1] == BLOCK_CODED)){ - ppi->TmpCodedMap[0] = BLOCK_CODED_LOW; - }else{ - ppi->TmpCodedMap[0] = DispFragPtr[0]; - } - }else{ - ppi->TmpCodedMap[0] = DispFragPtr[0]; - } - - /* All but first and last in row */ - for ( i = 1; (i < ppi->PlaneHFragments-1); i++ ){ - if ( DispFragPtr[i] == CANDIDATE_BLOCK ){ - if ( (DispFragPtr[i-1] == BLOCK_CODED) || - (DispFragPtr[i+1] == BLOCK_CODED) || - (DispFragPtr[i-ppi->PlaneHFragments] == BLOCK_CODED) || - (DispFragPtr[i-ppi->PlaneHFragments-1] == BLOCK_CODED) || - (DispFragPtr[i-ppi->PlaneHFragments+1] == BLOCK_CODED) ){ - ppi->TmpCodedMap[i] = BLOCK_CODED_LOW; - }else{ - ppi->TmpCodedMap[i] = DispFragPtr[i]; - } - }else{ - ppi->TmpCodedMap[i] = DispFragPtr[i]; - } - } - - /* Last block in row. */ - i = ppi->PlaneHFragments-1; - if ( DispFragPtr[i] == CANDIDATE_BLOCK ){ - if ( (DispFragPtr[i-1] == BLOCK_CODED) || - (DispFragPtr[i-ppi->PlaneHFragments] == BLOCK_CODED) || - (DispFragPtr[i-ppi->PlaneHFragments-1] == BLOCK_CODED) ){ - ppi->TmpCodedMap[i] = BLOCK_CODED_LOW; - }else{ - ppi->TmpCodedMap[i] = DispFragPtr[i]; - } - }else{ - ppi->TmpCodedMap[i] = DispFragPtr[i]; - } - } - - /* Now copy back the modified Fragment data */ - memcpy( &DispFragPtr[0], &ppi->TmpCodedMap[0], (ppi->PlaneHFragments) ); -} - -static unsigned char ApplyPakLowPass( PP_INSTANCE *ppi, - unsigned char * SrcPtr ){ - unsigned char * SrcPtr1 = SrcPtr - 1; - unsigned char * SrcPtr0 = SrcPtr1 - ppi->PlaneStride; /* Note the - use of - stride not - width. */ - unsigned char * SrcPtr2 = SrcPtr1 + ppi->PlaneStride; - - return (unsigned char)( ( (ogg_uint32_t)SrcPtr0[0] + - (ogg_uint32_t)SrcPtr0[1] + - (ogg_uint32_t)SrcPtr0[2] + - (ogg_uint32_t)SrcPtr1[0] + - (ogg_uint32_t)SrcPtr1[2] + - (ogg_uint32_t)SrcPtr2[0] + - (ogg_uint32_t)SrcPtr2[1] + - (ogg_uint32_t)SrcPtr2[2] ) >> 3 ); - -} - -static void RowDiffScan( PP_INSTANCE *ppi, - unsigned char * YuvPtr1, - unsigned char * YuvPtr2, - ogg_int16_t * YUVDiffsPtr, - unsigned char * bits_map_ptr, - signed char * SgcPtr, - signed char * DispFragPtr, - unsigned char * FDiffPixels, - ogg_int32_t * RowDiffsPtr, - unsigned char * ChLocalsPtr, int EdgeRow ){ - - ogg_int32_t i,j; - ogg_int32_t FragChangedPixels; - - ogg_int16_t Diff; /* Temp local workspace. */ - - /* Cannot use kernel if at edge or if PAK disabled */ - if ( (!ppi->PAKEnabled) || EdgeRow ){ - for ( i = 0; i < ppi->PlaneWidth; i += HFRAGPIXELS ){ - /* Reset count of pixels changed for the current fragment. */ - FragChangedPixels = 0; - - /* Test for break out conditions to save time. */ - if (*DispFragPtr == CANDIDATE_BLOCK){ - - /* Clear down entries in changed locals array */ - SET8_0(ChLocalsPtr); - - for ( j = 0; j < HFRAGPIXELS; j++ ){ - /* Take a local copy of the measured difference. */ - Diff = (int)YuvPtr1[j] - (int)YuvPtr2[j]; - - /* Store the actual difference value */ - YUVDiffsPtr[j] = Diff; - - /* Test against the Level thresholds and record the results */ - SgcPtr[0] += ppi->SgcThreshTable[Diff+255]; - - /* Test against the SRF thresholds */ - bits_map_ptr[j] = ppi->SrfThreshTable[Diff+255]; - FragChangedPixels += ppi->SrfThreshTable[Diff+255]; - } - }else{ - /* If we are breaking out here mark all pixels as changed. */ - if ( *DispFragPtr > BLOCK_NOT_CODED ){ - SET8_1(bits_map_ptr); - SET8_8(ChLocalsPtr); - }else{ - SET8_0(ChLocalsPtr); - } - } - - *RowDiffsPtr += FragChangedPixels; - *FDiffPixels += (unsigned char)FragChangedPixels; - - YuvPtr1 += HFRAGPIXELS; - YuvPtr2 += HFRAGPIXELS; - bits_map_ptr += HFRAGPIXELS; - ChLocalsPtr += HFRAGPIXELS; - YUVDiffsPtr += HFRAGPIXELS; - SgcPtr ++; - FDiffPixels ++; - - /* If we have a lot of changed pixels for this fragment on this - row then the fragment is almost sure to be picked (e.g. through - the line search) so we can mark it as selected and then ignore - it. */ - if (FragChangedPixels >= 7){ - *DispFragPtr = BLOCK_CODED_LOW; - } - DispFragPtr++; - } - }else{ - - /*************************************************************/ - /* First fragment of row !! */ - - i = 0; - /* Reset count of pixels changed for the current fragment. */ - FragChangedPixels = 0; - - /* Test for break out conditions to save time. */ - if (*DispFragPtr == CANDIDATE_BLOCK){ - /* Clear down entries in changed locals array */ - SET8_0(ChLocalsPtr); - - for ( j = 0; j < HFRAGPIXELS; j++ ){ - /* Take a local copy of the measured difference. */ - Diff = (int)YuvPtr1[j] - (int)YuvPtr2[j]; - - /* Store the actual difference value */ - YUVDiffsPtr[j] = Diff; - - /* Test against the Level thresholds and record the results */ - SgcPtr[0] += ppi->SgcThreshTable[Diff+255]; - - if (j>0 && ppi->SrfPakThreshTable[Diff+255] ) - Diff = (int)ApplyPakLowPass( ppi, &YuvPtr1[j] ) - - (int)ApplyPakLowPass( ppi, &YuvPtr2[j] ); - - /* Test against the SRF thresholds */ - bits_map_ptr[j] = ppi->SrfThreshTable[Diff+255]; - FragChangedPixels += ppi->SrfThreshTable[Diff+255]; - } - }else{ - /* If we are breaking out here mark all pixels as changed. */ - if ( *DispFragPtr > BLOCK_NOT_CODED ){ - SET8_1(bits_map_ptr); - SET8_8(ChLocalsPtr); - }else{ - SET8_0(ChLocalsPtr); - } - } - - *RowDiffsPtr += FragChangedPixels; - *FDiffPixels += (unsigned char)FragChangedPixels; - - YuvPtr1 += HFRAGPIXELS; - YuvPtr2 += HFRAGPIXELS; - bits_map_ptr += HFRAGPIXELS; - ChLocalsPtr += HFRAGPIXELS; - YUVDiffsPtr += HFRAGPIXELS; - SgcPtr ++; - FDiffPixels ++; - - /* If we have a lot of changed pixels for this fragment on this - row then the fragment is almost sure to be picked - (e.g. through the line search) so we can mark it as selected - and then ignore it. */ - if (FragChangedPixels >= 7){ - *DispFragPtr = BLOCK_CODED_LOW; - } - DispFragPtr++; - /*************************************************************/ - /* Fragment in between!! */ - - for ( i = HFRAGPIXELS ; i < ppi->PlaneWidth-HFRAGPIXELS; - i += HFRAGPIXELS ){ - /* Reset count of pixels changed for the current fragment. */ - FragChangedPixels = 0; - - /* Test for break out conditions to save time. */ - if (*DispFragPtr == CANDIDATE_BLOCK){ - /* Clear down entries in changed locals array */ - SET8_0(ChLocalsPtr); - for ( j = 0; j < HFRAGPIXELS; j++ ){ - /* Take a local copy of the measured difference. */ - Diff = (int)YuvPtr1[j] - (int)YuvPtr2[j]; - - /* Store the actual difference value */ - YUVDiffsPtr[j] = Diff; - - /* Test against the Level thresholds and record the results */ - SgcPtr[0] += ppi->SgcThreshTable[Diff+255]; - - if (ppi->SrfPakThreshTable[Diff+255] ) - Diff = (int)ApplyPakLowPass( ppi, &YuvPtr1[j] ) - - (int)ApplyPakLowPass( ppi, &YuvPtr2[j] ); - - - /* Test against the SRF thresholds */ - bits_map_ptr[j] = ppi->SrfThreshTable[Diff+255]; - FragChangedPixels += ppi->SrfThreshTable[Diff+255]; - } - }else{ - /* If we are breaking out here mark all pixels as changed. */ - if ( *DispFragPtr > BLOCK_NOT_CODED ){ - SET8_1(bits_map_ptr); - SET8_8(ChLocalsPtr); - }else{ - SET8_0(ChLocalsPtr); - } - } - - *RowDiffsPtr += FragChangedPixels; - *FDiffPixels += (unsigned char)FragChangedPixels; - - YuvPtr1 += HFRAGPIXELS; - YuvPtr2 += HFRAGPIXELS; - bits_map_ptr += HFRAGPIXELS; - ChLocalsPtr += HFRAGPIXELS; - YUVDiffsPtr += HFRAGPIXELS; - SgcPtr ++; - FDiffPixels ++; - - /* If we have a lot of changed pixels for this fragment on this - row then the fragment is almost sure to be picked - (e.g. through the line search) so we can mark it as selected - and then ignore it. */ - if (FragChangedPixels >= 7){ - *DispFragPtr = BLOCK_CODED_LOW; - } - DispFragPtr++; - } - /*************************************************************/ - /* Last fragment of row !! */ - - /* Reset count of pixels changed for the current fragment. */ - FragChangedPixels = 0; - - /* Test for break out conditions to save time. */ - if (*DispFragPtr == CANDIDATE_BLOCK){ - /* Clear down entries in changed locals array */ - SET8_0(ChLocalsPtr); - - for ( j = 0; j < HFRAGPIXELS; j++ ){ - /* Take a local copy of the measured difference. */ - Diff = (int)YuvPtr1[j] - (int)YuvPtr2[j]; - - /* Store the actual difference value */ - YUVDiffsPtr[j] = Diff; - - /* Test against the Level thresholds and record the results */ - SgcPtr[0] += ppi->SgcThreshTable[Diff+255]; - - if (j<7 && ppi->SrfPakThreshTable[Diff+255] ) - Diff = (int)ApplyPakLowPass( ppi, &YuvPtr1[j] ) - - (int)ApplyPakLowPass( ppi, &YuvPtr2[j] ); - - - /* Test against the SRF thresholds */ - bits_map_ptr[j] = ppi->SrfThreshTable[Diff+255]; - FragChangedPixels += ppi->SrfThreshTable[Diff+255]; - } - }else{ - /* If we are breaking out here mark all pixels as changed.*/ - if ( *DispFragPtr > BLOCK_NOT_CODED ) { - SET8_1(bits_map_ptr); - SET8_8(ChLocalsPtr); - }else{ - SET8_0(ChLocalsPtr); - } - } - /* If we have a lot of changed pixels for this fragment on this - row then the fragment is almost sure to be picked (e.g. through - the line search) so we can mark it as selected and then ignore - it. */ - *RowDiffsPtr += FragChangedPixels; - *FDiffPixels += (unsigned char)FragChangedPixels; - - /* If we have a lot of changed pixels for this fragment on this - row then the fragment is almost sure to be picked (e.g. through - the line search) so we can mark it as selected and then ignore - it. */ - if (FragChangedPixels >= 7){ - *DispFragPtr = BLOCK_CODED_LOW; - } - DispFragPtr++; - - } -} - -static void ConsolidateDiffScanResults( PP_INSTANCE *ppi, - unsigned char * FDiffPixels, - signed char * SgcScoresPtr, - signed char * DispFragPtr ){ - ogg_int32_t i; - - for ( i = 0; i < ppi->PlaneHFragments; i ++ ){ - /* Consider only those blocks that were candidates in the - difference scan. Ignore definite YES and NO cases. */ - if ( DispFragPtr[i] == CANDIDATE_BLOCK ){ - if ( ((ogg_uint32_t)abs(SgcScoresPtr[i]) > ppi->BlockSgcThresh) ){ - /* Block marked for update due to Sgc change */ - DispFragPtr[i] = BLOCK_CODED_SGC; - }else if ( FDiffPixels[i] == 0 ){ - /* Block is no longer a candidate for the main tests but will - still be considered a candidate in RowBarEnhBlockMap() */ - DispFragPtr[i] = CANDIDATE_BLOCK_LOW; - } - } - } -} - -static void RowChangedLocalsScan( PP_INSTANCE *ppi, - unsigned char * PixelMapPtr, - unsigned char * ChLocalsPtr, - signed char * DispFragPtr, - unsigned char RowType ){ - - unsigned char changed_locals = 0; - unsigned char * PixelsChangedPtr0; - unsigned char * PixelsChangedPtr1; - unsigned char * PixelsChangedPtr2; - ogg_int32_t i, j; - ogg_int32_t LastRowIndex = ppi->PlaneWidth - 1; - - /* Set up the line based pointers into the bits changed map. */ - PixelsChangedPtr0 = PixelMapPtr - ppi->PlaneWidth; - if ( PixelsChangedPtr0 < ppi->PixelChangedMap ) - PixelsChangedPtr0 += ppi->PixelMapCircularBufferSize; - PixelsChangedPtr0 -= 1; - - PixelsChangedPtr1 = PixelMapPtr - 1; - - PixelsChangedPtr2 = PixelMapPtr + ppi->PlaneWidth; - if ( PixelsChangedPtr2 >= - (ppi->PixelChangedMap + ppi->PixelMapCircularBufferSize) ) - PixelsChangedPtr2 -= ppi->PixelMapCircularBufferSize; - PixelsChangedPtr2 -= 1; - - if ( RowType == NOT_EDGE_ROW ){ - /* Scan through the row of pixels and calculate changed locals. */ - for ( i = 0; i < ppi->PlaneWidth; i += HFRAGPIXELS ){ - /* Skip a group of 8 pixels if the assosciated fragment has no - pixels of interest. */ - if ( *DispFragPtr == CANDIDATE_BLOCK ){ - for ( j = 0; j < HFRAGPIXELS; j++ ){ - changed_locals = 0; - - /* If the pixel itself has changed */ - if ( PixelsChangedPtr1[1] ){ - if ( (i > 0) || (j > 0) ){ - changed_locals += PixelsChangedPtr0[0]; - changed_locals += PixelsChangedPtr1[0]; - changed_locals += PixelsChangedPtr2[0]; - } - - changed_locals += PixelsChangedPtr0[1]; - changed_locals += PixelsChangedPtr2[1]; - - if ( (i + j) < LastRowIndex ){ - changed_locals += PixelsChangedPtr0[2]; - changed_locals += PixelsChangedPtr1[2]; - changed_locals += PixelsChangedPtr2[2]; - } - - /* Store the number of changed locals */ - *ChLocalsPtr |= changed_locals; - } - - /* Increment to next pixel in the row */ - ChLocalsPtr++; - PixelsChangedPtr0++; - PixelsChangedPtr1++; - PixelsChangedPtr2++; - } - }else{ - if ( *DispFragPtr > BLOCK_NOT_CODED ) - SET8_0(ChLocalsPtr); - - /* Step pointers */ - ChLocalsPtr += HFRAGPIXELS; - PixelsChangedPtr0 += HFRAGPIXELS; - PixelsChangedPtr1 += HFRAGPIXELS; - PixelsChangedPtr2 += HFRAGPIXELS; - } - - /* Move on to next fragment. */ - DispFragPtr++; - - } - }else{ - /* Scan through the row of pixels and calculate changed locals. */ - for ( i = 0; i < ppi->PlaneWidth; i += HFRAGPIXELS ){ - /* Skip a group of 8 pixels if the assosciated fragment has no - pixels of interest */ - if ( *DispFragPtr == CANDIDATE_BLOCK ){ - for ( j = 0; j < HFRAGPIXELS; j++ ){ - changed_locals = 0; - - /* If the pixel itself has changed */ - if ( PixelsChangedPtr1[1] ){ - if ( RowType == FIRST_ROW ){ - if ( (i > 0) || (j > 0) ){ - changed_locals += PixelsChangedPtr1[0]; - changed_locals += PixelsChangedPtr2[0]; - } - - changed_locals += PixelsChangedPtr2[1]; - - if ( (i + j) < LastRowIndex ){ - changed_locals += PixelsChangedPtr1[2]; - changed_locals += PixelsChangedPtr2[2]; - } - }else{ - if ( (i > 0) || (j > 0 ) ){ - changed_locals += PixelsChangedPtr0[0]; - changed_locals += PixelsChangedPtr1[0]; - } - - changed_locals += PixelsChangedPtr0[1]; - - if ( (i + j) < LastRowIndex ){ - changed_locals += PixelsChangedPtr0[2]; - changed_locals += PixelsChangedPtr1[2]; - } - } - - /* Store the number of changed locals */ - *ChLocalsPtr |= changed_locals; - } - - /* Increment to next pixel in the row */ - ChLocalsPtr++; - PixelsChangedPtr0++; - PixelsChangedPtr1++; - PixelsChangedPtr2++; - } - }else{ - if ( *DispFragPtr > BLOCK_NOT_CODED ) - SET8_0(ChLocalsPtr); - - /* Step pointers */ - ChLocalsPtr += HFRAGPIXELS; - PixelsChangedPtr0 += HFRAGPIXELS; - PixelsChangedPtr1 += HFRAGPIXELS; - PixelsChangedPtr2 += HFRAGPIXELS; - } - - /* Move on to next fragment. */ - DispFragPtr++; - } - } -} - -static void NoiseScoreRow( PP_INSTANCE *ppi, - unsigned char * PixelMapPtr, - unsigned char * ChLocalsPtr, - ogg_int16_t * YUVDiffsPtr, - unsigned char * PixelNoiseScorePtr, - ogg_uint32_t * FragScorePtr, - signed char * DispFragPtr, - ogg_int32_t * RowDiffsPtr ){ - ogg_int32_t i,j; - unsigned char changed_locals = 0; - ogg_int32_t Score; - ogg_uint32_t FragScore; - ogg_int32_t AbsDiff; - - /* For each pixel in the row */ - for ( i = 0; i < ppi->PlaneWidth; i += HFRAGPIXELS ){ - /* Skip a group of 8 pixels if the assosciated fragment has no - pixels of interest. */ - if ( *DispFragPtr == CANDIDATE_BLOCK ){ - /* Reset the cumulative fragment score. */ - FragScore = 0; - - /* Pixels grouped along the row into fragments */ - for ( j = 0; j < HFRAGPIXELS; j++ ){ - if ( PixelMapPtr[j] ){ - AbsDiff = (ogg_int32_t)( abs(YUVDiffsPtr[j]) ); - changed_locals = ChLocalsPtr[j]; - - /* Give this pixel a score based on changed locals and level - of its own change. */ - Score = (1 + ((ogg_int32_t)(changed_locals + - ppi->NoiseScoreBoostTable[AbsDiff]) - - ppi->NoiseSupLevel)); - - /* For no zero scores adjust by a level based score multiplier. */ - if ( Score > 0 ){ - Score = ((double)Score * - ppi->AbsDiff_ScoreMultiplierTable[AbsDiff] ); - if ( Score < 1 ) - Score = 1; - }else{ - /* Set -ve values to 0 */ - Score = 0; - - /* If there are no changed locals then clear the pixel - changed flag and decrement the pixels changed in - fragment count to speed later stages. */ - if ( changed_locals == 0 ){ - PixelMapPtr[j] = 0; - *RowDiffsPtr -= 1; - } - } - - /* Update the pixel scores etc. */ - PixelNoiseScorePtr[j] = (unsigned char)Score; - FragScore += (ogg_uint32_t)Score; - } - } - - /* Add fragment score (with plane correction factor) into main - data structure */ - *FragScorePtr += (ogg_int32_t)(FragScore * - ppi->YUVPlaneCorrectionFactor); - - /* If score is greater than trip threshold then mark blcok for update. */ - if ( *FragScorePtr > ppi->BlockThreshold ){ - *DispFragPtr = BLOCK_CODED_LOW; - } - } - - /* Increment the various pointers */ - FragScorePtr++; - DispFragPtr++; - PixelNoiseScorePtr += HFRAGPIXELS; - PixelMapPtr += HFRAGPIXELS; - ChLocalsPtr += HFRAGPIXELS; - YUVDiffsPtr += HFRAGPIXELS; - } -} - -static void PrimaryEdgeScoreRow( PP_INSTANCE *ppi, - unsigned char * ChangedLocalsPtr, - ogg_int16_t * YUVDiffsPtr, - unsigned char * PixelNoiseScorePtr, - ogg_uint32_t * FragScorePtr, - signed char * DispFragPtr, - unsigned char RowType ){ - ogg_uint32_t BodyNeighbours; - ogg_uint32_t AbsDiff; - unsigned char changed_locals = 0; - ogg_int32_t Score; - ogg_uint32_t FragScore; - unsigned char * CHLocalsPtr0; - unsigned char * CHLocalsPtr1; - unsigned char * CHLocalsPtr2; - ogg_int32_t i,j; - ogg_int32_t LastRowIndex = ppi->PlaneWidth - 1; - - /* Set up pointers into the current previous and next row of the - changed locals data structure. */ - CHLocalsPtr0 = ChangedLocalsPtr - ppi->PlaneWidth; - if ( CHLocalsPtr0 < ppi->ChLocals ) - CHLocalsPtr0 += ppi->ChLocalsCircularBufferSize; - CHLocalsPtr0 -= 1; - - CHLocalsPtr1 = ChangedLocalsPtr - 1; - - CHLocalsPtr2 = ChangedLocalsPtr + ppi->PlaneWidth; - if ( CHLocalsPtr2 >= (ppi->ChLocals + ppi->ChLocalsCircularBufferSize) ) - CHLocalsPtr2 -= ppi->ChLocalsCircularBufferSize; - CHLocalsPtr2 -= 1; - - - /* The defining rule used here is as follows. */ - /* An edge pixels has 3-5 changed locals. */ - /* And one or more of these changed locals has itself got 7-8 - changed locals. */ - - if ( RowType == NOT_EDGE_ROW ){ - /* Loop for all pixels in the row. */ - for ( i = 0; i < ppi->PlaneWidth; i += HFRAGPIXELS ){ - /* Does the fragment contain anything interesting to work with. */ - if ( *DispFragPtr == CANDIDATE_BLOCK ){ - /* Reset the cumulative fragment score. */ - FragScore = 0; - - /* Pixels grouped along the row into fragments */ - for ( j = 0; j < HFRAGPIXELS; j++ ){ - /* How many changed locals has the current pixel got. */ - changed_locals = ChangedLocalsPtr[j]; - - /* Is the pixel a suitable candidate */ - if ( (changed_locals > 2) && (changed_locals < 6) ){ - /* The pixel may qualify... have a closer look. */ - BodyNeighbours = 0; - - /* Count the number of "BodyNeighbours" .. Pixels that - have 7 or more changed neighbours. */ - if ( (i > 0) || (j > 0 ) ){ - if ( CHLocalsPtr0[0] >= 7 ) - BodyNeighbours++; - if ( CHLocalsPtr1[0] >= 7 ) - BodyNeighbours++; - if ( CHLocalsPtr2[0] >= 7 ) - BodyNeighbours++; - } - - if ( CHLocalsPtr0[1] >= 7 ) - BodyNeighbours++; - if ( CHLocalsPtr2[1] >= 7 ) - BodyNeighbours++; - - if ( (i + j) < LastRowIndex ){ - if ( CHLocalsPtr0[2] >= 7 ) - BodyNeighbours++; - if ( CHLocalsPtr1[2] >= 7 ) - BodyNeighbours++; - if ( CHLocalsPtr2[2] >= 7 ) - BodyNeighbours++; - } - - if ( BodyNeighbours > 0 ){ - AbsDiff = abs( YUVDiffsPtr[j] ); - Score = (ogg_int32_t) - ( (double)(BodyNeighbours * - BodyNeighbourScore) * - ppi->AbsDiff_ScoreMultiplierTable[AbsDiff] ); - if ( Score < 1 ) - Score = 1; - - /* Increment the score by a value determined by the - number of body neighbours. */ - PixelNoiseScorePtr[j] += (unsigned char)Score; - FragScore += (ogg_uint32_t)Score; - } - } - - /* Increment pointers into changed locals buffer */ - CHLocalsPtr0 ++; - CHLocalsPtr1 ++; - CHLocalsPtr2 ++; - } - - /* Add fragment score (with plane correction factor) into main - data structure */ - *FragScorePtr += (ogg_int32_t)(FragScore * - ppi->YUVPlaneCorrectionFactor); - - /* If score is greater than trip threshold then mark blcok for - update. */ - if ( *FragScorePtr > ppi->BlockThreshold ){ - *DispFragPtr = BLOCK_CODED_LOW; - } - - }else{ - /* Nothing to do for this fragment group */ - /* Advance pointers into changed locals buffer */ - CHLocalsPtr0 += HFRAGPIXELS; - CHLocalsPtr1 += HFRAGPIXELS; - CHLocalsPtr2 += HFRAGPIXELS; - } - - /* Increment the various pointers */ - FragScorePtr++; - DispFragPtr++; - PixelNoiseScorePtr += HFRAGPIXELS; - ChangedLocalsPtr += HFRAGPIXELS; - YUVDiffsPtr += HFRAGPIXELS; - } - }else{ - /* This is either the top or bottom row of pixels in a plane. */ - /* Loop for all pixels in the row. */ - for ( i = 0; i < ppi->PlaneWidth; i += HFRAGPIXELS ){ - /* Does the fragment contain anything interesting to work with. */ - if ( *DispFragPtr == CANDIDATE_BLOCK ){ - /* Reset the cumulative fragment score. */ - FragScore = 0; - - /* Pixels grouped along the row into fragments */ - for ( j = 0; j < HFRAGPIXELS; j++ ){ - /* How many changed locals has the current pixel got. */ - changed_locals = ChangedLocalsPtr[j]; - - /* Is the pixel a suitable candidate */ - if ( (changed_locals > 2) && (changed_locals < 6) ){ - /* The pixel may qualify... have a closer look. */ - BodyNeighbours = 0; - - /* Count the number of "BodyNeighbours" .. Pixels - that have 7 or more changed neighbours. */ - if ( RowType == LAST_ROW ){ - /* Test for cases where it could be the first pixel on - the line */ - if ( (i > 0) || (j > 0) ){ - if ( CHLocalsPtr0[0] >= 7 ) - BodyNeighbours++; - if ( CHLocalsPtr1[0] >= 7 ) - BodyNeighbours++; - } - - if ( CHLocalsPtr0[1] >= 7 ) - BodyNeighbours++; - - /* Test for the end of line case */ - if ( (i + j) < LastRowIndex ){ - if ( CHLocalsPtr0[2] >= 7 ) - BodyNeighbours++; - - if ( CHLocalsPtr1[2] >= 7 ) - BodyNeighbours++; - } - }else{ - /* First Row */ - /* Test for cases where it could be the first pixel on - the line */ - if ( (i > 0) || (j > 0) ){ - if ( CHLocalsPtr1[0] >= 7 ) - BodyNeighbours++; - if ( CHLocalsPtr2[0] >= 7 ) - BodyNeighbours++; - } - - /* Test for the end of line case */ - if ( CHLocalsPtr2[1] >= 7 ) - BodyNeighbours++; - - if ( (i + j) < LastRowIndex ){ - if ( CHLocalsPtr1[2] >= 7 ) - BodyNeighbours++; - if ( CHLocalsPtr2[2] >= 7 ) - BodyNeighbours++; - } - } - - /* Allocate a score according to the number of Body neighbours. */ - if ( BodyNeighbours > 0 ){ - AbsDiff = abs( YUVDiffsPtr[j] ); - Score = (ogg_int32_t) - ( (double)(BodyNeighbours * BodyNeighbourScore) * - ppi->AbsDiff_ScoreMultiplierTable[AbsDiff] ); - if ( Score < 1 ) - Score = 1; - - PixelNoiseScorePtr[j] += (unsigned char)Score; - FragScore += (ogg_uint32_t)Score; - } - } - - /* Increment pointers into changed locals buffer */ - CHLocalsPtr0 ++; - CHLocalsPtr1 ++; - CHLocalsPtr2 ++; - } - - /* Add fragment score (with plane correction factor) into main - data structure */ - *FragScorePtr += - (ogg_int32_t)(FragScore * ppi->YUVPlaneCorrectionFactor); - - /* If score is greater than trip threshold then mark blcok for - update. */ - if ( *FragScorePtr > ppi->BlockThreshold ){ - *DispFragPtr = BLOCK_CODED_LOW; - } - - }else{ - /* Nothing to do for this fragment group */ - /* Advance pointers into changed locals buffer */ - CHLocalsPtr0 += HFRAGPIXELS; - CHLocalsPtr1 += HFRAGPIXELS; - CHLocalsPtr2 += HFRAGPIXELS; - } - - /* Increment the various pointers */ - FragScorePtr++; - DispFragPtr++; - PixelNoiseScorePtr += HFRAGPIXELS; - ChangedLocalsPtr += HFRAGPIXELS; - YUVDiffsPtr += HFRAGPIXELS; - } - } -} - -static void PixelLineSearch( PP_INSTANCE *ppi, - unsigned char * ChangedLocalsPtr, - ogg_int32_t RowNumber, - ogg_int32_t ColNumber, - unsigned char direction, - ogg_uint32_t * line_length ){ - /* Exit if the pixel does not qualify or we have fallen off the edge - of either the image plane or the row. */ - if ( (RowNumber < 0) || - (RowNumber >= ppi->PlaneHeight) || - (ColNumber < 0) || - (ColNumber >= ppi->PlaneWidth) || - ((*ChangedLocalsPtr) <= 1) || - ((*ChangedLocalsPtr) >= 6) ){ - /* If not then it isn't part of any line. */ - return; - } - - if (*line_length < ppi->MaxLineSearchLen){ - ogg_uint32_t TmpLineLength; - ogg_uint32_t BestLineLength; - unsigned char * search_ptr; - - /* Increment the line length to include this pixel. */ - *line_length += 1; - BestLineLength = *line_length; - - /* Continue search */ - /* up */ - if ( direction == UP ){ - TmpLineLength = *line_length; - - search_ptr = ChangedLocalsPtr - ppi->PlaneWidth; - if ( search_ptr < ppi->ChLocals ) - search_ptr += ppi->ChLocalsCircularBufferSize; - - PixelLineSearch( ppi, search_ptr, RowNumber - 1, ColNumber, - direction, &TmpLineLength ); - - if ( TmpLineLength > BestLineLength ) - BestLineLength = TmpLineLength; - } - - /* up and left */ - if ( (BestLineLength < ppi->MaxLineSearchLen) && - ((direction == UP) || (direction == LEFT)) ){ - TmpLineLength = *line_length; - - search_ptr = ChangedLocalsPtr - ppi->PlaneWidth; - if ( search_ptr < ppi->ChLocals ) - search_ptr += ppi->ChLocalsCircularBufferSize; - search_ptr -= 1; - - PixelLineSearch( ppi, search_ptr, RowNumber - 1, ColNumber - 1, - direction, &TmpLineLength ); - - if ( TmpLineLength > BestLineLength ) - BestLineLength = TmpLineLength; - } - - /* up and right */ - if ( (BestLineLength < ppi->MaxLineSearchLen) && - ((direction == UP) || (direction == RIGHT)) ){ - TmpLineLength = *line_length; - - search_ptr = ChangedLocalsPtr - ppi->PlaneWidth; - if ( search_ptr < ppi->ChLocals ) - search_ptr += ppi->ChLocalsCircularBufferSize; - search_ptr += 1; - - PixelLineSearch( ppi, search_ptr, RowNumber - 1, ColNumber + 1, - direction, &TmpLineLength ); - - if ( TmpLineLength > BestLineLength ) - BestLineLength = TmpLineLength; - } - - /* left */ - if ( (BestLineLength < ppi->MaxLineSearchLen) && ( direction == LEFT ) ){ - TmpLineLength = *line_length; - PixelLineSearch( ppi, ChangedLocalsPtr - 1, RowNumber, ColNumber - 1, - direction, &TmpLineLength ); - - if ( TmpLineLength > BestLineLength ) - BestLineLength = TmpLineLength; - } - - /* right */ - if ( (BestLineLength < ppi->MaxLineSearchLen) && ( direction == RIGHT ) ){ - TmpLineLength = *line_length; - PixelLineSearch( ppi, ChangedLocalsPtr + 1, RowNumber, ColNumber + 1, - direction, &TmpLineLength ); - - if ( TmpLineLength > BestLineLength ) - BestLineLength = TmpLineLength; - } - - /* Down */ - if ( BestLineLength < ppi->MaxLineSearchLen ){ - TmpLineLength = *line_length; - if ( direction == DOWN ){ - search_ptr = ChangedLocalsPtr + ppi->PlaneWidth; - if ( search_ptr >= (ppi->ChLocals + ppi->ChLocalsCircularBufferSize) ) - search_ptr -= ppi->ChLocalsCircularBufferSize; - - PixelLineSearch( ppi, search_ptr, RowNumber + 1, ColNumber, direction, - &TmpLineLength ); - - if ( TmpLineLength > BestLineLength ) - BestLineLength = TmpLineLength; - } - - - /* down and left */ - if ( (BestLineLength < ppi->MaxLineSearchLen) && - ((direction == DOWN) || (direction == LEFT)) ){ - TmpLineLength = *line_length; - - search_ptr = ChangedLocalsPtr + ppi->PlaneWidth; - if ( search_ptr >= (ppi->ChLocals + ppi->ChLocalsCircularBufferSize) ) - search_ptr -= ppi->ChLocalsCircularBufferSize; - search_ptr -= 1; - - PixelLineSearch( ppi, search_ptr, RowNumber + 1, ColNumber - 1, - direction, &TmpLineLength ); - - if ( TmpLineLength > BestLineLength ) - BestLineLength = TmpLineLength; - } - - /* down and right */ - if ( (BestLineLength < ppi->MaxLineSearchLen) && - ((direction == DOWN) || (direction == RIGHT)) ){ - TmpLineLength = *line_length; - - search_ptr = ChangedLocalsPtr + ppi->PlaneWidth; - if ( search_ptr >= (ppi->ChLocals + ppi->ChLocalsCircularBufferSize) ) - search_ptr -= ppi->ChLocalsCircularBufferSize; - search_ptr += 1; - - PixelLineSearch( ppi, search_ptr, RowNumber + 1, ColNumber + 1, - direction, &TmpLineLength ); - - if ( TmpLineLength > BestLineLength ) - BestLineLength = TmpLineLength; - } - } - - /* Note the search value for this pixel. */ - *line_length = BestLineLength; - } -} - -static unsigned char LineSearchScorePixel( PP_INSTANCE *ppi, - unsigned char * ChangedLocalsPtr, - ogg_int32_t RowNumber, - ogg_int32_t ColNumber ){ - ogg_uint32_t line_length = 0; - ogg_uint32_t line_length2 = 0; - ogg_uint32_t line_length_score = 0; - ogg_uint32_t tmp_line_length = 0; - ogg_uint32_t tmp_line_length2 = 0; - - /* Look UP and Down */ - PixelLineSearch( ppi, ChangedLocalsPtr, RowNumber, - ColNumber, UP, &tmp_line_length ); - - if (tmp_line_length < ppi->MaxLineSearchLen) { - /* Look DOWN */ - PixelLineSearch( ppi, ChangedLocalsPtr, RowNumber, - ColNumber, DOWN, &tmp_line_length2 ); - line_length = tmp_line_length + tmp_line_length2 - 1; - - if ( line_length > ppi->MaxLineSearchLen ) - line_length = ppi->MaxLineSearchLen; - }else - line_length = tmp_line_length; - - /* If no max length line found then look left and right */ - if ( line_length < ppi->MaxLineSearchLen ){ - tmp_line_length = 0; - tmp_line_length2 = 0; - - PixelLineSearch( ppi, ChangedLocalsPtr, RowNumber, - ColNumber, LEFT, &tmp_line_length ); - if (tmp_line_length < ppi->MaxLineSearchLen){ - PixelLineSearch( ppi, ChangedLocalsPtr, RowNumber, - ColNumber, RIGHT, &tmp_line_length2 ); - line_length2 = tmp_line_length + tmp_line_length2 - 1; - - if ( line_length2 > ppi->MaxLineSearchLen ) - line_length2 = ppi->MaxLineSearchLen; - }else - line_length2 = tmp_line_length; - - } - - /* Take the largest line length */ - if ( line_length2 > line_length ) - line_length = line_length2; - - /* Create line length score */ - line_length_score = LineLengthScores[line_length]; - - return (unsigned char)line_length_score; -} - -static void LineSearchScoreRow( PP_INSTANCE *ppi, - unsigned char * ChangedLocalsPtr, - ogg_int16_t * YUVDiffsPtr, - unsigned char * PixelNoiseScorePtr, - ogg_uint32_t * FragScorePtr, - signed char * DispFragPtr, - ogg_int32_t RowNumber ){ - ogg_uint32_t AbsDiff; - unsigned char changed_locals = 0; - ogg_int32_t Score; - ogg_uint32_t FragScore; - ogg_int32_t i,j; - - /* The defining rule used here is as follows. */ - /* An edge pixels has 2-5 changed locals. */ - /* And one or more of these changed locals has itself got 7-8 - changed locals. */ - - /* Loop for all pixels in the row. */ - for ( i = 0; i < ppi->PlaneWidth; i += HFRAGPIXELS ){ - /* Does the fragment contain anything interesting to work with. */ - if ( *DispFragPtr == CANDIDATE_BLOCK ){ - /* Reset the cumulative fragment score. */ - FragScore = 0; - - /* Pixels grouped along the row into fragments */ - for ( j = 0; j < HFRAGPIXELS; j++ ){ - /* How many changed locals has the current pixel got. */ - changed_locals = ChangedLocalsPtr[j]; - - /* Is the pixel a suitable candidate for edge enhancement */ - if ( (changed_locals > 1) && (changed_locals < 6) && - (PixelNoiseScorePtr[j] < ppi->LineSearchTripTresh) ) { - Score = (ogg_int32_t) - LineSearchScorePixel( ppi, &ChangedLocalsPtr[j], RowNumber, i+j ); - - if ( Score ){ - AbsDiff = abs( YUVDiffsPtr[j] ); - Score = (ogg_int32_t) - ( (double)Score * ppi->AbsDiff_ScoreMultiplierTable[AbsDiff] ); - if ( Score < 1 ) - Score = 1; - - PixelNoiseScorePtr[j] += (unsigned char)Score; - FragScore += (ogg_uint32_t)Score; - } - } - } - - /* Add fragment score (with plane correction factor) into main - data structure */ - *FragScorePtr += - (ogg_int32_t)(FragScore * ppi->YUVPlaneCorrectionFactor); - - /* If score is greater than trip threshold then mark blcok for update. */ - if ( *FragScorePtr > ppi->BlockThreshold ){ - *DispFragPtr = BLOCK_CODED_LOW; - } - } - - /* Increment the various pointers */ - FragScorePtr++; - DispFragPtr++; - PixelNoiseScorePtr += HFRAGPIXELS; - ChangedLocalsPtr += HFRAGPIXELS; - YUVDiffsPtr += HFRAGPIXELS; - - } -} - -static void RowCopy( PP_INSTANCE *ppi, ogg_uint32_t BlockMapIndex ){ - - ogg_uint32_t i,j; - - ogg_uint32_t PixelIndex = ppi->ScanPixelIndexTable[BlockMapIndex]; - signed char * BlockMapPtr = &ppi->ScanDisplayFragments[BlockMapIndex]; - signed char * PrevFragmentsPtr = &ppi->PrevFragments[0][BlockMapIndex]; - - unsigned char * SourcePtr; - unsigned char * DestPtr; - - /* Copy pixels from changed blocks back to reference frame. */ - for ( i = 0; i < (ogg_uint32_t)ppi->PlaneHFragments; i ++ ){ - /* If the fragement is marked for update or was recently marked - for update (PrevFragmentsPtr[i]) */ - if ( (BlockMapPtr[i] > BLOCK_NOT_CODED) || - (PrevFragmentsPtr[i] == BLOCK_CODED) ){ - /* Set up the various pointers required. */ - SourcePtr = &ppi->ScanConfig.Yuv1ptr[PixelIndex]; - DestPtr = &ppi->ScanConfig.SrfWorkSpcPtr[PixelIndex]; - - /* For each row of the block */ - for ( j = 0; j < VFRAGPIXELS; j++ ){ - /* Copy the data unaltered from source to destination */ - memcpy(DestPtr,SourcePtr,8); - - /* Increment pointers for next line in the block */ - SourcePtr += ppi->PlaneWidth; - DestPtr += ppi->PlaneWidth; - } - } - - /* Increment pixel index for next block. */ - PixelIndex += HFRAGPIXELS; - } -} - -static void RowBarEnhBlockMap( PP_INSTANCE *ppi, - signed char * UpdatedBlockMapPtr, - signed char * BarBlockMapPtr, - ogg_uint32_t RowNumber ){ - int i; - - /* Start by blanking the row in the bar block map structure. */ - memset( BarBlockMapPtr, BLOCK_NOT_CODED, ppi->PlaneHFragments ); - - /* First row */ - if ( RowNumber == 0 ){ - - /* For each fragment in the row. */ - for ( i = 0; i < ppi->PlaneHFragments; i ++ ){ - /* Test for CANDIDATE_BLOCK or CANDIDATE_BLOCK_LOW. Uncoded or - coded blocks will be ignored. */ - if ( UpdatedBlockMapPtr[i] <= CANDIDATE_BLOCK ){ - /* Is one of the immediate neighbours updated in the main map. */ - /* Note special cases for blocks at the start and end of rows. */ - if ( i == 0 ){ - - if ((UpdatedBlockMapPtr[i+1] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i+ppi->PlaneHFragments]>BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i+ppi->PlaneHFragments+1]>BLOCK_NOT_CODED ) ) - BarBlockMapPtr[i] = BLOCK_CODED_BAR; - - - }else if ( i == (ppi->PlaneHFragments - 1) ){ - - if ((UpdatedBlockMapPtr[i-1] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i+ppi->PlaneHFragments-1]>BLOCK_NOT_CODED) || - (UpdatedBlockMapPtr[i+ppi->PlaneHFragments]>BLOCK_NOT_CODED) ) - BarBlockMapPtr[i] = BLOCK_CODED_BAR; - - }else{ - if((UpdatedBlockMapPtr[i-1] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i+1] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i+ppi->PlaneHFragments-1] > BLOCK_NOT_CODED)|| - (UpdatedBlockMapPtr[i+ppi->PlaneHFragments] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i+ppi->PlaneHFragments+1] > BLOCK_NOT_CODED) ) - BarBlockMapPtr[i] = BLOCK_CODED_BAR; - } - } - } - - } else if ( RowNumber == (ogg_uint32_t)(ppi->PlaneVFragments-1)) { - - /* Last row */ - /* Used to read PlaneHFragments */ - - /* For each fragment in the row. */ - for ( i = 0; i < ppi->PlaneHFragments; i ++ ){ - /* Test for CANDIDATE_BLOCK or CANDIDATE_BLOCK_LOW - Uncoded or coded blocks will be ignored. */ - if ( UpdatedBlockMapPtr[i] <= CANDIDATE_BLOCK ){ - /* Is one of the immediate neighbours updated in the main map. */ - /* Note special cases for blocks at the start and end of rows. */ - if ( i == 0 ){ - if((UpdatedBlockMapPtr[i+1] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i-ppi->PlaneHFragments] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i-ppi->PlaneHFragments+1] > BLOCK_NOT_CODED )) - BarBlockMapPtr[i] = BLOCK_CODED_BAR; - - }else if ( i == (ppi->PlaneHFragments - 1) ){ - if((UpdatedBlockMapPtr[i-1] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i-ppi->PlaneHFragments-1] > BLOCK_NOT_CODED)|| - (UpdatedBlockMapPtr[i-ppi->PlaneHFragments] > BLOCK_NOT_CODED ) ) - BarBlockMapPtr[i] = BLOCK_CODED_BAR; - }else{ - if((UpdatedBlockMapPtr[i-1] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i+1] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i-ppi->PlaneHFragments-1] > BLOCK_NOT_CODED)|| - (UpdatedBlockMapPtr[i-ppi->PlaneHFragments] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i-ppi->PlaneHFragments+1] > BLOCK_NOT_CODED) ) - BarBlockMapPtr[i] = BLOCK_CODED_BAR; - } - } - } - - }else{ - /* All other rows */ - /* For each fragment in the row. */ - for ( i = 0; i < ppi->PlaneHFragments; i ++ ){ - /* Test for CANDIDATE_BLOCK or CANDIDATE_BLOCK_LOW */ - /* Uncoded or coded blocks will be ignored. */ - if ( UpdatedBlockMapPtr[i] <= CANDIDATE_BLOCK ){ - /* Is one of the immediate neighbours updated in the main map. */ - /* Note special cases for blocks at the start and end of rows. */ - if ( i == 0 ){ - - if((UpdatedBlockMapPtr[i+1] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i-ppi->PlaneHFragments] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i-ppi->PlaneHFragments+1] > BLOCK_NOT_CODED)|| - (UpdatedBlockMapPtr[i+ppi->PlaneHFragments] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i+ppi->PlaneHFragments+1] > BLOCK_NOT_CODED) ) - BarBlockMapPtr[i] = BLOCK_CODED_BAR; - - }else if ( i == (ppi->PlaneHFragments - 1) ){ - - if((UpdatedBlockMapPtr[i-1] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i-ppi->PlaneHFragments-1] > BLOCK_NOT_CODED)|| - (UpdatedBlockMapPtr[i-ppi->PlaneHFragments] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i+ppi->PlaneHFragments-1] > BLOCK_NOT_CODED)|| - (UpdatedBlockMapPtr[i+ppi->PlaneHFragments] > BLOCK_NOT_CODED ) ) - BarBlockMapPtr[i] = BLOCK_CODED_BAR; - - }else{ - if((UpdatedBlockMapPtr[i-1] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i+1] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i-ppi->PlaneHFragments-1] > BLOCK_NOT_CODED)|| - (UpdatedBlockMapPtr[i-ppi->PlaneHFragments] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i-ppi->PlaneHFragments+1] > BLOCK_NOT_CODED)|| - (UpdatedBlockMapPtr[i+ppi->PlaneHFragments-1] > BLOCK_NOT_CODED)|| - (UpdatedBlockMapPtr[i+ppi->PlaneHFragments] > BLOCK_NOT_CODED ) || - (UpdatedBlockMapPtr[i+ppi->PlaneHFragments+1] > BLOCK_NOT_CODED )) - BarBlockMapPtr[i] = BLOCK_CODED_BAR; - } - } - } - } -} - -static void BarCopyBack( PP_INSTANCE *ppi, - signed char * UpdatedBlockMapPtr, - signed char * BarBlockMapPtr ){ - ogg_int32_t i; - - /* For each fragment in the row. */ - for ( i = 0; i < ppi->PlaneHFragments; i ++ ){ - if ( BarBlockMapPtr[i] > BLOCK_NOT_CODED ){ - UpdatedBlockMapPtr[i] = BarBlockMapPtr[i]; - } - } -} - -static void AnalysePlane( PP_INSTANCE *ppi, - unsigned char * PlanePtr0, - unsigned char * PlanePtr1, - ogg_uint32_t FragArrayOffset, - ogg_uint32_t PWidth, - ogg_uint32_t PHeight, - ogg_uint32_t PStride ) { - unsigned char * RawPlanePtr0; - unsigned char * RawPlanePtr1; - - ogg_int16_t * YUVDiffsPtr; - ogg_int16_t * YUVDiffsPtr1; - ogg_int16_t * YUVDiffsPtr2; - - ogg_uint32_t FragIndex; - ogg_uint32_t ScoreFragIndex1; - ogg_uint32_t ScoreFragIndex2; - ogg_uint32_t ScoreFragIndex3; - ogg_uint32_t ScoreFragIndex4; - - int UpdatedOrCandidateBlocks = 0; - - unsigned char * ChLocalsPtr0; - unsigned char * ChLocalsPtr1; - unsigned char * ChLocalsPtr2; - - unsigned char * PixelsChangedPtr0; - unsigned char * PixelsChangedPtr1; - - unsigned char * PixelScoresPtr1; - unsigned char * PixelScoresPtr2; - - signed char * DispFragPtr0; - signed char * DispFragPtr1; - signed char * DispFragPtr2; - - ogg_uint32_t * FragScoresPtr1; - ogg_uint32_t * FragScoresPtr2; - - ogg_int32_t * RowDiffsPtr; - ogg_int32_t * RowDiffsPtr1; - ogg_int32_t * RowDiffsPtr2; - - ogg_int32_t i,j; - - ogg_int32_t RowNumber1; - ogg_int32_t RowNumber2; - ogg_int32_t RowNumber3; - ogg_int32_t RowNumber4; - - int EdgeRow; - ogg_int32_t LineSearchRowNumber = 0; - - /* Variables used as temporary stores for frequently used values. */ - ogg_int32_t Row0Mod3; - ogg_int32_t Row1Mod3; - ogg_int32_t Row2Mod3; - ogg_int32_t BlockRowPixels; - - /* Set pixel difference threshold */ - if ( FragArrayOffset == 0 ){ - /* Luminance */ - ppi->LevelThresh = (int)ppi->SgcLevelThresh; - ppi->NegLevelThresh = -ppi->LevelThresh; - - ppi->SrfThresh = (int)ppi->SRFGreyThresh; - ppi->NegSrfThresh = -ppi->SrfThresh; - - /* Scores correction for Y pixels. */ - ppi->YUVPlaneCorrectionFactor = 1.0; - - ppi->BlockThreshold = ppi->PrimaryBlockThreshold; - ppi->BlockSgcThresh = ppi->SgcThresh; - }else{ - /* Chrominance */ - ppi->LevelThresh = (int)ppi->SuvcLevelThresh; - ppi->NegLevelThresh = -ppi->LevelThresh; - - ppi->SrfThresh = (int)ppi->SRFColThresh; - ppi->NegSrfThresh = -ppi->SrfThresh; - - /* Scores correction for UV pixels. */ - ppi->YUVPlaneCorrectionFactor = 1.5; - - /* Block threholds different for subsampled U and V blocks */ - ppi->BlockThreshold = - (ppi->PrimaryBlockThreshold / ppi->UVBlockThreshCorrection); - ppi->BlockSgcThresh = - (ppi->SgcThresh / ppi->UVSgcCorrection); - } - - /* Initialise the SRF thresh table and pointer. */ - memset( ppi->SrfThreshTable, 1, 512 ); - for ( i = ppi->NegSrfThresh; i <= ppi->SrfThresh; i++ ) - ppi->SrfThreshTable[i+255] = 0; - - /* Initialise the PAK thresh table. */ - for ( i = -255; i <= 255; i++ ) - if ( ppi->SrfThreshTable[i+255] && - (i <= ppi->HighChange) && - (i >= ppi->NegHighChange) ) - ppi->SrfPakThreshTable[i+255] = 1; - else - ppi->SrfPakThreshTable[i+255] = 0; - - /* Initialise the SGc lookup table */ - for ( i = -255; i <= 255; i++ ){ - if ( i <= ppi->NegLevelThresh ) - ppi->SgcThreshTable[i+255] = (unsigned char) -1; - else if ( i >= ppi->LevelThresh ) - ppi->SgcThreshTable[i+255] = 1; - else - ppi->SgcThreshTable[i+255] = 0; - } - - /* Set up plane dimension variables */ - ppi->PlaneHFragments = PWidth / HFRAGPIXELS; - ppi->PlaneVFragments = PHeight / VFRAGPIXELS; - ppi->PlaneWidth = PWidth; - ppi->PlaneHeight = PHeight; - ppi->PlaneStride = PStride; - - /* Set up local pointers into the raw image data. */ - RawPlanePtr0 = PlanePtr0; - RawPlanePtr1 = PlanePtr1; - - /* Note size and endo points for circular buffers. */ - ppi->YuvDiffsCircularBufferSize = YDIFF_CB_ROWS * ppi->PlaneWidth; - ppi->ChLocalsCircularBufferSize = CHLOCALS_CB_ROWS * ppi->PlaneWidth; - ppi->PixelMapCircularBufferSize = PMAP_CB_ROWS * ppi->PlaneWidth; - - /* Set high change thresh where PAK not needed */ - ppi->HighChange = ppi->SrfThresh * 4; - ppi->NegHighChange = -ppi->HighChange; - - /* Set up row difference pointers. */ - RowDiffsPtr = ppi->RowChangedPixels; - RowDiffsPtr1 = ppi->RowChangedPixels; - RowDiffsPtr2 = ppi->RowChangedPixels; - - BlockRowPixels = ppi->PlaneWidth * VFRAGPIXELS; - - for ( i = 0; i < (ppi->PlaneVFragments + 4); i++ ){ - RowNumber1 = (i - 1); - RowNumber2 = (i - 2); - RowNumber3 = (i - 3); - RowNumber4 = (i - 4); - - /* Pre calculate some frequently used values */ - Row0Mod3 = i % 3; - Row1Mod3 = RowNumber1 % 3; - Row2Mod3 = RowNumber2 % 3; - - /* For row diff scan last two iterations are invalid */ - if ( i < ppi->PlaneVFragments ){ - FragIndex = (i * ppi->PlaneHFragments) + FragArrayOffset; - YUVDiffsPtr = &ppi->yuv_differences[Row0Mod3 * BlockRowPixels]; - - PixelsChangedPtr0 = (&ppi->PixelChangedMap[Row0Mod3 * BlockRowPixels]); - DispFragPtr0 = &ppi->ScanDisplayFragments[FragIndex]; - - ChLocalsPtr0 = (&ppi->ChLocals[Row0Mod3 * BlockRowPixels]); - - } - - /* Set up the changed locals pointer to trail behind by one row of - fragments. */ - if ( i > 0 ){ - /* For last iteration the ch locals and noise scans are invalid */ - if ( RowNumber1 < ppi->PlaneVFragments ){ - ScoreFragIndex1 = (RowNumber1 * ppi->PlaneHFragments) + - FragArrayOffset; - - ChLocalsPtr1 = &ppi->ChLocals[Row1Mod3 * BlockRowPixels]; - PixelsChangedPtr1 = - &ppi->PixelChangedMap[(Row1Mod3) * BlockRowPixels]; - - PixelScoresPtr1 = &ppi->PixelScores[(RowNumber1 % 4) * BlockRowPixels]; - - YUVDiffsPtr1 = &ppi->yuv_differences[Row1Mod3 * BlockRowPixels]; - FragScoresPtr1 = &ppi->FragScores[ScoreFragIndex1]; - DispFragPtr1 = &ppi->ScanDisplayFragments[ScoreFragIndex1]; - - } - - if ( RowNumber2 >= 0 ){ - ScoreFragIndex2 = (RowNumber2 * ppi->PlaneHFragments) + - FragArrayOffset; - ChLocalsPtr2 = (&ppi->ChLocals[Row2Mod3 * BlockRowPixels]); - YUVDiffsPtr2 = &ppi->yuv_differences[Row2Mod3 * BlockRowPixels]; - - PixelScoresPtr2 = &ppi->PixelScores[(RowNumber2 % 4) * BlockRowPixels]; - - FragScoresPtr2 = &ppi->FragScores[ScoreFragIndex2]; - DispFragPtr2 = &ppi->ScanDisplayFragments[ScoreFragIndex2]; - }else{ - ChLocalsPtr2 = NULL; - } - }else{ - ChLocalsPtr1 = NULL; - ChLocalsPtr2 = NULL; - } - - /* Fast break out test for obvious yes and no cases in this row of - blocks */ - if ( i < ppi->PlaneVFragments ){ - dsp_save_fpu (ppi->dsp); - UpdatedOrCandidateBlocks = - RowSadScan( ppi, RawPlanePtr0, RawPlanePtr1, DispFragPtr0 ); - UpdatedOrCandidateBlocks |= - ColSadScan( ppi, RawPlanePtr0, RawPlanePtr1, DispFragPtr0 ); - dsp_restore_fpu (ppi->dsp); - }else{ - /* Make sure we still call other functions if RowSadScan() disabled */ - UpdatedOrCandidateBlocks = 1; - } - - /* Consolidation and fast break ot tests at Row 1 level */ - if ( (i > 0) && (RowNumber1 < ppi->PlaneVFragments) ){ - /* Mark as coded any candidate block that lies adjacent to a - coded block. */ - SadPass2( ppi, RowNumber1, DispFragPtr1 ); - - /* Check results of diff scan in last set of blocks. */ - /* Eliminate NO cases and add in +SGC cases */ - ConsolidateDiffScanResults( ppi, &ppi->FragDiffPixels[ScoreFragIndex1], - &ppi->SameGreyDirPixels[ScoreFragIndex1], - DispFragPtr1 - ); - } - - for ( j = 0; j < VFRAGPIXELS; j++ ){ - /* Last two iterations do not apply */ - if ( i < ppi->PlaneVFragments ){ - /* Is the current fragment at an edge. */ - EdgeRow = ( ( (i == 0) && (j == 0) ) || - ( (i == (ppi->PlaneVFragments - 1)) && - (j == (VFRAGPIXELS - 1)) ) ); - - /* Clear the arrays that will be used for the changed pixels maps */ - memset( PixelsChangedPtr0, 0, ppi->PlaneWidth ); - - /* Difference scan and map each row */ - if ( UpdatedOrCandidateBlocks ){ - /* Scan the row for interesting differences */ - /* Also clear the array that will be used for changed locals map */ - RowDiffScan( ppi, RawPlanePtr0, RawPlanePtr1, - YUVDiffsPtr, PixelsChangedPtr0, - &ppi->SameGreyDirPixels[FragIndex], - DispFragPtr0, &ppi->FragDiffPixels[FragIndex], - RowDiffsPtr, ChLocalsPtr0, EdgeRow); - }else{ - /* Clear the array that will be used for changed locals map */ - memset( ChLocalsPtr0, 0, ppi->PlaneWidth ); - } - - /* The actual image plane pointers must be incremented by - stride as this may be different (more) than the plane - width. Our own internal buffers use ppi->PlaneWidth. */ - RawPlanePtr0 += ppi->PlaneStride; - RawPlanePtr1 += ppi->PlaneStride; - PixelsChangedPtr0 += ppi->PlaneWidth; - ChLocalsPtr0 += ppi->PlaneWidth; - YUVDiffsPtr += ppi->PlaneWidth; - RowDiffsPtr++; - } - - /* Run behind calculating the changed locals data and noise scores. */ - if ( ChLocalsPtr1 != NULL ){ - /* Last few iterations do not apply */ - if ( RowNumber1 < ppi->PlaneVFragments ){ - /* Blank the next row in the pixel scores data structure. */ - memset( PixelScoresPtr1, 0, ppi->PlaneWidth ); - - /* Don't bother doing anything if there are no changed - pixels in this row */ - if ( *RowDiffsPtr1 ){ - /* Last valid row is a special case */ - if ( i < ppi->PlaneVFragments ) - RowChangedLocalsScan( ppi, PixelsChangedPtr1, ChLocalsPtr1, - DispFragPtr1, - ( (((i-1)==0) && (j==0)) ? - FIRST_ROW : NOT_EDGE_ROW) ); - else - RowChangedLocalsScan( ppi, PixelsChangedPtr1, ChLocalsPtr1, - DispFragPtr1, - ((j==(VFRAGPIXELS-1)) ? - LAST_ROW : NOT_EDGE_ROW) ); - - NoiseScoreRow( ppi, PixelsChangedPtr1, ChLocalsPtr1, YUVDiffsPtr1, - PixelScoresPtr1, FragScoresPtr1, DispFragPtr1, - RowDiffsPtr1 ); - } - - ChLocalsPtr1 += ppi->PlaneWidth; - PixelsChangedPtr1 += ppi->PlaneWidth; - YUVDiffsPtr1 += ppi->PlaneWidth; - PixelScoresPtr1 += ppi->PlaneWidth; - RowDiffsPtr1 ++; - } - - /* Run edge enhancement algorithms */ - if ( RowNumber2 < ppi->PlaneVFragments ){ - if ( ChLocalsPtr2 != NULL ){ - /* Don't bother doing anything if there are no changed - pixels in this row */ - if ( *RowDiffsPtr2 ){ - if ( RowNumber1 < ppi->PlaneVFragments ){ - PrimaryEdgeScoreRow( ppi, ChLocalsPtr2, YUVDiffsPtr2, - PixelScoresPtr2, FragScoresPtr2, - DispFragPtr2, - ( (((i-2)==0) && (j==0)) ? - FIRST_ROW : NOT_EDGE_ROW) ); - }else{ - /* Edge enhancement */ - PrimaryEdgeScoreRow( ppi, ChLocalsPtr2, YUVDiffsPtr2, - PixelScoresPtr2, FragScoresPtr2, - DispFragPtr2, - ((j==(VFRAGPIXELS-1)) ? - LAST_ROW : NOT_EDGE_ROW) ); - } - - /* Recursive line search */ - LineSearchScoreRow( ppi, ChLocalsPtr2, YUVDiffsPtr2, - PixelScoresPtr2, FragScoresPtr2, - DispFragPtr2, - LineSearchRowNumber ); - } - - ChLocalsPtr2 += ppi->PlaneWidth; - YUVDiffsPtr2 += ppi->PlaneWidth; - PixelScoresPtr2 += ppi->PlaneWidth; - LineSearchRowNumber += 1; - RowDiffsPtr2 ++; - } - } - } - } - - /* BAR algorithm */ - if ( (RowNumber3 >= 0) && (RowNumber3 < ppi->PlaneVFragments) ){ - ScoreFragIndex3 = (RowNumber3 * ppi->PlaneHFragments) + FragArrayOffset; - RowBarEnhBlockMap(ppi, - &ppi->ScanDisplayFragments[ScoreFragIndex3], - &ppi->BarBlockMap[(RowNumber3 % 3) * - ppi->PlaneHFragments], - RowNumber3 ); - } - - /* BAR copy back and "ppi->SRF filtering" or "pixel copy back" */ - if ( (RowNumber4 >= 0) && (RowNumber4 < ppi->PlaneVFragments) ){ - /* BAR copy back stage must lag by one more row to avoid BAR blocks - being used in BAR descisions. */ - ScoreFragIndex4 = (RowNumber4 * ppi->PlaneHFragments) + FragArrayOffset; - - BarCopyBack(ppi, &ppi->ScanDisplayFragments[ScoreFragIndex4], - &ppi->BarBlockMap[(RowNumber4 % 3) * ppi->PlaneHFragments]); - - /* Copy over the data from any blocks marked for update into the - output buffer. */ - RowCopy(ppi, ScoreFragIndex4); - } - } -} - -ogg_uint32_t YUVAnalyseFrame( PP_INSTANCE *ppi, ogg_uint32_t * KFIndicator ){ - - /* Initialise the map arrays. */ - InitScanMapArrays(ppi); - - /* If the motion level in the previous frame was high then adjust - the high and low SAD thresholds to speed things up. */ - ppi->ModifiedGrpLowSadThresh = ppi->GrpLowSadThresh; - ppi->ModifiedGrpHighSadThresh = ppi->GrpHighSadThresh; - - - /* Set up the internal plane height and width variables. */ - ppi->VideoYPlaneWidth = ppi->ScanConfig.VideoFrameWidth; - ppi->VideoYPlaneHeight = ppi->ScanConfig.VideoFrameHeight; - ppi->VideoUVPlaneWidth = ppi->ScanConfig.VideoFrameWidth / 2; - ppi->VideoUVPlaneHeight = ppi->ScanConfig.VideoFrameHeight / 2; - - /* To start with the strides will be set from the widths */ - ppi->VideoYPlaneStride = ppi->VideoYPlaneWidth; - ppi->VideoUPlaneStride = ppi->VideoUVPlaneWidth; - ppi->VideoVPlaneStride = ppi->VideoUVPlaneWidth; - - /* Set up the plane pointers */ - ppi->YPlanePtr0 = ppi->ScanConfig.Yuv0ptr; - ppi->YPlanePtr1 = ppi->ScanConfig.Yuv1ptr; - ppi->UPlanePtr0 = (ppi->ScanConfig.Yuv0ptr + ppi->YFramePixels); - ppi->UPlanePtr1 = (ppi->ScanConfig.Yuv1ptr + ppi->YFramePixels); - ppi->VPlanePtr0 = (ppi->ScanConfig.Yuv0ptr + ppi->YFramePixels + - ppi->UVFramePixels); - ppi->VPlanePtr1 = (ppi->ScanConfig.Yuv1ptr + ppi->YFramePixels + - ppi->UVFramePixels); - - /* Check previous frame lists and if necessary mark extra blocks for - update. */ - SetFromPrevious(ppi); - - /* Ananlyse the U and V palnes. */ - AnalysePlane( ppi, ppi->UPlanePtr0, ppi->UPlanePtr1, - ppi->ScanYPlaneFragments, ppi->VideoUVPlaneWidth, - ppi->VideoUVPlaneHeight, ppi->VideoUPlaneStride ); - AnalysePlane( ppi, ppi->VPlanePtr0, ppi->VPlanePtr1, - (ppi->ScanYPlaneFragments + ppi->ScanUVPlaneFragments), - ppi->VideoUVPlaneWidth, ppi->VideoUVPlaneHeight, - ppi->VideoVPlaneStride ); - - /* Now analyse the Y plane. */ - AnalysePlane( ppi, ppi->YPlanePtr0, ppi->YPlanePtr1, 0, - ppi->VideoYPlaneWidth, ppi->VideoYPlaneHeight, - ppi->VideoYPlaneStride ); - - /* Update the list of previous frame block updates. */ - UpdatePreviousBlockLists(ppi); - - /* Create an output block map for the calling process. */ - CreateOutputDisplayMap( ppi, ppi->ScanDisplayFragments, - ppi->PrevFragments[0], - ppi->ScanConfig.disp_fragments ); - - /* Set the candidate key frame indicator (0-100) */ - *KFIndicator = ppi->KFIndicator; - - /* Return the normalised block count (this is actually a motion - level weighting not a true block count). */ - return ppi->OutputBlocksUpdated; -} - diff --git a/Engine/lib/libtheora/lib/enc/toplevel_lookup.h b/Engine/lib/libtheora/lib/enc/toplevel_lookup.h deleted file mode 100644 index bf83a15b6..000000000 --- a/Engine/lib/libtheora/lib/enc/toplevel_lookup.h +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: toplevel_lookup.h 13884 2007-09-22 08:38:10Z giles $ - - ********************************************************************/ - -#include "codec_internal.h" - -const ogg_uint32_t PriorKeyFrameWeight[KEY_FRAME_CONTEXT] = { 1,2,3,4,5 }; - -/* Data structures controlling addition of residue blocks */ -const ogg_uint32_t ResidueErrorThresh[Q_TABLE_SIZE] = { - 750, 700, 650, 600, 590, 580, 570, 560, - 550, 540, 530, 520, 510, 500, 490, 480, - 470, 460, 450, 440, 430, 420, 410, 400, - 390, 380, 370, 360, 350, 340, 330, 320, - 310, 300, 290, 280, 270, 260, 250, 245, - 240, 235, 230, 225, 220, 215, 210, 205, - 200, 195, 190, 185, 180, 175, 170, 165, - 160, 155, 150, 145, 140, 135, 130, 130 }; -const ogg_uint32_t ResidueBlockFactor[Q_TABLE_SIZE] = { - 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2 }; diff --git a/Engine/lib/libtheora/lib/enc/x86_32/dct_decode_mmx.c b/Engine/lib/libtheora/lib/enc/x86_32/dct_decode_mmx.c deleted file mode 100644 index 547e974e3..000000000 --- a/Engine/lib/libtheora/lib/enc/x86_32/dct_decode_mmx.c +++ /dev/null @@ -1,409 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2008 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: dct_decode_mmx.c 15400 2008-10-15 12:10:58Z tterribe $ - - ********************************************************************/ - -#include - -#include "../codec_internal.h" - -#if defined(USE_ASM) - -static const __attribute__((aligned(8),used)) ogg_int64_t OC_V3= - 0x0003000300030003LL; -static const __attribute__((aligned(8),used)) ogg_int64_t OC_V4= - 0x0004000400040004LL; - -static void loop_filter_v(unsigned char *_pix,int _ystride, - const ogg_int16_t *_ll){ - long esi; - _pix-=_ystride*2; - __asm__ __volatile__( - /*mm0=0*/ - "pxor %%mm0,%%mm0\n\t" - /*esi=_ystride*3*/ - "lea (%[ystride],%[ystride],2),%[s]\n\t" - /*mm7=_pix[0...8]*/ - "movq (%[pix]),%%mm7\n\t" - /*mm4=_pix[0...8+_ystride*3]*/ - "movq (%[pix],%[s]),%%mm4\n\t" - /*mm6=_pix[0...8]*/ - "movq %%mm7,%%mm6\n\t" - /*Expand unsigned _pix[0...3] to 16 bits.*/ - "punpcklbw %%mm0,%%mm6\n\t" - "movq %%mm4,%%mm5\n\t" - /*Expand unsigned _pix[4...8] to 16 bits.*/ - "punpckhbw %%mm0,%%mm7\n\t" - /*Expand other arrays too.*/ - "punpcklbw %%mm0,%%mm4\n\t" - "punpckhbw %%mm0,%%mm5\n\t" - /*mm7:mm6=_p[0...8]-_p[0...8+_ystride*3]:*/ - "psubw %%mm4,%%mm6\n\t" - "psubw %%mm5,%%mm7\n\t" - /*mm5=mm4=_pix[0...8+_ystride]*/ - "movq (%[pix],%[ystride]),%%mm4\n\t" - /*mm1=mm3=mm2=_pix[0..8]+_ystride*2]*/ - "movq (%[pix],%[ystride],2),%%mm2\n\t" - "movq %%mm4,%%mm5\n\t" - "movq %%mm2,%%mm3\n\t" - "movq %%mm2,%%mm1\n\t" - /*Expand these arrays.*/ - "punpckhbw %%mm0,%%mm5\n\t" - "punpcklbw %%mm0,%%mm4\n\t" - "punpckhbw %%mm0,%%mm3\n\t" - "punpcklbw %%mm0,%%mm2\n\t" - /*Preload...*/ - "movq %[OC_V3],%%mm0\n\t" - /*mm3:mm2=_pix[0...8+_ystride*2]-_pix[0...8+_ystride]*/ - "psubw %%mm5,%%mm3\n\t" - "psubw %%mm4,%%mm2\n\t" - /*Scale by 3.*/ - "pmullw %%mm0,%%mm3\n\t" - "pmullw %%mm0,%%mm2\n\t" - /*Preload...*/ - "movq %[OC_V4],%%mm0\n\t" - /*f=mm3:mm2==_pix[0...8]-_pix[0...8+_ystride*3]+ - 3*(_pix[0...8+_ystride*2]-_pix[0...8+_ystride])*/ - "paddw %%mm7,%%mm3\n\t" - "paddw %%mm6,%%mm2\n\t" - /*Add 4.*/ - "paddw %%mm0,%%mm3\n\t" - "paddw %%mm0,%%mm2\n\t" - /*"Divide" by 8.*/ - "psraw $3,%%mm3\n\t" - "psraw $3,%%mm2\n\t" - /*Now compute lflim of mm3:mm2 cf. Section 7.10 of the sepc.*/ - /*Free up mm5.*/ - "packuswb %%mm5,%%mm4\n\t" - /*mm0=L L L L*/ - "movq (%[ll]),%%mm0\n\t" - /*if(R_i<-2L||R_i>2L)R_i=0:*/ - "movq %%mm2,%%mm5\n\t" - "pxor %%mm6,%%mm6\n\t" - "movq %%mm0,%%mm7\n\t" - "psubw %%mm0,%%mm6\n\t" - "psllw $1,%%mm7\n\t" - "psllw $1,%%mm6\n\t" - /*mm2==R_3 R_2 R_1 R_0*/ - /*mm5==R_3 R_2 R_1 R_0*/ - /*mm6==-2L -2L -2L -2L*/ - /*mm7==2L 2L 2L 2L*/ - "pcmpgtw %%mm2,%%mm7\n\t" - "pcmpgtw %%mm6,%%mm5\n\t" - "pand %%mm7,%%mm2\n\t" - "movq %%mm0,%%mm7\n\t" - "pand %%mm5,%%mm2\n\t" - "psllw $1,%%mm7\n\t" - "movq %%mm3,%%mm5\n\t" - /*mm3==R_7 R_6 R_5 R_4*/ - /*mm5==R_7 R_6 R_5 R_4*/ - /*mm6==-2L -2L -2L -2L*/ - /*mm7==2L 2L 2L 2L*/ - "pcmpgtw %%mm3,%%mm7\n\t" - "pcmpgtw %%mm6,%%mm5\n\t" - "pand %%mm7,%%mm3\n\t" - "movq %%mm0,%%mm7\n\t" - "pand %%mm5,%%mm3\n\t" - /*if(R_i<-L)R_i'=R_i+2L; - if(R_i>L)R_i'=R_i-2L; - if(R_i<-L||R_i>L)R_i=-R_i':*/ - "psraw $1,%%mm6\n\t" - "movq %%mm2,%%mm5\n\t" - "psllw $1,%%mm7\n\t" - /*mm2==R_3 R_2 R_1 R_0*/ - /*mm5==R_3 R_2 R_1 R_0*/ - /*mm6==-L -L -L -L*/ - /*mm0==L L L L*/ - /*mm5=R_i>L?FF:00*/ - "pcmpgtw %%mm0,%%mm5\n\t" - /*mm6=-L>R_i?FF:00*/ - "pcmpgtw %%mm2,%%mm6\n\t" - /*mm7=R_i>L?2L:0*/ - "pand %%mm5,%%mm7\n\t" - /*mm2=R_i>L?R_i-2L:R_i*/ - "psubw %%mm7,%%mm2\n\t" - "movq %%mm0,%%mm7\n\t" - /*mm5=-L>R_i||R_i>L*/ - "por %%mm6,%%mm5\n\t" - "psllw $1,%%mm7\n\t" - /*mm7=-L>R_i?2L:0*/ - "pand %%mm6,%%mm7\n\t" - "pxor %%mm6,%%mm6\n\t" - /*mm2=-L>R_i?R_i+2L:R_i*/ - "paddw %%mm7,%%mm2\n\t" - "psubw %%mm0,%%mm6\n\t" - /*mm5=-L>R_i||R_i>L?-R_i':0*/ - "pand %%mm2,%%mm5\n\t" - "movq %%mm0,%%mm7\n\t" - /*mm2=-L>R_i||R_i>L?0:R_i*/ - "psubw %%mm5,%%mm2\n\t" - "psllw $1,%%mm7\n\t" - /*mm2=-L>R_i||R_i>L?-R_i':R_i*/ - "psubw %%mm5,%%mm2\n\t" - "movq %%mm3,%%mm5\n\t" - /*mm3==R_7 R_6 R_5 R_4*/ - /*mm5==R_7 R_6 R_5 R_4*/ - /*mm6==-L -L -L -L*/ - /*mm0==L L L L*/ - /*mm6=-L>R_i?FF:00*/ - "pcmpgtw %%mm3,%%mm6\n\t" - /*mm5=R_i>L?FF:00*/ - "pcmpgtw %%mm0,%%mm5\n\t" - /*mm7=R_i>L?2L:0*/ - "pand %%mm5,%%mm7\n\t" - /*mm2=R_i>L?R_i-2L:R_i*/ - "psubw %%mm7,%%mm3\n\t" - "psllw $1,%%mm0\n\t" - /*mm5=-L>R_i||R_i>L*/ - "por %%mm6,%%mm5\n\t" - /*mm0=-L>R_i?2L:0*/ - "pand %%mm6,%%mm0\n\t" - /*mm3=-L>R_i?R_i+2L:R_i*/ - "paddw %%mm0,%%mm3\n\t" - /*mm5=-L>R_i||R_i>L?-R_i':0*/ - "pand %%mm3,%%mm5\n\t" - /*mm2=-L>R_i||R_i>L?0:R_i*/ - "psubw %%mm5,%%mm3\n\t" - /*mm2=-L>R_i||R_i>L?-R_i':R_i*/ - "psubw %%mm5,%%mm3\n\t" - /*Unfortunately, there's no unsigned byte+signed byte with unsigned - saturation op code, so we have to promote things back 16 bits.*/ - "pxor %%mm0,%%mm0\n\t" - "movq %%mm4,%%mm5\n\t" - "punpcklbw %%mm0,%%mm4\n\t" - "punpckhbw %%mm0,%%mm5\n\t" - "movq %%mm1,%%mm6\n\t" - "punpcklbw %%mm0,%%mm1\n\t" - "punpckhbw %%mm0,%%mm6\n\t" - /*_pix[0...8+_ystride]+=R_i*/ - "paddw %%mm2,%%mm4\n\t" - "paddw %%mm3,%%mm5\n\t" - /*_pix[0...8+_ystride*2]-=R_i*/ - "psubw %%mm2,%%mm1\n\t" - "psubw %%mm3,%%mm6\n\t" - "packuswb %%mm5,%%mm4\n\t" - "packuswb %%mm6,%%mm1\n\t" - /*Write it back out.*/ - "movq %%mm4,(%[pix],%[ystride])\n\t" - "movq %%mm1,(%[pix],%[ystride],2)\n\t" - :[s]"=&S"(esi) - :[pix]"r"(_pix),[ystride]"r"((long)_ystride),[ll]"r"(_ll), - [OC_V3]"m"(OC_V3),[OC_V4]"m"(OC_V4) - :"memory" - ); -} - -/*This code implements the bulk of loop_filter_h(). - Data are striped p0 p1 p2 p3 ... p0 p1 p2 p3 ..., so in order to load all - four p0's to one register we must transpose the values in four mmx regs. - When half is done we repeat this for the rest.*/ -static void loop_filter_h4(unsigned char *_pix,long _ystride, - const ogg_int16_t *_ll){ - long esi; - long edi; - __asm__ __volatile__( - /*x x x x 3 2 1 0*/ - "movd (%[pix]),%%mm0\n\t" - /*esi=_ystride*3*/ - "lea (%[ystride],%[ystride],2),%[s]\n\t" - /*x x x x 7 6 5 4*/ - "movd (%[pix],%[ystride]),%%mm1\n\t" - /*x x x x B A 9 8*/ - "movd (%[pix],%[ystride],2),%%mm2\n\t" - /*x x x x F E D C*/ - "movd (%[pix],%[s]),%%mm3\n\t" - /*mm0=7 3 6 2 5 1 4 0*/ - "punpcklbw %%mm1,%%mm0\n\t" - /*mm2=F B E A D 9 C 8*/ - "punpcklbw %%mm3,%%mm2\n\t" - /*mm1=7 3 6 2 5 1 4 0*/ - "movq %%mm0,%%mm1\n\t" - /*mm0=F B 7 3 E A 6 2*/ - "punpckhwd %%mm2,%%mm0\n\t" - /*mm1=D 9 5 1 C 8 4 0*/ - "punpcklwd %%mm2,%%mm1\n\t" - "pxor %%mm7,%%mm7\n\t" - /*mm5=D 9 5 1 C 8 4 0*/ - "movq %%mm1,%%mm5\n\t" - /*mm1=x C x 8 x 4 x 0==pix[0]*/ - "punpcklbw %%mm7,%%mm1\n\t" - /*mm5=x D x 9 x 5 x 1==pix[1]*/ - "punpckhbw %%mm7,%%mm5\n\t" - /*mm3=F B 7 3 E A 6 2*/ - "movq %%mm0,%%mm3\n\t" - /*mm0=x E x A x 6 x 2==pix[2]*/ - "punpcklbw %%mm7,%%mm0\n\t" - /*mm3=x F x B x 7 x 3==pix[3]*/ - "punpckhbw %%mm7,%%mm3\n\t" - /*mm1=mm1-mm3==pix[0]-pix[3]*/ - "psubw %%mm3,%%mm1\n\t" - /*Save a copy of pix[2] for later.*/ - "movq %%mm0,%%mm4\n\t" - /*mm0=mm0-mm5==pix[2]-pix[1]*/ - "psubw %%mm5,%%mm0\n\t" - /*Scale by 3.*/ - "pmullw %[OC_V3],%%mm0\n\t" - /*f=mm1==_pix[0]-_pix[3]+ 3*(_pix[2]-_pix[1])*/ - "paddw %%mm1,%%mm0\n\t" - /*Add 4.*/ - "paddw %[OC_V4],%%mm0\n\t" - /*"Divide" by 8, producing the residuals R_i.*/ - "psraw $3,%%mm0\n\t" - /*Now compute lflim of mm0 cf. Section 7.10 of the sepc.*/ - /*mm6=L L L L*/ - "movq (%[ll]),%%mm6\n\t" - /*if(R_i<-2L||R_i>2L)R_i=0:*/ - "movq %%mm0,%%mm1\n\t" - "pxor %%mm2,%%mm2\n\t" - "movq %%mm6,%%mm3\n\t" - "psubw %%mm6,%%mm2\n\t" - "psllw $1,%%mm3\n\t" - "psllw $1,%%mm2\n\t" - /*mm0==R_3 R_2 R_1 R_0*/ - /*mm1==R_3 R_2 R_1 R_0*/ - /*mm2==-2L -2L -2L -2L*/ - /*mm3==2L 2L 2L 2L*/ - "pcmpgtw %%mm0,%%mm3\n\t" - "pcmpgtw %%mm2,%%mm1\n\t" - "pand %%mm3,%%mm0\n\t" - "pand %%mm1,%%mm0\n\t" - /*if(R_i<-L)R_i'=R_i+2L; - if(R_i>L)R_i'=R_i-2L; - if(R_i<-L||R_i>L)R_i=-R_i':*/ - "psraw $1,%%mm2\n\t" - "movq %%mm0,%%mm1\n\t" - "movq %%mm6,%%mm3\n\t" - /*mm0==R_3 R_2 R_1 R_0*/ - /*mm1==R_3 R_2 R_1 R_0*/ - /*mm2==-L -L -L -L*/ - /*mm6==L L L L*/ - /*mm2=-L>R_i?FF:00*/ - "pcmpgtw %%mm0,%%mm2\n\t" - /*mm1=R_i>L?FF:00*/ - "pcmpgtw %%mm6,%%mm1\n\t" - /*mm3=2L 2L 2L 2L*/ - "psllw $1,%%mm3\n\t" - /*mm6=2L 2L 2L 2L*/ - "psllw $1,%%mm6\n\t" - /*mm3=R_i>L?2L:0*/ - "pand %%mm1,%%mm3\n\t" - /*mm6=-L>R_i?2L:0*/ - "pand %%mm2,%%mm6\n\t" - /*mm0=R_i>L?R_i-2L:R_i*/ - "psubw %%mm3,%%mm0\n\t" - /*mm1=-L>R_i||R_i>L*/ - "por %%mm2,%%mm1\n\t" - /*mm0=-L>R_i?R_i+2L:R_i*/ - "paddw %%mm6,%%mm0\n\t" - /*mm1=-L>R_i||R_i>L?R_i':0*/ - "pand %%mm0,%%mm1\n\t" - /*mm0=-L>R_i||R_i>L?0:R_i*/ - "psubw %%mm1,%%mm0\n\t" - /*mm0=-L>R_i||R_i>L?-R_i':R_i*/ - "psubw %%mm1,%%mm0\n\t" - /*_pix[1]+=R_i;*/ - "paddw %%mm0,%%mm5\n\t" - /*_pix[2]-=R_i;*/ - "psubw %%mm0,%%mm4\n\t" - /*mm5=x x x x D 9 5 1*/ - "packuswb %%mm7,%%mm5\n\t" - /*mm4=x x x x E A 6 2*/ - "packuswb %%mm7,%%mm4\n\t" - /*mm5=E D A 9 6 5 2 1*/ - "punpcklbw %%mm4,%%mm5\n\t" - /*edi=6 5 2 1*/ - "movd %%mm5,%%edi\n\t" - "movw %%di,1(%[pix])\n\t" - /*Why is there such a big stall here?*/ - "psrlq $32,%%mm5\n\t" - "shrl $16,%%edi\n\t" - "movw %%di,1(%[pix],%[ystride])\n\t" - /*edi=E D A 9*/ - "movd %%mm5,%%edi\n\t" - "movw %%di,1(%[pix],%[ystride],2)\n\t" - "shrl $16,%%edi\n\t" - "movw %%di,1(%[pix],%[s])\n\t" - :[s]"=&S"(esi),[d]"=&D"(edi), - [pix]"+r"(_pix),[ystride]"+r"(_ystride),[ll]"+r"(_ll) - :[OC_V3]"m"(OC_V3),[OC_V4]"m"(OC_V4) - :"memory" - ); -} - -static void loop_filter_h(unsigned char *_pix,int _ystride, - const ogg_int16_t *_ll){ - _pix-=2; - loop_filter_h4(_pix,_ystride,_ll); - loop_filter_h4(_pix+(_ystride<<2),_ystride,_ll); -} - -static void loop_filter_mmx(PB_INSTANCE *pbi, int FLimit){ - int j; - ogg_int16_t __attribute__((aligned(8))) ll[4]; - unsigned char *cp = pbi->display_fragments; - ogg_uint32_t *bp = pbi->recon_pixel_index_table; - - if ( FLimit == 0 ) return; - ll[0]=ll[1]=ll[2]=ll[3]=FLimit; - - for ( j = 0; j < 3 ; j++){ - ogg_uint32_t *bp_begin = bp; - ogg_uint32_t *bp_end; - int stride; - int h; - - switch(j) { - case 0: /* y */ - bp_end = bp + pbi->YPlaneFragments; - h = pbi->HFragments; - stride = pbi->YStride; - break; - default: /* u,v, 4:20 specific */ - bp_end = bp + pbi->UVPlaneFragments; - h = pbi->HFragments >> 1; - stride = pbi->UVStride; - break; - } - - while(bpbp_left) - loop_filter_h(&pbi->LastFrameRecon[bp[0]],stride,ll); - if(bp_left>bp_begin) - loop_filter_v(&pbi->LastFrameRecon[bp[0]],stride,ll); - if(bp+1LastFrameRecon[bp[0]]+8,stride,ll); - if(bp+hLastFrameRecon[bp[h]],stride,ll); - } - bp++; - cp++; - } - } - } - - __asm__ __volatile__("emms\n\t"); -} - -/* install our implementation in the function table */ -void dsp_mmx_dct_decode_init(DspFunctions *funcs) -{ - funcs->LoopFilter = loop_filter_mmx; -} - -#endif /* USE_ASM */ diff --git a/Engine/lib/libtheora/lib/enc/x86_32/dsp_mmx.c b/Engine/lib/libtheora/lib/enc/x86_32/dsp_mmx.c deleted file mode 100644 index 3c8a46e6a..000000000 --- a/Engine/lib/libtheora/lib/enc/x86_32/dsp_mmx.c +++ /dev/null @@ -1,666 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: dsp_mmx.c 15153 2008-08-04 18:37:55Z tterribe $ - - ********************************************************************/ - -#include - -#include "../codec_internal.h" -#include "../dsp.h" - -#if defined(USE_ASM) - -static const __attribute__ ((aligned(8),used)) ogg_int64_t V128 = 0x0080008000800080LL; - -#define DSP_OP_AVG(a,b) ((((int)(a)) + ((int)(b)))/2) -#define DSP_OP_DIFF(a,b) (((int)(a)) - ((int)(b))) -#define DSP_OP_ABS_DIFF(a,b) abs((((int)(a)) - ((int)(b)))) - -#define SUB_LOOP \ - " movq (%0), %%mm0 \n\t" /* mm0 = FiltPtr */ \ - " movq (%1), %%mm1 \n\t" /* mm1 = ReconPtr */ \ - " movq %%mm0, %%mm2 \n\t" /* dup to prepare for up conversion */\ - " movq %%mm1, %%mm3 \n\t" /* dup to prepare for up conversion */\ - /* convert from UINT8 to INT16 */ \ - " punpcklbw %%mm7, %%mm0 \n\t" /* mm0 = INT16(FiltPtr) */ \ - " punpcklbw %%mm7, %%mm1 \n\t" /* mm1 = INT16(ReconPtr) */ \ - " punpckhbw %%mm7, %%mm2 \n\t" /* mm2 = INT16(FiltPtr) */ \ - " punpckhbw %%mm7, %%mm3 \n\t" /* mm3 = INT16(ReconPtr) */ \ - /* start calculation */ \ - " psubw %%mm1, %%mm0 \n\t" /* mm0 = FiltPtr - ReconPtr */ \ - " psubw %%mm3, %%mm2 \n\t" /* mm2 = FiltPtr - ReconPtr */ \ - " movq %%mm0, (%2) \n\t" /* write answer out */ \ - " movq %%mm2, 8(%2) \n\t" /* write answer out */ \ - /* Increment pointers */ \ - " add $16, %2 \n\t" \ - " add %3, %0 \n\t" \ - " add %4, %1 \n\t" - -static void sub8x8__mmx (unsigned char *FiltPtr, unsigned char *ReconPtr, - ogg_int16_t *DctInputPtr, ogg_uint32_t PixelsPerLine, - ogg_uint32_t ReconPixelsPerLine) -{ - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " pxor %%mm7, %%mm7 \n\t" - SUB_LOOP - SUB_LOOP - SUB_LOOP - SUB_LOOP - SUB_LOOP - SUB_LOOP - SUB_LOOP - SUB_LOOP - : "+r" (FiltPtr), - "+r" (ReconPtr), - "+r" (DctInputPtr) - : "m" (PixelsPerLine), - "m" (ReconPixelsPerLine) - : "memory" - ); -} - -#define SUB_128_LOOP \ - " movq (%0), %%mm0 \n\t" /* mm0 = FiltPtr */ \ - " movq %%mm0, %%mm2 \n\t" /* dup to prepare for up conversion */\ - /* convert from UINT8 to INT16 */ \ - " punpcklbw %%mm7, %%mm0 \n\t" /* mm0 = INT16(FiltPtr) */ \ - " punpckhbw %%mm7, %%mm2 \n\t" /* mm2 = INT16(FiltPtr) */ \ - /* start calculation */ \ - " psubw %%mm1, %%mm0 \n\t" /* mm0 = FiltPtr - 128 */ \ - " psubw %%mm1, %%mm2 \n\t" /* mm2 = FiltPtr - 128 */ \ - " movq %%mm0, (%1) \n\t" /* write answer out */ \ - " movq %%mm2, 8(%1) \n\t" /* write answer out */ \ - /* Increment pointers */ \ - " add $16, %1 \n\t" \ - " add %2, %0 \n\t" - - -static void sub8x8_128__mmx (unsigned char *FiltPtr, ogg_int16_t *DctInputPtr, - ogg_uint32_t PixelsPerLine) -{ - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " pxor %%mm7, %%mm7 \n\t" - " movq %[V128], %%mm1 \n\t" - SUB_128_LOOP - SUB_128_LOOP - SUB_128_LOOP - SUB_128_LOOP - SUB_128_LOOP - SUB_128_LOOP - SUB_128_LOOP - SUB_128_LOOP - : "+r" (FiltPtr), - "+r" (DctInputPtr) - : "m" (PixelsPerLine), - [V128] "m" (V128) - : "memory" - ); -} - -#define SUB_AVG2_LOOP \ - " movq (%0), %%mm0 \n\t" /* mm0 = FiltPtr */ \ - " movq (%1), %%mm1 \n\t" /* mm1 = ReconPtr1 */ \ - " movq (%2), %%mm4 \n\t" /* mm1 = ReconPtr2 */ \ - " movq %%mm0, %%mm2 \n\t" /* dup to prepare for up conversion */\ - " movq %%mm1, %%mm3 \n\t" /* dup to prepare for up conversion */\ - " movq %%mm4, %%mm5 \n\t" /* dup to prepare for up conversion */\ - /* convert from UINT8 to INT16 */ \ - " punpcklbw %%mm7, %%mm0 \n\t" /* mm0 = INT16(FiltPtr) */ \ - " punpcklbw %%mm7, %%mm1 \n\t" /* mm1 = INT16(ReconPtr1) */ \ - " punpcklbw %%mm7, %%mm4 \n\t" /* mm1 = INT16(ReconPtr2) */ \ - " punpckhbw %%mm7, %%mm2 \n\t" /* mm2 = INT16(FiltPtr) */ \ - " punpckhbw %%mm7, %%mm3 \n\t" /* mm3 = INT16(ReconPtr1) */ \ - " punpckhbw %%mm7, %%mm5 \n\t" /* mm3 = INT16(ReconPtr2) */ \ - /* average ReconPtr1 and ReconPtr2 */ \ - " paddw %%mm4, %%mm1 \n\t" /* mm1 = ReconPtr1 + ReconPtr2 */ \ - " paddw %%mm5, %%mm3 \n\t" /* mm3 = ReconPtr1 + ReconPtr2 */ \ - " psrlw $1, %%mm1 \n\t" /* mm1 = (ReconPtr1 + ReconPtr2) / 2 */ \ - " psrlw $1, %%mm3 \n\t" /* mm3 = (ReconPtr1 + ReconPtr2) / 2 */ \ - " psubw %%mm1, %%mm0 \n\t" /* mm0 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ \ - " psubw %%mm3, %%mm2 \n\t" /* mm2 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ \ - " movq %%mm0, (%3) \n\t" /* write answer out */ \ - " movq %%mm2, 8(%3) \n\t" /* write answer out */ \ - /* Increment pointers */ \ - " add $16, %3 \n\t" \ - " add %4, %0 \n\t" \ - " add %5, %1 \n\t" \ - " add %5, %2 \n\t" - - -static void sub8x8avg2__mmx (unsigned char *FiltPtr, unsigned char *ReconPtr1, - unsigned char *ReconPtr2, ogg_int16_t *DctInputPtr, - ogg_uint32_t PixelsPerLine, - ogg_uint32_t ReconPixelsPerLine) -{ - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " pxor %%mm7, %%mm7 \n\t" - SUB_AVG2_LOOP - SUB_AVG2_LOOP - SUB_AVG2_LOOP - SUB_AVG2_LOOP - SUB_AVG2_LOOP - SUB_AVG2_LOOP - SUB_AVG2_LOOP - SUB_AVG2_LOOP - : "+r" (FiltPtr), - "+r" (ReconPtr1), - "+r" (ReconPtr2), - "+r" (DctInputPtr) - : "m" (PixelsPerLine), - "m" (ReconPixelsPerLine) - : "memory" - ); -} - -static ogg_uint32_t row_sad8__mmx (unsigned char *Src1, unsigned char *Src2) -{ - ogg_uint32_t MaxSad; - - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " pxor %%mm6, %%mm6 \n\t" /* zero out mm6 for unpack */ - " pxor %%mm7, %%mm7 \n\t" /* zero out mm7 for unpack */ - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ - " movq (%2), %%mm1 \n\t" - - " movq %%mm0, %%mm2 \n\t" - " psubusb %%mm1, %%mm0 \n\t" /* A - B */ - " psubusb %%mm2, %%mm1 \n\t" /* B - A */ - " por %%mm1, %%mm0 \n\t" /* and or gives abs difference */ - - " movq %%mm0, %%mm1 \n\t" - - " punpcklbw %%mm6, %%mm0 \n\t" /* ; unpack low four bytes to higher precision */ - " punpckhbw %%mm7, %%mm1 \n\t" /* ; unpack high four bytes to higher precision */ - - " movq %%mm0, %%mm2 \n\t" - " movq %%mm1, %%mm3 \n\t" - " psrlq $32, %%mm2 \n\t" /* fold and add */ - " psrlq $32, %%mm3 \n\t" - " paddw %%mm2, %%mm0 \n\t" - " paddw %%mm3, %%mm1 \n\t" - " movq %%mm0, %%mm2 \n\t" - " movq %%mm1, %%mm3 \n\t" - " psrlq $16, %%mm2 \n\t" - " psrlq $16, %%mm3 \n\t" - " paddw %%mm2, %%mm0 \n\t" - " paddw %%mm3, %%mm1 \n\t" - - " psubusw %%mm0, %%mm1 \n\t" - " paddw %%mm0, %%mm1 \n\t" /* mm1 = max(mm1, mm0) */ - " movd %%mm1, %0 \n\t" - " andl $0xffff, %0 \n\t" - - : "=m" (MaxSad), - "+r" (Src1), - "+r" (Src2) - : - : "memory" - ); - return MaxSad; -} - -static ogg_uint32_t col_sad8x8__mmx (unsigned char *Src1, unsigned char *Src2, - ogg_uint32_t stride) -{ - ogg_uint32_t MaxSad; - - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " pxor %%mm3, %%mm3 \n\t" /* zero out mm3 for unpack */ - " pxor %%mm4, %%mm4 \n\t" /* mm4 low sum */ - " pxor %%mm5, %%mm5 \n\t" /* mm5 high sum */ - " pxor %%mm6, %%mm6 \n\t" /* mm6 low sum */ - " pxor %%mm7, %%mm7 \n\t" /* mm7 high sum */ - " mov $4, %%edi \n\t" /* 4 rows */ - "1: \n\t" - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ - " movq (%2), %%mm1 \n\t" /* take 8 bytes */ - - " movq %%mm0, %%mm2 \n\t" - " psubusb %%mm1, %%mm0 \n\t" /* A - B */ - " psubusb %%mm2, %%mm1 \n\t" /* B - A */ - " por %%mm1, %%mm0 \n\t" /* and or gives abs difference */ - " movq %%mm0, %%mm1 \n\t" - - " punpcklbw %%mm3, %%mm0 \n\t" /* unpack to higher precision for accumulation */ - " paddw %%mm0, %%mm4 \n\t" /* accumulate difference... */ - " punpckhbw %%mm3, %%mm1 \n\t" /* unpack high four bytes to higher precision */ - " paddw %%mm1, %%mm5 \n\t" /* accumulate difference... */ - " add %3, %1 \n\t" /* Inc pointer into the new data */ - " add %3, %2 \n\t" /* Inc pointer into the new data */ - - " dec %%edi \n\t" - " jnz 1b \n\t" - - " mov $4, %%edi \n\t" /* 4 rows */ - "2: \n\t" - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ - " movq (%2), %%mm1 \n\t" /* take 8 bytes */ - - " movq %%mm0, %%mm2 \n\t" - " psubusb %%mm1, %%mm0 \n\t" /* A - B */ - " psubusb %%mm2, %%mm1 \n\t" /* B - A */ - " por %%mm1, %%mm0 \n\t" /* and or gives abs difference */ - " movq %%mm0, %%mm1 \n\t" - - " punpcklbw %%mm3, %%mm0 \n\t" /* unpack to higher precision for accumulation */ - " paddw %%mm0, %%mm6 \n\t" /* accumulate difference... */ - " punpckhbw %%mm3, %%mm1 \n\t" /* unpack high four bytes to higher precision */ - " paddw %%mm1, %%mm7 \n\t" /* accumulate difference... */ - " add %3, %1 \n\t" /* Inc pointer into the new data */ - " add %3, %2 \n\t" /* Inc pointer into the new data */ - - " dec %%edi \n\t" - " jnz 2b \n\t" - - " psubusw %%mm6, %%mm7 \n\t" - " paddw %%mm6, %%mm7 \n\t" /* mm7 = max(mm7, mm6) */ - " psubusw %%mm4, %%mm5 \n\t" - " paddw %%mm4, %%mm5 \n\t" /* mm5 = max(mm5, mm4) */ - " psubusw %%mm5, %%mm7 \n\t" - " paddw %%mm5, %%mm7 \n\t" /* mm7 = max(mm5, mm7) */ - " movq %%mm7, %%mm6 \n\t" - " psrlq $32, %%mm6 \n\t" - " psubusw %%mm6, %%mm7 \n\t" - " paddw %%mm6, %%mm7 \n\t" /* mm7 = max(mm5, mm7) */ - " movq %%mm7, %%mm6 \n\t" - " psrlq $16, %%mm6 \n\t" - " psubusw %%mm6, %%mm7 \n\t" - " paddw %%mm6, %%mm7 \n\t" /* mm7 = max(mm5, mm7) */ - " movd %%mm7, %0 \n\t" - " andl $0xffff, %0 \n\t" - - : "=r" (MaxSad), - "+r" (Src1), - "+r" (Src2) - : "r" (stride) - : "memory", "edi" - ); - - return MaxSad; -} - -#define SAD_LOOP \ - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ \ - " movq (%2), %%mm1 \n\t" \ - " movq %%mm0, %%mm2 \n\t" \ - " psubusb %%mm1, %%mm0 \n\t" /* A - B */ \ - " psubusb %%mm2, %%mm1 \n\t" /* B - A */ \ - " por %%mm1, %%mm0 \n\t" /* and or gives abs difference */ \ - " movq %%mm0, %%mm1 \n\t" \ - " punpcklbw %%mm6, %%mm0 \n\t" /* unpack to higher precision for accumulation */ \ - " paddw %%mm0, %%mm7 \n\t" /* accumulate difference... */ \ - " punpckhbw %%mm6, %%mm1 \n\t" /* unpack high four bytes to higher precision */ \ - " add %3, %1 \n\t" /* Inc pointer into the new data */ \ - " paddw %%mm1, %%mm7 \n\t" /* accumulate difference... */ \ - " add %4, %2 \n\t" /* Inc pointer into ref data */ - -static ogg_uint32_t sad8x8__mmx (unsigned char *ptr1, ogg_uint32_t stride1, - unsigned char *ptr2, ogg_uint32_t stride2) -{ - ogg_uint32_t DiffVal; - - __asm__ __volatile__ ( - " .p2align 4 \n\t" - " pxor %%mm6, %%mm6 \n\t" /* zero out mm6 for unpack */ - " pxor %%mm7, %%mm7 \n\t" /* mm7 contains the result */ - SAD_LOOP - SAD_LOOP - SAD_LOOP - SAD_LOOP - SAD_LOOP - SAD_LOOP - SAD_LOOP - SAD_LOOP - " movq %%mm7, %%mm0 \n\t" - " psrlq $32, %%mm7 \n\t" - " paddw %%mm0, %%mm7 \n\t" - " movq %%mm7, %%mm0 \n\t" - " psrlq $16, %%mm7 \n\t" - " paddw %%mm0, %%mm7 \n\t" - " movd %%mm7, %0 \n\t" - " andl $0xffff, %0 \n\t" - - : "=m" (DiffVal), - "+r" (ptr1), - "+r" (ptr2) - : "r" (stride1), - "r" (stride2) - : "memory" - ); - - return DiffVal; -} - -static ogg_uint32_t sad8x8_thres__mmx (unsigned char *ptr1, ogg_uint32_t stride1, - unsigned char *ptr2, ogg_uint32_t stride2, - ogg_uint32_t thres) -{ - return sad8x8__mmx (ptr1, stride1, ptr2, stride2); -} - -static ogg_uint32_t sad8x8_xy2_thres__mmx (unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr1, - unsigned char *RefDataPtr2, ogg_uint32_t RefStride, - ogg_uint32_t thres) -{ - ogg_uint32_t DiffVal; - - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " pcmpeqd %%mm5, %%mm5 \n\t" /* fefefefefefefefe in mm5 */ - " paddb %%mm5, %%mm5 \n\t" - - " pxor %%mm6, %%mm6 \n\t" /* zero out mm6 for unpack */ - " pxor %%mm7, %%mm7 \n\t" /* mm7 contains the result */ - " mov $8, %%edi \n\t" /* 8 rows */ - "1: \n\t" - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ - - " movq (%2), %%mm2 \n\t" - " movq (%3), %%mm3 \n\t" /* take average of mm2 and mm3 */ - " movq %%mm2, %%mm1 \n\t" - " pand %%mm3, %%mm1 \n\t" - " pxor %%mm2, %%mm3 \n\t" - " pand %%mm5, %%mm3 \n\t" - " psrlq $1, %%mm3 \n\t" - " paddb %%mm3, %%mm1 \n\t" - - " movq %%mm0, %%mm2 \n\t" - - " psubusb %%mm1, %%mm0 \n\t" /* A - B */ - " psubusb %%mm2, %%mm1 \n\t" /* B - A */ - " por %%mm1, %%mm0 \n\t" /* and or gives abs difference */ - " movq %%mm0, %%mm1 \n\t" - - " punpcklbw %%mm6, %%mm0 \n\t" /* unpack to higher precision for accumulation */ - " paddw %%mm0, %%mm7 \n\t" /* accumulate difference... */ - " punpckhbw %%mm6, %%mm1 \n\t" /* unpack high four bytes to higher precision */ - " add %4, %1 \n\t" /* Inc pointer into the new data */ - " paddw %%mm1, %%mm7 \n\t" /* accumulate difference... */ - " add %5, %2 \n\t" /* Inc pointer into ref data */ - " add %5, %3 \n\t" /* Inc pointer into ref data */ - - " dec %%edi \n\t" - " jnz 1b \n\t" - - " movq %%mm7, %%mm0 \n\t" - " psrlq $32, %%mm7 \n\t" - " paddw %%mm0, %%mm7 \n\t" - " movq %%mm7, %%mm0 \n\t" - " psrlq $16, %%mm7 \n\t" - " paddw %%mm0, %%mm7 \n\t" - " movd %%mm7, %0 \n\t" - " andl $0xffff, %0 \n\t" - - : "=m" (DiffVal), - "+r" (SrcData), - "+r" (RefDataPtr1), - "+r" (RefDataPtr2) - : "m" (SrcStride), - "m" (RefStride) - : "edi", "memory" - ); - - return DiffVal; -} - -static ogg_uint32_t intra8x8_err__mmx (unsigned char *DataPtr, ogg_uint32_t Stride) -{ - ogg_uint32_t XSum; - ogg_uint32_t XXSum; - - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " pxor %%mm5, %%mm5 \n\t" - " pxor %%mm6, %%mm6 \n\t" - " pxor %%mm7, %%mm7 \n\t" - " mov $8, %%edi \n\t" - "1: \n\t" - " movq (%2), %%mm0 \n\t" /* take 8 bytes */ - " movq %%mm0, %%mm2 \n\t" - - " punpcklbw %%mm6, %%mm0 \n\t" - " punpckhbw %%mm6, %%mm2 \n\t" - - " paddw %%mm0, %%mm5 \n\t" - " paddw %%mm2, %%mm5 \n\t" - - " pmaddwd %%mm0, %%mm0 \n\t" - " pmaddwd %%mm2, %%mm2 \n\t" - - " paddd %%mm0, %%mm7 \n\t" - " paddd %%mm2, %%mm7 \n\t" - - " add %3, %2 \n\t" /* Inc pointer into src data */ - - " dec %%edi \n\t" - " jnz 1b \n\t" - - " movq %%mm5, %%mm0 \n\t" - " psrlq $32, %%mm5 \n\t" - " paddw %%mm0, %%mm5 \n\t" - " movq %%mm5, %%mm0 \n\t" - " psrlq $16, %%mm5 \n\t" - " paddw %%mm0, %%mm5 \n\t" - " movd %%mm5, %%edi \n\t" - " movsx %%di, %%edi \n\t" - " movl %%edi, %0 \n\t" - - " movq %%mm7, %%mm0 \n\t" - " psrlq $32, %%mm7 \n\t" - " paddd %%mm0, %%mm7 \n\t" - " movd %%mm7, %1 \n\t" - - : "=r" (XSum), - "=r" (XXSum), - "+r" (DataPtr) - : "r" (Stride) - : "edi", "memory" - ); - - /* Compute population variance as mis-match metric. */ - return (( (XXSum<<6) - XSum*XSum ) ); -} - -static ogg_uint32_t inter8x8_err__mmx (unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr, ogg_uint32_t RefStride) -{ - ogg_uint32_t XSum; - ogg_uint32_t XXSum; - - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " pxor %%mm5, %%mm5 \n\t" - " pxor %%mm6, %%mm6 \n\t" - " pxor %%mm7, %%mm7 \n\t" - " mov $8, %%edi \n\t" - "1: \n\t" - " movq (%2), %%mm0 \n\t" /* take 8 bytes */ - " movq (%3), %%mm1 \n\t" - " movq %%mm0, %%mm2 \n\t" - " movq %%mm1, %%mm3 \n\t" - - " punpcklbw %%mm6, %%mm0 \n\t" - " punpcklbw %%mm6, %%mm1 \n\t" - " punpckhbw %%mm6, %%mm2 \n\t" - " punpckhbw %%mm6, %%mm3 \n\t" - - " psubsw %%mm1, %%mm0 \n\t" - " psubsw %%mm3, %%mm2 \n\t" - - " paddw %%mm0, %%mm5 \n\t" - " paddw %%mm2, %%mm5 \n\t" - - " pmaddwd %%mm0, %%mm0 \n\t" - " pmaddwd %%mm2, %%mm2 \n\t" - - " paddd %%mm0, %%mm7 \n\t" - " paddd %%mm2, %%mm7 \n\t" - - " add %4, %2 \n\t" /* Inc pointer into src data */ - " add %5, %3 \n\t" /* Inc pointer into ref data */ - - " dec %%edi \n\t" - " jnz 1b \n\t" - - " movq %%mm5, %%mm0 \n\t" - " psrlq $32, %%mm5 \n\t" - " paddw %%mm0, %%mm5 \n\t" - " movq %%mm5, %%mm0 \n\t" - " psrlq $16, %%mm5 \n\t" - " paddw %%mm0, %%mm5 \n\t" - " movd %%mm5, %%edi \n\t" - " movsx %%di, %%edi \n\t" - " movl %%edi, %0 \n\t" - - " movq %%mm7, %%mm0 \n\t" - " psrlq $32, %%mm7 \n\t" - " paddd %%mm0, %%mm7 \n\t" - " movd %%mm7, %1 \n\t" - - : "=m" (XSum), - "=m" (XXSum), - "+r" (SrcData), - "+r" (RefDataPtr) - : "m" (SrcStride), - "m" (RefStride) - : "edi", "memory" - ); - - /* Compute and return population variance as mis-match metric. */ - return (( (XXSum<<6) - XSum*XSum )); -} - -static ogg_uint32_t inter8x8_err_xy2__mmx (unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr1, - unsigned char *RefDataPtr2, ogg_uint32_t RefStride) -{ - ogg_uint32_t XSum; - ogg_uint32_t XXSum; - - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " pcmpeqd %%mm4, %%mm4 \n\t" /* fefefefefefefefe in mm4 */ - " paddb %%mm4, %%mm4 \n\t" - " pxor %%mm5, %%mm5 \n\t" - " pxor %%mm6, %%mm6 \n\t" - " pxor %%mm7, %%mm7 \n\t" - " mov $8, %%edi \n\t" - "1: \n\t" - " movq (%2), %%mm0 \n\t" /* take 8 bytes */ - - " movq (%3), %%mm2 \n\t" - " movq (%4), %%mm3 \n\t" /* take average of mm2 and mm3 */ - " movq %%mm2, %%mm1 \n\t" - " pand %%mm3, %%mm1 \n\t" - " pxor %%mm2, %%mm3 \n\t" - " pand %%mm4, %%mm3 \n\t" - " psrlq $1, %%mm3 \n\t" - " paddb %%mm3, %%mm1 \n\t" - - " movq %%mm0, %%mm2 \n\t" - " movq %%mm1, %%mm3 \n\t" - - " punpcklbw %%mm6, %%mm0 \n\t" - " punpcklbw %%mm6, %%mm1 \n\t" - " punpckhbw %%mm6, %%mm2 \n\t" - " punpckhbw %%mm6, %%mm3 \n\t" - - " psubsw %%mm1, %%mm0 \n\t" - " psubsw %%mm3, %%mm2 \n\t" - - " paddw %%mm0, %%mm5 \n\t" - " paddw %%mm2, %%mm5 \n\t" - - " pmaddwd %%mm0, %%mm0 \n\t" - " pmaddwd %%mm2, %%mm2 \n\t" - - " paddd %%mm0, %%mm7 \n\t" - " paddd %%mm2, %%mm7 \n\t" - - " add %5, %2 \n\t" /* Inc pointer into src data */ - " add %6, %3 \n\t" /* Inc pointer into ref data */ - " add %6, %4 \n\t" /* Inc pointer into ref data */ - - " dec %%edi \n\t" - " jnz 1b \n\t" - - " movq %%mm5, %%mm0 \n\t" - " psrlq $32, %%mm5 \n\t" - " paddw %%mm0, %%mm5 \n\t" - " movq %%mm5, %%mm0 \n\t" - " psrlq $16, %%mm5 \n\t" - " paddw %%mm0, %%mm5 \n\t" - " movd %%mm5, %%edi \n\t" - " movsx %%di, %%edi \n\t" - " movl %%edi, %0 \n\t" - - " movq %%mm7, %%mm0 \n\t" - " psrlq $32, %%mm7 \n\t" - " paddd %%mm0, %%mm7 \n\t" - " movd %%mm7, %1 \n\t" - - : "=m" (XSum), - "=m" (XXSum), - "+r" (SrcData), - "+r" (RefDataPtr1), - "+r" (RefDataPtr2) - : "m" (SrcStride), - "m" (RefStride) - : "edi", "memory" - ); - - /* Compute and return population variance as mis-match metric. */ - return (( (XXSum<<6) - XSum*XSum )); -} - -static void restore_fpu (void) -{ - __asm__ __volatile__ ( - " emms \n\t" - ); -} - -void dsp_mmx_init(DspFunctions *funcs) -{ - funcs->restore_fpu = restore_fpu; - funcs->sub8x8 = sub8x8__mmx; - funcs->sub8x8_128 = sub8x8_128__mmx; - funcs->sub8x8avg2 = sub8x8avg2__mmx; - funcs->row_sad8 = row_sad8__mmx; - funcs->col_sad8x8 = col_sad8x8__mmx; - funcs->sad8x8 = sad8x8__mmx; - funcs->sad8x8_thres = sad8x8_thres__mmx; - funcs->sad8x8_xy2_thres = sad8x8_xy2_thres__mmx; - funcs->intra8x8_err = intra8x8_err__mmx; - funcs->inter8x8_err = inter8x8_err__mmx; - funcs->inter8x8_err_xy2 = inter8x8_err_xy2__mmx; -} - -#endif /* USE_ASM */ diff --git a/Engine/lib/libtheora/lib/enc/x86_32/dsp_mmxext.c b/Engine/lib/libtheora/lib/enc/x86_32/dsp_mmxext.c deleted file mode 100644 index 297c3213a..000000000 --- a/Engine/lib/libtheora/lib/enc/x86_32/dsp_mmxext.c +++ /dev/null @@ -1,347 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: dsp_mmxext.c 15153 2008-08-04 18:37:55Z tterribe $ - - ********************************************************************/ - -#include - -#include "../codec_internal.h" -#include "../dsp.h" - -#if defined(USE_ASM) - -#define SAD_MMXEXT_LOOP \ - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ \ - " movq (%2), %%mm1 \n\t" \ - " psadbw %%mm1, %%mm0 \n\t" \ - " add %3, %1 \n\t" /* Inc pointer into the new data */ \ - " paddw %%mm0, %%mm7 \n\t" /* accumulate difference... */ \ - " add %4, %2 \n\t" /* Inc pointer into ref data */ - - -static ogg_uint32_t sad8x8__mmxext (unsigned char *ptr1, ogg_uint32_t stride1, - unsigned char *ptr2, ogg_uint32_t stride2) -{ - ogg_uint32_t DiffVal; - - __asm__ __volatile__ ( - " .p2align 4 \n\t" - " pxor %%mm7, %%mm7 \n\t" /* mm7 contains the result */ - - SAD_MMXEXT_LOOP - SAD_MMXEXT_LOOP - SAD_MMXEXT_LOOP - SAD_MMXEXT_LOOP - SAD_MMXEXT_LOOP - SAD_MMXEXT_LOOP - SAD_MMXEXT_LOOP - - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ - " movq (%2), %%mm1 \n\t" - " psadbw %%mm1, %%mm0 \n\t" - " paddw %%mm0, %%mm7 \n\t" /* accumulate difference... */ - " movd %%mm7, %0 \n\t" - - : "=r" (DiffVal), - "+r" (ptr1), - "+r" (ptr2) - : "r" (stride1), - "r" (stride2) - : "memory" - ); - - return DiffVal; -} - -#define SAD_TRES_LOOP \ - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ \ - " movq (%2), %%mm1 \n\t" \ - " psadbw %%mm1, %%mm0 \n\t" \ - " add %3, %1 \n\t" /* Inc pointer into the new data */ \ - " paddw %%mm0, %%mm7 \n\t" /* accumulate difference... */ \ - " add %4, %2 \n\t" /* Inc pointer into ref data */ - - -static ogg_uint32_t sad8x8_thres__mmxext (unsigned char *ptr1, ogg_uint32_t stride1, - unsigned char *ptr2, ogg_uint32_t stride2, - ogg_uint32_t thres) -{ - ogg_uint32_t DiffVal; - - __asm__ __volatile__ ( - " .p2align 4 \n\t" - " pxor %%mm7, %%mm7 \n\t" /* mm7 contains the result */ - - SAD_TRES_LOOP - SAD_TRES_LOOP - SAD_TRES_LOOP - SAD_TRES_LOOP - SAD_TRES_LOOP - SAD_TRES_LOOP - SAD_TRES_LOOP - SAD_TRES_LOOP - - " movd %%mm7, %0 \n\t" - - : "=r" (DiffVal), - "+r" (ptr1), - "+r" (ptr2) - : "r" (stride1), - "r" (stride2) - : "memory" - ); - - return DiffVal; -} - -#define SAD_XY2_TRES \ - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ \ - " movq (%2), %%mm1 \n\t" \ - " movq (%3), %%mm2 \n\t" \ - " pavgb %%mm2, %%mm1 \n\t" \ - " psadbw %%mm1, %%mm0 \n\t" \ - \ - " add %4, %1 \n\t" /* Inc pointer into the new data */ \ - " paddw %%mm0, %%mm7 \n\t" /* accumulate difference... */ \ - " add %5, %2 \n\t" /* Inc pointer into ref data */ \ - " add %5, %3 \n\t" /* Inc pointer into ref data */ - - -static ogg_uint32_t sad8x8_xy2_thres__mmxext (unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr1, - unsigned char *RefDataPtr2, ogg_uint32_t RefStride, - ogg_uint32_t thres) -{ - ogg_uint32_t DiffVal; - - __asm__ __volatile__ ( - " .p2align 4 \n\t" - " pxor %%mm7, %%mm7 \n\t" /* mm7 contains the result */ - SAD_XY2_TRES - SAD_XY2_TRES - SAD_XY2_TRES - SAD_XY2_TRES - SAD_XY2_TRES - SAD_XY2_TRES - SAD_XY2_TRES - SAD_XY2_TRES - - " movd %%mm7, %0 \n\t" - : "=m" (DiffVal), - "+r" (SrcData), - "+r" (RefDataPtr1), - "+r" (RefDataPtr2) - : "m" (SrcStride), - "m" (RefStride) - : "memory" - ); - - return DiffVal; -} - -static ogg_uint32_t row_sad8__mmxext (unsigned char *Src1, unsigned char *Src2) -{ - ogg_uint32_t MaxSad; - - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " movd (%1), %%mm0 \n\t" - " movd (%2), %%mm1 \n\t" - " psadbw %%mm0, %%mm1 \n\t" - " movd 4(%1), %%mm2 \n\t" - " movd 4(%2), %%mm3 \n\t" - " psadbw %%mm2, %%mm3 \n\t" - - " pmaxsw %%mm1, %%mm3 \n\t" - " movd %%mm3, %0 \n\t" - " andl $0xffff, %0 \n\t" - - : "=m" (MaxSad), - "+r" (Src1), - "+r" (Src2) - : - : "memory" - ); - - return MaxSad; -} - -static ogg_uint32_t col_sad8x8__mmxext (unsigned char *Src1, unsigned char *Src2, - ogg_uint32_t stride) -{ - ogg_uint32_t MaxSad; - - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " pxor %%mm3, %%mm3 \n\t" /* zero out mm3 for unpack */ - " pxor %%mm4, %%mm4 \n\t" /* mm4 low sum */ - " pxor %%mm5, %%mm5 \n\t" /* mm5 high sum */ - " pxor %%mm6, %%mm6 \n\t" /* mm6 low sum */ - " pxor %%mm7, %%mm7 \n\t" /* mm7 high sum */ - " mov $4, %%edi \n\t" /* 4 rows */ - "1: \n\t" - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ - " movq (%2), %%mm1 \n\t" /* take 8 bytes */ - - " movq %%mm0, %%mm2 \n\t" - " psubusb %%mm1, %%mm0 \n\t" /* A - B */ - " psubusb %%mm2, %%mm1 \n\t" /* B - A */ - " por %%mm1, %%mm0 \n\t" /* and or gives abs difference */ - " movq %%mm0, %%mm1 \n\t" - - " punpcklbw %%mm3, %%mm0 \n\t" /* unpack to higher precision for accumulation */ - " paddw %%mm0, %%mm4 \n\t" /* accumulate difference... */ - " punpckhbw %%mm3, %%mm1 \n\t" /* unpack high four bytes to higher precision */ - " paddw %%mm1, %%mm5 \n\t" /* accumulate difference... */ - " add %3, %1 \n\t" /* Inc pointer into the new data */ - " add %3, %2 \n\t" /* Inc pointer into the new data */ - - " dec %%edi \n\t" - " jnz 1b \n\t" - - " mov $4, %%edi \n\t" /* 4 rows */ - "2: \n\t" - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ - " movq (%2), %%mm1 \n\t" /* take 8 bytes */ - - " movq %%mm0, %%mm2 \n\t" - " psubusb %%mm1, %%mm0 \n\t" /* A - B */ - " psubusb %%mm2, %%mm1 \n\t" /* B - A */ - " por %%mm1, %%mm0 \n\t" /* and or gives abs difference */ - " movq %%mm0, %%mm1 \n\t" - - " punpcklbw %%mm3, %%mm0 \n\t" /* unpack to higher precision for accumulation */ - " paddw %%mm0, %%mm6 \n\t" /* accumulate difference... */ - " punpckhbw %%mm3, %%mm1 \n\t" /* unpack high four bytes to higher precision */ - " paddw %%mm1, %%mm7 \n\t" /* accumulate difference... */ - " add %3, %1 \n\t" /* Inc pointer into the new data */ - " add %3, %2 \n\t" /* Inc pointer into the new data */ - - " dec %%edi \n\t" - " jnz 2b \n\t" - - " pmaxsw %%mm6, %%mm7 \n\t" - " pmaxsw %%mm4, %%mm5 \n\t" - " pmaxsw %%mm5, %%mm7 \n\t" - " movq %%mm7, %%mm6 \n\t" - " psrlq $32, %%mm6 \n\t" - " pmaxsw %%mm6, %%mm7 \n\t" - " movq %%mm7, %%mm6 \n\t" - " psrlq $16, %%mm6 \n\t" - " pmaxsw %%mm6, %%mm7 \n\t" - " movd %%mm7, %0 \n\t" - " andl $0xffff, %0 \n\t" - - : "=r" (MaxSad), - "+r" (Src1), - "+r" (Src2) - : "r" (stride) - : "memory", "edi" - ); - - return MaxSad; -} - -static ogg_uint32_t inter8x8_err_xy2__mmxext (unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr1, - unsigned char *RefDataPtr2, ogg_uint32_t RefStride) -{ - ogg_uint32_t XSum; - ogg_uint32_t XXSum; - - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " pxor %%mm4, %%mm4 \n\t" - " pxor %%mm5, %%mm5 \n\t" - " pxor %%mm6, %%mm6 \n\t" - " pxor %%mm7, %%mm7 \n\t" - " mov $8, %%edi \n\t" - "1: \n\t" - " movq (%2), %%mm0 \n\t" /* take 8 bytes */ - - " movq (%3), %%mm2 \n\t" - " movq (%4), %%mm1 \n\t" /* take average of mm2 and mm1 */ - " pavgb %%mm2, %%mm1 \n\t" - - " movq %%mm0, %%mm2 \n\t" - " movq %%mm1, %%mm3 \n\t" - - " punpcklbw %%mm6, %%mm0 \n\t" - " punpcklbw %%mm4, %%mm1 \n\t" - " punpckhbw %%mm6, %%mm2 \n\t" - " punpckhbw %%mm4, %%mm3 \n\t" - - " psubsw %%mm1, %%mm0 \n\t" - " psubsw %%mm3, %%mm2 \n\t" - - " paddw %%mm0, %%mm5 \n\t" - " paddw %%mm2, %%mm5 \n\t" - - " pmaddwd %%mm0, %%mm0 \n\t" - " pmaddwd %%mm2, %%mm2 \n\t" - - " paddd %%mm0, %%mm7 \n\t" - " paddd %%mm2, %%mm7 \n\t" - - " add %5, %2 \n\t" /* Inc pointer into src data */ - " add %6, %3 \n\t" /* Inc pointer into ref data */ - " add %6, %4 \n\t" /* Inc pointer into ref data */ - - " dec %%edi \n\t" - " jnz 1b \n\t" - - " movq %%mm5, %%mm0 \n\t" - " psrlq $32, %%mm5 \n\t" - " paddw %%mm0, %%mm5 \n\t" - " movq %%mm5, %%mm0 \n\t" - " psrlq $16, %%mm5 \n\t" - " paddw %%mm0, %%mm5 \n\t" - " movd %%mm5, %%edi \n\t" - " movsx %%di, %%edi \n\t" - " movl %%edi, %0 \n\t" - - " movq %%mm7, %%mm0 \n\t" - " psrlq $32, %%mm7 \n\t" - " paddd %%mm0, %%mm7 \n\t" - " movd %%mm7, %1 \n\t" - - : "=m" (XSum), - "=m" (XXSum), - "+r" (SrcData), - "+r" (RefDataPtr1), - "+r" (RefDataPtr2) - : "m" (SrcStride), - "m" (RefStride) - : "edi", "memory" - ); - - /* Compute and return population variance as mis-match metric. */ - return (( (XXSum<<6) - XSum*XSum )); -} - -void dsp_mmxext_init(DspFunctions *funcs) -{ - funcs->row_sad8 = row_sad8__mmxext; - funcs->col_sad8x8 = col_sad8x8__mmxext; - funcs->sad8x8 = sad8x8__mmxext; - funcs->sad8x8_thres = sad8x8_thres__mmxext; - funcs->sad8x8_xy2_thres = sad8x8_xy2_thres__mmxext; - funcs->inter8x8_err_xy2 = inter8x8_err_xy2__mmxext; -} - -#endif /* USE_ASM */ diff --git a/Engine/lib/libtheora/lib/enc/x86_32/fdct_mmx.c b/Engine/lib/libtheora/lib/enc/x86_32/fdct_mmx.c deleted file mode 100644 index 8de691f81..000000000 --- a/Engine/lib/libtheora/lib/enc/x86_32/fdct_mmx.c +++ /dev/null @@ -1,339 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: fdct_mmx.c 15153 2008-08-04 18:37:55Z tterribe $ - - ********************************************************************/ - -/* mmx fdct implementation */ - -#include "theora/theora.h" -#include "../codec_internal.h" -#include "../dsp.h" - -#if defined(USE_ASM) - -static const __attribute__ ((aligned(8),used)) ogg_int64_t xC1S7 = 0x0fb15fb15fb15fb15LL; -static const __attribute__ ((aligned(8),used)) ogg_int64_t xC2S6 = 0x0ec83ec83ec83ec83LL; -static const __attribute__ ((aligned(8),used)) ogg_int64_t xC3S5 = 0x0d4dbd4dbd4dbd4dbLL; -static const __attribute__ ((aligned(8),used)) ogg_int64_t xC4S4 = 0x0b505b505b505b505LL; -static const __attribute__ ((aligned(8),used)) ogg_int64_t xC5S3 = 0x08e3a8e3a8e3a8e3aLL; -static const __attribute__ ((aligned(8),used)) ogg_int64_t xC6S2 = 0x061f861f861f861f8LL; -static const __attribute__ ((aligned(8),used)) ogg_int64_t xC7S1 = 0x031f131f131f131f1LL; - -/* execute stage 1 of forward DCT */ -#define Fdct_mmx(ip0,ip1,ip2,ip3,ip4,ip5,ip6,ip7,temp) \ - " movq " #ip0 ", %%mm0 \n\t" \ - " movq " #ip1 ", %%mm1 \n\t" \ - " movq " #ip3 ", %%mm2 \n\t" \ - " movq " #ip5 ", %%mm3 \n\t" \ - " movq %%mm0, %%mm4 \n\t" \ - " movq %%mm1, %%mm5 \n\t" \ - " movq %%mm2, %%mm6 \n\t" \ - " movq %%mm3, %%mm7 \n\t" \ - \ - " paddsw " #ip7 ", %%mm0 \n\t" /* mm0 = ip0 + ip7 = is07 */ \ - " paddsw " #ip2 ", %%mm1 \n\t" /* mm1 = ip1 + ip2 = is12 */ \ - " paddsw " #ip4 ", %%mm2 \n\t" /* mm2 = ip3 + ip4 = is34 */ \ - " paddsw " #ip6 ", %%mm3 \n\t" /* mm3 = ip5 + ip6 = is56 */ \ - " psubsw " #ip7 ", %%mm4 \n\t" /* mm4 = ip0 - ip7 = id07 */ \ - " psubsw " #ip2 ", %%mm5 \n\t" /* mm5 = ip1 - ip2 = id12 */ \ - \ - " psubsw %%mm2, %%mm0 \n\t" /* mm0 = is07 - is34 */ \ - \ - " paddsw %%mm2, %%mm2 \n\t" \ - \ - " psubsw " #ip4 ", %%mm6 \n\t" /* mm6 = ip3 - ip4 = id34 */ \ - \ - " paddsw %%mm0, %%mm2 \n\t" /* mm2 = is07 + is34 = is0734 */ \ - " psubsw %%mm3, %%mm1 \n\t" /* mm1 = is12 - is56 */ \ - " movq %%mm0," #temp " \n\t" /* Save is07 - is34 to free mm0; */ \ - " paddsw %%mm3, %%mm3 \n\t" \ - " paddsw %%mm1, %%mm3 \n\t" /* mm3 = is12 + 1s56 = is1256 */ \ - \ - " psubsw " #ip6 ", %%mm7 \n\t" /* mm7 = ip5 - ip6 = id56 */ \ - /* ------------------------------------------------------------------- */ \ - " psubsw %%mm7, %%mm5 \n\t" /* mm5 = id12 - id56 */ \ - " paddsw %%mm7, %%mm7 \n\t" \ - " paddsw %%mm5, %%mm7 \n\t" /* mm7 = id12 + id56 */ \ - /* ------------------------------------------------------------------- */ \ - " psubsw %%mm3, %%mm2 \n\t" /* mm2 = is0734 - is1256 */ \ - " paddsw %%mm3, %%mm3 \n\t" \ - \ - " movq %%mm2, %%mm0 \n\t" /* make a copy */ \ - " paddsw %%mm2, %%mm3 \n\t" /* mm3 = is0734 + is1256 */ \ - \ - " pmulhw %[xC4S4], %%mm0 \n\t" /* mm0 = xC4S4 * ( is0734 - is1256 ) - ( is0734 - is1256 ) */ \ - " paddw %%mm2, %%mm0 \n\t" /* mm0 = xC4S4 * ( is0734 - is1256 ) */ \ - " psrlw $15, %%mm2 \n\t" \ - " paddw %%mm2, %%mm0 \n\t" /* Truncate mm0, now it is op[4] */ \ - \ - " movq %%mm3, %%mm2 \n\t" \ - " movq %%mm0," #ip4 " \n\t" /* save ip4, now mm0,mm2 are free */ \ - \ - " movq %%mm3, %%mm0 \n\t" \ - " pmulhw %[xC4S4], %%mm3 \n\t" /* mm3 = xC4S4 * ( is0734 +is1256 ) - ( is0734 +is1256 ) */ \ - \ - " psrlw $15, %%mm2 \n\t" \ - " paddw %%mm0, %%mm3 \n\t" /* mm3 = xC4S4 * ( is0734 +is1256 ) */ \ - " paddw %%mm2, %%mm3 \n\t" /* Truncate mm3, now it is op[0] */ \ - \ - " movq %%mm3," #ip0 " \n\t" \ - /* ------------------------------------------------------------------- */ \ - " movq " #temp ", %%mm3 \n\t" /* mm3 = irot_input_y */ \ - " pmulhw %[xC2S6], %%mm3 \n\t" /* mm3 = xC2S6 * irot_input_y - irot_input_y */ \ - \ - " movq " #temp ", %%mm2 \n\t" \ - " movq %%mm2, %%mm0 \n\t" \ - \ - " psrlw $15, %%mm2 \n\t" /* mm3 = xC2S6 * irot_input_y */ \ - " paddw %%mm0, %%mm3 \n\t" \ - \ - " paddw %%mm2, %%mm3 \n\t" /* Truncated */ \ - " movq %%mm5, %%mm0 \n\t" \ - \ - " movq %%mm5, %%mm2 \n\t" \ - " pmulhw %[xC6S2], %%mm0 \n\t" /* mm0 = xC6S2 * irot_input_x */ \ - \ - " psrlw $15, %%mm2 \n\t" \ - " paddw %%mm2, %%mm0 \n\t" /* Truncated */ \ - \ - " paddsw %%mm0, %%mm3 \n\t" /* ip[2] */ \ - " movq %%mm3," #ip2 " \n\t" /* Save ip2 */ \ - \ - " movq %%mm5, %%mm0 \n\t" \ - " movq %%mm5, %%mm2 \n\t" \ - \ - " pmulhw %[xC2S6], %%mm5 \n\t" /* mm5 = xC2S6 * irot_input_x - irot_input_x */ \ - " psrlw $15, %%mm2 \n\t" \ - \ - " movq " #temp ", %%mm3 \n\t" \ - " paddw %%mm0, %%mm5 \n\t" /* mm5 = xC2S6 * irot_input_x */ \ - \ - " paddw %%mm2, %%mm5 \n\t" /* Truncated */ \ - " movq %%mm3, %%mm2 \n\t" \ - \ - " pmulhw %[xC6S2], %%mm3 \n\t" /* mm3 = xC6S2 * irot_input_y */ \ - " psrlw $15, %%mm2 \n\t" \ - \ - " paddw %%mm2, %%mm3 \n\t" /* Truncated */ \ - " psubsw %%mm5, %%mm3 \n\t" \ - \ - " movq %%mm3," #ip6 " \n\t" \ - /* ------------------------------------------------------------------- */ \ - " movq %[xC4S4], %%mm0 \n\t" \ - " movq %%mm1, %%mm2 \n\t" \ - " movq %%mm1, %%mm3 \n\t" \ - \ - " pmulhw %%mm0, %%mm1 \n\t" /* mm0 = xC4S4 * ( is12 - is56 ) - ( is12 - is56 ) */ \ - " psrlw $15, %%mm2 \n\t" \ - \ - " paddw %%mm3, %%mm1 \n\t" /* mm0 = xC4S4 * ( is12 - is56 ) */ \ - " paddw %%mm2, %%mm1 \n\t" /* Truncate mm1, now it is icommon_product1 */ \ - \ - " movq %%mm7, %%mm2 \n\t" \ - " movq %%mm7, %%mm3 \n\t" \ - \ - " pmulhw %%mm0, %%mm7 \n\t" /* mm7 = xC4S4 * ( id12 + id56 ) - ( id12 + id56 ) */ \ - " psrlw $15, %%mm2 \n\t" \ - \ - " paddw %%mm3, %%mm7 \n\t" /* mm7 = xC4S4 * ( id12 + id56 ) */ \ - " paddw %%mm2, %%mm7 \n\t" /* Truncate mm7, now it is icommon_product2 */ \ - /* ------------------------------------------------------------------- */ \ - " pxor %%mm0, %%mm0 \n\t" /* Clear mm0 */ \ - " psubsw %%mm6, %%mm0 \n\t" /* mm0 = - id34 */ \ - \ - " psubsw %%mm7, %%mm0 \n\t" /* mm0 = - ( id34 + idcommon_product2 ) */ \ - " paddsw %%mm6, %%mm6 \n\t" \ - " paddsw %%mm0, %%mm6 \n\t" /* mm6 = id34 - icommon_product2 */ \ - \ - " psubsw %%mm1, %%mm4 \n\t" /* mm4 = id07 - icommon_product1 */ \ - " paddsw %%mm1, %%mm1 \n\t" \ - " paddsw %%mm4, %%mm1 \n\t" /* mm1 = id07 + icommon_product1 */ \ - /* ------------------------------------------------------------------- */ \ - " movq %[xC1S7], %%mm7 \n\t" \ - " movq %%mm1, %%mm2 \n\t" \ - \ - " movq %%mm1, %%mm3 \n\t" \ - " pmulhw %%mm7, %%mm1 \n\t" /* mm1 = xC1S7 * irot_input_x - irot_input_x */ \ - \ - " movq %[xC7S1], %%mm7 \n\t" \ - " psrlw $15, %%mm2 \n\t" \ - \ - " paddw %%mm3, %%mm1 \n\t" /* mm1 = xC1S7 * irot_input_x */ \ - " paddw %%mm2, %%mm1 \n\t" /* Trucated */ \ - \ - " pmulhw %%mm7, %%mm3 \n\t" /* mm3 = xC7S1 * irot_input_x */ \ - " paddw %%mm2, %%mm3 \n\t" /* Truncated */ \ - \ - " movq %%mm0, %%mm5 \n\t" \ - " movq %%mm0, %%mm2 \n\t" \ - \ - " movq %[xC1S7], %%mm7 \n\t" \ - " pmulhw %%mm7, %%mm0 \n\t" /* mm0 = xC1S7 * irot_input_y - irot_input_y */ \ - \ - " movq %[xC7S1], %%mm7 \n\t" \ - " psrlw $15, %%mm2 \n\t" \ - \ - " paddw %%mm5, %%mm0 \n\t" /* mm0 = xC1S7 * irot_input_y */ \ - " paddw %%mm2, %%mm0 \n\t" /* Truncated */ \ - \ - " pmulhw %%mm7, %%mm5 \n\t" /* mm5 = xC7S1 * irot_input_y */ \ - " paddw %%mm2, %%mm5 \n\t" /* Truncated */ \ - \ - " psubsw %%mm5, %%mm1 \n\t" /* mm1 = xC1S7 * irot_input_x - xC7S1 * irot_input_y = ip1 */ \ - " paddsw %%mm0, %%mm3 \n\t" /* mm3 = xC7S1 * irot_input_x - xC1S7 * irot_input_y = ip7 */ \ - \ - " movq %%mm1," #ip1 " \n\t" \ - " movq %%mm3," #ip7 " \n\t" \ - /* ------------------------------------------------------------------- */ \ - " movq %[xC3S5], %%mm0 \n\t" \ - " movq %[xC5S3], %%mm1 \n\t" \ - \ - " movq %%mm6, %%mm5 \n\t" \ - " movq %%mm6, %%mm7 \n\t" \ - \ - " movq %%mm4, %%mm2 \n\t" \ - " movq %%mm4, %%mm3 \n\t" \ - \ - " pmulhw %%mm0, %%mm4 \n\t" /* mm4 = xC3S5 * irot_input_x - irot_input_x */ \ - " pmulhw %%mm1, %%mm6 \n\t" /* mm6 = xC5S3 * irot_input_y - irot_input_y */ \ - \ - " psrlw $15, %%mm2 \n\t" \ - " psrlw $15, %%mm5 \n\t" \ - \ - " paddw %%mm3, %%mm4 \n\t" /* mm4 = xC3S5 * irot_input_x */ \ - " paddw %%mm7, %%mm6 \n\t" /* mm6 = xC5S3 * irot_input_y */ \ - \ - " paddw %%mm2, %%mm4 \n\t" /* Truncated */ \ - " paddw %%mm5, %%mm6 \n\t" /* Truncated */ \ - \ - " psubsw %%mm6, %%mm4 \n\t" /* ip3 */ \ - " movq %%mm4," #ip3 " \n\t" \ - \ - " movq %%mm3, %%mm4 \n\t" \ - " movq %%mm7, %%mm6 \n\t" \ - \ - " pmulhw %%mm1, %%mm3 \n\t" /* mm3 = xC5S3 * irot_input_x - irot_input_x */ \ - " pmulhw %%mm0, %%mm7 \n\t" /* mm7 = xC3S5 * irot_input_y - irot_input_y */ \ - \ - " paddw %%mm2, %%mm4 \n\t" \ - " paddw %%mm5, %%mm6 \n\t" \ - \ - " paddw %%mm4, %%mm3 \n\t" /* mm3 = xC5S3 * irot_input_x */ \ - " paddw %%mm6, %%mm7 \n\t" /* mm7 = xC3S5 * irot_input_y */ \ - \ - " paddw %%mm7, %%mm3 \n\t" /* ip5 */ \ - " movq %%mm3," #ip5 " \n\t" - -#define Transpose_mmx(ip0,ip1,ip2,ip3,ip4,ip5,ip6,ip7, \ - op0,op1,op2,op3,op4,op5,op6,op7) \ - " movq " #ip0 ", %%mm0 \n\t" /* mm0 = a0 a1 a2 a3 */ \ - " movq " #ip4 ", %%mm4 \n\t" /* mm4 = e4 e5 e6 e7 */ \ - " movq " #ip1 ", %%mm1 \n\t" /* mm1 = b0 b1 b2 b3 */ \ - " movq " #ip5 ", %%mm5 \n\t" /* mm5 = f4 f5 f6 f7 */ \ - " movq " #ip2 ", %%mm2 \n\t" /* mm2 = c0 c1 c2 c3 */ \ - " movq " #ip6 ", %%mm6 \n\t" /* mm6 = g4 g5 g6 g7 */ \ - " movq " #ip3 ", %%mm3 \n\t" /* mm3 = d0 d1 d2 d3 */ \ - " movq %%mm1," #op1 " \n\t" /* save b0 b1 b2 b3 */ \ - " movq " #ip7 ", %%mm7 \n\t" /* mm7 = h0 h1 h2 h3 */ \ - /* Transpose 2x8 block */ \ - " movq %%mm4, %%mm1 \n\t" /* mm1 = e3 e2 e1 e0 */ \ - " punpcklwd %%mm5, %%mm4 \n\t" /* mm4 = f1 e1 f0 e0 */ \ - " movq %%mm0," #op0 " \n\t" /* save a3 a2 a1 a0 */ \ - " punpckhwd %%mm5, %%mm1 \n\t" /* mm1 = f3 e3 f2 e2 */ \ - " movq %%mm6, %%mm0 \n\t" /* mm0 = g3 g2 g1 g0 */ \ - " punpcklwd %%mm7, %%mm6 \n\t" /* mm6 = h1 g1 h0 g0 */ \ - " movq %%mm4, %%mm5 \n\t" /* mm5 = f1 e1 f0 e0 */ \ - " punpckldq %%mm6, %%mm4 \n\t" /* mm4 = h0 g0 f0 e0 = MM4 */ \ - " punpckhdq %%mm6, %%mm5 \n\t" /* mm5 = h1 g1 f1 e1 = MM5 */ \ - " movq %%mm1, %%mm6 \n\t" /* mm6 = f3 e3 f2 e2 */ \ - " movq %%mm4," #op4 " \n\t" \ - " punpckhwd %%mm7, %%mm0 \n\t" /* mm0 = h3 g3 h2 g2 */ \ - " movq %%mm5," #op5 " \n\t" \ - " punpckhdq %%mm0, %%mm6 \n\t" /* mm6 = h3 g3 f3 e3 = MM7 */ \ - " movq " #op0 ", %%mm4 \n\t" /* mm4 = a3 a2 a1 a0 */ \ - " punpckldq %%mm0, %%mm1 \n\t" /* mm1 = h2 g2 f2 e2 = MM6 */ \ - " movq " #op1 ", %%mm5 \n\t" /* mm5 = b3 b2 b1 b0 */ \ - " movq %%mm4, %%mm0 \n\t" /* mm0 = a3 a2 a1 a0 */ \ - " movq %%mm6," #op7 " \n\t" \ - " punpcklwd %%mm5, %%mm0 \n\t" /* mm0 = b1 a1 b0 a0 */ \ - " movq %%mm1," #op6 " \n\t" \ - " punpckhwd %%mm5, %%mm4 \n\t" /* mm4 = b3 a3 b2 a2 */ \ - " movq %%mm2, %%mm5 \n\t" /* mm5 = c3 c2 c1 c0 */ \ - " punpcklwd %%mm3, %%mm2 \n\t" /* mm2 = d1 c1 d0 c0 */ \ - " movq %%mm0, %%mm1 \n\t" /* mm1 = b1 a1 b0 a0 */ \ - " punpckldq %%mm2, %%mm0 \n\t" /* mm0 = d0 c0 b0 a0 = MM0 */ \ - " punpckhdq %%mm2, %%mm1 \n\t" /* mm1 = d1 c1 b1 a1 = MM1 */ \ - " movq %%mm4, %%mm2 \n\t" /* mm2 = b3 a3 b2 a2 */ \ - " movq %%mm0," #op0 " \n\t" \ - " punpckhwd %%mm3, %%mm5 \n\t" /* mm5 = d3 c3 d2 c2 */ \ - " movq %%mm1," #op1 " \n\t" \ - " punpckhdq %%mm5, %%mm4 \n\t" /* mm4 = d3 c3 b3 a3 = MM3 */ \ - " punpckldq %%mm5, %%mm2 \n\t" /* mm2 = d2 c2 b2 a2 = MM2 */ \ - " movq %%mm4," #op3 " \n\t" \ - " movq %%mm2," #op2 " \n\t" - - -/* This performs a 2D Forward DCT on an 8x8 block with short - coefficients. We try to do the truncation to match the C - version. */ -static void fdct_short__mmx ( ogg_int16_t *InputData, ogg_int16_t *OutputData) -{ - ogg_int16_t __attribute__((aligned(8))) temp[8*8]; - - __asm__ __volatile__ ( - " .p2align 4 \n\t" - /* - * Input data is an 8x8 block. To make processing of the data more efficent - * we will transpose the block of data to two 4x8 blocks??? - */ - Transpose_mmx ( (%0), 16(%0), 32(%0), 48(%0), 8(%0), 24(%0), 40(%0), 56(%0), - (%1), 16(%1), 32(%1), 48(%1), 8(%1), 24(%1), 40(%1), 56(%1)) - Fdct_mmx ( (%1), 16(%1), 32(%1), 48(%1), 8(%1), 24(%1), 40(%1), 56(%1), (%2)) - - Transpose_mmx (64(%0), 80(%0), 96(%0),112(%0), 72(%0), 88(%0),104(%0),120(%0), - 64(%1), 80(%1), 96(%1),112(%1), 72(%1), 88(%1),104(%1),120(%1)) - Fdct_mmx (64(%1), 80(%1), 96(%1),112(%1), 72(%1), 88(%1),104(%1),120(%1), (%2)) - - Transpose_mmx ( 0(%1), 16(%1), 32(%1), 48(%1), 64(%1), 80(%1), 96(%1),112(%1), - 0(%1), 16(%1), 32(%1), 48(%1), 64(%1), 80(%1), 96(%1),112(%1)) - Fdct_mmx ( 0(%1), 16(%1), 32(%1), 48(%1), 64(%1), 80(%1), 96(%1),112(%1), (%2)) - - Transpose_mmx ( 8(%1), 24(%1), 40(%1), 56(%1), 72(%1), 88(%1),104(%1),120(%1), - 8(%1), 24(%1), 40(%1), 56(%1), 72(%1), 88(%1),104(%1),120(%1)) - Fdct_mmx ( 8(%1), 24(%1), 40(%1), 56(%1), 72(%1), 88(%1),104(%1),120(%1), (%2)) - - " emms \n\t" - - : "+r" (InputData), - "+r" (OutputData) - : "r" (temp), - [xC1S7] "m" (xC1S7), /* gcc 3.1+ allows named asm parameters */ - [xC2S6] "m" (xC2S6), - [xC3S5] "m" (xC3S5), - [xC4S4] "m" (xC4S4), - [xC5S3] "m" (xC5S3), - [xC6S2] "m" (xC6S2), - [xC7S1] "m" (xC7S1) - : "memory" - ); -} - -/* install our implementation in the function table */ -void dsp_mmx_fdct_init(DspFunctions *funcs) -{ - funcs->fdct_short = fdct_short__mmx; -} - -#endif /* USE_ASM */ diff --git a/Engine/lib/libtheora/lib/enc/x86_32/idct_mmx.c b/Engine/lib/libtheora/lib/enc/x86_32/idct_mmx.c deleted file mode 100644 index 5fc6a1f66..000000000 --- a/Engine/lib/libtheora/lib/enc/x86_32/idct_mmx.c +++ /dev/null @@ -1,1452 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: idct_mmx.c 15153 2008-08-04 18:37:55Z tterribe $ - - ********************************************************************/ - -#include "../codec_internal.h" - -#if defined(USE_ASM) - -#define ASM asm - -/**************************************************************************** -* -* Description : IDCT with multiple versions based on # of non 0 coeffs -* -***************************************************************************** -*/ - -// Dequantization + inverse discrete cosine transform. - -// Constants used in MMX implementation of dequantization and idct. -// All the MMX stuff works with 4 16-bit quantities at a time and -// we create 11 constants of size 4 x 16 bits. -// The first 4 are used to mask the individual 16-bit words within a group -// and are used in the address-shuffling part of the dequantization. -// The last 7 are fixed-point approximations to the cosines of angles -// occurring in the DCT; each of these contains 4 copies of the same value. - -// There is only one (statically initialized) instance of this object -// wrapped in an allocator object that forces its starting address -// to be evenly divisible by 32. Hence the actual object occupies 2.75 -// cache lines on a Pentium processor. - -// Offsets in bytes used by the assembler code below -// must of course agree with the idctConstants constructor. - -#define MaskOffset 0 // 4 masks come in order low word to high -#define CosineOffset 32 // 7 cosines come in order pi/16 * (1 ... 7) -#define EightOffset 88 -#define IdctAdjustBeforeShift 8 - -/* -UINT16 idctcosTbl[ 7] = -{ - 64277, 60547, 54491, 46341, 36410, 25080, 12785 -}; - -void fillidctconstants(void) -{ - int j = 16; - UINT16 * p; - do - { - idctconstants[ --j] = 0; - } - while( j); - - idctconstants[0] = idctconstants[5] = idctconstants[10] = idctconstants[15] = 65535; - - j = 1; - do - { - p = idctconstants + ( (j+3) << 2); - p[0] = p[1] = p[2] = p[3] = idctcosTbl[ j - 1]; - } - while( ++j <= 7); - - idctconstants[44] = idctconstants[45] = idctconstants[46] = idctconstants[47] = IdctAdjustBeforeShift; -} -*/ - -ogg_uint16_t idctconstants[(4+7+1) * 4] = { - 65535, 0, 0, 0, 0, 65535, 0, 0, - 0, 0, 65535, 0, 0, 0, 0, 65535, - 64277, 64277, 64277, 64277, 60547, 60547, 60547, 60547, - 54491, 54491, 54491, 54491, 46341, 46341, 46341, 46341, - 36410, 36410, 36410, 36410, 25080, 25080, 25080, 25080, - 12785, 12785, 12785, 12785, 8, 8, 8, 8, -}; - -/* Dequantization + inverse DCT. - - Dequantization multiplies user's 16-bit signed indices (range -512 to +511) - by unsigned 16-bit quantization table entries. - These table entries are upscaled by 4, max is 30 * 128 * 4 < 2^14. - Result is scaled signed DCT coefficients (abs value < 2^15). - - In the data stream, the coefficients are sent in order of increasing - total (horizontal + vertical) frequency. The exact picture is as follows: - - 00 01 05 06 16 17 33 34 - 02 04 07 15 20 32 35 52 - 03 10 14 21 31 36 51 53 - 11 13 22 30 37 50 54 65 - - 12 23 27 40 47 55 64 66 - 24 26 41 46 56 63 67 74 - 25 42 45 57 62 70 73 75 - 43 44 60 61 71 72 76 77 - - Here the position in the matrix corresponds to the (horiz,vert) - freqency indices and the octal entry in the matrix is the position - of the coefficient in the data stream. Thus the coefficients are sent - in sort of a diagonal "snake". - - The dequantization stage "uncurls the snake" and stores the expanded - coefficients in more convenient positions. These are not exactly the - natural positions given above but take into account our implementation - of the idct, which basically requires two one-dimensional idcts and - two transposes. - - We fold the first transpose into the storage of the expanded coefficients. - We don't actually do a full transpose because this would require doubling - the size of the idct buffer; rather, we just transpose each of the 4x4 - subblocks. Using slightly varying addressing schemes in each of the - four 4x8 idcts then allows these transforms to be done in place. - - Transposing the 4x4 subblocks in the matrix above gives - - 00 02 03 11 16 20 31 37 - 01 04 10 13 17 32 36 50 - 05 07 14 22 33 35 51 54 - 06 15 21 30 34 52 53 65 - - 12 24 25 43 47 56 62 71 - 23 26 42 44 55 63 70 72 - 27 41 45 60 64 67 73 76 - 40 46 57 61 66 74 75 77 - - Finally, we reverse the words in each 4 word group to clarify - direction of shifts. - - 11 03 02 00 37 31 20 16 - 13 10 04 01 50 36 32 17 - 22 14 07 05 54 51 35 33 - 30 21 15 06 65 53 52 34 - - 43 25 24 12 71 62 56 47 - 44 42 26 23 72 70 63 55 - 60 45 41 27 76 73 67 64 - 61 57 46 40 77 75 74 66 - - This matrix then shows the 16 4x16 destination words in terms of - the 16 4x16 input words. - - We implement this algorithm by manipulation of mmx registers, - which seems to be the fastest way to proceed. It is completely - hand-written; there does not seem to be enough recurrence to - reasonably compartmentalize any of it. Hence the resulting - program is ugly and bloated. Furthermore, due to the absence of - register pressure, it is boring and artless. I hate it. - - The idct itself is more interesting. Since the two-dimensional dct - basis functions are products of the one-dimesional dct basis functions, - we can compute an inverse (or forward) dct via two 1-D transforms, - on rows then on columns. To exploit MMX parallelism, we actually do - both operations on columns, interposing a (partial) transpose between - the two 1-D transforms, the first transpose being done by the expansion - described above. - - The 8-sample one-dimensional DCT is a standard orthogonal expansion using - the (unnormalized) basis functions - - b[k]( i) = cos( pi * k * (2i + 1) / 16); - - here k = 0 ... 7 is the frequency and i = 0 ... 7 is the spatial coordinate. - To normalize, b[0] should be multiplied by 1/sqrt( 8) and the other b[k] - should be multiplied by 1/2. - - The 8x8 two-dimensional DCT is just the product of one-dimensional DCTs - in each direction. The (unnormalized) basis functions are - - B[k,l]( i, j) = b[k]( i) * b[l]( j); - - this time k and l are the horizontal and vertical frequencies, - i and j are the horizontal and vertical spatial coordinates; - all indices vary from 0 ... 7 (as above) - and there are now 4 cases of normalization. - - Our 1-D idct expansion uses constants C1 ... C7 given by - - (*) Ck = C(-k) = cos( pi * k/16) = S(8-k) = -S(k-8) = sin( pi * (8-k)/16) - - and the following 1-D algorithm transforming I0 ... I7 to R0 ... R7 : - - A = (C1 * I1) + (C7 * I7) B = (C7 * I1) - (C1 * I7) - C = (C3 * I3) + (C5 * I5) D = (C3 * I5) - (C5 * I3) - A. = C4 * (A - C) B. = C4 * (B - D) - C. = A + C D. = B + D - - E = C4 * (I0 + I4) F = C4 * (I0 - I4) - G = (C2 * I2) + (C6 * I6) H = (C6 * I2) - (C2 * I6) - E. = E - G - G. = E + G - - A.. = F + A. B.. = B. - H - F. = F - A. H. = B. + H - - R0 = G. + C. R1 = A.. + H. R3 = E. + D. R5 = F. + B.. - R7 = G. - C. R2 = A.. - H. R4 = E. - D. R6 = F. - B.. - - It is due to Vetterli and Lightenberg and may be found in the JPEG - reference book by Pennebaker and Mitchell. - - Correctness of the algorithm follows from (*) together with the - addition formulas for sine and cosine: - - cos( A + B) = cos( A) * cos( B) - sin( A) * sin( B) - sin( A + B) = sin( A) * cos( B) + cos( A) * sin( B) - - Note that this implementation absorbs the difference in normalization - between the 0th and higher frequencies, although the results produced - are actually twice as big as they should be. Since we do this for each - dimension, the 2-D idct results are 4x the desired results. Finally, - taking into account that the dequantization multiplies by 4 as well, - our actual results are 16x too big. We fix this by shifting the final - results right by 4 bits. - - High precision version approximates C1 ... C7 to 16 bits. - Since MMX only provides a signed multiply, C1 ... C5 appear to be - negative and multiplies involving them must be adjusted to compensate - for this. C6 and C7 do not require this adjustment since - they are < 1/2 and are correctly treated as positive numbers. - - Following macro does four 8-sample one-dimensional idcts in parallel. - This is actually not such a difficult program to write once you - make a couple of observations (I of course was unable to make these - observations until I'd half-written a couple of other versions). - - 1. Everything is easy once you are done with the multiplies. - This is because, given X and Y in registers, one may easily - calculate X+Y and X-Y using just those 2 registers. - - 2. You always need at least 2 extra registers to calculate products, - so storing 2 temporaries is inevitable. C. and D. seem to be - the best candidates. - - 3. The products should be calculated in decreasing order of complexity - (which translates into register pressure). Since C1 ... C5 require - adjustment (and C6, C7 do not), we begin by calculating C and D. -*/ - -/************************************************************************************** - * - * Routine: BeginIDCT - * - * Description: The Macro does IDct on 4 1-D Dcts - * - * Input: None - * - * Output: None - * - * Return: None - * - * Special Note: None - * - * Error: None - * - *************************************************************************************** - */ - -#define MtoSTR(s) #s - -#define Dump "call MMX_dump\n" - -#define BeginIDCT "#BeginIDCT\n" \ - \ - " movq " I(3)","r2"\n" \ - \ - " movq " C(3)","r6"\n" \ - " movq " r2","r4"\n" \ - " movq " J(5)","r7"\n" \ - " pmulhw " r6","r4"\n" \ - " movq " C(5)","r1"\n" \ - " pmulhw " r7","r6"\n" \ - " movq " r1","r5"\n" \ - " pmulhw " r2","r1"\n" \ - " movq " I(1)","r3"\n" \ - " pmulhw " r7","r5"\n" \ - " movq " C(1)","r0"\n" \ - " paddw " r2","r4"\n" \ - " paddw " r7","r6"\n" \ - " paddw " r1","r2"\n" \ - " movq " J(7)","r1"\n" \ - " paddw " r5","r7"\n" \ - " movq " r0","r5"\n" \ - " pmulhw " r3","r0"\n" \ - " paddsw " r7","r4"\n" \ - " pmulhw " r1","r5"\n" \ - " movq " C(7)","r7"\n" \ - " psubsw " r2","r6"\n" \ - " paddw " r3","r0"\n" \ - " pmulhw " r7","r3"\n" \ - " movq " I(2)","r2"\n" \ - " pmulhw " r1","r7"\n" \ - " paddw " r1","r5"\n" \ - " movq " r2","r1"\n" \ - " pmulhw " C(2)","r2"\n" \ - " psubsw " r5","r3"\n" \ - " movq " J(6)","r5"\n" \ - " paddsw " r7","r0"\n" \ - " movq " r5","r7"\n" \ - " psubsw " r4","r0"\n" \ - " pmulhw " C(2)","r5"\n" \ - " paddw " r1","r2"\n" \ - " pmulhw " C(6)","r1"\n" \ - " paddsw " r4","r4"\n" \ - " paddsw " r0","r4"\n" \ - " psubsw " r6","r3"\n" \ - " paddw " r7","r5"\n" \ - " paddsw " r6","r6"\n" \ - " pmulhw " C(6)","r7"\n" \ - " paddsw " r3","r6"\n" \ - " movq " r4","I(1)"\n" \ - " psubsw " r5","r1"\n" \ - " movq " C(4)","r4"\n" \ - " movq " r3","r5"\n" \ - " pmulhw " r4","r3"\n" \ - " paddsw " r2","r7"\n" \ - " movq " r6","I(2)"\n" \ - " movq " r0","r2"\n" \ - " movq " I(0)","r6"\n" \ - " pmulhw " r4","r0"\n" \ - " paddw " r3","r5"\n" \ - "\n" \ - " movq " J(4)","r3"\n" \ - " psubsw " r1","r5"\n" \ - " paddw " r0","r2"\n" \ - " psubsw " r3","r6"\n" \ - " movq " r6","r0"\n" \ - " pmulhw " r4","r6"\n" \ - " paddsw " r3","r3"\n" \ - " paddsw " r1","r1"\n" \ - " paddsw " r0","r3"\n" \ - " paddsw " r5","r1"\n" \ - " pmulhw " r3","r4"\n" \ - " paddsw " r0","r6"\n" \ - " psubsw " r2","r6"\n" \ - " paddsw " r2","r2"\n" \ - " movq " I(1)","r0"\n" \ - " paddsw " r6","r2"\n" \ - " paddw " r3","r4"\n" \ - " psubsw " r1","r2"\n" \ - "#end BeginIDCT\n" -// end BeginIDCT macro (38 cycles). - - -// Two versions of the end of the idct depending on whether we're feeding -// into a transpose or dividing the final results by 16 and storing them. - -/************************************************************************************** - * - * Routine: RowIDCT - * - * Description: The Macro does 1-D IDct on 4 Rows - * - * Input: None - * - * Output: None - * - * Return: None - * - * Special Note: None - * - * Error: None - * - *************************************************************************************** - */ - -// RowIDCT gets ready to transpose. - -#define RowIDCT ASM("\n"\ - "#RowIDCT\n" \ - BeginIDCT \ - "\n" \ - " movq "I(2)","r3"\n" /* r3 = D. */ \ - " psubsw "r7","r4"\n" /* r4 = E. = E - G */ \ - " paddsw "r1","r1"\n" /* r1 = H. + H. */ \ - " paddsw "r7","r7"\n" /* r7 = G + G */ \ - " paddsw "r2","r1"\n" /* r1 = R1 = A.. + H. */\ - " paddsw "r4","r7"\n" /* r7 = G. = E + G */ \ - " psubsw "r3","r4"\n" /* r4 = R4 = E. - D. */ \ - " paddsw "r3","r3"\n" \ - " psubsw "r5","r6"\n" /* r6 = R6 = F. - B.. */\ - " paddsw "r5","r5"\n" \ - " paddsw "r4","r3"\n" /* r3 = R3 = E. + D. */ \ - " paddsw "r6","r5"\n" /* r5 = R5 = F. + B.. */\ - " psubsw "r0","r7"\n" /* r7 = R7 = G. - C. */ \ - " paddsw "r0","r0"\n" \ - " movq "r1","I(1)"\n" /* save R1 */ \ - " paddsw "r7","r0"\n" /* r0 = R0 = G. + C. */ \ - "#end RowIDCT" \ -); -// end RowIDCT macro (8 + 38 = 46 cycles) - - -/************************************************************************************** - * - * Routine: ColumnIDCT - * - * Description: The Macro does 1-D IDct on 4 columns - * - * Input: None - * - * Output: None - * - * Return: None - * - * Special Note: None - * - * Error: None - * - *************************************************************************************** - */ -// Column IDCT normalizes and stores final results. - -#define ColumnIDCT ASM("\n" \ - "#ColumnIDCT\n" \ - BeginIDCT \ - "\n" \ - " paddsw "Eight","r2"\n" \ - " paddsw "r1","r1"\n" /* r1 = H. + H. */ \ - " paddsw "r2","r1"\n" /* r1 = R1 = A.. + H. */\ - " psraw ""$4"","r2"\n" /* r2 = NR2 */ \ - " psubsw "r7","r4"\n" /* r4 = E. = E - G */ \ - " psraw ""$4"","r1"\n" /* r1 = NR1 */ \ - " movq "I(2)","r3"\n" /* r3 = D. */ \ - " paddsw "r7","r7"\n" /* r7 = G + G */ \ - " movq "r2","I(2)"\n" /* store NR2 at I2 */ \ - " paddsw "r4","r7"\n" /* r7 = G. = E + G */ \ - " movq "r1","I(1)"\n" /* store NR1 at I1 */ \ - " psubsw "r3","r4"\n" /* r4 = R4 = E. - D. */ \ - " paddsw "Eight","r4"\n" \ - " paddsw "r3","r3"\n" /* r3 = D. + D. */ \ - " paddsw "r4","r3"\n" /* r3 = R3 = E. + D. */ \ - " psraw ""$4"","r4"\n" /* r4 = NR4 */ \ - " psubsw "r5","r6"\n" /* r6 = R6 = F. - B.. */\ - " psraw ""$4"","r3"\n" /* r3 = NR3 */ \ - " paddsw "Eight","r6"\n" \ - " paddsw "r5","r5"\n" /* r5 = B.. + B.. */ \ - " paddsw "r6","r5"\n" /* r5 = R5 = F. + B.. */\ - " psraw ""$4"","r6"\n" /* r6 = NR6 */ \ - " movq "r4","J(4)"\n" /* store NR4 at J4 */ \ - " psraw ""$4"","r5"\n" /* r5 = NR5 */ \ - " movq "r3","I(3)"\n" /* store NR3 at I3 */ \ - " psubsw "r0","r7"\n" /* r7 = R7 = G. - C. */ \ - " paddsw "Eight","r7"\n" \ - " paddsw "r0","r0"\n" /* r0 = C. + C. */ \ - " paddsw "r7","r0"\n" /* r0 = R0 = G. + C. */ \ - " psraw ""$4"","r7"\n" /* r7 = NR7 */ \ - " movq "r6","J(6)"\n" /* store NR6 at J6 */ \ - " psraw ""$4"","r0"\n" /* r0 = NR0 */ \ - " movq "r5","J(5)"\n" /* store NR5 at J5 */ \ - " movq "r7","J(7)"\n" /* store NR7 at J7 */ \ - " movq "r0","I(0)"\n" /* store NR0 at I0 */ \ - "#end ColumnIDCT\n" \ -); -// end ColumnIDCT macro (38 + 19 = 57 cycles) - -/************************************************************************************** - * - * Routine: Transpose - * - * Description: The Macro does two 4x4 transposes in place. - * - * Input: None - * - * Output: None - * - * Return: None - * - * Special Note: None - * - * Error: None - * - *************************************************************************************** - */ - -/* Following macro does two 4x4 transposes in place. - - At entry (we assume): - - r0 = a3 a2 a1 a0 - I(1) = b3 b2 b1 b0 - r2 = c3 c2 c1 c0 - r3 = d3 d2 d1 d0 - - r4 = e3 e2 e1 e0 - r5 = f3 f2 f1 f0 - r6 = g3 g2 g1 g0 - r7 = h3 h2 h1 h0 - - At exit, we have: - - I(0) = d0 c0 b0 a0 - I(1) = d1 c1 b1 a1 - I(2) = d2 c2 b2 a2 - I(3) = d3 c3 b3 a3 - - J(4) = h0 g0 f0 e0 - J(5) = h1 g1 f1 e1 - J(6) = h2 g2 f2 e2 - J(7) = h3 g3 f3 e3 - - I(0) I(1) I(2) I(3) is the transpose of r0 I(1) r2 r3. - J(4) J(5) J(6) J(7) is the transpose of r4 r5 r6 r7. - - Since r1 is free at entry, we calculate the Js first. */ - - -#define Transpose ASM("\n#Transpose\n" \ - \ - " movq "r4","r1"\n" \ - " punpcklwd "r5","r4"\n" \ - " movq "r0","I(0)"\n" \ - " punpckhwd "r5","r1"\n" \ - " movq "r6","r0"\n" \ - " punpcklwd "r7","r6"\n" \ - " movq "r4","r5"\n" \ - " punpckldq "r6","r4"\n" \ - " punpckhdq "r6","r5"\n" \ - " movq "r1","r6"\n" \ - " movq "r4","J(4)"\n" \ - " punpckhwd "r7","r0"\n" \ - " movq "r5","J(5)"\n" \ - " punpckhdq "r0","r6"\n" \ - " movq "I(0)","r4"\n" \ - " punpckldq "r0","r1"\n" \ - " movq "I(1)","r5"\n" \ - " movq "r4","r0"\n" \ - " movq "r6","J(7)"\n" \ - " punpcklwd "r5","r0"\n" \ - " movq "r1","J(6)"\n" \ - " punpckhwd "r5","r4"\n" \ - " movq "r2","r5"\n" \ - " punpcklwd "r3","r2"\n" \ - " movq "r0","r1"\n" \ - " punpckldq "r2","r0"\n" \ - " punpckhdq "r2","r1"\n" \ - " movq "r4","r2"\n" \ - " movq "r0","I(0)"\n" \ - " punpckhwd "r3","r5"\n" \ - " movq "r1","I(1)"\n" \ - " punpckhdq "r5","r4"\n" \ - " punpckldq "r5","r2"\n" \ - \ - " movq "r4","I(3)"\n" \ - \ - " movq "r2","I(2)"\n" \ - "#end Transpose\n" \ -); -// end Transpose macro (19 cycles). - -/* -static void MMX_dump() -{ - ASM - ("\ - movq %mm0,(%edi)\n\ - movq %mm1,8(%edi)\n\ - movq %mm2,16(%edi)\n\ - movq %mm3,24(%edi)\n\ - movq %mm4,32(%edi)\n\ - movq %mm5,40(%edi)\n\ - movq %mm6,48(%edi)\n\ - movq %mm7,56(%edi)\n\ - ret" - ); -} -*/ - -/************************************************************************************** - * - * Routine: MMX_idct - * - * Description: Perform IDCT on a 8x8 block - * - * Input: Pointer to input and output buffer - * - * Output: None - * - * Return: None - * - * Special Note: The input coefficients are in ZigZag order - * - * Error: None - * - *************************************************************************************** - */ -void IDctSlow__mmx( Q_LIST_ENTRY * InputData, - ogg_int16_t *QuantMatrix, - ogg_int16_t * OutputData ) { - -# define MIDM(M,I) MtoSTR(M+I*8(%ecx)) -# define M(I) MIDM( MaskOffset , I ) -# define MIDC(M,I) MtoSTR(M+(I-1)*8(%ecx)) -# define C(I) MIDC( CosineOffset , I ) -# define MIDEight(M) MtoSTR(M(%ecx)) -# define Eight MIDEight(EightOffset) - -# define r0 "%mm0" -# define r1 "%mm1" -# define r2 "%mm2" -# define r3 "%mm3" -# define r4 "%mm4" -# define r5 "%mm5" -# define r6 "%mm6" -# define r7 "%mm7" - - __asm__ __volatile__ ( - /* eax = quantized input */ - /* esi = quantization table */ - /* edx = destination (= idct buffer) */ - /* ecx = idctconstants */ - "" - : - :"a"(InputData), "S"(QuantMatrix), "d"(OutputData), "c"(idctconstants) - ); - - ASM( - "movq (%eax), "r0"\n" - "pmullw (%esi), "r0"\n" /* r0 = 03 02 01 00 */ - "movq 16(%eax), "r1"\n" - "pmullw 16(%esi), "r1"\n" /* r1 = 13 12 11 10 */ - "movq "M(0)", "r2"\n" /* r2 = __ __ __ FF */ - "movq "r0", "r3"\n" /* r3 = 03 02 01 00 */ - "movq 8(%eax), "r4"\n" - "psrlq $16, "r0"\n" /* r0 = __ 03 02 01 */ - "pmullw 8(%esi), "r4"\n" /* r4 = 07 06 05 04 */ - "pand "r2", "r3"\n" /* r3 = __ __ __ 00 */ - "movq "r0", "r5"\n" /* r5 = __ 03 02 01 */ - "movq "r1", "r6"\n" /* r6 = 13 12 11 10 */ - "pand "r2", "r5"\n" /* r5 = __ __ __ 01 */ - "psllq $32, "r6"\n" /* r6 = 11 10 __ __ */ - "movq "M(3)", "r7"\n" /* r7 = FF __ __ __ */ - "pxor "r5", "r0"\n" /* r0 = __ 03 02 __ */ - "pand "r6", "r7"\n" /* r7 = 11 __ __ __ */ - "por "r3", "r0"\n" /* r0 = __ 03 02 00 */ - "pxor "r7", "r6"\n" /* r6 = __ 10 __ __ */ - "por "r7", "r0"\n" /* r0 = 11 03 02 00 = R0 */ - "movq "M(3)", "r7"\n" /* r7 = FF __ __ __ */ - "movq "r4", "r3"\n" /* r3 = 07 06 05 04 */ - "movq "r0", (%edx)\n" /* write R0 = r0 */ - "pand "r2", "r3"\n" /* r3 = __ __ __ 04 */ - "movq 32(%eax), "r0"\n" - "psllq $16, "r3"\n" /* r3 = __ __ 04 __ */ - "pmullw 32(%esi), "r0"\n" /* r0 = 23 22 21 20 */ - "pand "r1", "r7"\n" /* r7 = 13 __ __ __ */ - "por "r3", "r5"\n" /* r5 = __ __ 04 01 */ - "por "r6", "r7"\n" /* r7 = 13 10 __ __ */ - "movq 24(%eax), "r3"\n" - "por "r5", "r7"\n" /* r7 = 13 10 04 01 = R1 */ - "pmullw 24(%esi), "r3"\n" /* r3 = 17 16 15 14 */ - "psrlq $16, "r4"\n" /* r4 = __ 07 06 05 */ - "movq "r7", 16(%edx)\n" /* write R1 = r7 */ - "movq "r4", "r5"\n" /* r5 = __ 07 06 05 */ - "movq "r0", "r7"\n" /* r7 = 23 22 21 20 */ - "psrlq $16, "r4"\n" /* r4 = __ __ 07 06 */ - "psrlq $48, "r7"\n" /* r7 = __ __ __ 23 */ - "movq "r2", "r6"\n" /* r6 = __ __ __ FF */ - "pand "r2", "r5"\n" /* r5 = __ __ __ 05 */ - "pand "r4", "r6"\n" /* r6 = __ __ __ 06 */ - "movq "r7", 80(%edx)\n" /* partial R9 = __ __ __ 23 */ - "pxor "r6", "r4"\n" /* r4 = __ __ 07 __ */ - "psrlq $32, "r1"\n" /* r1 = __ __ 13 12 */ - "por "r5", "r4"\n" /* r4 = __ __ 07 05 */ - "movq "M(3)", "r7"\n" /* r7 = FF __ __ __ */ - "pand "r2", "r1"\n" /* r1 = __ __ __ 12 */ - "movq 48(%eax), "r5"\n" - "psllq $16, "r0"\n" /* r0 = 22 21 20 __ */ - "pmullw 48(%esi), "r5"\n" /* r5 = 33 32 31 30 */ - "pand "r0", "r7"\n" /* r7 = 22 __ __ __ */ - "movq "r1", 64(%edx)\n" /* partial R8 = __ __ __ 12 */ - "por "r4", "r7"\n" /* r7 = 22 __ 07 05 */ - "movq "r3", "r4"\n" /* r4 = 17 16 15 14 */ - "pand "r2", "r3"\n" /* r3 = __ __ __ 14 */ - "movq "M(2)", "r1"\n" /* r1 = __ FF __ __ */ - "psllq $32, "r3"\n" /* r3 = __ 14 __ __ */ - "por "r3", "r7"\n" /* r7 = 22 14 07 05 = R2 */ - "movq "r5", "r3"\n" /* r3 = 33 32 31 30 */ - "psllq $48, "r3"\n" /* r3 = 30 __ __ __ */ - "pand "r0", "r1"\n" /* r1 = __ 21 __ __ */ - "movq "r7", 32(%edx)\n" /* write R2 = r7 */ - "por "r3", "r6"\n" /* r6 = 30 __ __ 06 */ - "movq "M(1)", "r7"\n" /* r7 = __ __ FF __ */ - "por "r1", "r6"\n" /* r6 = 30 21 __ 06 */ - "movq 56(%eax), "r1"\n" - "pand "r4", "r7"\n" /* r7 = __ __ 15 __ */ - "pmullw 56(%esi), "r1"\n" /* r1 = 37 36 35 34 */ - "por "r6", "r7"\n" /* r7 = 30 21 15 06 = R3 */ - "pand "M(1)", "r0"\n" /* r0 = __ __ 20 __ */ - "psrlq $32, "r4"\n" /* r4 = __ __ 17 16 */ - "movq "r7", 48(%edx)\n" /* write R3 = r7 */ - "movq "r4", "r6"\n" /* r6 = __ __ 17 16 */ - "movq "M(3)", "r7"\n" /* r7 = FF __ __ __ */ - "pand "r2", "r4"\n" /* r4 = __ __ __ 16 */ - "movq "M(1)", "r3"\n" /* r3 = __ __ FF __ */ - "pand "r1", "r7"\n" /* r7 = 37 __ __ __ */ - "pand "r5", "r3"\n" /* r3 = __ __ 31 __ */ - "por "r4", "r0"\n" /* r0 = __ __ 20 16 */ - "psllq $16, "r3"\n" /* r3 = __ 31 __ __ */ - "por "r0", "r7"\n" /* r7 = 37 __ 20 16 */ - "movq "M(2)", "r4"\n" /* r4 = __ FF __ __ */ - "por "r3", "r7"\n" /* r7 = 37 31 20 16 = R4 */ - "movq 80(%eax), "r0"\n" - "movq "r4", "r3"\n" /* r3 = __ __ FF __ */ - "pmullw 80(%esi), "r0"\n" /* r0 = 53 52 51 50 */ - "pand "r5", "r4"\n" /* r4 = __ 32 __ __ */ - "movq "r7", 8(%edx)\n" /* write R4 = r7 */ - "por "r4", "r6"\n" /* r6 = __ 32 17 16 */ - "movq "r3", "r4"\n" /* r4 = __ FF __ __ */ - "psrlq $16, "r6"\n" /* r6 = __ __ 32 17 */ - "movq "r0", "r7"\n" /* r7 = 53 52 51 50 */ - "pand "r1", "r4"\n" /* r4 = __ 36 __ __ */ - "psllq $48, "r7"\n" /* r7 = 50 __ __ __ */ - "por "r4", "r6"\n" /* r6 = __ 36 32 17 */ - "movq 88(%eax), "r4"\n" - "por "r6", "r7"\n" /* r7 = 50 36 32 17 = R5 */ - "pmullw 88(%esi), "r4"\n" /* r4 = 57 56 55 54 */ - "psrlq $16, "r3"\n" /* r3 = __ __ FF __ */ - "movq "r7", 24(%edx)\n" /* write R5 = r7 */ - "pand "r1", "r3"\n" /* r3 = __ __ 35 __ */ - "psrlq $48, "r5"\n" /* r5 = __ __ __ 33 */ - "pand "r2", "r1"\n" /* r1 = __ __ __ 34 */ - "movq 104(%eax), "r6"\n" - "por "r3", "r5"\n" /* r5 = __ __ 35 33 */ - "pmullw 104(%esi), "r6"\n" /* r6 = 67 66 65 64 */ - "psrlq $16, "r0"\n" /* r0 = __ 53 52 51 */ - "movq "r4", "r7"\n" /* r7 = 57 56 55 54 */ - "movq "r2", "r3"\n" /* r3 = __ __ __ FF */ - "psllq $48, "r7"\n" /* r7 = 54 __ __ __ */ - "pand "r0", "r3"\n" /* r3 = __ __ __ 51 */ - "pxor "r3", "r0"\n" /* r0 = __ 53 52 __ */ - "psllq $32, "r3"\n" /* r3 = __ 51 __ __ */ - "por "r5", "r7"\n" /* r7 = 54 __ 35 33 */ - "movq "r6", "r5"\n" /* r5 = 67 66 65 64 */ - "pand "M(1)", "r6"\n" /* r6 = __ __ 65 __ */ - "por "r3", "r7"\n" /* r7 = 54 51 35 33 = R6 */ - "psllq $32, "r6"\n" /* r6 = 65 __ __ __ */ - "por "r1", "r0"\n" /* r0 = __ 53 52 34 */ - "movq "r7", 40(%edx)\n" /* write R6 = r7 */ - "por "r6", "r0"\n" /* r0 = 65 53 52 34 = R7 */ - "movq 120(%eax), "r7"\n" - "movq "r5", "r6"\n" /* r6 = 67 66 65 64 */ - "pmullw 120(%esi), "r7"\n" /* r7 = 77 76 75 74 */ - "psrlq $32, "r5"\n" /* r5 = __ __ 67 66 */ - "pand "r2", "r6"\n" /* r6 = __ __ __ 64 */ - "movq "r5", "r1"\n" /* r1 = __ __ 67 66 */ - "movq "r0", 56(%edx)\n" /* write R7 = r0 */ - "pand "r2", "r1"\n" /* r1 = __ __ __ 66 */ - "movq 112(%eax), "r0"\n" - "movq "r7", "r3"\n" /* r3 = 77 76 75 74 */ - "pmullw 112(%esi), "r0"\n" /* r0 = 73 72 71 70 */ - "psllq $16, "r3"\n" /* r3 = 76 75 74 __ */ - "pand "M(3)", "r7"\n" /* r7 = 77 __ __ __ */ - "pxor "r1", "r5"\n" /* r5 = __ __ 67 __ */ - "por "r5", "r6"\n" /* r6 = __ __ 67 64 */ - "movq "r3", "r5"\n" /* r5 = 76 75 74 __ */ - "pand "M(3)", "r5"\n" /* r5 = 76 __ __ __ */ - "por "r1", "r7"\n" /* r7 = 77 __ __ 66 */ - "movq 96(%eax), "r1"\n" - "pxor "r5", "r3"\n" /* r3 = __ 75 74 __ */ - "pmullw 96(%esi), "r1"\n" /* r1 = 63 62 61 60 */ - "por "r3", "r7"\n" /* r7 = 77 75 74 66 = R15 */ - "por "r5", "r6"\n" /* r6 = 76 __ 67 64 */ - "movq "r0", "r5"\n" /* r5 = 73 72 71 70 */ - "movq "r7", 120(%edx)\n" /* store R15 = r7 */ - "psrlq $16, "r5"\n" /* r5 = __ 73 72 71 */ - "pand "M(2)", "r5"\n" /* r5 = __ 73 __ __ */ - "movq "r0", "r7"\n" /* r7 = 73 72 71 70 */ - "por "r5", "r6"\n" /* r6 = 76 73 67 64 = R14 */ - "pand "r2", "r0"\n" /* r0 = __ __ __ 70 */ - "pxor "r0", "r7"\n" /* r7 = 73 72 71 __ */ - "psllq $32, "r0"\n" /* r0 = __ 70 __ __ */ - "movq "r6", 104(%edx)\n" /* write R14 = r6 */ - "psrlq $16, "r4"\n" /* r4 = __ 57 56 55 */ - "movq 72(%eax), "r5"\n" - "psllq $16, "r7"\n" /* r7 = 72 71 __ __ */ - "pmullw 72(%esi), "r5"\n" /* r5 = 47 46 45 44 */ - "movq "r7", "r6"\n" /* r6 = 72 71 __ __ */ - "movq "M(2)", "r3"\n" /* r3 = __ FF __ __ */ - "psllq $16, "r6"\n" /* r6 = 71 __ __ __ */ - "pand "M(3)", "r7"\n" /* r7 = 72 __ __ __ */ - "pand "r1", "r3"\n" /* r3 = __ 62 __ __ */ - "por "r0", "r7"\n" /* r7 = 72 70 __ __ */ - "movq "r1", "r0"\n" /* r0 = 63 62 61 60 */ - "pand "M(3)", "r1"\n" /* r1 = 63 __ __ __ */ - "por "r3", "r6"\n" /* r6 = 71 62 __ __ */ - "movq "r4", "r3"\n" /* r3 = __ 57 56 55 */ - "psrlq $32, "r1"\n" /* r1 = __ __ 63 __ */ - "pand "r2", "r3"\n" /* r3 = __ __ __ 55 */ - "por "r1", "r7"\n" /* r7 = 72 70 63 __ */ - "por "r3", "r7"\n" /* r7 = 72 70 63 55 = R13 */ - "movq "r4", "r3"\n" /* r3 = __ 57 56 55 */ - "pand "M(1)", "r3"\n" /* r3 = __ __ 56 __ */ - "movq "r5", "r1"\n" /* r1 = 47 46 45 44 */ - "movq "r7", 88(%edx)\n" /* write R13 = r7 */ - "psrlq $48, "r5"\n" /* r5 = __ __ __ 47 */ - "movq 64(%eax), "r7"\n" - "por "r3", "r6"\n" /* r6 = 71 62 56 __ */ - "pmullw 64(%esi), "r7"\n" /* r7 = 43 42 41 40 */ - "por "r5", "r6"\n" /* r6 = 71 62 56 47 = R12 */ - "pand "M(2)", "r4"\n" /* r4 = __ 57 __ __ */ - "psllq $32, "r0"\n" /* r0 = 61 60 __ __ */ - "movq "r6", 72(%edx)\n" /* write R12 = r6 */ - "movq "r0", "r6"\n" /* r6 = 61 60 __ __ */ - "pand "M(3)", "r0"\n" /* r0 = 61 __ __ __ */ - "psllq $16, "r6"\n" /* r6 = 60 __ __ __ */ - "movq 40(%eax), "r5"\n" - "movq "r1", "r3"\n" /* r3 = 47 46 45 44 */ - "pmullw 40(%esi), "r5"\n" /* r5 = 27 26 25 24 */ - "psrlq $16, "r1"\n" /* r1 = __ 47 46 45 */ - "pand "M(1)", "r1"\n" /* r1 = __ __ 46 __ */ - "por "r4", "r0"\n" /* r0 = 61 57 __ __ */ - "pand "r7", "r2"\n" /* r2 = __ __ __ 40 */ - "por "r1", "r0"\n" /* r0 = 61 57 46 __ */ - "por "r2", "r0"\n" /* r0 = 61 57 46 40 = R11 */ - "psllq $16, "r3"\n" /* r3 = 46 45 44 __ */ - "movq "r3", "r4"\n" /* r4 = 46 45 44 __ */ - "movq "r5", "r2"\n" /* r2 = 27 26 25 24 */ - "movq "r0", 112(%edx)\n" /* write R11 = r0 */ - "psrlq $48, "r2"\n" /* r2 = __ __ __ 27 */ - "pand "M(2)", "r4"\n" /* r4 = __ 45 __ __ */ - "por "r2", "r6"\n" /* r6 = 60 __ __ 27 */ - "movq "M(1)", "r2"\n" /* r2 = __ __ FF __ */ - "por "r4", "r6"\n" /* r6 = 60 45 __ 27 */ - "pand "r7", "r2"\n" /* r2 = __ __ 41 __ */ - "psllq $32, "r3"\n" /* r3 = 44 __ __ __ */ - "por 80(%edx), "r3"\n" /* r3 = 44 __ __ 23 */ - "por "r2", "r6"\n" /* r6 = 60 45 41 27 = R10 */ - "movq "M(3)", "r2"\n" /* r2 = FF __ __ __ */ - "psllq $16, "r5"\n" /* r5 = 26 25 24 __ */ - "movq "r6", 96(%edx)\n" /* store R10 = r6 */ - "pand "r5", "r2"\n" /* r2 = 26 __ __ __ */ - "movq "M(2)", "r6"\n" /* r6 = __ FF __ __ */ - "pxor "r2", "r5"\n" /* r5 = __ 25 24 __ */ - "pand "r7", "r6"\n" /* r6 = __ 42 __ __ */ - "psrlq $32, "r2"\n" /* r2 = __ __ 26 __ */ - "pand "M(3)", "r7"\n" /* r7 = 43 __ __ __ */ - "por "r2", "r3"\n" /* r3 = 44 __ 26 23 */ - "por 64(%edx), "r7"\n" /* r7 = 43 __ __ 12 */ - "por "r3", "r6"\n" /* r6 = 44 42 26 23 = R9 */ - "por "r5", "r7"\n" /* r7 = 43 25 24 12 = R8 */ - "movq "r6", 80(%edx)\n" /* store R9 = r6 */ - "movq "r7", 64(%edx)\n" /* store R8 = r7 */ - ); - /* 123c ( / 64 coeffs < 2c / coeff) */ -# undef M - -/* Done w/dequant + descramble + partial transpose; now do the idct itself. */ - -# define I( K) MtoSTR(K*16(%edx)) -# define J( K) MtoSTR(((K - 4)*16)+8(%edx)) - - RowIDCT /* 46 c */ - Transpose /* 19 c */ - -# undef I -# undef J -# define I( K) MtoSTR((K*16)+64(%edx)) -# define J( K) MtoSTR(((K-4)*16)+72(%edx)) - - RowIDCT /* 46 c */ - Transpose /* 19 c */ - -# undef I -# undef J -# define I( K) MtoSTR((K * 16)(%edx)) -# define J( K) I( K) - - ColumnIDCT /* 57 c */ - -# undef I -# undef J -# define I( K) MtoSTR((K*16)+8(%edx)) -# define J( K) I( K) - - ColumnIDCT /* 57 c */ - -# undef I -# undef J - /* 368 cycles ( / 64 coeff < 6 c / coeff) */ - - ASM("emms\n"); -} - -/************************************************************************************** - * - * Routine: MMX_idct10 - * - * Description: Perform IDCT on a 8x8 block with at most 10 nonzero coefficients - * - * Input: Pointer to input and output buffer - * - * Output: None - * - * Return: None - * - * Special Note: The input coefficients are in transposed ZigZag order - * - * Error: None - * - *************************************************************************************** - */ -/* --------------------------------------------------------------- */ -// This macro does four 4-sample one-dimensional idcts in parallel. Inputs -// 4 thru 7 are assumed to be zero. -#define BeginIDCT_10 "#BeginIDCT_10\n" \ - " movq "I(3)","r2"\n" \ - \ - " movq "C(3)","r6"\n" \ - " movq "r2","r4"\n" \ - \ - " movq "C(5)","r1"\n" \ - " pmulhw "r6","r4"\n" \ - \ - " movq "I(1)","r3"\n" \ - " pmulhw "r2","r1"\n" \ - \ - " movq "C(1)","r0"\n" \ - " paddw "r2","r4"\n" \ - \ - " pxor "r6","r6"\n" \ - " paddw "r1","r2"\n" \ - \ - " movq "I(2)","r5"\n" \ - " pmulhw "r3","r0"\n" \ - \ - " movq "r5","r1"\n" \ - " paddw "r3","r0"\n" \ - \ - " pmulhw "C(7)","r3"\n" \ - " psubsw "r2","r6"\n" \ - \ - " pmulhw "C(2)","r5"\n" \ - " psubsw "r4","r0"\n" \ - \ - " movq "I(2)","r7"\n" \ - " paddsw "r4","r4"\n" \ - \ - " paddw "r5","r7"\n" \ - " paddsw "r0","r4"\n" \ - \ - " pmulhw "C(6)","r1"\n" \ - " psubsw "r6","r3"\n" \ - \ - " movq "r4","I(1)"\n" \ - " paddsw "r6","r6"\n" \ - \ - " movq "C(4)","r4"\n" \ - " paddsw "r3","r6"\n" \ - \ - " movq "r3","r5"\n" \ - " pmulhw "r4","r3"\n" \ - \ - " movq "r6","I(2)"\n" \ - " movq "r0","r2"\n" \ - \ - " movq "I(0)","r6"\n" \ - " pmulhw "r4","r0"\n" \ - \ - " paddw "r3","r5"\n" \ - " paddw "r0","r2"\n" \ - \ - " psubsw "r1","r5"\n" \ - " pmulhw "r4","r6"\n" \ - \ - " paddw "I(0)","r6"\n" \ - " paddsw "r1","r1"\n" \ - \ - " movq "r6","r4"\n" \ - " paddsw "r5","r1"\n" \ - \ - " psubsw "r2","r6"\n" \ - " paddsw "r2","r2"\n" \ - \ - " movq "I(1)","r0"\n" \ - " paddsw "r6","r2"\n" \ - \ - " psubsw "r1","r2"\n" \ - "#end BeginIDCT_10\n" -// end BeginIDCT_10 macro (25 cycles). - -#define RowIDCT_10 ASM("\n" \ - "#RowIDCT_10\n" \ - BeginIDCT_10 \ - "\n" \ - " movq "I(2)","r3"\n" /* r3 = D. */ \ - " psubsw "r7","r4"\n" /* r4 = E. = E - G */ \ - " paddsw "r1","r1"\n" /* r1 = H. + H. */ \ - " paddsw "r7","r7"\n" /* r7 = G + G */ \ - " paddsw "r2","r1"\n" /* r1 = R1 = A.. + H. */\ - " paddsw "r4","r7"\n" /* r7 = G. = E + G */ \ - " psubsw "r3","r4"\n" /* r4 = R4 = E. - D. */ \ - " paddsw "r3","r3"\n" \ - " psubsw "r5","r6"\n" /* r6 = R6 = F. - B.. */\ - " paddsw "r5","r5"\n" \ - " paddsw "r4","r3"\n" /* r3 = R3 = E. + D. */ \ - " paddsw "r6","r5"\n" /* r5 = R5 = F. + B.. */\ - " psubsw "r0","r7"\n" /* r7 = R7 = G. - C. */ \ - " paddsw "r0","r0"\n" \ - " movq "r1","I(1)"\n" /* save R1 */ \ - " paddsw "r7","r0"\n" /* r0 = R0 = G. + C. */ \ - "#end RowIDCT_10\n" \ -); -// end RowIDCT macro (8 + 38 = 46 cycles) - -// Column IDCT normalizes and stores final results. - -#define ColumnIDCT_10 ASM("\n" \ - "#ColumnIDCT_10\n" \ - BeginIDCT_10 \ - "\n" \ - " paddsw "Eight","r2"\n" \ - " paddsw "r1","r1"\n" /* r1 = H. + H. */ \ - " paddsw "r2","r1"\n" /* r1 = R1 = A.. + H. */\ - " psraw ""$4"","r2"\n" /* r2 = NR2 */ \ - " psubsw "r7","r4"\n" /* r4 = E. = E - G */ \ - " psraw ""$4"","r1"\n" /* r1 = NR1 */ \ - " movq "I(2)","r3"\n" /* r3 = D. */ \ - " paddsw "r7","r7"\n" /* r7 = G + G */ \ - " movq "r2","I(2)"\n" /* store NR2 at I2 */ \ - " paddsw "r4","r7"\n" /* r7 = G. = E + G */ \ - " movq "r1","I(1)"\n" /* store NR1 at I1 */ \ - " psubsw "r3","r4"\n" /* r4 = R4 = E. - D. */ \ - " paddsw "Eight","r4"\n" \ - " paddsw "r3","r3"\n" /* r3 = D. + D. */ \ - " paddsw "r4","r3"\n" /* r3 = R3 = E. + D. */ \ - " psraw ""$4"","r4"\n" /* r4 = NR4 */ \ - " psubsw "r5","r6"\n" /* r6 = R6 = F. - B.. */\ - " psraw ""$4"","r3"\n" /* r3 = NR3 */ \ - " paddsw "Eight","r6"\n" \ - " paddsw "r5","r5"\n" /* r5 = B.. + B.. */ \ - " paddsw "r6","r5"\n" /* r5 = R5 = F. + B.. */\ - " psraw ""$4"","r6"\n" /* r6 = NR6 */ \ - " movq "r4","J(4)"\n" /* store NR4 at J4 */ \ - " psraw ""$4"","r5"\n" /* r5 = NR5 */ \ - " movq "r3","I(3)"\n" /* store NR3 at I3 */ \ - " psubsw "r0","r7"\n" /* r7 = R7 = G. - C. */ \ - " paddsw "Eight","r7"\n" \ - " paddsw "r0","r0"\n" /* r0 = C. + C. */ \ - " paddsw "r7","r0"\n" /* r0 = R0 = G. + C. */ \ - " psraw ""$4"","r7"\n" /* r7 = NR7 */ \ - " movq "r6","J(6)"\n" /* store NR6 at J6 */ \ - " psraw ""$4"","r0"\n" /* r0 = NR0 */ \ - " movq "r5","J(5)"\n" /* store NR5 at J5 */ \ - \ - " movq "r7","J(7)"\n" /* store NR7 at J7 */ \ - \ - " movq "r0","I(0)"\n" /* store NR0 at I0 */ \ - "#end ColumnIDCT_10\n" \ -); -// end ColumnIDCT macro (38 + 19 = 57 cycles) -/* --------------------------------------------------------------- */ - - -/* --------------------------------------------------------------- */ -/* IDCT 10 */ -void IDct10__mmx( Q_LIST_ENTRY * InputData, - ogg_int16_t *QuantMatrix, - ogg_int16_t * OutputData ) { - -# define MIDM(M,I) MtoSTR(M+I*8(%ecx)) -# define M(I) MIDM( MaskOffset , I ) -# define MIDC(M,I) MtoSTR(M+(I-1)*8(%ecx)) -# define C(I) MIDC( CosineOffset , I ) -# define MIDEight(M) MtoSTR(M(%ecx)) -# define Eight MIDEight(EightOffset) - -# define r0 "%mm0" -# define r1 "%mm1" -# define r2 "%mm2" -# define r3 "%mm3" -# define r4 "%mm4" -# define r5 "%mm5" -# define r6 "%mm6" -# define r7 "%mm7" - - __asm__ __volatile__ ( - /* eax = quantized input */ - /* esi = quantization table */ - /* edx = destination (= idct buffer) */ - /* ecx = idctconstants */ - "" - : - :"a"(InputData), "S"(QuantMatrix), "d"(OutputData), "c"(idctconstants) - ); - - ASM( - "movq (%eax), "r0"\n" - "pmullw (%esi), "r0"\n" /* r0 = 03 02 01 00 */ - "movq 16(%eax), "r1"\n" - "pmullw 16(%esi), "r1"\n" /* r1 = 13 12 11 10 */ - "movq "M(0)", "r2"\n" /* r2 = __ __ __ FF */ - "movq "r0", "r3"\n" /* r3 = 03 02 01 00 */ - "movq 8(%eax), "r4"\n" - "psrlq $16, "r0"\n" /* r0 = __ 03 02 01 */ - "pmullw 8(%esi), "r4"\n" /* r4 = 07 06 05 04 */ - "pand "r2", "r3"\n" /* r3 = __ __ __ 00 */ - "movq "r0", "r5"\n" /* r5 = __ 03 02 01 */ - "pand "r2", "r5"\n" /* r5 = __ __ __ 01 */ - "psllq $32, "r1"\n" /* r1 = 11 10 __ __ */ - "movq "M(3)", "r7"\n" /* r7 = FF __ __ __ */ - "pxor "r5", "r0"\n" /* r0 = __ 03 02 __ */ - "pand "r1", "r7"\n" /* r7 = 11 __ __ __ */ - "por "r3", "r0"\n" /* r0 = __ 03 02 00 */ - "pxor "r7", "r1"\n" /* r1 = __ 10 __ __ */ - "por "r7", "r0"\n" /* r0 = 11 03 02 00 = R0 */ - "movq "r4", "r3"\n" /* r3 = 07 06 05 04 */ - "movq "r0", (%edx)\n" /* write R0 = r0 */ - "pand "r2", "r3"\n" /* r3 = __ __ __ 04 */ - "psllq $16, "r3"\n" /* r3 = __ __ 04 __ */ - "por "r3", "r5"\n" /* r5 = __ __ 04 01 */ - "por "r5", "r1"\n" /* r1 = __ 10 04 01 = R1 */ - "psrlq $16, "r4"\n" /* r4 = __ 07 06 05 */ - "movq "r1", 16(%edx)\n" /* write R1 = r1 */ - "movq "r4", "r5"\n" /* r5 = __ 07 06 05 */ - "psrlq $16, "r4"\n" /* r4 = __ __ 07 06 */ - "movq "r2", "r6"\n" /* r6 = __ __ __ FF */ - "pand "r2", "r5"\n" /* r5 = __ __ __ 05 */ - "pand "r4", "r6"\n" /* r6 = __ __ __ 06 */ - "pxor "r6", "r4"\n" /* r4 = __ __ 07 __ */ - "por "r5", "r4"\n" /* r4 = __ __ 07 05 */ - "movq "r4", 32(%edx)\n" /* write R2 = r4 */ - "movq "r6", 48(%edx)\n" /* write R3 = r6 */ - ); -# undef M - -/* Done w/dequant + descramble + partial transpose; now do the idct itself. */ - -# define I( K) MtoSTR((K*16)(%edx)) -# define J( K) MtoSTR(((K - 4) * 16)+8(%edx)) - - RowIDCT_10 /* 33 c */ - Transpose /* 19 c */ - -# undef I -# undef J -//# define I( K) [edx + ( K * 16) + 64] -//# define J( K) [edx + ( (K - 4) * 16) + 72] - -// RowIDCT ; 46 c -// Transpose ; 19 c - -//# undef I -//# undef J -# define I( K) MtoSTR((K * 16)(%edx)) -# define J( K) I( K) - - ColumnIDCT_10 /* 44 c */ - -# undef I -# undef J -# define I( K) MtoSTR((K * 16)+8(%edx)) -# define J( K) I( K) - - ColumnIDCT_10 /* 44 c */ - -# undef I -# undef J - - ASM("emms\n"); -} - -/************************************************************************************** - * - * Routine: MMX_idct3 - * - * Description: Perform IDCT on a 8x8 block with at most 3 nonzero coefficients - * - * Input: Pointer to input and output buffer - * - * Output: None - * - * Return: None - * - * Special Note: Only works for three nonzero coefficients. - * - * Error: None - * - *************************************************************************************** - */ -/*************************************************************************************** - In IDCT 3, we are dealing with only three Non-Zero coefficients in the 8x8 block. - In the case that we work in the fashion RowIDCT -> ColumnIDCT, we only have to - do 1-D row idcts on the first two rows, the rest six rows remain zero anyway. - After row IDCTs, since every column could have nonzero coefficients, we need do - eight 1-D column IDCT. However, for each column, there are at most two nonzero - coefficients, coefficient 0 and coefficient 1. Same for the coefficents for the - two 1-d row idcts. For this reason, the process of a 1-D IDCT is simplified - - from a full version: - - A = (C1 * I1) + (C7 * I7) B = (C7 * I1) - (C1 * I7) - C = (C3 * I3) + (C5 * I5) D = (C3 * I5) - (C5 * I3) - A. = C4 * (A - C) B. = C4 * (B - D) - C. = A + C D. = B + D - - E = C4 * (I0 + I4) F = C4 * (I0 - I4) - G = (C2 * I2) + (C6 * I6) H = (C6 * I2) - (C2 * I6) - E. = E - G - G. = E + G - - A.. = F + A. B.. = B. - H - F. = F - A. H. = B. + H - - R0 = G. + C. R1 = A.. + H. R3 = E. + D. R5 = F. + B.. - R7 = G. - C. R2 = A.. - H. R4 = E. - D. R6 = F. - B.. - - To: - - - A = (C1 * I1) B = (C7 * I1) - C = 0 D = 0 - A. = C4 * A B. = C4 * B - C. = A D. = B - - E = C4 * I0 F = E - G = 0 H = 0 - E. = E - G. = E - - A.. = E + A. B.. = B. - F. = E - A. H. = B. - - R0 = E + A R1 = E + A. + B. R3 = E + B R5 = E - A. + B. - R7 = E - A R2 = E + A. - B. R4 = E - B R6 = F - A. - B. - -******************************************************************************************/ - -#define RowIDCT_3 ASM("\n"\ - "#RowIDCT_3\n"\ - " movq "I(1)","r7"\n" /* r7 = I1 */ \ - " movq "C(1)","r0"\n" /* r0 = C1 */ \ - " movq "C(7)","r3"\n" /* r3 = C7 */ \ - " pmulhw "r7","r0"\n" /* r0 = C1 * I1 - I1 */ \ - " pmulhw "r7","r3"\n" /* r3 = C7 * I1 = B, D. */ \ - " movq "I(0)","r6"\n" /* r6 = I0 */ \ - " movq "C(4)","r4"\n" /* r4 = C4 */ \ - " paddw "r7","r0"\n" /* r0 = C1 * I1 = A, C. */ \ - " movq "r6","r1"\n" /* make a copy of I0 */ \ - " pmulhw "r4","r6"\n" /* r2 = C4 * I0 - I0 */ \ - " movq "r0","r2"\n" /* make a copy of A */ \ - " movq "r3","r5"\n" /* make a copy of B */ \ - " pmulhw "r4","r2"\n" /* r2 = C4 * A - A */ \ - " pmulhw "r4","r5"\n" /* r5 = C4 * B - B */ \ - " paddw "r1","r6"\n" /* r2 = C4 * I0 = E, F */ \ - " movq "r6","r4"\n" /* r4 = E */ \ - " paddw "r0","r2"\n" /* r2 = A. */ \ - " paddw "r3","r5"\n" /* r5 = B. */ \ - " movq "r6","r7"\n" /* r7 = E */ \ - " movq "r5","r1"\n" /* r1 = B. */ \ - /* r0 = A */ \ - /* r3 = B */ \ - /* r2 = A. */ \ - /* r5 = B. */ \ - /* r6 = E */ \ - /* r4 = E */ \ - /* r7 = E */ \ - /* r1 = B. */ \ - " psubw "r2","r6"\n" /* r6 = E - A. */ \ - " psubw "r3","r4"\n" /* r4 = E - B ----R4 */ \ - " psubw "r0","r7"\n" /* r7 = E - A ----R7 */ \ - " paddw "r2","r2"\n" /* r2 = A. + A. */ \ - " paddw "r3","r3"\n" /* r3 = B + B */ \ - " paddw "r0","r0"\n" /* r0 = A + A */ \ - " paddw "r6","r2"\n" /* r2 = E + A. */ \ - " paddw "r4","r3"\n" /* r3 = E + B ----R3 */ \ - " psubw "r1","r2"\n" /* r2 = E + A. - B. ----R2 */ \ - " psubw "r5","r6"\n" /* r6 = E - A. - B. ----R6 */ \ - " paddw "r1","r1"\n" /* r1 = B. + B. */ \ - " paddw "r5","r5"\n" /* r5 = B. + B. */ \ - " paddw "r7","r0"\n" /* r0 = E + A ----R0 */ \ - " paddw "r2","r1"\n" /* r1 = E + A. + B. -----R1 */ \ - " movq "r1","I(1)"\n" /* save r1 */ \ - " paddw "r6","r5"\n" /* r5 = E - A. + B. -----R5 */ \ - "#end RowIDCT_3\n"\ -); -//End of RowIDCT_3 - -#define ColumnIDCT_3 ASM("\n"\ - "#ColumnIDCT_3\n"\ - " movq "I(1)","r7"\n" /* r7 = I1 */ \ - " movq "C(1)","r0"\n" /* r0 = C1 */ \ - " movq "C(7)","r3"\n" /* r3 = C7 */ \ - " pmulhw "r7","r0"\n" /* r0 = C1 * I1 - I1 */ \ - " pmulhw "r7","r3"\n" /* r3 = C7 * I1 = B, D. */ \ - " movq "I(0)","r6"\n" /* r6 = I0 */ \ - " movq "C(4)","r4"\n" /* r4 = C4 */ \ - " paddw "r7","r0"\n" /* r0 = C1 * I1 = A, C. */ \ - " movq "r6","r1"\n" /* make a copy of I0 */ \ - " pmulhw "r4","r6"\n" /* r2 = C4 * I0 - I0 */ \ - " movq "r0","r2"\n" /* make a copy of A */ \ - " movq "r3","r5"\n" /* make a copy of B */ \ - " pmulhw "r4","r2"\n" /* r2 = C4 * A - A */ \ - " pmulhw "r4","r5"\n" /* r5 = C4 * B - B */ \ - " paddw "r1","r6"\n" /* r2 = C4 * I0 = E, F */ \ - " movq "r6","r4"\n" /* r4 = E */ \ - " paddw "Eight","r6"\n" /* +8 for shift */ \ - " paddw "Eight","r4"\n" /* +8 for shift */ \ - " paddw "r0","r2"\n" /* r2 = A. */ \ - " paddw "r3","r5"\n" /* r5 = B. */ \ - " movq "r6","r7"\n" /* r7 = E */ \ - " movq "r5","r1"\n" /* r1 = B. */ \ -/* r0 = A */ \ -/* r3 = B */ \ -/* r2 = A. */ \ -/* r5 = B. */ \ -/* r6 = E */ \ -/* r4 = E */ \ -/* r7 = E */ \ -/* r1 = B. */ \ - " psubw "r2","r6"\n" /* r6 = E - A. */ \ - " psubw "r3","r4"\n" /* r4 = E - B ----R4 */ \ - " psubw "r0","r7"\n" /* r7 = E - A ----R7 */ \ - " paddw "r2","r2"\n" /* r2 = A. + A. */ \ - " paddw "r3","r3"\n" /* r3 = B + B */ \ - " paddw "r0","r0"\n" /* r0 = A + A */ \ - " paddw "r6","r2"\n" /* r2 = E + A. */ \ - " paddw "r4","r3"\n" /* r3 = E + B ----R3 */ \ - " psraw $4,"r4"\n" /* shift */ \ - " movq "r4","J(4)"\n" /* store R4 at J4 */ \ - " psraw $4,"r3"\n" /* shift */ \ - " movq "r3","I(3)"\n" /* store R3 at I3 */ \ - " psubw "r1","r2"\n" /* r2 = E + A. - B. ----R2 */ \ - " psubw "r5","r6"\n" /* r6 = E - A. - B. ----R6 */ \ - " paddw "r1","r1"\n" /* r1 = B. + B. */ \ - " paddw "r5","r5"\n" /* r5 = B. + B. */ \ - " paddw "r7","r0"\n" /* r0 = E + A ----R0 */ \ - " paddw "r2","r1"\n" /* r1 = E + A. + B. -----R1 */ \ - " psraw $4,"r7"\n" /* shift */ \ - " psraw $4,"r2"\n" /* shift */ \ - " psraw $4,"r0"\n" /* shift */ \ - " psraw $4,"r1"\n" /* shift */ \ - " movq "r7","J(7)"\n" /* store R7 to J7 */ \ - " movq "r0","I(0)"\n" /* store R0 to I0 */ \ - " movq "r1","I(1)"\n" /* store R1 to I1 */ \ - " movq "r2","I(2)"\n" /* store R2 to I2 */ \ - " movq "r1","I(1)"\n" /* save r1 */ \ - " paddw "r6","r5"\n" /* r5 = E - A. + B. -----R5 */ \ - " psraw $4,"r5"\n" /* shift */ \ - " movq "r5","J(5)"\n" /* store R5 at J5 */ \ - " psraw $4,"r6"\n" /* shift */ \ - " movq "r6","J(6)"\n" /* store R6 at J6 */ \ - "#end ColumnIDCT_3\n"\ -); -//End of ColumnIDCT_3 - -void IDct3__mmx( Q_LIST_ENTRY * InputData, - ogg_int16_t *QuantMatrix, - ogg_int16_t * OutputData ) { - -# define MIDM(M,I) MtoSTR(M+I*8(%ecx)) -# define M(I) MIDM( MaskOffset , I ) -# define MIDC(M,I) MtoSTR(M+(I-1)*8(%ecx)) -# define C(I) MIDC( CosineOffset , I ) -# define MIDEight(M) MtoSTR(M(%ecx)) -# define Eight MIDEight(EightOffset) - -# define r0 "%mm0" -# define r1 "%mm1" -# define r2 "%mm2" -# define r3 "%mm3" -# define r4 "%mm4" -# define r5 "%mm5" -# define r6 "%mm6" -# define r7 "%mm7" - - __asm__ __volatile__ ( - /* eax = quantized input */ - /* esi = quantization table */ - /* edx = destination (= idct buffer) */ - /* ecx = idctconstants */ - "" - : - :"a"(InputData), "S"(QuantMatrix), "d"(OutputData), "c"(idctconstants) - ); - - ASM( - "movq (%eax), "r0"\n" - "pmullw (%esi), "r0"\n" /* r0 = 03 02 01 00 */ - "movq "M(0)", "r2"\n" /* r2 = __ __ __ FF */ - "movq "r0", "r3"\n" /* r3 = 03 02 01 00 */ - "psrlq $16, "r0"\n" /* r0 = __ 03 02 01 */ - "pand "r2", "r3"\n" /* r3 = __ __ __ 00 */ - "movq "r0", "r5"\n" /* r5 = __ 03 02 01 */ - "pand "r2", "r5"\n" /* r5 = __ __ __ 01 */ - "pxor "r5", "r0"\n" /* r0 = __ 03 02 __ */ - "por "r3", "r0"\n" /* r0 = __ 03 02 00 */ - "movq "r0", (%edx)\n" /* write R0 = r0 */ - "movq "r5", 16(%edx)\n" /* write R1 = r5 */ - ); -# undef M - -/* Done partial transpose; now do the idct itself. */ - -# define I( K) MtoSTR(K*16(%edx)) -# define J( K) MtoSTR(((K - 4)*16)+8(%edx)) - - RowIDCT_3 /* 33 c */ - Transpose /* 19 c */ - -# undef I -# undef J -//# define I( K) [edx + ( K * 16) + 64] -//# define J( K) [edx + ( (K - 4) * 16) + 72] - -// RowIDCT ; 46 c -// Transpose ; 19 c - -//# undef I -//# undef J -# define I( K) MtoSTR((K * 16)(%edx)) -# define J( K) I( K) - - ColumnIDCT_3 /* 44 c */ - -# undef I -# undef J -# define I( K) MtoSTR((K*16)+8(%edx)) -# define J( K) I( K) - - ColumnIDCT_3 /* 44 c */ - -# undef I -# undef J - - ASM("emms\n"); -} - - -/* install our implementation in the function table */ -void dsp_mmx_idct_init(DspFunctions *funcs) -{ - funcs->IDctSlow = IDctSlow__mmx; - funcs->IDct10 = IDct10__mmx; - funcs->IDct3 = IDct3__mmx; -} - -#endif /* USE_ASM */ diff --git a/Engine/lib/libtheora/lib/enc/x86_32/recon_mmx.c b/Engine/lib/libtheora/lib/enc/x86_32/recon_mmx.c deleted file mode 100644 index 7a931afe4..000000000 --- a/Engine/lib/libtheora/lib/enc/x86_32/recon_mmx.c +++ /dev/null @@ -1,182 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: recon_mmx.c 15153 2008-08-04 18:37:55Z tterribe $ - - ********************************************************************/ - -#include "../codec_internal.h" - -#if defined(USE_ASM) - -static const __attribute__ ((aligned(8),used)) ogg_int64_t V128 = 0x8080808080808080LL; - -static void copy8x8__mmx (unsigned char *src, - unsigned char *dest, - unsigned int stride) -{ - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " lea (%2, %2, 2), %%edi \n\t" - - " movq (%1), %%mm0 \n\t" - " movq (%1, %2), %%mm1 \n\t" - " movq (%1, %2, 2), %%mm2 \n\t" - " movq (%1, %%edi), %%mm3 \n\t" - - " lea (%1, %2, 4), %1 \n\t" - - " movq %%mm0, (%0) \n\t" - " movq %%mm1, (%0, %2) \n\t" - " movq %%mm2, (%0, %2, 2) \n\t" - " movq %%mm3, (%0, %%edi) \n\t" - - " lea (%0, %2, 4), %0 \n\t" - - " movq (%1), %%mm0 \n\t" - " movq (%1, %2), %%mm1 \n\t" - " movq (%1, %2, 2), %%mm2 \n\t" - " movq (%1, %%edi), %%mm3 \n\t" - - " movq %%mm0, (%0) \n\t" - " movq %%mm1, (%0, %2) \n\t" - " movq %%mm2, (%0, %2, 2) \n\t" - " movq %%mm3, (%0, %%edi) \n\t" - : "+a" (dest) - : "c" (src), - "d" (stride) - : "memory", "edi" - ); -} - -static void recon_intra8x8__mmx (unsigned char *ReconPtr, ogg_int16_t *ChangePtr, - ogg_uint32_t LineStep) -{ - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " movq %[V128], %%mm0 \n\t" /* Set mm0 to 0x8080808080808080 */ - - " lea 128(%1), %%edi \n\t" /* Endpoint in input buffer */ - "1: \n\t" - " movq (%1), %%mm2 \n\t" /* First four input values */ - - " packsswb 8(%1), %%mm2 \n\t" /* pack with next(high) four values */ - " por %%mm0, %%mm0 \n\t" - " pxor %%mm0, %%mm2 \n\t" /* Convert result to unsigned (same as add 128) */ - " lea 16(%1), %1 \n\t" /* Step source buffer */ - " cmp %%edi, %1 \n\t" /* are we done */ - - " movq %%mm2, (%0) \n\t" /* store results */ - - " lea (%0, %2), %0 \n\t" /* Step output buffer */ - " jc 1b \n\t" /* Loop back if we are not done */ - : "+r" (ReconPtr) - : "r" (ChangePtr), - "r" (LineStep), - [V128] "m" (V128) - : "memory", "edi" - ); -} - -static void recon_inter8x8__mmx (unsigned char *ReconPtr, unsigned char *RefPtr, - ogg_int16_t *ChangePtr, ogg_uint32_t LineStep) -{ - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " pxor %%mm0, %%mm0 \n\t" - " lea 128(%1), %%edi \n\t" - - "1: \n\t" - " movq (%2), %%mm2 \n\t" /* (+3 misaligned) 8 reference pixels */ - - " movq (%1), %%mm4 \n\t" /* first 4 changes */ - " movq %%mm2, %%mm3 \n\t" - " movq 8(%1), %%mm5 \n\t" /* last 4 changes */ - " punpcklbw %%mm0, %%mm2 \n\t" /* turn first 4 refs into positive 16-bit #s */ - " paddsw %%mm4, %%mm2 \n\t" /* add in first 4 changes */ - " punpckhbw %%mm0, %%mm3 \n\t" /* turn last 4 refs into positive 16-bit #s */ - " paddsw %%mm5, %%mm3 \n\t" /* add in last 4 changes */ - " add %3, %2 \n\t" /* next row of reference pixels */ - " packuswb %%mm3, %%mm2 \n\t" /* pack result to unsigned 8-bit values */ - " lea 16(%1), %1 \n\t" /* next row of changes */ - " cmp %%edi, %1 \n\t" /* are we done? */ - - " movq %%mm2, (%0) \n\t" /* store result */ - - " lea (%0, %3), %0 \n\t" /* next row of output */ - " jc 1b \n\t" - : "+r" (ReconPtr) - : "r" (ChangePtr), - "r" (RefPtr), - "r" (LineStep) - : "memory", "edi" - ); -} - -static void recon_inter8x8_half__mmx (unsigned char *ReconPtr, unsigned char *RefPtr1, - unsigned char *RefPtr2, ogg_int16_t *ChangePtr, - ogg_uint32_t LineStep) -{ - __asm__ __volatile__ ( - " .p2align 4 \n\t" - - " pxor %%mm0, %%mm0 \n\t" - " lea 128(%1), %%edi \n\t" - - "1: \n\t" - " movq (%2), %%mm2 \n\t" /* (+3 misaligned) 8 reference pixels */ - " movq (%3), %%mm4 \n\t" /* (+3 misaligned) 8 reference pixels */ - - " movq %%mm2, %%mm3 \n\t" - " punpcklbw %%mm0, %%mm2 \n\t" /* mm2 = start ref1 as positive 16-bit #s */ - " movq %%mm4, %%mm5 \n\t" - " movq (%1), %%mm6 \n\t" /* first 4 changes */ - " punpckhbw %%mm0, %%mm3 \n\t" /* mm3 = end ref1 as positive 16-bit #s */ - " movq 8(%1), %%mm7 \n\t" /* last 4 changes */ - " punpcklbw %%mm0, %%mm4 \n\t" /* mm4 = start ref2 as positive 16-bit #s */ - " punpckhbw %%mm0, %%mm5 \n\t" /* mm5 = end ref2 as positive 16-bit #s */ - " paddw %%mm4, %%mm2 \n\t" /* mm2 = start (ref1 + ref2) */ - " paddw %%mm5, %%mm3 \n\t" /* mm3 = end (ref1 + ref2) */ - " psrlw $1, %%mm2 \n\t" /* mm2 = start (ref1 + ref2)/2 */ - " psrlw $1, %%mm3 \n\t" /* mm3 = end (ref1 + ref2)/2 */ - " paddw %%mm6, %%mm2 \n\t" /* add changes to start */ - " paddw %%mm7, %%mm3 \n\t" /* add changes to end */ - " lea 16(%1), %1 \n\t" /* next row of changes */ - " packuswb %%mm3, %%mm2 \n\t" /* pack start|end to unsigned 8-bit */ - " add %4, %2 \n\t" /* next row of reference pixels */ - " add %4, %3 \n\t" /* next row of reference pixels */ - " movq %%mm2, (%0) \n\t" /* store result */ - " add %4, %0 \n\t" /* next row of output */ - " cmp %%edi, %1 \n\t" /* are we done? */ - " jc 1b \n\t" - : "+r" (ReconPtr) - : "r" (ChangePtr), - "r" (RefPtr1), - "r" (RefPtr2), - "m" (LineStep) - : "memory", "edi" - ); -} - -void dsp_mmx_recon_init(DspFunctions *funcs) -{ - funcs->copy8x8 = copy8x8__mmx; - funcs->recon_intra8x8 = recon_intra8x8__mmx; - funcs->recon_inter8x8 = recon_inter8x8__mmx; - funcs->recon_inter8x8_half = recon_inter8x8_half__mmx; -} - -#endif /* USE_ASM */ diff --git a/Engine/lib/libtheora/lib/enc/x86_32_vs/dsp_mmx.c b/Engine/lib/libtheora/lib/enc/x86_32_vs/dsp_mmx.c deleted file mode 100644 index cecc0eb76..000000000 --- a/Engine/lib/libtheora/lib/enc/x86_32_vs/dsp_mmx.c +++ /dev/null @@ -1,1605 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: mcomp.c,v 1.8 2003/12/03 08:59:41 arc Exp $ - - ********************************************************************/ - -#include - -#include "../codec_internal.h" -#include "../dsp.h" - -#if 0 -//These are to let me selectively enable the C versions, these are needed -#define DSP_OP_AVG(a,b) ((((int)(a)) + ((int)(b)))/2) -#define DSP_OP_DIFF(a,b) (((int)(a)) - ((int)(b))) -#define DSP_OP_ABS_DIFF(a,b) abs((((int)(a)) - ((int)(b)))) -#endif - - -static const ogg_int64_t V128 = 0x0080008000800080; - -static void sub8x8__mmx (unsigned char *FiltPtr, unsigned char *ReconPtr, - ogg_int16_t *DctInputPtr, ogg_uint32_t PixelsPerLine, - ogg_uint32_t ReconPixelsPerLine) -{ - - //Make non-zero to use the C-version -#if 0 - int i; - - /* For each block row */ - for (i=8; i; i--) { - DctInputPtr[0] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[0], ReconPtr[0]); - DctInputPtr[1] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[1], ReconPtr[1]); - DctInputPtr[2] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[2], ReconPtr[2]); - DctInputPtr[3] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[3], ReconPtr[3]); - DctInputPtr[4] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[4], ReconPtr[4]); - DctInputPtr[5] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[5], ReconPtr[5]); - DctInputPtr[6] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[6], ReconPtr[6]); - DctInputPtr[7] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[7], ReconPtr[7]); - - /* Start next row */ - FiltPtr += PixelsPerLine; - ReconPtr += ReconPixelsPerLine; - DctInputPtr += 8; - } -#else - __asm { - align 16 - - pxor mm7, mm7 - - mov eax, FiltPtr - mov ebx, ReconPtr - mov edx, DctInputPtr - - /* You can't use rept in inline masm and macro parsing seems screwed with inline asm*/ - - /* ITERATION 1 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm1, [ebx] /* mm1 = ReconPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - movq mm3, mm1 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 /* mm1 = INT16(ReconPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 /* mm3 = INT16(ReconPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - ReconPtr */ - psubw mm2, mm3 /* mm2 = FiltPtr - ReconPtr */ - movq [edx], mm0 /* write answer out */ - movq [8 + edx], mm2 /* write answer out */ - /* Increment pointers */ - add edx, 16 - add eax, PixelsPerLine - add ebx, ReconPixelsPerLine - - - /* ITERATION 2 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm1, [ebx] /* mm1 = ReconPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - movq mm3, mm1 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 /* mm1 = INT16(ReconPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 /* mm3 = INT16(ReconPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - ReconPtr */ - psubw mm2, mm3 /* mm2 = FiltPtr - ReconPtr */ - movq [edx], mm0 /* write answer out */ - movq [8 + edx], mm2 /* write answer out */ - /* Increment pointers */ - add edx, 16 - add eax, PixelsPerLine - add ebx, ReconPixelsPerLine - - - /* ITERATION 3 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm1, [ebx] /* mm1 = ReconPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - movq mm3, mm1 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 /* mm1 = INT16(ReconPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 /* mm3 = INT16(ReconPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - ReconPtr */ - psubw mm2, mm3 /* mm2 = FiltPtr - ReconPtr */ - movq [edx], mm0 /* write answer out */ - movq [8 + edx], mm2 /* write answer out */ - /* Increment pointers */ - add edx, 16 - add eax, PixelsPerLine - add ebx, ReconPixelsPerLine - - - /* ITERATION 4 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm1, [ebx] /* mm1 = ReconPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - movq mm3, mm1 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 /* mm1 = INT16(ReconPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 /* mm3 = INT16(ReconPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - ReconPtr */ - psubw mm2, mm3 /* mm2 = FiltPtr - ReconPtr */ - movq [edx], mm0 /* write answer out */ - movq [8 + edx], mm2 /* write answer out */ - /* Increment pointers */ - add edx, 16 - add eax, PixelsPerLine - add ebx, ReconPixelsPerLine - - - /* ITERATION 5 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm1, [ebx] /* mm1 = ReconPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - movq mm3, mm1 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 /* mm1 = INT16(ReconPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 /* mm3 = INT16(ReconPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - ReconPtr */ - psubw mm2, mm3 /* mm2 = FiltPtr - ReconPtr */ - movq [edx], mm0 /* write answer out */ - movq [8 + edx], mm2 /* write answer out */ - /* Increment pointers */ - add edx, 16 - add eax, PixelsPerLine - add ebx, ReconPixelsPerLine - - - /* ITERATION 6 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm1, [ebx] /* mm1 = ReconPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - movq mm3, mm1 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 /* mm1 = INT16(ReconPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 /* mm3 = INT16(ReconPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - ReconPtr */ - psubw mm2, mm3 /* mm2 = FiltPtr - ReconPtr */ - movq [edx], mm0 /* write answer out */ - movq [8 + edx], mm2 /* write answer out */ - /* Increment pointers */ - add edx, 16 - add eax, PixelsPerLine - add ebx, ReconPixelsPerLine - - - /* ITERATION 7 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm1, [ebx] /* mm1 = ReconPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - movq mm3, mm1 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 /* mm1 = INT16(ReconPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 /* mm3 = INT16(ReconPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - ReconPtr */ - psubw mm2, mm3 /* mm2 = FiltPtr - ReconPtr */ - movq [edx], mm0 /* write answer out */ - movq [8 + edx], mm2 /* write answer out */ - /* Increment pointers */ - add edx, 16 - add eax, PixelsPerLine - add ebx, ReconPixelsPerLine - - - /* ITERATION 8 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm1, [ebx] /* mm1 = ReconPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - movq mm3, mm1 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 /* mm1 = INT16(ReconPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 /* mm3 = INT16(ReconPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - ReconPtr */ - psubw mm2, mm3 /* mm2 = FiltPtr - ReconPtr */ - movq [edx], mm0 /* write answer out */ - movq [8 + edx], mm2 /* write answer out */ - /* Increment pointers */ - add edx, 16 - add eax, PixelsPerLine - add ebx, ReconPixelsPerLine - - - - - - }; - -#endif -} - -static void sub8x8_128__mmx (unsigned char *FiltPtr, ogg_int16_t *DctInputPtr, - ogg_uint32_t PixelsPerLine) -{ - -#if 0 - int i; - /* For each block row */ - for (i=8; i; i--) { - /* INTRA mode so code raw image data */ - /* We convert the data to 8 bit signed (by subtracting 128) as - this reduces the internal precision requirments in the DCT - transform. */ - DctInputPtr[0] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[0], 128); - DctInputPtr[1] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[1], 128); - DctInputPtr[2] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[2], 128); - DctInputPtr[3] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[3], 128); - DctInputPtr[4] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[4], 128); - DctInputPtr[5] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[5], 128); - DctInputPtr[6] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[6], 128); - DctInputPtr[7] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[7], 128); - - /* Start next row */ - FiltPtr += PixelsPerLine; - DctInputPtr += 8; - } - -#else - __asm { - align 16 - - pxor mm7, mm7 - - mov eax, FiltPtr - mov ebx, DctInputPtr - - movq mm1, V128 - - /* ITERATION 1 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - 128 */ - psubw mm2, mm1 /* mm2 = FiltPtr - 128 */ - movq [ebx], mm0 /* write answer out */ - movq [8 + ebx], mm2 /* write answer out */ - /* Increment pointers */ - add ebx, 16 - add eax, PixelsPerLine - - - /* ITERATION 2 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - 128 */ - psubw mm2, mm1 /* mm2 = FiltPtr - 128 */ - movq [ebx], mm0 /* write answer out */ - movq [8 + ebx], mm2 /* write answer out */ - /* Increment pointers */ - add ebx, 16 - add eax, PixelsPerLine - - - /* ITERATION 3 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - 128 */ - psubw mm2, mm1 /* mm2 = FiltPtr - 128 */ - movq [ebx], mm0 /* write answer out */ - movq [8 + ebx], mm2 /* write answer out */ - /* Increment pointers */ - add ebx, 16 - add eax, PixelsPerLine - - - /* ITERATION 4 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - 128 */ - psubw mm2, mm1 /* mm2 = FiltPtr - 128 */ - movq [ebx], mm0 /* write answer out */ - movq [8 + ebx], mm2 /* write answer out */ - /* Increment pointers */ - add ebx, 16 - add eax, PixelsPerLine - - - /* ITERATION 5 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - 128 */ - psubw mm2, mm1 /* mm2 = FiltPtr - 128 */ - movq [ebx], mm0 /* write answer out */ - movq [8 + ebx], mm2 /* write answer out */ - /* Increment pointers */ - add ebx, 16 - add eax, PixelsPerLine - - - /* ITERATION 6 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - 128 */ - psubw mm2, mm1 /* mm2 = FiltPtr - 128 */ - movq [ebx], mm0 /* write answer out */ - movq [8 + ebx], mm2 /* write answer out */ - /* Increment pointers */ - add ebx, 16 - add eax, PixelsPerLine - - - /* ITERATION 7 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - 128 */ - psubw mm2, mm1 /* mm2 = FiltPtr - 128 */ - movq [ebx], mm0 /* write answer out */ - movq [8 + ebx], mm2 /* write answer out */ - /* Increment pointers */ - add ebx, 16 - add eax, PixelsPerLine - - - /* ITERATION 8 */ - movq mm0, [eax] /* mm0 = FiltPtr */ - movq mm2, mm0 /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 /* mm0 = INT16(FiltPtr) */ - punpckhbw mm2, mm7 /* mm2 = INT16(FiltPtr) */ - /* start calculation */ - psubw mm0, mm1 /* mm0 = FiltPtr - 128 */ - psubw mm2, mm1 /* mm2 = FiltPtr - 128 */ - movq [ebx], mm0 /* write answer out */ - movq [8 + ebx], mm2 /* write answer out */ - /* Increment pointers */ - add ebx, 16 - add eax, PixelsPerLine - - }; - -#endif -} - - - - -static void sub8x8avg2__mmx (unsigned char *FiltPtr, unsigned char *ReconPtr1, - unsigned char *ReconPtr2, ogg_int16_t *DctInputPtr, - ogg_uint32_t PixelsPerLine, - ogg_uint32_t ReconPixelsPerLine) -{ - -#if 0 - int i; - - /* For each block row */ - for (i=8; i; i--) { - DctInputPtr[0] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[0], DSP_OP_AVG (ReconPtr1[0], ReconPtr2[0])); - DctInputPtr[1] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[1], DSP_OP_AVG (ReconPtr1[1], ReconPtr2[1])); - DctInputPtr[2] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[2], DSP_OP_AVG (ReconPtr1[2], ReconPtr2[2])); - DctInputPtr[3] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[3], DSP_OP_AVG (ReconPtr1[3], ReconPtr2[3])); - DctInputPtr[4] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[4], DSP_OP_AVG (ReconPtr1[4], ReconPtr2[4])); - DctInputPtr[5] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[5], DSP_OP_AVG (ReconPtr1[5], ReconPtr2[5])); - DctInputPtr[6] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[6], DSP_OP_AVG (ReconPtr1[6], ReconPtr2[6])); - DctInputPtr[7] = (ogg_int16_t) DSP_OP_DIFF (FiltPtr[7], DSP_OP_AVG (ReconPtr1[7], ReconPtr2[7])); - - /* Start next row */ - FiltPtr += PixelsPerLine; - ReconPtr1 += ReconPixelsPerLine; - ReconPtr2 += ReconPixelsPerLine; - DctInputPtr += 8; - } -#else - - __asm { - align 16 - - pxor mm7, mm7 - - mov eax, FiltPtr - mov ebx, ReconPtr1 - mov ecx, ReconPtr2 - mov edx, DctInputPtr - - /* ITERATION 1 */ - movq mm0, [eax] ; /* mm0 = FiltPtr */ - movq mm1, [ebx] ; /* mm1 = ReconPtr1 */ - movq mm4, [ecx] ; /* mm1 = ReconPtr2 */ - movq mm2, mm0 ; /* dup to prepare for up conversion */ - movq mm3, mm1 ; /* dup to prepare for up conversion */ - movq mm5, mm4 ; /* dup to prepare for up conversion */ - ; /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 ; /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 ; /* mm1 = INT16(ReconPtr1) */ - punpcklbw mm4, mm7 ; /* mm1 = INT16(ReconPtr2) */ - punpckhbw mm2, mm7 ; /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 ; /* mm3 = INT16(ReconPtr1) */ - punpckhbw mm5, mm7 ; /* mm3 = INT16(ReconPtr2) */ - ; /* average ReconPtr1 and ReconPtr2 */ - paddw mm1, mm4 ; /* mm1 = ReconPtr1 + ReconPtr2 */ - paddw mm3, mm5 ; /* mm3 = ReconPtr1 + ReconPtr2 */ - psrlw mm1, 1 ; /* mm1 = (ReconPtr1 + ReconPtr2) / 2 */ - psrlw mm3, 1 ; /* mm3 = (ReconPtr1 + ReconPtr2) / 2 */ - psubw mm0, mm1 ; /* mm0 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - psubw mm2, mm3 ; /* mm2 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - movq [edx], mm0 ; /* write answer out */ - movq [8 + edx], mm2 ; /* write answer out */ - ; /* Increment pointers */ - add edx, 16 ; - add eax, PixelsPerLine ; - add ebx, ReconPixelsPerLine ; - add ecx, ReconPixelsPerLine ; - - - /* ITERATION 2 */ - movq mm0, [eax] ; /* mm0 = FiltPtr */ - movq mm1, [ebx] ; /* mm1 = ReconPtr1 */ - movq mm4, [ecx] ; /* mm1 = ReconPtr2 */ - movq mm2, mm0 ; /* dup to prepare for up conversion */ - movq mm3, mm1 ; /* dup to prepare for up conversion */ - movq mm5, mm4 ; /* dup to prepare for up conversion */ - ; /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 ; /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 ; /* mm1 = INT16(ReconPtr1) */ - punpcklbw mm4, mm7 ; /* mm1 = INT16(ReconPtr2) */ - punpckhbw mm2, mm7 ; /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 ; /* mm3 = INT16(ReconPtr1) */ - punpckhbw mm5, mm7 ; /* mm3 = INT16(ReconPtr2) */ - ; /* average ReconPtr1 and ReconPtr2 */ - paddw mm1, mm4 ; /* mm1 = ReconPtr1 + ReconPtr2 */ - paddw mm3, mm5 ; /* mm3 = ReconPtr1 + ReconPtr2 */ - psrlw mm1, 1 ; /* mm1 = (ReconPtr1 + ReconPtr2) / 2 */ - psrlw mm3, 1 ; /* mm3 = (ReconPtr1 + ReconPtr2) / 2 */ - psubw mm0, mm1 ; /* mm0 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - psubw mm2, mm3 ; /* mm2 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - movq [edx], mm0 ; /* write answer out */ - movq [8 + edx], mm2 ; /* write answer out */ - ; /* Increment pointers */ - add edx, 16 ; - add eax, PixelsPerLine ; - add ebx, ReconPixelsPerLine ; - add ecx, ReconPixelsPerLine ; - - - /* ITERATION 3 */ - movq mm0, [eax] ; /* mm0 = FiltPtr */ - movq mm1, [ebx] ; /* mm1 = ReconPtr1 */ - movq mm4, [ecx] ; /* mm1 = ReconPtr2 */ - movq mm2, mm0 ; /* dup to prepare for up conversion */ - movq mm3, mm1 ; /* dup to prepare for up conversion */ - movq mm5, mm4 ; /* dup to prepare for up conversion */ - ; /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 ; /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 ; /* mm1 = INT16(ReconPtr1) */ - punpcklbw mm4, mm7 ; /* mm1 = INT16(ReconPtr2) */ - punpckhbw mm2, mm7 ; /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 ; /* mm3 = INT16(ReconPtr1) */ - punpckhbw mm5, mm7 ; /* mm3 = INT16(ReconPtr2) */ - ; /* average ReconPtr1 and ReconPtr2 */ - paddw mm1, mm4 ; /* mm1 = ReconPtr1 + ReconPtr2 */ - paddw mm3, mm5 ; /* mm3 = ReconPtr1 + ReconPtr2 */ - psrlw mm1, 1 ; /* mm1 = (ReconPtr1 + ReconPtr2) / 2 */ - psrlw mm3, 1 ; /* mm3 = (ReconPtr1 + ReconPtr2) / 2 */ - psubw mm0, mm1 ; /* mm0 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - psubw mm2, mm3 ; /* mm2 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - movq [edx], mm0 ; /* write answer out */ - movq [8 + edx], mm2 ; /* write answer out */ - ; /* Increment pointers */ - add edx, 16 ; - add eax, PixelsPerLine ; - add ebx, ReconPixelsPerLine ; - add ecx, ReconPixelsPerLine ; - - - /* ITERATION 4 */ - movq mm0, [eax] ; /* mm0 = FiltPtr */ - movq mm1, [ebx] ; /* mm1 = ReconPtr1 */ - movq mm4, [ecx] ; /* mm1 = ReconPtr2 */ - movq mm2, mm0 ; /* dup to prepare for up conversion */ - movq mm3, mm1 ; /* dup to prepare for up conversion */ - movq mm5, mm4 ; /* dup to prepare for up conversion */ - ; /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 ; /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 ; /* mm1 = INT16(ReconPtr1) */ - punpcklbw mm4, mm7 ; /* mm1 = INT16(ReconPtr2) */ - punpckhbw mm2, mm7 ; /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 ; /* mm3 = INT16(ReconPtr1) */ - punpckhbw mm5, mm7 ; /* mm3 = INT16(ReconPtr2) */ - ; /* average ReconPtr1 and ReconPtr2 */ - paddw mm1, mm4 ; /* mm1 = ReconPtr1 + ReconPtr2 */ - paddw mm3, mm5 ; /* mm3 = ReconPtr1 + ReconPtr2 */ - psrlw mm1, 1 ; /* mm1 = (ReconPtr1 + ReconPtr2) / 2 */ - psrlw mm3, 1 ; /* mm3 = (ReconPtr1 + ReconPtr2) / 2 */ - psubw mm0, mm1 ; /* mm0 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - psubw mm2, mm3 ; /* mm2 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - movq [edx], mm0 ; /* write answer out */ - movq [8 + edx], mm2 ; /* write answer out */ - ; /* Increment pointers */ - add edx, 16 ; - add eax, PixelsPerLine ; - add ebx, ReconPixelsPerLine ; - add ecx, ReconPixelsPerLine ; - - - /* ITERATION 5 */ - movq mm0, [eax] ; /* mm0 = FiltPtr */ - movq mm1, [ebx] ; /* mm1 = ReconPtr1 */ - movq mm4, [ecx] ; /* mm1 = ReconPtr2 */ - movq mm2, mm0 ; /* dup to prepare for up conversion */ - movq mm3, mm1 ; /* dup to prepare for up conversion */ - movq mm5, mm4 ; /* dup to prepare for up conversion */ - ; /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 ; /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 ; /* mm1 = INT16(ReconPtr1) */ - punpcklbw mm4, mm7 ; /* mm1 = INT16(ReconPtr2) */ - punpckhbw mm2, mm7 ; /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 ; /* mm3 = INT16(ReconPtr1) */ - punpckhbw mm5, mm7 ; /* mm3 = INT16(ReconPtr2) */ - ; /* average ReconPtr1 and ReconPtr2 */ - paddw mm1, mm4 ; /* mm1 = ReconPtr1 + ReconPtr2 */ - paddw mm3, mm5 ; /* mm3 = ReconPtr1 + ReconPtr2 */ - psrlw mm1, 1 ; /* mm1 = (ReconPtr1 + ReconPtr2) / 2 */ - psrlw mm3, 1 ; /* mm3 = (ReconPtr1 + ReconPtr2) / 2 */ - psubw mm0, mm1 ; /* mm0 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - psubw mm2, mm3 ; /* mm2 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - movq [edx], mm0 ; /* write answer out */ - movq [8 + edx], mm2 ; /* write answer out */ - ; /* Increment pointers */ - add edx, 16 ; - add eax, PixelsPerLine ; - add ebx, ReconPixelsPerLine ; - add ecx, ReconPixelsPerLine ; - - - /* ITERATION 6 */ - movq mm0, [eax] ; /* mm0 = FiltPtr */ - movq mm1, [ebx] ; /* mm1 = ReconPtr1 */ - movq mm4, [ecx] ; /* mm1 = ReconPtr2 */ - movq mm2, mm0 ; /* dup to prepare for up conversion */ - movq mm3, mm1 ; /* dup to prepare for up conversion */ - movq mm5, mm4 ; /* dup to prepare for up conversion */ - ; /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 ; /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 ; /* mm1 = INT16(ReconPtr1) */ - punpcklbw mm4, mm7 ; /* mm1 = INT16(ReconPtr2) */ - punpckhbw mm2, mm7 ; /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 ; /* mm3 = INT16(ReconPtr1) */ - punpckhbw mm5, mm7 ; /* mm3 = INT16(ReconPtr2) */ - ; /* average ReconPtr1 and ReconPtr2 */ - paddw mm1, mm4 ; /* mm1 = ReconPtr1 + ReconPtr2 */ - paddw mm3, mm5 ; /* mm3 = ReconPtr1 + ReconPtr2 */ - psrlw mm1, 1 ; /* mm1 = (ReconPtr1 + ReconPtr2) / 2 */ - psrlw mm3, 1 ; /* mm3 = (ReconPtr1 + ReconPtr2) / 2 */ - psubw mm0, mm1 ; /* mm0 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - psubw mm2, mm3 ; /* mm2 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - movq [edx], mm0 ; /* write answer out */ - movq [8 + edx], mm2 ; /* write answer out */ - ; /* Increment pointers */ - add edx, 16 ; - add eax, PixelsPerLine ; - add ebx, ReconPixelsPerLine ; - add ecx, ReconPixelsPerLine ; - - - /* ITERATION 7 */ - movq mm0, [eax] ; /* mm0 = FiltPtr */ - movq mm1, [ebx] ; /* mm1 = ReconPtr1 */ - movq mm4, [ecx] ; /* mm1 = ReconPtr2 */ - movq mm2, mm0 ; /* dup to prepare for up conversion */ - movq mm3, mm1 ; /* dup to prepare for up conversion */ - movq mm5, mm4 ; /* dup to prepare for up conversion */ - ; /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 ; /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 ; /* mm1 = INT16(ReconPtr1) */ - punpcklbw mm4, mm7 ; /* mm1 = INT16(ReconPtr2) */ - punpckhbw mm2, mm7 ; /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 ; /* mm3 = INT16(ReconPtr1) */ - punpckhbw mm5, mm7 ; /* mm3 = INT16(ReconPtr2) */ - ; /* average ReconPtr1 and ReconPtr2 */ - paddw mm1, mm4 ; /* mm1 = ReconPtr1 + ReconPtr2 */ - paddw mm3, mm5 ; /* mm3 = ReconPtr1 + ReconPtr2 */ - psrlw mm1, 1 ; /* mm1 = (ReconPtr1 + ReconPtr2) / 2 */ - psrlw mm3, 1 ; /* mm3 = (ReconPtr1 + ReconPtr2) / 2 */ - psubw mm0, mm1 ; /* mm0 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - psubw mm2, mm3 ; /* mm2 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - movq [edx], mm0 ; /* write answer out */ - movq [8 + edx], mm2 ; /* write answer out */ - ; /* Increment pointers */ - add edx, 16 ; - add eax, PixelsPerLine ; - add ebx, ReconPixelsPerLine ; - add ecx, ReconPixelsPerLine ; - - - /* ITERATION 8 */ - movq mm0, [eax] ; /* mm0 = FiltPtr */ - movq mm1, [ebx] ; /* mm1 = ReconPtr1 */ - movq mm4, [ecx] ; /* mm1 = ReconPtr2 */ - movq mm2, mm0 ; /* dup to prepare for up conversion */ - movq mm3, mm1 ; /* dup to prepare for up conversion */ - movq mm5, mm4 ; /* dup to prepare for up conversion */ - ; /* convert from UINT8 to INT16 */ - punpcklbw mm0, mm7 ; /* mm0 = INT16(FiltPtr) */ - punpcklbw mm1, mm7 ; /* mm1 = INT16(ReconPtr1) */ - punpcklbw mm4, mm7 ; /* mm1 = INT16(ReconPtr2) */ - punpckhbw mm2, mm7 ; /* mm2 = INT16(FiltPtr) */ - punpckhbw mm3, mm7 ; /* mm3 = INT16(ReconPtr1) */ - punpckhbw mm5, mm7 ; /* mm3 = INT16(ReconPtr2) */ - ; /* average ReconPtr1 and ReconPtr2 */ - paddw mm1, mm4 ; /* mm1 = ReconPtr1 + ReconPtr2 */ - paddw mm3, mm5 ; /* mm3 = ReconPtr1 + ReconPtr2 */ - psrlw mm1, 1 ; /* mm1 = (ReconPtr1 + ReconPtr2) / 2 */ - psrlw mm3, 1 ; /* mm3 = (ReconPtr1 + ReconPtr2) / 2 */ - psubw mm0, mm1 ; /* mm0 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - psubw mm2, mm3 ; /* mm2 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - movq [edx], mm0 ; /* write answer out */ - movq [8 + edx], mm2 ; /* write answer out */ - ; /* Increment pointers */ - add edx, 16 ; - add eax, PixelsPerLine ; - add ebx, ReconPixelsPerLine ; - add ecx, ReconPixelsPerLine ; - - }; - - - - - -#endif -} - -static ogg_uint32_t row_sad8__mmx (unsigned char *Src1, unsigned char *Src2) -{ - -#if 0 - ogg_uint32_t SadValue; - ogg_uint32_t SadValue1; - - SadValue = DSP_OP_ABS_DIFF (Src1[0], Src2[0]) + - DSP_OP_ABS_DIFF (Src1[1], Src2[1]) + - DSP_OP_ABS_DIFF (Src1[2], Src2[2]) + - DSP_OP_ABS_DIFF (Src1[3], Src2[3]); - - SadValue1 = DSP_OP_ABS_DIFF (Src1[4], Src2[4]) + - DSP_OP_ABS_DIFF (Src1[5], Src2[5]) + - DSP_OP_ABS_DIFF (Src1[6], Src2[6]) + - DSP_OP_ABS_DIFF (Src1[7], Src2[7]); - - SadValue = ( SadValue > SadValue1 ) ? SadValue : SadValue1; - - return SadValue; - -#else - ogg_uint32_t MaxSad; - - - __asm { - align 16 - mov ebx, Src1 - mov ecx, Src2 - - - pxor mm6, mm6 ; /* zero out mm6 for unpack */ - pxor mm7, mm7 ; /* zero out mm7 for unpack */ - movq mm0, [ebx] ; /* take 8 bytes */ - movq mm1, [ecx] ; - - movq mm2, mm0 ; - psubusb mm0, mm1 ; /* A - B */ - psubusb mm1, mm2 ; /* B - A */ - por mm0, mm1 ; /* and or gives abs difference */ - - movq mm1, mm0 ; - - punpcklbw mm0, mm6 ; /* ; unpack low four bytes to higher precision */ - punpckhbw mm1, mm7 ; /* ; unpack high four bytes to higher precision */ - - movq mm2, mm0 ; - movq mm3, mm1 ; - psrlq mm2, 32 ; /* fold and add */ - psrlq mm3, 32 ; - paddw mm0, mm2 ; - paddw mm1, mm3 ; - movq mm2, mm0 ; - movq mm3, mm1 ; - psrlq mm2, 16 ; - psrlq mm3, 16 ; - paddw mm0, mm2 ; - paddw mm1, mm3 ; - - psubusw mm1, mm0 ; - paddw mm1, mm0 ; /* mm1 = max(mm1, mm0) */ - movd eax, mm1 ; - - and eax, 0xffff - mov MaxSad, eax - }; - return MaxSad; - - - - - -#endif -} - - - - -static ogg_uint32_t col_sad8x8__mmx (unsigned char *Src1, unsigned char *Src2, - ogg_uint32_t stride) -{ - -#if 0 - ogg_uint32_t SadValue[8] = {0,0,0,0,0,0,0,0}; - ogg_uint32_t SadValue2[8] = {0,0,0,0,0,0,0,0}; - ogg_uint32_t MaxSad = 0; - ogg_uint32_t i; - - for ( i = 0; i < 4; i++ ){ - SadValue[0] += abs(Src1[0] - Src2[0]); - SadValue[1] += abs(Src1[1] - Src2[1]); - SadValue[2] += abs(Src1[2] - Src2[2]); - SadValue[3] += abs(Src1[3] - Src2[3]); - SadValue[4] += abs(Src1[4] - Src2[4]); - SadValue[5] += abs(Src1[5] - Src2[5]); - SadValue[6] += abs(Src1[6] - Src2[6]); - SadValue[7] += abs(Src1[7] - Src2[7]); - - Src1 += stride; - Src2 += stride; - } - - for ( i = 0; i < 4; i++ ){ - SadValue2[0] += abs(Src1[0] - Src2[0]); - SadValue2[1] += abs(Src1[1] - Src2[1]); - SadValue2[2] += abs(Src1[2] - Src2[2]); - SadValue2[3] += abs(Src1[3] - Src2[3]); - SadValue2[4] += abs(Src1[4] - Src2[4]); - SadValue2[5] += abs(Src1[5] - Src2[5]); - SadValue2[6] += abs(Src1[6] - Src2[6]); - SadValue2[7] += abs(Src1[7] - Src2[7]); - - Src1 += stride; - Src2 += stride; - } - - for ( i = 0; i < 8; i++ ){ - if ( SadValue[i] > MaxSad ) - MaxSad = SadValue[i]; - if ( SadValue2[i] > MaxSad ) - MaxSad = SadValue2[i]; - } - - return MaxSad; -#else - ogg_uint32_t MaxSad; - - - __asm { - align 16 - mov ebx, Src1 - mov ecx, Src2 - - pxor mm3, mm3 ; /* zero out mm3 for unpack */ - pxor mm4, mm4 ; /* mm4 low sum */ - pxor mm5, mm5 ; /* mm5 high sum */ - pxor mm6, mm6 ; /* mm6 low sum */ - pxor mm7, mm7 ; /* mm7 high sum */ - mov edi, 4 ; /* 4 rows */ - label_1: ; - movq mm0, [ebx] ; /* take 8 bytes */ - movq mm1, [ecx] ; /* take 8 bytes */ - - movq mm2, mm0 ; - psubusb mm0, mm1 ; /* A - B */ - psubusb mm1, mm2 ; /* B - A */ - por mm0, mm1 ; /* and or gives abs difference */ - movq mm1, mm0 ; - - punpcklbw mm0, mm3 ; /* unpack to higher precision for accumulation */ - paddw mm4, mm0 ; /* accumulate difference... */ - punpckhbw mm1, mm3 ; /* unpack high four bytes to higher precision */ - paddw mm5, mm1 ; /* accumulate difference... */ - add ebx, stride ; /* Inc pointer into the new data */ - add ecx, stride ; /* Inc pointer into the new data */ - - dec edi ; - jnz label_1 ; - - mov edi, 4 ; /* 4 rows */ - label_2: ; - movq mm0, [ebx] ; /* take 8 bytes */ - movq mm1, [ecx] ; /* take 8 bytes */ - - movq mm2, mm0 ; - psubusb mm0, mm1 ; /* A - B */ - psubusb mm1, mm2 ; /* B - A */ - por mm0, mm1 ; /* and or gives abs difference */ - movq mm1, mm0 ; - - punpcklbw mm0, mm3 ; /* unpack to higher precision for accumulation */ - paddw mm6, mm0 ; /* accumulate difference... */ - punpckhbw mm1, mm3 ; /* unpack high four bytes to higher precision */ - paddw mm7, mm1 ; /* accumulate difference... */ - add ebx, stride ; /* Inc pointer into the new data */ - add ecx, stride ; /* Inc pointer into the new data */ - - dec edi ; - jnz label_2 ; - - psubusw mm7, mm6 ; - paddw mm7, mm6 ; /* mm7 = max(mm7, mm6) */ - psubusw mm5, mm4 ; - paddw mm5, mm4 ; /* mm5 = max(mm5, mm4) */ - psubusw mm7, mm5 ; - paddw mm7, mm5 ; /* mm7 = max(mm5, mm7) */ - movq mm6, mm7 ; - psrlq mm6, 32 ; - psubusw mm7, mm6 ; - paddw mm7, mm6 ; /* mm7 = max(mm5, mm7) */ - movq mm6, mm7 ; - psrlq mm6, 16 ; - psubusw mm7, mm6 ; - paddw mm7, mm6 ; /* mm7 = max(mm5, mm7) */ - movd eax, mm7 ; - and eax, 0xffff ; - - mov MaxSad, eax - }; - - return MaxSad; - - -#endif -} - -static ogg_uint32_t sad8x8__mmx (unsigned char *ptr1, ogg_uint32_t stride1, - unsigned char *ptr2, ogg_uint32_t stride2) -{ - -#if 0 - ogg_uint32_t i; - ogg_uint32_t sad = 0; - - for (i=8; i; i--) { - sad += DSP_OP_ABS_DIFF(ptr1[0], ptr2[0]); - sad += DSP_OP_ABS_DIFF(ptr1[1], ptr2[1]); - sad += DSP_OP_ABS_DIFF(ptr1[2], ptr2[2]); - sad += DSP_OP_ABS_DIFF(ptr1[3], ptr2[3]); - sad += DSP_OP_ABS_DIFF(ptr1[4], ptr2[4]); - sad += DSP_OP_ABS_DIFF(ptr1[5], ptr2[5]); - sad += DSP_OP_ABS_DIFF(ptr1[6], ptr2[6]); - sad += DSP_OP_ABS_DIFF(ptr1[7], ptr2[7]); - - /* Step to next row of block. */ - ptr1 += stride1; - ptr2 += stride2; - } - - return sad; -#else - ogg_uint32_t DiffVal; - - __asm { - align 16 - - mov ebx, ptr1 - mov edx, ptr2 - - pxor mm6, mm6 ; /* zero out mm6 for unpack */ - pxor mm7, mm7 ; /* mm7 contains the result */ - - ; /* ITERATION 1 */ - movq mm0, [ebx] ; /* take 8 bytes */ - movq mm1, [edx] ; - movq mm2, mm0 ; - - psubusb mm0, mm1 ; /* A - B */ - psubusb mm1, mm2 ; /* B - A */ - por mm0, mm1 ; /* and or gives abs difference */ - movq mm1, mm0 ; - - punpcklbw mm0, mm6 ; /* unpack to higher precision for accumulation */ - paddw mm7, mm0 ; /* accumulate difference... */ - punpckhbw mm1, mm6 ; /* unpack high four bytes to higher precision */ - add ebx, stride1 ; /* Inc pointer into the new data */ - paddw mm7, mm1 ; /* accumulate difference... */ - add edx, stride2 ; /* Inc pointer into ref data */ - - ; /* ITERATION 2 */ - movq mm0, [ebx] ; /* take 8 bytes */ - movq mm1, [edx] ; - movq mm2, mm0 ; - - psubusb mm0, mm1 ; /* A - B */ - psubusb mm1, mm2 ; /* B - A */ - por mm0, mm1 ; /* and or gives abs difference */ - movq mm1, mm0 ; - - punpcklbw mm0, mm6 ; /* unpack to higher precision for accumulation */ - paddw mm7, mm0 ; /* accumulate difference... */ - punpckhbw mm1, mm6 ; /* unpack high four bytes to higher precision */ - add ebx, stride1 ; /* Inc pointer into the new data */ - paddw mm7, mm1 ; /* accumulate difference... */ - add edx, stride2 ; /* Inc pointer into ref data */ - - - ; /* ITERATION 3 */ - movq mm0, [ebx] ; /* take 8 bytes */ - movq mm1, [edx] ; - movq mm2, mm0 ; - - psubusb mm0, mm1 ; /* A - B */ - psubusb mm1, mm2 ; /* B - A */ - por mm0, mm1 ; /* and or gives abs difference */ - movq mm1, mm0 ; - - punpcklbw mm0, mm6 ; /* unpack to higher precision for accumulation */ - paddw mm7, mm0 ; /* accumulate difference... */ - punpckhbw mm1, mm6 ; /* unpack high four bytes to higher precision */ - add ebx, stride1 ; /* Inc pointer into the new data */ - paddw mm7, mm1 ; /* accumulate difference... */ - add edx, stride2 ; /* Inc pointer into ref data */ - - ; /* ITERATION 4 */ - movq mm0, [ebx] ; /* take 8 bytes */ - movq mm1, [edx] ; - movq mm2, mm0 ; - - psubusb mm0, mm1 ; /* A - B */ - psubusb mm1, mm2 ; /* B - A */ - por mm0, mm1 ; /* and or gives abs difference */ - movq mm1, mm0 ; - - punpcklbw mm0, mm6 ; /* unpack to higher precision for accumulation */ - paddw mm7, mm0 ; /* accumulate difference... */ - punpckhbw mm1, mm6 ; /* unpack high four bytes to higher precision */ - add ebx, stride1 ; /* Inc pointer into the new data */ - paddw mm7, mm1 ; /* accumulate difference... */ - add edx, stride2 ; /* Inc pointer into ref data */ - - - ; /* ITERATION 5 */ - movq mm0, [ebx] ; /* take 8 bytes */ - movq mm1, [edx] ; - movq mm2, mm0 ; - - psubusb mm0, mm1 ; /* A - B */ - psubusb mm1, mm2 ; /* B - A */ - por mm0, mm1 ; /* and or gives abs difference */ - movq mm1, mm0 ; - - punpcklbw mm0, mm6 ; /* unpack to higher precision for accumulation */ - paddw mm7, mm0 ; /* accumulate difference... */ - punpckhbw mm1, mm6 ; /* unpack high four bytes to higher precision */ - add ebx, stride1 ; /* Inc pointer into the new data */ - paddw mm7, mm1 ; /* accumulate difference... */ - add edx, stride2 ; /* Inc pointer into ref data */ - - - ; /* ITERATION 6 */ - movq mm0, [ebx] ; /* take 8 bytes */ - movq mm1, [edx] ; - movq mm2, mm0 ; - - psubusb mm0, mm1 ; /* A - B */ - psubusb mm1, mm2 ; /* B - A */ - por mm0, mm1 ; /* and or gives abs difference */ - movq mm1, mm0 ; - - punpcklbw mm0, mm6 ; /* unpack to higher precision for accumulation */ - paddw mm7, mm0 ; /* accumulate difference... */ - punpckhbw mm1, mm6 ; /* unpack high four bytes to higher precision */ - add ebx, stride1 ; /* Inc pointer into the new data */ - paddw mm7, mm1 ; /* accumulate difference... */ - add edx, stride2 ; /* Inc pointer into ref data */ - - - ; /* ITERATION 7 */ - movq mm0, [ebx] ; /* take 8 bytes */ - movq mm1, [edx] ; - movq mm2, mm0 ; - - psubusb mm0, mm1 ; /* A - B */ - psubusb mm1, mm2 ; /* B - A */ - por mm0, mm1 ; /* and or gives abs difference */ - movq mm1, mm0 ; - - punpcklbw mm0, mm6 ; /* unpack to higher precision for accumulation */ - paddw mm7, mm0 ; /* accumulate difference... */ - punpckhbw mm1, mm6 ; /* unpack high four bytes to higher precision */ - add ebx, stride1 ; /* Inc pointer into the new data */ - paddw mm7, mm1 ; /* accumulate difference... */ - add edx, stride2 ; /* Inc pointer into ref data */ - - - - ; /* ITERATION 8 */ - movq mm0, [ebx] ; /* take 8 bytes */ - movq mm1, [edx] ; - movq mm2, mm0 ; - - psubusb mm0, mm1 ; /* A - B */ - psubusb mm1, mm2 ; /* B - A */ - por mm0, mm1 ; /* and or gives abs difference */ - movq mm1, mm0 ; - - punpcklbw mm0, mm6 ; /* unpack to higher precision for accumulation */ - paddw mm7, mm0 ; /* accumulate difference... */ - punpckhbw mm1, mm6 ; /* unpack high four bytes to higher precision */ - add ebx, stride1 ; /* Inc pointer into the new data */ - paddw mm7, mm1 ; /* accumulate difference... */ - add edx, stride2 ; /* Inc pointer into ref data */ - - - - ; /* ------ */ - - movq mm0, mm7 ; - psrlq mm7, 32 ; - paddw mm7, mm0 ; - movq mm0, mm7 ; - psrlq mm7, 16 ; - paddw mm7, mm0 ; - movd eax, mm7 ; - and eax, 0xffff ; - - mov DiffVal, eax - }; - - return DiffVal; - - - -#endif -} - -static ogg_uint32_t sad8x8_thres__mmx (unsigned char *ptr1, ogg_uint32_t stride1, - unsigned char *ptr2, ogg_uint32_t stride2, - ogg_uint32_t thres) -{ -#if 0 - ogg_uint32_t i; - ogg_uint32_t sad = 0; - - for (i=8; i; i--) { - sad += DSP_OP_ABS_DIFF(ptr1[0], ptr2[0]); - sad += DSP_OP_ABS_DIFF(ptr1[1], ptr2[1]); - sad += DSP_OP_ABS_DIFF(ptr1[2], ptr2[2]); - sad += DSP_OP_ABS_DIFF(ptr1[3], ptr2[3]); - sad += DSP_OP_ABS_DIFF(ptr1[4], ptr2[4]); - sad += DSP_OP_ABS_DIFF(ptr1[5], ptr2[5]); - sad += DSP_OP_ABS_DIFF(ptr1[6], ptr2[6]); - sad += DSP_OP_ABS_DIFF(ptr1[7], ptr2[7]); - - if (sad > thres ) - break; - - /* Step to next row of block. */ - ptr1 += stride1; - ptr2 += stride2; - } - - return sad; -#else - return sad8x8__mmx (ptr1, stride1, ptr2, stride2); -#endif -} - - -static ogg_uint32_t sad8x8_xy2_thres__mmx (unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr1, - unsigned char *RefDataPtr2, ogg_uint32_t RefStride, - ogg_uint32_t thres) -{ -#if 0 - ogg_uint32_t i; - ogg_uint32_t sad = 0; - - for (i=8; i; i--) { - sad += DSP_OP_ABS_DIFF(SrcData[0], DSP_OP_AVG (RefDataPtr1[0], RefDataPtr2[0])); - sad += DSP_OP_ABS_DIFF(SrcData[1], DSP_OP_AVG (RefDataPtr1[1], RefDataPtr2[1])); - sad += DSP_OP_ABS_DIFF(SrcData[2], DSP_OP_AVG (RefDataPtr1[2], RefDataPtr2[2])); - sad += DSP_OP_ABS_DIFF(SrcData[3], DSP_OP_AVG (RefDataPtr1[3], RefDataPtr2[3])); - sad += DSP_OP_ABS_DIFF(SrcData[4], DSP_OP_AVG (RefDataPtr1[4], RefDataPtr2[4])); - sad += DSP_OP_ABS_DIFF(SrcData[5], DSP_OP_AVG (RefDataPtr1[5], RefDataPtr2[5])); - sad += DSP_OP_ABS_DIFF(SrcData[6], DSP_OP_AVG (RefDataPtr1[6], RefDataPtr2[6])); - sad += DSP_OP_ABS_DIFF(SrcData[7], DSP_OP_AVG (RefDataPtr1[7], RefDataPtr2[7])); - - if ( sad > thres ) - break; - - /* Step to next row of block. */ - SrcData += SrcStride; - RefDataPtr1 += RefStride; - RefDataPtr2 += RefStride; - } - - return sad; -#else - ogg_uint32_t DiffVal; - - __asm { - align 16 - - mov ebx, SrcData - mov ecx, RefDataPtr1 - mov edx, RefDataPtr2 - - - pcmpeqd mm5, mm5 ; /* fefefefefefefefe in mm5 */ - paddb mm5, mm5 ; - ; - pxor mm6, mm6 ; /* zero out mm6 for unpack */ - pxor mm7, mm7 ; /* mm7 contains the result */ - mov edi, 8 ; /* 8 rows */ - loop_start: ; - movq mm0, [ebx] ; /* take 8 bytes */ - - movq mm2, [ecx] ; - movq mm3, [edx] ; /* take average of mm2 and mm3 */ - movq mm1, mm2 ; - pand mm1, mm3 ; - pxor mm3, mm2 ; - pand mm3, mm5 ; - psrlq mm3, 1 ; - paddb mm1, mm3 ; - - movq mm2, mm0 ; - - psubusb mm0, mm1 ; /* A - B */ - psubusb mm1, mm2 ; /* B - A */ - por mm0, mm1 ; /* and or gives abs difference */ - movq mm1, mm0 ; - - punpcklbw mm0, mm6 ; /* unpack to higher precision for accumulation */ - paddw mm7, mm0 ; /* accumulate difference... */ - punpckhbw mm1, mm6 ; /* unpack high four bytes to higher precision */ - add ebx, SrcStride ; /* Inc pointer into the new data */ - paddw mm7, mm1 ; /* accumulate difference... */ - add ecx, RefStride ; /* Inc pointer into ref data */ - add edx, RefStride ; /* Inc pointer into ref data */ - - dec edi ; - jnz loop_start ; - - movq mm0, mm7 ; - psrlq mm7, 32 ; - paddw mm7, mm0 ; - movq mm0, mm7 ; - psrlq mm7, 16 ; - paddw mm7, mm0 ; - movd eax, mm7 ; - and eax, 0xffff ; - - mov DiffVal, eax - }; - - return DiffVal; - - - -#endif -} - -static ogg_uint32_t intra8x8_err__mmx (unsigned char *DataPtr, ogg_uint32_t Stride) -{ -#if 0 - ogg_uint32_t i; - ogg_uint32_t XSum=0; - ogg_uint32_t XXSum=0; - - for (i=8; i; i--) { - /* Examine alternate pixel locations. */ - XSum += DataPtr[0]; - XXSum += DataPtr[0]*DataPtr[0]; - XSum += DataPtr[1]; - XXSum += DataPtr[1]*DataPtr[1]; - XSum += DataPtr[2]; - XXSum += DataPtr[2]*DataPtr[2]; - XSum += DataPtr[3]; - XXSum += DataPtr[3]*DataPtr[3]; - XSum += DataPtr[4]; - XXSum += DataPtr[4]*DataPtr[4]; - XSum += DataPtr[5]; - XXSum += DataPtr[5]*DataPtr[5]; - XSum += DataPtr[6]; - XXSum += DataPtr[6]*DataPtr[6]; - XSum += DataPtr[7]; - XXSum += DataPtr[7]*DataPtr[7]; - - /* Step to next row of block. */ - DataPtr += Stride; - } - - /* Compute population variance as mis-match metric. */ - return (( (XXSum<<6) - XSum*XSum ) ); -#else - ogg_uint32_t XSum; - ogg_uint32_t XXSum; - - __asm { - align 16 - - mov ecx, DataPtr - - pxor mm5, mm5 ; - pxor mm6, mm6 ; - pxor mm7, mm7 ; - mov edi, 8 ; - loop_start: - movq mm0, [ecx] ; /* take 8 bytes */ - movq mm2, mm0 ; - - punpcklbw mm0, mm6 ; - punpckhbw mm2, mm6 ; - - paddw mm5, mm0 ; - paddw mm5, mm2 ; - - pmaddwd mm0, mm0 ; - pmaddwd mm2, mm2 ; - ; - paddd mm7, mm0 ; - paddd mm7, mm2 ; - - add ecx, Stride ; /* Inc pointer into src data */ - - dec edi ; - jnz loop_start ; - - movq mm0, mm5 ; - psrlq mm5, 32 ; - paddw mm5, mm0 ; - movq mm0, mm5 ; - psrlq mm5, 16 ; - paddw mm5, mm0 ; - movd edi, mm5 ; - movsx edi, di ; - mov eax, edi ; - - movq mm0, mm7 ; - psrlq mm7, 32 ; - paddd mm7, mm0 ; - movd ebx, mm7 ; - - mov XSum, eax - mov XXSum, ebx; - - }; - /* Compute population variance as mis-match metric. */ - return (( (XXSum<<6) - XSum*XSum ) ); - - - -#endif -} - -static ogg_uint32_t inter8x8_err__mmx (unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr, ogg_uint32_t RefStride) -{ - -#if 0 - ogg_uint32_t i; - ogg_uint32_t XSum=0; - ogg_uint32_t XXSum=0; - ogg_int32_t DiffVal; - - for (i=8; i; i--) { - DiffVal = DSP_OP_DIFF (SrcData[0], RefDataPtr[0]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF (SrcData[1], RefDataPtr[1]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF (SrcData[2], RefDataPtr[2]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF (SrcData[3], RefDataPtr[3]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF (SrcData[4], RefDataPtr[4]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF (SrcData[5], RefDataPtr[5]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF (SrcData[6], RefDataPtr[6]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF (SrcData[7], RefDataPtr[7]); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - /* Step to next row of block. */ - SrcData += SrcStride; - RefDataPtr += RefStride; - } - - /* Compute and return population variance as mis-match metric. */ - return (( (XXSum<<6) - XSum*XSum )); -#else - ogg_uint32_t XSum; - ogg_uint32_t XXSum; - - - __asm { - align 16 - - mov ecx, SrcData - mov edx, RefDataPtr - - pxor mm5, mm5 ; - pxor mm6, mm6 ; - pxor mm7, mm7 ; - mov edi, 8 ; - loop_start: ; - movq mm0, [ecx] ; /* take 8 bytes */ - movq mm1, [edx] ; - movq mm2, mm0 ; - movq mm3, mm1 ; - - punpcklbw mm0, mm6 ; - punpcklbw mm1, mm6 ; - punpckhbw mm2, mm6 ; - punpckhbw mm3, mm6 ; - - psubsw mm0, mm1 ; - psubsw mm2, mm3 ; - - paddw mm5, mm0 ; - paddw mm5, mm2 ; - - pmaddwd mm0, mm0 ; - pmaddwd mm2, mm2 ; - ; - paddd mm7, mm0 ; - paddd mm7, mm2 ; - - add ecx, SrcStride ; /* Inc pointer into src data */ - add edx, RefStride ; /* Inc pointer into ref data */ - - dec edi ; - jnz loop_start ; - - movq mm0, mm5 ; - psrlq mm5, 32 ; - paddw mm5, mm0 ; - movq mm0, mm5 ; - psrlq mm5, 16 ; - paddw mm5, mm0 ; - movd edi, mm5 ; - movsx edi, di ; - mov eax, edi ; - - movq mm0, mm7 ; - psrlq mm7, 32 ; - paddd mm7, mm0 ; - movd ebx, mm7 ; - - mov XSum, eax - mov XXSum, ebx - - }; - - /* Compute and return population variance as mis-match metric. */ - return (( (XXSum<<6) - XSum*XSum )); - - -#endif -} - -static ogg_uint32_t inter8x8_err_xy2__mmx (unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr1, - unsigned char *RefDataPtr2, ogg_uint32_t RefStride) -{ -#if 0 - ogg_uint32_t i; - ogg_uint32_t XSum=0; - ogg_uint32_t XXSum=0; - ogg_int32_t DiffVal; - - for (i=8; i; i--) { - DiffVal = DSP_OP_DIFF(SrcData[0], DSP_OP_AVG (RefDataPtr1[0], RefDataPtr2[0])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF(SrcData[1], DSP_OP_AVG (RefDataPtr1[1], RefDataPtr2[1])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF(SrcData[2], DSP_OP_AVG (RefDataPtr1[2], RefDataPtr2[2])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF(SrcData[3], DSP_OP_AVG (RefDataPtr1[3], RefDataPtr2[3])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF(SrcData[4], DSP_OP_AVG (RefDataPtr1[4], RefDataPtr2[4])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF(SrcData[5], DSP_OP_AVG (RefDataPtr1[5], RefDataPtr2[5])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF(SrcData[6], DSP_OP_AVG (RefDataPtr1[6], RefDataPtr2[6])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - DiffVal = DSP_OP_DIFF(SrcData[7], DSP_OP_AVG (RefDataPtr1[7], RefDataPtr2[7])); - XSum += DiffVal; - XXSum += DiffVal*DiffVal; - - /* Step to next row of block. */ - SrcData += SrcStride; - RefDataPtr1 += RefStride; - RefDataPtr2 += RefStride; - } - - /* Compute and return population variance as mis-match metric. */ - return (( (XXSum<<6) - XSum*XSum )); -#else - ogg_uint32_t XSum; - ogg_uint32_t XXSum; - - __asm { - align 16 - - mov ebx, SrcData - mov ecx, RefDataPtr1 - mov edx, RefDataPtr2 - - pcmpeqd mm4, mm4 ; /* fefefefefefefefe in mm4 */ - paddb mm4, mm4 ; - pxor mm5, mm5 ; - pxor mm6, mm6 ; - pxor mm7, mm7 ; - mov edi, 8 ; - loop_start: ; - movq mm0, [ebx] ; /* take 8 bytes */ - - movq mm2, [ecx] ; - movq mm3, [edx] ; /* take average of mm2 and mm3 */ - movq mm1, mm2 ; - pand mm1, mm3 ; - pxor mm3, mm2 ; - pand mm3, mm4 ; - psrlq mm3, 1 ; - paddb mm1, mm3 ; - - movq mm2, mm0 ; - movq mm3, mm1 ; - - punpcklbw mm0, mm6 ; - punpcklbw mm1, mm6 ; - punpckhbw mm2, mm6 ; - punpckhbw mm3, mm6 ; - - psubsw mm0, mm1 ; - psubsw mm2, mm3 ; - - paddw mm5, mm0 ; - paddw mm5, mm2 ; - - pmaddwd mm0, mm0 ; - pmaddwd mm2, mm2 ; - ; - paddd mm7, mm0 ; - paddd mm7, mm2 ; - - add ebx, SrcStride ; /* Inc pointer into src data */ - add ecx, RefStride ; /* Inc pointer into ref data */ - add edx, RefStride ; /* Inc pointer into ref data */ - - dec edi ; - jnz loop_start ; - - movq mm0, mm5 ; - psrlq mm5, 32 ; - paddw mm5, mm0 ; - movq mm0, mm5 ; - psrlq mm5, 16 ; - paddw mm5, mm0 ; - movd edi, mm5 ; - movsx edi, di ; - mov XSum, edi ; /* movl eax, edi ; Modified for vc to resuse eax*/ - - movq mm0, mm7 ; - psrlq mm7, 32 ; - paddd mm7, mm0 ; - movd XXSum, mm7 ; /*movd eax, mm7 ; Modified for vc to reuse eax */ - }; - - return (( (XXSum<<6) - XSum*XSum )); - -#endif -} - -static void restore_fpu (void) -{ - - __asm { - emms - } - -} - -void dsp_mmx_init(DspFunctions *funcs) -{ - funcs->restore_fpu = restore_fpu; - funcs->sub8x8 = sub8x8__mmx; - funcs->sub8x8_128 = sub8x8_128__mmx; - funcs->sub8x8avg2 = sub8x8avg2__mmx; - funcs->row_sad8 = row_sad8__mmx; - funcs->col_sad8x8 = col_sad8x8__mmx; - funcs->sad8x8 = sad8x8__mmx; - funcs->sad8x8_thres = sad8x8_thres__mmx; - funcs->sad8x8_xy2_thres = sad8x8_xy2_thres__mmx; - funcs->intra8x8_err = intra8x8_err__mmx; - funcs->inter8x8_err = inter8x8_err__mmx; - funcs->inter8x8_err_xy2 = inter8x8_err_xy2__mmx; -} - diff --git a/Engine/lib/libtheora/lib/enc/x86_32_vs/fdct_mmx.c b/Engine/lib/libtheora/lib/enc/x86_32_vs/fdct_mmx.c deleted file mode 100644 index 65cd9c367..000000000 --- a/Engine/lib/libtheora/lib/enc/x86_32_vs/fdct_mmx.c +++ /dev/null @@ -1,333 +0,0 @@ -;//========================================================================== -;// -;// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY -;// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -;// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR -;// PURPOSE. -;// -;// Copyright (c) 1999 - 2001 On2 Technologies Inc. All Rights Reserved. -;// -;//-------------------------------------------------------------------------- - -#include "theora/theora.h" -#include "../codec_internal.h" -#include "../dsp.h" - - -static const ogg_int64_t xC1S7 = 0x0fb15fb15fb15fb15; -static const ogg_int64_t xC2S6 = 0x0ec83ec83ec83ec83; -static const ogg_int64_t xC3S5 = 0x0d4dbd4dbd4dbd4db; -static const ogg_int64_t xC4S4 = 0x0b505b505b505b505; -static const ogg_int64_t xC5S3 = 0x08e3a8e3a8e3a8e3a; -static const ogg_int64_t xC6S2 = 0x061f861f861f861f8; -static const ogg_int64_t xC7S1 = 0x031f131f131f131f1; - - -static __inline void Transpose_mmx( ogg_int16_t *InputData1, ogg_int16_t *OutputData1, - ogg_int16_t *InputData2, ogg_int16_t *OutputData2) -{ - - __asm { - align 16 - mov eax, InputData1 - mov ebx, InputData2 - mov ecx, OutputData1 - mov edx, OutputData2 - - - movq mm0, [eax] ; /* mm0 = a0 a1 a2 a3 */ - movq mm4, [ebx] ; /* mm4 = e4 e5 e6 e7 */ - movq mm1, [16 + eax] ; /* mm1 = b0 b1 b2 b3 */ - movq mm5, [16 + ebx] ; /* mm5 = f4 f5 f6 f7 */ - movq mm2, [32 + eax] ; /* mm2 = c0 c1 c2 c3 */ - movq mm6, [32 + ebx] ; /* mm6 = g4 g5 g6 g7 */ - movq mm3, [48 + eax] ; /* mm3 = d0 d1 d2 d3 */ - movq [16 + ecx], mm1 ; /* save b0 b1 b2 b3 */ - movq mm7, [48 + ebx] ; /* mm7 = h0 h1 h2 h3 */ - ; /* Transpose 2x8 block */ - movq mm1, mm4 ; /* mm1 = e3 e2 e1 e0 */ - punpcklwd mm4, mm5 ; /* mm4 = f1 e1 f0 e0 */ - movq [ecx], mm0 ; /* save a3 a2 a1 a0 */ - punpckhwd mm1, mm5 ; /* mm1 = f3 e3 f2 e2 */ - movq mm0, mm6 ; /* mm0 = g3 g2 g1 g0 */ - punpcklwd mm6, mm7 ; /* mm6 = h1 g1 h0 g0 */ - movq mm5, mm4 ; /* mm5 = f1 e1 f0 e0 */ - punpckldq mm4, mm6 ; /* mm4 = h0 g0 f0 e0 = MM4 */ - punpckhdq mm5, mm6 ; /* mm5 = h1 g1 f1 e1 = MM5 */ - movq mm6, mm1 ; /* mm6 = f3 e3 f2 e2 */ - movq [edx], mm4 ; - punpckhwd mm0, mm7 ; /* mm0 = h3 g3 h2 g2 */ - movq [16 + edx], mm5 ; - punpckhdq mm6, mm0 ; /* mm6 = h3 g3 f3 e3 = MM7 */ - movq mm4, [ecx] ; /* mm4 = a3 a2 a1 a0 */ - punpckldq mm1, mm0 ; /* mm1 = h2 g2 f2 e2 = MM6 */ - movq mm5, [16 + ecx] ; /* mm5 = b3 b2 b1 b0 */ - movq mm0, mm4 ; /* mm0 = a3 a2 a1 a0 */ - movq [48 + edx], mm6 ; - punpcklwd mm0, mm5 ; /* mm0 = b1 a1 b0 a0 */ - movq [32 + edx], mm1 ; - punpckhwd mm4, mm5 ; /* mm4 = b3 a3 b2 a2 */ - movq mm5, mm2 ; /* mm5 = c3 c2 c1 c0 */ - punpcklwd mm2, mm3 ; /* mm2 = d1 c1 d0 c0 */ - movq mm1, mm0 ; /* mm1 = b1 a1 b0 a0 */ - punpckldq mm0, mm2 ; /* mm0 = d0 c0 b0 a0 = MM0 */ - punpckhdq mm1, mm2 ; /* mm1 = d1 c1 b1 a1 = MM1 */ - movq mm2, mm4 ; /* mm2 = b3 a3 b2 a2 */ - movq [ecx], mm0 ; - punpckhwd mm5, mm3 ; /* mm5 = d3 c3 d2 c2 */ - movq [16 + ecx], mm1 ; - punpckhdq mm4, mm5 ; /* mm4 = d3 c3 b3 a3 = MM3 */ - punpckldq mm2, mm5 ; /* mm2 = d2 c2 b2 a2 = MM2 */ - movq [48 + ecx], mm4 ; - movq [32 + ecx], mm2 ; - - }; - - -} - -static __inline void Fdct_mmx( ogg_int16_t *InputData1, ogg_int16_t *InputData2, ogg_int16_t *temp) -{ - - __asm { - align 16 - - - mov eax, InputData1 - mov ebx, InputData2 - mov ecx, temp - movq mm0, [eax] ; - movq mm1, [16 + eax] ; - movq mm2, [48 + eax] ; - movq mm3, [16 + ebx] ; - movq mm4, mm0 ; - movq mm5, mm1 ; - movq mm6, mm2 ; - movq mm7, mm3 ; - ; - paddsw mm0, [48 + ebx] ; /* mm0 = ip0 + ip7 = is07 */ - paddsw mm1, [32 + eax] ; /* mm1 = ip1 + ip2 = is12 */ - paddsw mm2, [ebx] ; /* mm2 = ip3 + ip4 = is34 */ - paddsw mm3, [32 + ebx] ; /* mm3 = ip5 + ip6 = is56 */ - psubsw mm4, [48 + ebx] ; /* mm4 = ip0 - ip7 = id07 */ - psubsw mm5, [32 + eax] ; /* mm5 = ip1 - ip2 = id12 */ - ; - psubsw mm0, mm2 ; /* mm0 = is07 - is34 */ - ; - paddsw mm2, mm2 ; - ; - psubsw mm6, [ebx] ; /* mm6 = ip3 - ip4 = id34 */ - ; - paddsw mm2, mm0 ; /* mm2 = is07 + is34 = is0734 */ - psubsw mm1, mm3 ; /* mm1 = is12 - is56 */ - movq [ecx], mm0 ; /* Save is07 - is34 to free mm0; */ - paddsw mm3, mm3 ; - paddsw mm3, mm1 ; /* mm3 = is12 + 1s56 = is1256 */ - ; - psubsw mm7, [32 + ebx] ; /* mm7 = ip5 - ip6 = id56 */ - ; /* ------------------------------------------------------------------- */ - psubsw mm5, mm7 ; /* mm5 = id12 - id56 */ - paddsw mm7, mm7 ; - paddsw mm7, mm5 ; /* mm7 = id12 + id56 */ - ; /* ------------------------------------------------------------------- */ - psubsw mm2, mm3 ; /* mm2 = is0734 - is1256 */ - paddsw mm3, mm3 ; - ; - movq mm0, mm2 ; /* make a copy */ - paddsw mm3, mm2 ; /* mm3 = is0734 + is1256 */ - ; - pmulhw mm0, xC4S4 ; /* mm0 = xC4S4 * ( is0734 - is1256 ) - ( is0734 - is1256 ) */ - paddw mm0, mm2 ; /* mm0 = xC4S4 * ( is0734 - is1256 ) */ - psrlw mm2, 15 ; - paddw mm0, mm2 ; /* Truncate mm0, now it is op[4] */ - ; - movq mm2, mm3 ; - movq [ebx], mm0 ; /* save ip4, now mm0,mm2 are free */ - ; - movq mm0, mm3 ; - pmulhw mm3, xC4S4 ; /* mm3 = xC4S4 * ( is0734 +is1256 ) - ( is0734 +is1256 ) */ - ; - psrlw mm2, 15 ; - paddw mm3, mm0 ; /* mm3 = xC4S4 * ( is0734 +is1256 ) */ - paddw mm3, mm2 ; /* Truncate mm3, now it is op[0] */ - ; - movq [eax], mm3 ; - ; /* ------------------------------------------------------------------- */ - movq mm3, [ecx] ; /* mm3 = irot_input_y */ - pmulhw mm3, xC2S6 ; /* mm3 = xC2S6 * irot_input_y - irot_input_y */ - ; - movq mm2, [ecx] ; - movq mm0, mm2 ; - ; - psrlw mm2, 15 ; /* mm3 = xC2S6 * irot_input_y */ - paddw mm3, mm0 ; - ; - paddw mm3, mm2 ; /* Truncated */ - movq mm0, mm5 ; - ; - movq mm2, mm5 ; - pmulhw mm0, xC6S2 ; /* mm0 = xC6S2 * irot_input_x */ - ; - psrlw mm2, 15 ; - paddw mm0, mm2 ; /* Truncated */ - ; - paddsw mm3, mm0 ; /* ip[2] */ - movq [32 + eax], mm3 ; /* Save ip2 */ - ; - movq mm0, mm5 ; - movq mm2, mm5 ; - ; - pmulhw mm5, xC2S6 ; /* mm5 = xC2S6 * irot_input_x - irot_input_x */ - psrlw mm2, 15 ; - ; - movq mm3, [ecx] ; - paddw mm5, mm0 ; /* mm5 = xC2S6 * irot_input_x */ - ; - paddw mm5, mm2 ; /* Truncated */ - movq mm2, mm3 ; - ; - pmulhw mm3, xC6S2 ; /* mm3 = xC6S2 * irot_input_y */ - psrlw mm2, 15 ; - ; - paddw mm3, mm2 ; /* Truncated */ - psubsw mm3, mm5 ; - ; - movq [32 + ebx], mm3 ; - ; /* ------------------------------------------------------------------- */ - movq mm0, xC4S4 ; - movq mm2, mm1 ; - movq mm3, mm1 ; - ; - pmulhw mm1, mm0 ; /* mm0 = xC4S4 * ( is12 - is56 ) - ( is12 - is56 ) */ - psrlw mm2, 15 ; - ; - paddw mm1, mm3 ; /* mm0 = xC4S4 * ( is12 - is56 ) */ - paddw mm1, mm2 ; /* Truncate mm1, now it is icommon_product1 */ - ; - movq mm2, mm7 ; - movq mm3, mm7 ; - ; - pmulhw mm7, mm0 ; /* mm7 = xC4S4 * ( id12 + id56 ) - ( id12 + id56 ) */ - psrlw mm2, 15 ; - ; - paddw mm7, mm3 ; /* mm7 = xC4S4 * ( id12 + id56 ) */ - paddw mm7, mm2 ; /* Truncate mm7, now it is icommon_product2 */ - ; /* ------------------------------------------------------------------- */ - pxor mm0, mm0 ; /* Clear mm0 */ - psubsw mm0, mm6 ; /* mm0 = - id34 */ - ; - psubsw mm0, mm7 ; /* mm0 = - ( id34 + idcommon_product2 ) */ - paddsw mm6, mm6 ; - paddsw mm6, mm0 ; /* mm6 = id34 - icommon_product2 */ - ; - psubsw mm4, mm1 ; /* mm4 = id07 - icommon_product1 */ - paddsw mm1, mm1 ; - paddsw mm1, mm4 ; /* mm1 = id07 + icommon_product1 */ - ; /* ------------------------------------------------------------------- */ - movq mm7, xC1S7 ; - movq mm2, mm1 ; - ; - movq mm3, mm1 ; - pmulhw mm1, mm7 ; /* mm1 = xC1S7 * irot_input_x - irot_input_x */ - ; - movq mm7, xC7S1 ; - psrlw mm2, 15 ; - ; - paddw mm1, mm3 ; /* mm1 = xC1S7 * irot_input_x */ - paddw mm1, mm2 ; /* Trucated */ - ; - pmulhw mm3, mm7 ; /* mm3 = xC7S1 * irot_input_x */ - paddw mm3, mm2 ; /* Truncated */ - ; - movq mm5, mm0 ; - movq mm2, mm0 ; - ; - movq mm7, xC1S7 ; - pmulhw mm0, mm7 ; /* mm0 = xC1S7 * irot_input_y - irot_input_y */ - ; - movq mm7, xC7S1 ; - psrlw mm2, 15 ; - ; - paddw mm0, mm5 ; /* mm0 = xC1S7 * irot_input_y */ - paddw mm0, mm2 ; /* Truncated */ - ; - pmulhw mm5, mm7 ; /* mm5 = xC7S1 * irot_input_y */ - paddw mm5, mm2 ; /* Truncated */ - ; - psubsw mm1, mm5 ; /* mm1 = xC1S7 * irot_input_x - xC7S1 * irot_input_y = ip1 */ - paddsw mm3, mm0 ; /* mm3 = xC7S1 * irot_input_x - xC1S7 * irot_input_y = ip7 */ - ; - movq [16 + eax], mm1 ; - movq [48 + ebx], mm3 ; - ; /* ------------------------------------------------------------------- */ - movq mm0, xC3S5 ; - movq mm1, xC5S3 ; - ; - movq mm5, mm6 ; - movq mm7, mm6 ; - ; - movq mm2, mm4 ; - movq mm3, mm4 ; - ; - pmulhw mm4, mm0 ; /* mm4 = xC3S5 * irot_input_x - irot_input_x */ - pmulhw mm6, mm1 ; /* mm6 = xC5S3 * irot_input_y - irot_input_y */ - ; - psrlw mm2, 15 ; - psrlw mm5, 15 ; - ; - paddw mm4, mm3 ; /* mm4 = xC3S5 * irot_input_x */ - paddw mm6, mm7 ; /* mm6 = xC5S3 * irot_input_y */ - ; - paddw mm4, mm2 ; /* Truncated */ - paddw mm6, mm5 ; /* Truncated */ - ; - psubsw mm4, mm6 ; /* ip3 */ - movq [48 + eax], mm4 ; - ; - movq mm4, mm3 ; - movq mm6, mm7 ; - ; - pmulhw mm3, mm1 ; /* mm3 = xC5S3 * irot_input_x - irot_input_x */ - pmulhw mm7, mm0 ; /* mm7 = xC3S5 * irot_input_y - irot_input_y */ - ; - paddw mm4, mm2 ; - paddw mm6, mm5 ; - ; - paddw mm3, mm4 ; /* mm3 = xC5S3 * irot_input_x */ - paddw mm7, mm6 ; /* mm7 = xC3S5 * irot_input_y */ - ; - paddw mm3, mm7 ; /* ip5 */ - movq [16 + ebx], mm3 ; - -}; - -} - - -static void fdct_short__mmx ( ogg_int16_t *InputData, ogg_int16_t *OutputData) -{ - - static ogg_int16_t tmp[32]; - ogg_int16_t* align_tmp = (ogg_int16_t*)((unsigned char*)tmp + (16 - ((int)tmp)&15)); - - - Transpose_mmx(InputData, OutputData, InputData + 4, OutputData + 4); - Fdct_mmx(OutputData, OutputData + 4, align_tmp); - - Transpose_mmx(InputData + 32, OutputData + 32, InputData + 36, OutputData + 36); - Fdct_mmx(OutputData+32, OutputData + 36, align_tmp); - - Transpose_mmx(OutputData, OutputData, OutputData + 32, OutputData + 32); - Fdct_mmx(OutputData, OutputData + 32, align_tmp); - - Transpose_mmx(OutputData + 4, OutputData + 4, OutputData + 36, OutputData + 36); - Fdct_mmx(OutputData + 4, OutputData + 36, align_tmp); - - __asm emms - -} - -void dsp_mmx_fdct_init(DspFunctions *funcs) -{ - funcs->fdct_short = fdct_short__mmx; -} diff --git a/Engine/lib/libtheora/lib/enc/x86_32_vs/recon_mmx.c b/Engine/lib/libtheora/lib/enc/x86_32_vs/recon_mmx.c deleted file mode 100644 index 1e0f1f095..000000000 --- a/Engine/lib/libtheora/lib/enc/x86_32_vs/recon_mmx.c +++ /dev/null @@ -1,197 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: reconstruct.c,v 1.6 2003/12/03 08:59:41 arc Exp $ - - ********************************************************************/ - -#include "../codec_internal.h" - - -static const unsigned __int64 V128 = 0x8080808080808080; - -static void copy8x8__mmx (unsigned char *src, - unsigned char *dest, - unsigned int stride) -{ - - //Is this even the fastest way to do this? - __asm { - align 16 - - mov eax, src - mov ebx, dest - mov ecx, stride - - lea edi, [ecx + ecx * 2] - movq mm0, [eax] - movq mm1, [eax + ecx] - movq mm2, [eax + ecx * 2] - movq mm3, [eax + edi] - lea eax, [eax + ecx * 4] - movq [ebx], mm0 - movq [ebx + ecx], mm1 - movq [ebx + ecx * 2], mm2 - movq [ebx + edi], mm3 - lea ebx, [ebx + ecx * 4] - movq mm0, [eax] - movq mm1, [eax + ecx] - movq mm2, [eax + ecx * 2] - movq mm3, [eax + edi] - movq [ebx], mm0 - movq [ebx + ecx], mm1 - movq [ebx + ecx * 2], mm2 - movq [ebx + edi], mm3 - - }; - -} - -static void recon_intra8x8__mmx (unsigned char *ReconPtr, ogg_int16_t *ChangePtr, - ogg_uint32_t LineStep) -{ - - __asm { - align 16 - - mov eax, ReconPtr - mov ebx, ChangePtr - mov ecx, LineStep - - movq mm0, V128 - - lea edi, [128 + ebx] - loop_start: - movq mm2, [ebx] - - packsswb mm2, [8 + ebx] - por mm0, mm0 - pxor mm2, mm0 - lea ebx, [16 + ebx] - cmp ebx, edi - - movq [eax], mm2 - - - - lea eax, [eax + ecx] - jc loop_start - - - }; - -} - - - - - -static void recon_inter8x8__mmx (unsigned char *ReconPtr, unsigned char *RefPtr, - ogg_int16_t *ChangePtr, ogg_uint32_t LineStep) -{ - - __asm { - - align 16 - - mov eax, ReconPtr - mov ebx, ChangePtr - mov ecx, LineStep - mov edx, RefPtr - - pxor mm0, mm0 - lea edi, [128 + ebx] - - loop_start: - movq mm2, [edx] - - movq mm4, [ebx] - movq mm3, mm2 - movq mm5, [8 + ebx] - punpcklbw mm2, mm0 - paddsw mm2, mm4 - punpckhbw mm3, mm0 - paddsw mm3, mm5 - add edx, ecx - packuswb mm2, mm3 - lea ebx, [16 + ebx] - cmp ebx, edi - - movq [eax], mm2 - - lea eax, [eax + ecx] - jc loop_start - - }; -} - - - - -static void recon_inter8x8_half__mmx (unsigned char *ReconPtr, unsigned char *RefPtr1, - unsigned char *RefPtr2, ogg_int16_t *ChangePtr, - ogg_uint32_t LineStep) -{ - __asm { - align 16 - - mov eax, ReconPtr - mov ebx, ChangePtr - mov ecx, RefPtr1 - mov edx, RefPtr2 - - pxor mm0, mm0 - lea edi, [128 + ebx] - - loop_start: - movq mm2, [ecx] - movq mm4, [edx] - - movq mm3, mm2 - punpcklbw mm2, mm0 - movq mm5, mm4 - movq mm6, [ebx] - punpckhbw mm3, mm0 - movq mm7, [8 + ebx] - punpcklbw mm4, mm0 - punpckhbw mm5, mm0 - paddw mm2, mm4 - paddw mm3, mm5 - psrlw mm2, 1 - psrlw mm3, 1 - paddw mm2, mm6 - paddw mm3, mm7 - lea ebx, [16 + ebx] - packuswb mm2, mm3 - add ecx, LineStep - add edx, LineStep - movq [eax], mm2 - add eax, LineStep - cmp ebx, edi - jc loop_start - - }; - -} - - - - -void dsp_mmx_recon_init(DspFunctions *funcs) -{ - funcs->copy8x8 = copy8x8__mmx; - funcs->recon_intra8x8 = recon_intra8x8__mmx; - funcs->recon_inter8x8 = recon_inter8x8__mmx; - funcs->recon_inter8x8_half = recon_inter8x8_half__mmx; -} - diff --git a/Engine/lib/libtheora/lib/enc/x86_64/dct_decode_mmx.c b/Engine/lib/libtheora/lib/enc/x86_64/dct_decode_mmx.c deleted file mode 100644 index 547e974e3..000000000 --- a/Engine/lib/libtheora/lib/enc/x86_64/dct_decode_mmx.c +++ /dev/null @@ -1,409 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2008 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: dct_decode_mmx.c 15400 2008-10-15 12:10:58Z tterribe $ - - ********************************************************************/ - -#include - -#include "../codec_internal.h" - -#if defined(USE_ASM) - -static const __attribute__((aligned(8),used)) ogg_int64_t OC_V3= - 0x0003000300030003LL; -static const __attribute__((aligned(8),used)) ogg_int64_t OC_V4= - 0x0004000400040004LL; - -static void loop_filter_v(unsigned char *_pix,int _ystride, - const ogg_int16_t *_ll){ - long esi; - _pix-=_ystride*2; - __asm__ __volatile__( - /*mm0=0*/ - "pxor %%mm0,%%mm0\n\t" - /*esi=_ystride*3*/ - "lea (%[ystride],%[ystride],2),%[s]\n\t" - /*mm7=_pix[0...8]*/ - "movq (%[pix]),%%mm7\n\t" - /*mm4=_pix[0...8+_ystride*3]*/ - "movq (%[pix],%[s]),%%mm4\n\t" - /*mm6=_pix[0...8]*/ - "movq %%mm7,%%mm6\n\t" - /*Expand unsigned _pix[0...3] to 16 bits.*/ - "punpcklbw %%mm0,%%mm6\n\t" - "movq %%mm4,%%mm5\n\t" - /*Expand unsigned _pix[4...8] to 16 bits.*/ - "punpckhbw %%mm0,%%mm7\n\t" - /*Expand other arrays too.*/ - "punpcklbw %%mm0,%%mm4\n\t" - "punpckhbw %%mm0,%%mm5\n\t" - /*mm7:mm6=_p[0...8]-_p[0...8+_ystride*3]:*/ - "psubw %%mm4,%%mm6\n\t" - "psubw %%mm5,%%mm7\n\t" - /*mm5=mm4=_pix[0...8+_ystride]*/ - "movq (%[pix],%[ystride]),%%mm4\n\t" - /*mm1=mm3=mm2=_pix[0..8]+_ystride*2]*/ - "movq (%[pix],%[ystride],2),%%mm2\n\t" - "movq %%mm4,%%mm5\n\t" - "movq %%mm2,%%mm3\n\t" - "movq %%mm2,%%mm1\n\t" - /*Expand these arrays.*/ - "punpckhbw %%mm0,%%mm5\n\t" - "punpcklbw %%mm0,%%mm4\n\t" - "punpckhbw %%mm0,%%mm3\n\t" - "punpcklbw %%mm0,%%mm2\n\t" - /*Preload...*/ - "movq %[OC_V3],%%mm0\n\t" - /*mm3:mm2=_pix[0...8+_ystride*2]-_pix[0...8+_ystride]*/ - "psubw %%mm5,%%mm3\n\t" - "psubw %%mm4,%%mm2\n\t" - /*Scale by 3.*/ - "pmullw %%mm0,%%mm3\n\t" - "pmullw %%mm0,%%mm2\n\t" - /*Preload...*/ - "movq %[OC_V4],%%mm0\n\t" - /*f=mm3:mm2==_pix[0...8]-_pix[0...8+_ystride*3]+ - 3*(_pix[0...8+_ystride*2]-_pix[0...8+_ystride])*/ - "paddw %%mm7,%%mm3\n\t" - "paddw %%mm6,%%mm2\n\t" - /*Add 4.*/ - "paddw %%mm0,%%mm3\n\t" - "paddw %%mm0,%%mm2\n\t" - /*"Divide" by 8.*/ - "psraw $3,%%mm3\n\t" - "psraw $3,%%mm2\n\t" - /*Now compute lflim of mm3:mm2 cf. Section 7.10 of the sepc.*/ - /*Free up mm5.*/ - "packuswb %%mm5,%%mm4\n\t" - /*mm0=L L L L*/ - "movq (%[ll]),%%mm0\n\t" - /*if(R_i<-2L||R_i>2L)R_i=0:*/ - "movq %%mm2,%%mm5\n\t" - "pxor %%mm6,%%mm6\n\t" - "movq %%mm0,%%mm7\n\t" - "psubw %%mm0,%%mm6\n\t" - "psllw $1,%%mm7\n\t" - "psllw $1,%%mm6\n\t" - /*mm2==R_3 R_2 R_1 R_0*/ - /*mm5==R_3 R_2 R_1 R_0*/ - /*mm6==-2L -2L -2L -2L*/ - /*mm7==2L 2L 2L 2L*/ - "pcmpgtw %%mm2,%%mm7\n\t" - "pcmpgtw %%mm6,%%mm5\n\t" - "pand %%mm7,%%mm2\n\t" - "movq %%mm0,%%mm7\n\t" - "pand %%mm5,%%mm2\n\t" - "psllw $1,%%mm7\n\t" - "movq %%mm3,%%mm5\n\t" - /*mm3==R_7 R_6 R_5 R_4*/ - /*mm5==R_7 R_6 R_5 R_4*/ - /*mm6==-2L -2L -2L -2L*/ - /*mm7==2L 2L 2L 2L*/ - "pcmpgtw %%mm3,%%mm7\n\t" - "pcmpgtw %%mm6,%%mm5\n\t" - "pand %%mm7,%%mm3\n\t" - "movq %%mm0,%%mm7\n\t" - "pand %%mm5,%%mm3\n\t" - /*if(R_i<-L)R_i'=R_i+2L; - if(R_i>L)R_i'=R_i-2L; - if(R_i<-L||R_i>L)R_i=-R_i':*/ - "psraw $1,%%mm6\n\t" - "movq %%mm2,%%mm5\n\t" - "psllw $1,%%mm7\n\t" - /*mm2==R_3 R_2 R_1 R_0*/ - /*mm5==R_3 R_2 R_1 R_0*/ - /*mm6==-L -L -L -L*/ - /*mm0==L L L L*/ - /*mm5=R_i>L?FF:00*/ - "pcmpgtw %%mm0,%%mm5\n\t" - /*mm6=-L>R_i?FF:00*/ - "pcmpgtw %%mm2,%%mm6\n\t" - /*mm7=R_i>L?2L:0*/ - "pand %%mm5,%%mm7\n\t" - /*mm2=R_i>L?R_i-2L:R_i*/ - "psubw %%mm7,%%mm2\n\t" - "movq %%mm0,%%mm7\n\t" - /*mm5=-L>R_i||R_i>L*/ - "por %%mm6,%%mm5\n\t" - "psllw $1,%%mm7\n\t" - /*mm7=-L>R_i?2L:0*/ - "pand %%mm6,%%mm7\n\t" - "pxor %%mm6,%%mm6\n\t" - /*mm2=-L>R_i?R_i+2L:R_i*/ - "paddw %%mm7,%%mm2\n\t" - "psubw %%mm0,%%mm6\n\t" - /*mm5=-L>R_i||R_i>L?-R_i':0*/ - "pand %%mm2,%%mm5\n\t" - "movq %%mm0,%%mm7\n\t" - /*mm2=-L>R_i||R_i>L?0:R_i*/ - "psubw %%mm5,%%mm2\n\t" - "psllw $1,%%mm7\n\t" - /*mm2=-L>R_i||R_i>L?-R_i':R_i*/ - "psubw %%mm5,%%mm2\n\t" - "movq %%mm3,%%mm5\n\t" - /*mm3==R_7 R_6 R_5 R_4*/ - /*mm5==R_7 R_6 R_5 R_4*/ - /*mm6==-L -L -L -L*/ - /*mm0==L L L L*/ - /*mm6=-L>R_i?FF:00*/ - "pcmpgtw %%mm3,%%mm6\n\t" - /*mm5=R_i>L?FF:00*/ - "pcmpgtw %%mm0,%%mm5\n\t" - /*mm7=R_i>L?2L:0*/ - "pand %%mm5,%%mm7\n\t" - /*mm2=R_i>L?R_i-2L:R_i*/ - "psubw %%mm7,%%mm3\n\t" - "psllw $1,%%mm0\n\t" - /*mm5=-L>R_i||R_i>L*/ - "por %%mm6,%%mm5\n\t" - /*mm0=-L>R_i?2L:0*/ - "pand %%mm6,%%mm0\n\t" - /*mm3=-L>R_i?R_i+2L:R_i*/ - "paddw %%mm0,%%mm3\n\t" - /*mm5=-L>R_i||R_i>L?-R_i':0*/ - "pand %%mm3,%%mm5\n\t" - /*mm2=-L>R_i||R_i>L?0:R_i*/ - "psubw %%mm5,%%mm3\n\t" - /*mm2=-L>R_i||R_i>L?-R_i':R_i*/ - "psubw %%mm5,%%mm3\n\t" - /*Unfortunately, there's no unsigned byte+signed byte with unsigned - saturation op code, so we have to promote things back 16 bits.*/ - "pxor %%mm0,%%mm0\n\t" - "movq %%mm4,%%mm5\n\t" - "punpcklbw %%mm0,%%mm4\n\t" - "punpckhbw %%mm0,%%mm5\n\t" - "movq %%mm1,%%mm6\n\t" - "punpcklbw %%mm0,%%mm1\n\t" - "punpckhbw %%mm0,%%mm6\n\t" - /*_pix[0...8+_ystride]+=R_i*/ - "paddw %%mm2,%%mm4\n\t" - "paddw %%mm3,%%mm5\n\t" - /*_pix[0...8+_ystride*2]-=R_i*/ - "psubw %%mm2,%%mm1\n\t" - "psubw %%mm3,%%mm6\n\t" - "packuswb %%mm5,%%mm4\n\t" - "packuswb %%mm6,%%mm1\n\t" - /*Write it back out.*/ - "movq %%mm4,(%[pix],%[ystride])\n\t" - "movq %%mm1,(%[pix],%[ystride],2)\n\t" - :[s]"=&S"(esi) - :[pix]"r"(_pix),[ystride]"r"((long)_ystride),[ll]"r"(_ll), - [OC_V3]"m"(OC_V3),[OC_V4]"m"(OC_V4) - :"memory" - ); -} - -/*This code implements the bulk of loop_filter_h(). - Data are striped p0 p1 p2 p3 ... p0 p1 p2 p3 ..., so in order to load all - four p0's to one register we must transpose the values in four mmx regs. - When half is done we repeat this for the rest.*/ -static void loop_filter_h4(unsigned char *_pix,long _ystride, - const ogg_int16_t *_ll){ - long esi; - long edi; - __asm__ __volatile__( - /*x x x x 3 2 1 0*/ - "movd (%[pix]),%%mm0\n\t" - /*esi=_ystride*3*/ - "lea (%[ystride],%[ystride],2),%[s]\n\t" - /*x x x x 7 6 5 4*/ - "movd (%[pix],%[ystride]),%%mm1\n\t" - /*x x x x B A 9 8*/ - "movd (%[pix],%[ystride],2),%%mm2\n\t" - /*x x x x F E D C*/ - "movd (%[pix],%[s]),%%mm3\n\t" - /*mm0=7 3 6 2 5 1 4 0*/ - "punpcklbw %%mm1,%%mm0\n\t" - /*mm2=F B E A D 9 C 8*/ - "punpcklbw %%mm3,%%mm2\n\t" - /*mm1=7 3 6 2 5 1 4 0*/ - "movq %%mm0,%%mm1\n\t" - /*mm0=F B 7 3 E A 6 2*/ - "punpckhwd %%mm2,%%mm0\n\t" - /*mm1=D 9 5 1 C 8 4 0*/ - "punpcklwd %%mm2,%%mm1\n\t" - "pxor %%mm7,%%mm7\n\t" - /*mm5=D 9 5 1 C 8 4 0*/ - "movq %%mm1,%%mm5\n\t" - /*mm1=x C x 8 x 4 x 0==pix[0]*/ - "punpcklbw %%mm7,%%mm1\n\t" - /*mm5=x D x 9 x 5 x 1==pix[1]*/ - "punpckhbw %%mm7,%%mm5\n\t" - /*mm3=F B 7 3 E A 6 2*/ - "movq %%mm0,%%mm3\n\t" - /*mm0=x E x A x 6 x 2==pix[2]*/ - "punpcklbw %%mm7,%%mm0\n\t" - /*mm3=x F x B x 7 x 3==pix[3]*/ - "punpckhbw %%mm7,%%mm3\n\t" - /*mm1=mm1-mm3==pix[0]-pix[3]*/ - "psubw %%mm3,%%mm1\n\t" - /*Save a copy of pix[2] for later.*/ - "movq %%mm0,%%mm4\n\t" - /*mm0=mm0-mm5==pix[2]-pix[1]*/ - "psubw %%mm5,%%mm0\n\t" - /*Scale by 3.*/ - "pmullw %[OC_V3],%%mm0\n\t" - /*f=mm1==_pix[0]-_pix[3]+ 3*(_pix[2]-_pix[1])*/ - "paddw %%mm1,%%mm0\n\t" - /*Add 4.*/ - "paddw %[OC_V4],%%mm0\n\t" - /*"Divide" by 8, producing the residuals R_i.*/ - "psraw $3,%%mm0\n\t" - /*Now compute lflim of mm0 cf. Section 7.10 of the sepc.*/ - /*mm6=L L L L*/ - "movq (%[ll]),%%mm6\n\t" - /*if(R_i<-2L||R_i>2L)R_i=0:*/ - "movq %%mm0,%%mm1\n\t" - "pxor %%mm2,%%mm2\n\t" - "movq %%mm6,%%mm3\n\t" - "psubw %%mm6,%%mm2\n\t" - "psllw $1,%%mm3\n\t" - "psllw $1,%%mm2\n\t" - /*mm0==R_3 R_2 R_1 R_0*/ - /*mm1==R_3 R_2 R_1 R_0*/ - /*mm2==-2L -2L -2L -2L*/ - /*mm3==2L 2L 2L 2L*/ - "pcmpgtw %%mm0,%%mm3\n\t" - "pcmpgtw %%mm2,%%mm1\n\t" - "pand %%mm3,%%mm0\n\t" - "pand %%mm1,%%mm0\n\t" - /*if(R_i<-L)R_i'=R_i+2L; - if(R_i>L)R_i'=R_i-2L; - if(R_i<-L||R_i>L)R_i=-R_i':*/ - "psraw $1,%%mm2\n\t" - "movq %%mm0,%%mm1\n\t" - "movq %%mm6,%%mm3\n\t" - /*mm0==R_3 R_2 R_1 R_0*/ - /*mm1==R_3 R_2 R_1 R_0*/ - /*mm2==-L -L -L -L*/ - /*mm6==L L L L*/ - /*mm2=-L>R_i?FF:00*/ - "pcmpgtw %%mm0,%%mm2\n\t" - /*mm1=R_i>L?FF:00*/ - "pcmpgtw %%mm6,%%mm1\n\t" - /*mm3=2L 2L 2L 2L*/ - "psllw $1,%%mm3\n\t" - /*mm6=2L 2L 2L 2L*/ - "psllw $1,%%mm6\n\t" - /*mm3=R_i>L?2L:0*/ - "pand %%mm1,%%mm3\n\t" - /*mm6=-L>R_i?2L:0*/ - "pand %%mm2,%%mm6\n\t" - /*mm0=R_i>L?R_i-2L:R_i*/ - "psubw %%mm3,%%mm0\n\t" - /*mm1=-L>R_i||R_i>L*/ - "por %%mm2,%%mm1\n\t" - /*mm0=-L>R_i?R_i+2L:R_i*/ - "paddw %%mm6,%%mm0\n\t" - /*mm1=-L>R_i||R_i>L?R_i':0*/ - "pand %%mm0,%%mm1\n\t" - /*mm0=-L>R_i||R_i>L?0:R_i*/ - "psubw %%mm1,%%mm0\n\t" - /*mm0=-L>R_i||R_i>L?-R_i':R_i*/ - "psubw %%mm1,%%mm0\n\t" - /*_pix[1]+=R_i;*/ - "paddw %%mm0,%%mm5\n\t" - /*_pix[2]-=R_i;*/ - "psubw %%mm0,%%mm4\n\t" - /*mm5=x x x x D 9 5 1*/ - "packuswb %%mm7,%%mm5\n\t" - /*mm4=x x x x E A 6 2*/ - "packuswb %%mm7,%%mm4\n\t" - /*mm5=E D A 9 6 5 2 1*/ - "punpcklbw %%mm4,%%mm5\n\t" - /*edi=6 5 2 1*/ - "movd %%mm5,%%edi\n\t" - "movw %%di,1(%[pix])\n\t" - /*Why is there such a big stall here?*/ - "psrlq $32,%%mm5\n\t" - "shrl $16,%%edi\n\t" - "movw %%di,1(%[pix],%[ystride])\n\t" - /*edi=E D A 9*/ - "movd %%mm5,%%edi\n\t" - "movw %%di,1(%[pix],%[ystride],2)\n\t" - "shrl $16,%%edi\n\t" - "movw %%di,1(%[pix],%[s])\n\t" - :[s]"=&S"(esi),[d]"=&D"(edi), - [pix]"+r"(_pix),[ystride]"+r"(_ystride),[ll]"+r"(_ll) - :[OC_V3]"m"(OC_V3),[OC_V4]"m"(OC_V4) - :"memory" - ); -} - -static void loop_filter_h(unsigned char *_pix,int _ystride, - const ogg_int16_t *_ll){ - _pix-=2; - loop_filter_h4(_pix,_ystride,_ll); - loop_filter_h4(_pix+(_ystride<<2),_ystride,_ll); -} - -static void loop_filter_mmx(PB_INSTANCE *pbi, int FLimit){ - int j; - ogg_int16_t __attribute__((aligned(8))) ll[4]; - unsigned char *cp = pbi->display_fragments; - ogg_uint32_t *bp = pbi->recon_pixel_index_table; - - if ( FLimit == 0 ) return; - ll[0]=ll[1]=ll[2]=ll[3]=FLimit; - - for ( j = 0; j < 3 ; j++){ - ogg_uint32_t *bp_begin = bp; - ogg_uint32_t *bp_end; - int stride; - int h; - - switch(j) { - case 0: /* y */ - bp_end = bp + pbi->YPlaneFragments; - h = pbi->HFragments; - stride = pbi->YStride; - break; - default: /* u,v, 4:20 specific */ - bp_end = bp + pbi->UVPlaneFragments; - h = pbi->HFragments >> 1; - stride = pbi->UVStride; - break; - } - - while(bpbp_left) - loop_filter_h(&pbi->LastFrameRecon[bp[0]],stride,ll); - if(bp_left>bp_begin) - loop_filter_v(&pbi->LastFrameRecon[bp[0]],stride,ll); - if(bp+1LastFrameRecon[bp[0]]+8,stride,ll); - if(bp+hLastFrameRecon[bp[h]],stride,ll); - } - bp++; - cp++; - } - } - } - - __asm__ __volatile__("emms\n\t"); -} - -/* install our implementation in the function table */ -void dsp_mmx_dct_decode_init(DspFunctions *funcs) -{ - funcs->LoopFilter = loop_filter_mmx; -} - -#endif /* USE_ASM */ diff --git a/Engine/lib/libtheora/lib/enc/x86_64/dsp_mmx.c b/Engine/lib/libtheora/lib/enc/x86_64/dsp_mmx.c deleted file mode 100644 index 6c2689e63..000000000 --- a/Engine/lib/libtheora/lib/enc/x86_64/dsp_mmx.c +++ /dev/null @@ -1,303 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: dsp_mmx.c 15397 2008-10-14 02:06:24Z tterribe $ - - ********************************************************************/ - -#include - -#include "../codec_internal.h" -#include "../dsp.h" - -#if defined(USE_ASM) - -typedef unsigned long long ogg_uint64_t; - -static const __attribute__ ((aligned(8),used)) ogg_int64_t V128 = 0x0080008000800080LL; - -#define DSP_OP_AVG(a,b) ((((int)(a)) + ((int)(b)))/2) -#define DSP_OP_DIFF(a,b) (((int)(a)) - ((int)(b))) -#define DSP_OP_ABS_DIFF(a,b) abs((((int)(a)) - ((int)(b)))) - -static void sub8x8__mmx (unsigned char *FiltPtr, unsigned char *ReconPtr, - ogg_int16_t *DctInputPtr, ogg_uint32_t PixelsPerLine, - ogg_uint32_t ReconPixelsPerLine) -{ - __asm__ __volatile__ ( - " .balign 16 \n\t" - - " pxor %%mm7, %%mm7 \n\t" - - ".rept 8 \n\t" - " movq (%0), %%mm0 \n\t" /* mm0 = FiltPtr */ - " movq (%1), %%mm1 \n\t" /* mm1 = ReconPtr */ - " movq %%mm0, %%mm2 \n\t" /* dup to prepare for up conversion */ - " movq %%mm1, %%mm3 \n\t" /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - " punpcklbw %%mm7, %%mm0 \n\t" /* mm0 = INT16(FiltPtr) */ - " punpcklbw %%mm7, %%mm1 \n\t" /* mm1 = INT16(ReconPtr) */ - " punpckhbw %%mm7, %%mm2 \n\t" /* mm2 = INT16(FiltPtr) */ - " punpckhbw %%mm7, %%mm3 \n\t" /* mm3 = INT16(ReconPtr) */ - /* start calculation */ - " psubw %%mm1, %%mm0 \n\t" /* mm0 = FiltPtr - ReconPtr */ - " psubw %%mm3, %%mm2 \n\t" /* mm2 = FiltPtr - ReconPtr */ - " movq %%mm0, (%2) \n\t" /* write answer out */ - " movq %%mm2, 8(%2) \n\t" /* write answer out */ - /* Increment pointers */ - " add $16, %2 \n\t" - " add %3, %0 \n\t" - " add %4, %1 \n\t" - ".endr \n\t" - - : "+r" (FiltPtr), - "+r" (ReconPtr), - "+r" (DctInputPtr) - : "r" ((ogg_uint64_t)PixelsPerLine), - "r" ((ogg_uint64_t)ReconPixelsPerLine) - : "memory" - ); -} - -static void sub8x8_128__mmx (unsigned char *FiltPtr, ogg_int16_t *DctInputPtr, - ogg_uint32_t PixelsPerLine) -{ - ogg_uint64_t ppl = PixelsPerLine; - - __asm__ __volatile__ ( - " .balign 16 \n\t" - - " pxor %%mm7, %%mm7 \n\t" - " movq %[V128], %%mm1 \n\t" - - ".rept 8 \n\t" - " movq (%0), %%mm0 \n\t" /* mm0 = FiltPtr */ - " movq %%mm0, %%mm2 \n\t" /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - " punpcklbw %%mm7, %%mm0 \n\t" /* mm0 = INT16(FiltPtr) */ - " punpckhbw %%mm7, %%mm2 \n\t" /* mm2 = INT16(FiltPtr) */ - /* start calculation */ - " psubw %%mm1, %%mm0 \n\t" /* mm0 = FiltPtr - 128 */ - " psubw %%mm1, %%mm2 \n\t" /* mm2 = FiltPtr - 128 */ - " movq %%mm0, (%1) \n\t" /* write answer out */ - " movq %%mm2, 8(%1) \n\t" /* write answer out */ - /* Increment pointers */ - " add $16, %1 \n\t" - " add %2, %0 \n\t" - ".endr \n\t" - - : "+r" (FiltPtr), - "+r" (DctInputPtr) - : "r" (ppl), /* gcc bug? a cast won't work here, e.g. (ogg_uint64_t)PixelsPerLine */ - [V128] "m" (V128) - : "memory" - ); -} - -static void sub8x8avg2__mmx (unsigned char *FiltPtr, unsigned char *ReconPtr1, - unsigned char *ReconPtr2, ogg_int16_t *DctInputPtr, - ogg_uint32_t PixelsPerLine, - ogg_uint32_t ReconPixelsPerLine) -{ - __asm__ __volatile__ ( - " .balign 16 \n\t" - - " pxor %%mm7, %%mm7 \n\t" - - ".rept 8 \n\t" - " movq (%0), %%mm0 \n\t" /* mm0 = FiltPtr */ - " movq (%1), %%mm1 \n\t" /* mm1 = ReconPtr1 */ - " movq (%2), %%mm4 \n\t" /* mm1 = ReconPtr2 */ - " movq %%mm0, %%mm2 \n\t" /* dup to prepare for up conversion */ - " movq %%mm1, %%mm3 \n\t" /* dup to prepare for up conversion */ - " movq %%mm4, %%mm5 \n\t" /* dup to prepare for up conversion */ - /* convert from UINT8 to INT16 */ - " punpcklbw %%mm7, %%mm0 \n\t" /* mm0 = INT16(FiltPtr) */ - " punpcklbw %%mm7, %%mm1 \n\t" /* mm1 = INT16(ReconPtr1) */ - " punpcklbw %%mm7, %%mm4 \n\t" /* mm1 = INT16(ReconPtr2) */ - " punpckhbw %%mm7, %%mm2 \n\t" /* mm2 = INT16(FiltPtr) */ - " punpckhbw %%mm7, %%mm3 \n\t" /* mm3 = INT16(ReconPtr1) */ - " punpckhbw %%mm7, %%mm5 \n\t" /* mm3 = INT16(ReconPtr2) */ - /* average ReconPtr1 and ReconPtr2 */ - " paddw %%mm4, %%mm1 \n\t" /* mm1 = ReconPtr1 + ReconPtr2 */ - " paddw %%mm5, %%mm3 \n\t" /* mm3 = ReconPtr1 + ReconPtr2 */ - " psrlw $1, %%mm1 \n\t" /* mm1 = (ReconPtr1 + ReconPtr2) / 2 */ - " psrlw $1, %%mm3 \n\t" /* mm3 = (ReconPtr1 + ReconPtr2) / 2 */ - " psubw %%mm1, %%mm0 \n\t" /* mm0 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - " psubw %%mm3, %%mm2 \n\t" /* mm2 = FiltPtr - ((ReconPtr1 + ReconPtr2) / 2) */ - " movq %%mm0, (%3) \n\t" /* write answer out */ - " movq %%mm2, 8(%3) \n\t" /* write answer out */ - /* Increment pointers */ - " add $16, %3 \n\t" - " add %4, %0 \n\t" - " add %5, %1 \n\t" - " add %5, %2 \n\t" - ".endr \n\t" - - : "+r" (FiltPtr), - "+r" (ReconPtr1), - "+r" (ReconPtr2), - "+r" (DctInputPtr) - : "r" ((ogg_uint64_t)PixelsPerLine), - "r" ((ogg_uint64_t)ReconPixelsPerLine) - : "memory" - ); -} - -static ogg_uint32_t intra8x8_err__mmx (unsigned char *DataPtr, ogg_uint32_t Stride) -{ - ogg_uint64_t XSum; - ogg_uint64_t XXSum; - - __asm__ __volatile__ ( - " .balign 16 \n\t" - - " pxor %%mm5, %%mm5 \n\t" - " pxor %%mm6, %%mm6 \n\t" - " pxor %%mm7, %%mm7 \n\t" - " mov $8, %%rdi \n\t" - "1: \n\t" - " movq (%2), %%mm0 \n\t" /* take 8 bytes */ - " movq %%mm0, %%mm2 \n\t" - - " punpcklbw %%mm6, %%mm0 \n\t" - " punpckhbw %%mm6, %%mm2 \n\t" - - " paddw %%mm0, %%mm5 \n\t" - " paddw %%mm2, %%mm5 \n\t" - - " pmaddwd %%mm0, %%mm0 \n\t" - " pmaddwd %%mm2, %%mm2 \n\t" - - " paddd %%mm0, %%mm7 \n\t" - " paddd %%mm2, %%mm7 \n\t" - - " add %3, %2 \n\t" /* Inc pointer into src data */ - - " dec %%rdi \n\t" - " jnz 1b \n\t" - - " movq %%mm5, %%mm0 \n\t" - " psrlq $32, %%mm5 \n\t" - " paddw %%mm0, %%mm5 \n\t" - " movq %%mm5, %%mm0 \n\t" - " psrlq $16, %%mm5 \n\t" - " paddw %%mm0, %%mm5 \n\t" - " movd %%mm5, %%rdi \n\t" - " movsx %%di, %%rdi \n\t" - " mov %%rdi, %0 \n\t" - - " movq %%mm7, %%mm0 \n\t" - " psrlq $32, %%mm7 \n\t" - " paddd %%mm0, %%mm7 \n\t" - " movd %%mm7, %1 \n\t" - - : "=r" (XSum), - "=r" (XXSum), - "+r" (DataPtr) - : "r" ((ogg_uint64_t)Stride) - : "rdi", "memory" - ); - - /* Compute population variance as mis-match metric. */ - return (( (XXSum<<6) - XSum*XSum ) ); -} - -static ogg_uint32_t inter8x8_err__mmx (unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr, ogg_uint32_t RefStride) -{ - ogg_uint64_t XSum; - ogg_uint64_t XXSum; - - __asm__ __volatile__ ( - " .balign 16 \n\t" - - " pxor %%mm5, %%mm5 \n\t" - " pxor %%mm6, %%mm6 \n\t" - " pxor %%mm7, %%mm7 \n\t" - " mov $8, %%rdi \n\t" - "1: \n\t" - " movq (%2), %%mm0 \n\t" /* take 8 bytes */ - " movq (%3), %%mm1 \n\t" - " movq %%mm0, %%mm2 \n\t" - " movq %%mm1, %%mm3 \n\t" - - " punpcklbw %%mm6, %%mm0 \n\t" - " punpcklbw %%mm6, %%mm1 \n\t" - " punpckhbw %%mm6, %%mm2 \n\t" - " punpckhbw %%mm6, %%mm3 \n\t" - - " psubsw %%mm1, %%mm0 \n\t" - " psubsw %%mm3, %%mm2 \n\t" - - " paddw %%mm0, %%mm5 \n\t" - " paddw %%mm2, %%mm5 \n\t" - - " pmaddwd %%mm0, %%mm0 \n\t" - " pmaddwd %%mm2, %%mm2 \n\t" - - " paddd %%mm0, %%mm7 \n\t" - " paddd %%mm2, %%mm7 \n\t" - - " add %4, %2 \n\t" /* Inc pointer into src data */ - " add %5, %3 \n\t" /* Inc pointer into ref data */ - - " dec %%rdi \n\t" - " jnz 1b \n\t" - - " movq %%mm5, %%mm0 \n\t" - " psrlq $32, %%mm5 \n\t" - " paddw %%mm0, %%mm5 \n\t" - " movq %%mm5, %%mm0 \n\t" - " psrlq $16, %%mm5 \n\t" - " paddw %%mm0, %%mm5 \n\t" - " movd %%mm5, %%rdi \n\t" - " movsx %%di, %%rdi \n\t" - " mov %%rdi, %0 \n\t" - - " movq %%mm7, %%mm0 \n\t" - " psrlq $32, %%mm7 \n\t" - " paddd %%mm0, %%mm7 \n\t" - " movd %%mm7, %1 \n\t" - - : "=m" (XSum), - "=m" (XXSum), - "+r" (SrcData), - "+r" (RefDataPtr) - : "r" ((ogg_uint64_t)SrcStride), - "r" ((ogg_uint64_t)RefStride) - : "rdi", "memory" - ); - - /* Compute and return population variance as mis-match metric. */ - return (( (XXSum<<6) - XSum*XSum )); -} - -static void restore_fpu (void) -{ - __asm__ __volatile__ ( - " emms \n\t" - ); -} - -void dsp_mmx_init(DspFunctions *funcs) -{ - funcs->restore_fpu = restore_fpu; - funcs->sub8x8 = sub8x8__mmx; - funcs->sub8x8_128 = sub8x8_128__mmx; - funcs->sub8x8avg2 = sub8x8avg2__mmx; - funcs->intra8x8_err = intra8x8_err__mmx; - funcs->inter8x8_err = inter8x8_err__mmx; -} - -#endif /* USE_ASM */ diff --git a/Engine/lib/libtheora/lib/enc/x86_64/dsp_mmxext.c b/Engine/lib/libtheora/lib/enc/x86_64/dsp_mmxext.c deleted file mode 100644 index f0aeed96e..000000000 --- a/Engine/lib/libtheora/lib/enc/x86_64/dsp_mmxext.c +++ /dev/null @@ -1,323 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: dsp_mmxext.c 15397 2008-10-14 02:06:24Z tterribe $ - - ********************************************************************/ - -#include - -#include "../codec_internal.h" -#include "../dsp.h" - -#if defined(USE_ASM) - -typedef unsigned long long ogg_uint64_t; - -static ogg_uint32_t sad8x8__mmxext (unsigned char *ptr1, ogg_uint32_t stride1, - unsigned char *ptr2, ogg_uint32_t stride2) -{ - ogg_uint32_t DiffVal; - - __asm__ __volatile__ ( - " .balign 16 \n\t" - " pxor %%mm7, %%mm7 \n\t" /* mm7 contains the result */ - - ".rept 7 \n\t" - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ - " movq (%2), %%mm1 \n\t" - " psadbw %%mm1, %%mm0 \n\t" - " add %3, %1 \n\t" /* Inc pointer into the new data */ - " paddw %%mm0, %%mm7 \n\t" /* accumulate difference... */ - " add %4, %2 \n\t" /* Inc pointer into ref data */ - ".endr \n\t" - - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ - " movq (%2), %%mm1 \n\t" - " psadbw %%mm1, %%mm0 \n\t" - " paddw %%mm0, %%mm7 \n\t" /* accumulate difference... */ - " movd %%mm7, %0 \n\t" - - : "=r" (DiffVal), - "+r" (ptr1), - "+r" (ptr2) - : "r" ((ogg_uint64_t)stride1), - "r" ((ogg_uint64_t)stride2) - : "memory" - ); - - return DiffVal; -} - -static ogg_uint32_t sad8x8_thres__mmxext (unsigned char *ptr1, ogg_uint32_t stride1, - unsigned char *ptr2, ogg_uint32_t stride2, - ogg_uint32_t thres) -{ - ogg_uint32_t DiffVal; - - __asm__ __volatile__ ( - " .balign 16 \n\t" - " pxor %%mm7, %%mm7 \n\t" /* mm7 contains the result */ - - ".rept 8 \n\t" - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ - " movq (%2), %%mm1 \n\t" - " psadbw %%mm1, %%mm0 \n\t" - " add %3, %1 \n\t" /* Inc pointer into the new data */ - " paddw %%mm0, %%mm7 \n\t" /* accumulate difference... */ - " add %4, %2 \n\t" /* Inc pointer into ref data */ - ".endr \n\t" - - " movd %%mm7, %0 \n\t" - - : "=r" (DiffVal), - "+r" (ptr1), - "+r" (ptr2) - : "r" ((ogg_uint64_t)stride1), - "r" ((ogg_uint64_t)stride2) - : "memory" - ); - - return DiffVal; -} - -static ogg_uint32_t sad8x8_xy2_thres__mmxext (unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr1, - unsigned char *RefDataPtr2, ogg_uint32_t RefStride, - ogg_uint32_t thres) -{ - ogg_uint32_t DiffVal; - - __asm__ __volatile__ ( - " .balign 16 \n\t" - " pxor %%mm7, %%mm7 \n\t" /* mm7 contains the result */ - ".rept 8 \n\t" - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ - " movq (%2), %%mm1 \n\t" - " movq (%3), %%mm2 \n\t" - " pavgb %%mm2, %%mm1 \n\t" - " psadbw %%mm1, %%mm0 \n\t" - - " add %4, %1 \n\t" /* Inc pointer into the new data */ - " paddw %%mm0, %%mm7 \n\t" /* accumulate difference... */ - " add %5, %2 \n\t" /* Inc pointer into ref data */ - " add %5, %3 \n\t" /* Inc pointer into ref data */ - ".endr \n\t" - - " movd %%mm7, %0 \n\t" - : "=m" (DiffVal), - "+r" (SrcData), - "+r" (RefDataPtr1), - "+r" (RefDataPtr2) - : "r" ((ogg_uint64_t)SrcStride), - "r" ((ogg_uint64_t)RefStride) - : "memory" - ); - - return DiffVal; -} - -static ogg_uint32_t row_sad8__mmxext (unsigned char *Src1, unsigned char *Src2) -{ - ogg_uint32_t MaxSad; - - __asm__ __volatile__ ( - " .balign 16 \n\t" - - " movd (%1), %%mm0 \n\t" - " movd (%2), %%mm1 \n\t" - " psadbw %%mm0, %%mm1 \n\t" - " movd 4(%1), %%mm2 \n\t" - " movd 4(%2), %%mm3 \n\t" - " psadbw %%mm2, %%mm3 \n\t" - - " pmaxsw %%mm1, %%mm3 \n\t" - " movd %%mm3, %0 \n\t" - " andl $0xffff, %0 \n\t" - - : "=m" (MaxSad), - "+r" (Src1), - "+r" (Src2) - : - : "memory" - ); - - return MaxSad; -} - -static ogg_uint32_t col_sad8x8__mmxext (unsigned char *Src1, unsigned char *Src2, - ogg_uint32_t stride) -{ - ogg_uint32_t MaxSad; - - __asm__ __volatile__ ( - " .balign 16 \n\t" - - " pxor %%mm3, %%mm3 \n\t" /* zero out mm3 for unpack */ - " pxor %%mm4, %%mm4 \n\t" /* mm4 low sum */ - " pxor %%mm5, %%mm5 \n\t" /* mm5 high sum */ - " pxor %%mm6, %%mm6 \n\t" /* mm6 low sum */ - " pxor %%mm7, %%mm7 \n\t" /* mm7 high sum */ - " mov $4, %%rdi \n\t" /* 4 rows */ - "1: \n\t" - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ - " movq (%2), %%mm1 \n\t" /* take 8 bytes */ - - " movq %%mm0, %%mm2 \n\t" - " psubusb %%mm1, %%mm0 \n\t" /* A - B */ - " psubusb %%mm2, %%mm1 \n\t" /* B - A */ - " por %%mm1, %%mm0 \n\t" /* and or gives abs difference */ - " movq %%mm0, %%mm1 \n\t" - - " punpcklbw %%mm3, %%mm0 \n\t" /* unpack to higher precision for accumulation */ - " paddw %%mm0, %%mm4 \n\t" /* accumulate difference... */ - " punpckhbw %%mm3, %%mm1 \n\t" /* unpack high four bytes to higher precision */ - " paddw %%mm1, %%mm5 \n\t" /* accumulate difference... */ - " add %3, %1 \n\t" /* Inc pointer into the new data */ - " add %3, %2 \n\t" /* Inc pointer into the new data */ - - " dec %%rdi \n\t" - " jnz 1b \n\t" - - " mov $4, %%rdi \n\t" /* 4 rows */ - "2: \n\t" - " movq (%1), %%mm0 \n\t" /* take 8 bytes */ - " movq (%2), %%mm1 \n\t" /* take 8 bytes */ - - " movq %%mm0, %%mm2 \n\t" - " psubusb %%mm1, %%mm0 \n\t" /* A - B */ - " psubusb %%mm2, %%mm1 \n\t" /* B - A */ - " por %%mm1, %%mm0 \n\t" /* and or gives abs difference */ - " movq %%mm0, %%mm1 \n\t" - - " punpcklbw %%mm3, %%mm0 \n\t" /* unpack to higher precision for accumulation */ - " paddw %%mm0, %%mm6 \n\t" /* accumulate difference... */ - " punpckhbw %%mm3, %%mm1 \n\t" /* unpack high four bytes to higher precision */ - " paddw %%mm1, %%mm7 \n\t" /* accumulate difference... */ - " add %3, %1 \n\t" /* Inc pointer into the new data */ - " add %3, %2 \n\t" /* Inc pointer into the new data */ - - " dec %%rdi \n\t" - " jnz 2b \n\t" - - " pmaxsw %%mm6, %%mm7 \n\t" - " pmaxsw %%mm4, %%mm5 \n\t" - " pmaxsw %%mm5, %%mm7 \n\t" - " movq %%mm7, %%mm6 \n\t" - " psrlq $32, %%mm6 \n\t" - " pmaxsw %%mm6, %%mm7 \n\t" - " movq %%mm7, %%mm6 \n\t" - " psrlq $16, %%mm6 \n\t" - " pmaxsw %%mm6, %%mm7 \n\t" - " movd %%mm7, %0 \n\t" - " andl $0xffff, %0 \n\t" - - : "=r" (MaxSad), - "+r" (Src1), - "+r" (Src2) - : "r" ((ogg_uint64_t)stride) - : "memory", "rdi" - ); - - return MaxSad; -} - -static ogg_uint32_t inter8x8_err_xy2__mmxext (unsigned char *SrcData, ogg_uint32_t SrcStride, - unsigned char *RefDataPtr1, - unsigned char *RefDataPtr2, ogg_uint32_t RefStride) -{ - ogg_uint64_t XSum; - ogg_uint64_t XXSum; - - __asm__ __volatile__ ( - " .balign 16 \n\t" - - " pxor %%mm4, %%mm4 \n\t" - " pxor %%mm5, %%mm5 \n\t" - " pxor %%mm6, %%mm6 \n\t" - " pxor %%mm7, %%mm7 \n\t" - " mov $8, %%rdi \n\t" - "1: \n\t" - " movq (%2), %%mm0 \n\t" /* take 8 bytes */ - - " movq (%3), %%mm2 \n\t" - " movq (%4), %%mm1 \n\t" /* take average of mm2 and mm1 */ - " pavgb %%mm2, %%mm1 \n\t" - - " movq %%mm0, %%mm2 \n\t" - " movq %%mm1, %%mm3 \n\t" - - " punpcklbw %%mm6, %%mm0 \n\t" - " punpcklbw %%mm4, %%mm1 \n\t" - " punpckhbw %%mm6, %%mm2 \n\t" - " punpckhbw %%mm4, %%mm3 \n\t" - - " psubsw %%mm1, %%mm0 \n\t" - " psubsw %%mm3, %%mm2 \n\t" - - " paddw %%mm0, %%mm5 \n\t" - " paddw %%mm2, %%mm5 \n\t" - - " pmaddwd %%mm0, %%mm0 \n\t" - " pmaddwd %%mm2, %%mm2 \n\t" - - " paddd %%mm0, %%mm7 \n\t" - " paddd %%mm2, %%mm7 \n\t" - - " add %5, %2 \n\t" /* Inc pointer into src data */ - " add %6, %3 \n\t" /* Inc pointer into ref data */ - " add %6, %4 \n\t" /* Inc pointer into ref data */ - - " dec %%rdi \n\t" - " jnz 1b \n\t" - - " movq %%mm5, %%mm0 \n\t" - " psrlq $32, %%mm5 \n\t" - " paddw %%mm0, %%mm5 \n\t" - " movq %%mm5, %%mm0 \n\t" - " psrlq $16, %%mm5 \n\t" - " paddw %%mm0, %%mm5 \n\t" - " movd %%mm5, %%edi \n\t" - " movsx %%di, %%edi \n\t" - " movl %%edi, %0 \n\t" - - " movq %%mm7, %%mm0 \n\t" - " psrlq $32, %%mm7 \n\t" - " paddd %%mm0, %%mm7 \n\t" - " movd %%mm7, %1 \n\t" - - : "=m" (XSum), - "=m" (XXSum), - "+r" (SrcData), - "+r" (RefDataPtr1), - "+r" (RefDataPtr2) - : "r" ((ogg_uint64_t)SrcStride), - "r" ((ogg_uint64_t)RefStride) - : "rdi", "memory" - ); - - /* Compute and return population variance as mis-match metric. */ - return (( (XXSum<<6) - XSum*XSum )); -} - -void dsp_mmxext_init(DspFunctions *funcs) -{ - funcs->row_sad8 = row_sad8__mmxext; - funcs->col_sad8x8 = col_sad8x8__mmxext; - funcs->sad8x8 = sad8x8__mmxext; - funcs->sad8x8_thres = sad8x8_thres__mmxext; - funcs->sad8x8_xy2_thres = sad8x8_xy2_thres__mmxext; - funcs->inter8x8_err_xy2 = inter8x8_err_xy2__mmxext; -} - -#endif /* USE_ASM */ diff --git a/Engine/lib/libtheora/lib/enc/x86_64/fdct_mmx.c b/Engine/lib/libtheora/lib/enc/x86_64/fdct_mmx.c deleted file mode 100644 index 3765561cf..000000000 --- a/Engine/lib/libtheora/lib/enc/x86_64/fdct_mmx.c +++ /dev/null @@ -1,342 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 1999-2006 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ********************************************************************/ - -/* mmx fdct implementation for x86_64 */ -/* $Id: fdct_mmx.c 15397 2008-10-14 02:06:24Z tterribe $ */ - -#include "theora/theora.h" -#include "../codec_internal.h" -#include "../dsp.h" - -#if defined(USE_ASM) - -static const __attribute__ ((aligned(8),used)) ogg_int64_t xC1S7 = 0x0fb15fb15fb15fb15LL; -static const __attribute__ ((aligned(8),used)) ogg_int64_t xC2S6 = 0x0ec83ec83ec83ec83LL; -static const __attribute__ ((aligned(8),used)) ogg_int64_t xC3S5 = 0x0d4dbd4dbd4dbd4dbLL; -static const __attribute__ ((aligned(8),used)) ogg_int64_t xC4S4 = 0x0b505b505b505b505LL; -static const __attribute__ ((aligned(8),used)) ogg_int64_t xC5S3 = 0x08e3a8e3a8e3a8e3aLL; -static const __attribute__ ((aligned(8),used)) ogg_int64_t xC6S2 = 0x061f861f861f861f8LL; -static const __attribute__ ((aligned(8),used)) ogg_int64_t xC7S1 = 0x031f131f131f131f1LL; - -#if defined(__MINGW32__) || defined(__CYGWIN__) || \ - defined(__OS2__) || (defined (__OpenBSD__) && !defined(__ELF__)) -# define M(a) "_" #a -#else -# define M(a) #a -#endif - -/* execute stage 1 of forward DCT */ -#define Fdct_mmx(ip0,ip1,ip2,ip3,ip4,ip5,ip6,ip7,temp) \ - " movq " #ip0 ", %%mm0 \n\t" \ - " movq " #ip1 ", %%mm1 \n\t" \ - " movq " #ip3 ", %%mm2 \n\t" \ - " movq " #ip5 ", %%mm3 \n\t" \ - " movq %%mm0, %%mm4 \n\t" \ - " movq %%mm1, %%mm5 \n\t" \ - " movq %%mm2, %%mm6 \n\t" \ - " movq %%mm3, %%mm7 \n\t" \ - \ - " paddsw " #ip7 ", %%mm0 \n\t" /* mm0 = ip0 + ip7 = is07 */ \ - " paddsw " #ip2 ", %%mm1 \n\t" /* mm1 = ip1 + ip2 = is12 */ \ - " paddsw " #ip4 ", %%mm2 \n\t" /* mm2 = ip3 + ip4 = is34 */ \ - " paddsw " #ip6 ", %%mm3 \n\t" /* mm3 = ip5 + ip6 = is56 */ \ - " psubsw " #ip7 ", %%mm4 \n\t" /* mm4 = ip0 - ip7 = id07 */ \ - " psubsw " #ip2 ", %%mm5 \n\t" /* mm5 = ip1 - ip2 = id12 */ \ - \ - " psubsw %%mm2, %%mm0 \n\t" /* mm0 = is07 - is34 */ \ - \ - " paddsw %%mm2, %%mm2 \n\t" \ - \ - " psubsw " #ip4 ", %%mm6 \n\t" /* mm6 = ip3 - ip4 = id34 */ \ - \ - " paddsw %%mm0, %%mm2 \n\t" /* mm2 = is07 + is34 = is0734 */ \ - " psubsw %%mm3, %%mm1 \n\t" /* mm1 = is12 - is56 */ \ - " movq %%mm0," #temp " \n\t" /* Save is07 - is34 to free mm0; */ \ - " paddsw %%mm3, %%mm3 \n\t" \ - " paddsw %%mm1, %%mm3 \n\t" /* mm3 = is12 + 1s56 = is1256 */ \ - \ - " psubsw " #ip6 ", %%mm7 \n\t" /* mm7 = ip5 - ip6 = id56 */ \ - /* ------------------------------------------------------------------- */ \ - " psubsw %%mm7, %%mm5 \n\t" /* mm5 = id12 - id56 */ \ - " paddsw %%mm7, %%mm7 \n\t" \ - " paddsw %%mm5, %%mm7 \n\t" /* mm7 = id12 + id56 */ \ - /* ------------------------------------------------------------------- */ \ - " psubsw %%mm3, %%mm2 \n\t" /* mm2 = is0734 - is1256 */ \ - " paddsw %%mm3, %%mm3 \n\t" \ - \ - " movq %%mm2, %%mm0 \n\t" /* make a copy */ \ - " paddsw %%mm2, %%mm3 \n\t" /* mm3 = is0734 + is1256 */ \ - \ - " pmulhw %[xC4S4], %%mm0 \n\t" /* mm0 = xC4S4 * ( is0734 - is1256 ) - ( is0734 - is1256 ) */ \ - " paddw %%mm2, %%mm0 \n\t" /* mm0 = xC4S4 * ( is0734 - is1256 ) */ \ - " psrlw $15, %%mm2 \n\t" \ - " paddw %%mm2, %%mm0 \n\t" /* Truncate mm0, now it is op[4] */ \ - \ - " movq %%mm3, %%mm2 \n\t" \ - " movq %%mm0," #ip4 " \n\t" /* save ip4, now mm0,mm2 are free */ \ - \ - " movq %%mm3, %%mm0 \n\t" \ - " pmulhw %[xC4S4], %%mm3 \n\t" /* mm3 = xC4S4 * ( is0734 +is1256 ) - ( is0734 +is1256 ) */ \ - \ - " psrlw $15, %%mm2 \n\t" \ - " paddw %%mm0, %%mm3 \n\t" /* mm3 = xC4S4 * ( is0734 +is1256 ) */ \ - " paddw %%mm2, %%mm3 \n\t" /* Truncate mm3, now it is op[0] */ \ - \ - " movq %%mm3," #ip0 " \n\t" \ - /* ------------------------------------------------------------------- */ \ - " movq " #temp ", %%mm3 \n\t" /* mm3 = irot_input_y */ \ - " pmulhw %[xC2S6], %%mm3 \n\t" /* mm3 = xC2S6 * irot_input_y - irot_input_y */ \ - \ - " movq " #temp ", %%mm2 \n\t" \ - " movq %%mm2, %%mm0 \n\t" \ - \ - " psrlw $15, %%mm2 \n\t" /* mm3 = xC2S6 * irot_input_y */ \ - " paddw %%mm0, %%mm3 \n\t" \ - \ - " paddw %%mm2, %%mm3 \n\t" /* Truncated */ \ - " movq %%mm5, %%mm0 \n\t" \ - \ - " movq %%mm5, %%mm2 \n\t" \ - " pmulhw %[xC6S2], %%mm0 \n\t" /* mm0 = xC6S2 * irot_input_x */ \ - \ - " psrlw $15, %%mm2 \n\t" \ - " paddw %%mm2, %%mm0 \n\t" /* Truncated */ \ - \ - " paddsw %%mm0, %%mm3 \n\t" /* ip[2] */ \ - " movq %%mm3," #ip2 " \n\t" /* Save ip2 */ \ - \ - " movq %%mm5, %%mm0 \n\t" \ - " movq %%mm5, %%mm2 \n\t" \ - \ - " pmulhw %[xC2S6], %%mm5 \n\t" /* mm5 = xC2S6 * irot_input_x - irot_input_x */ \ - " psrlw $15, %%mm2 \n\t" \ - \ - " movq " #temp ", %%mm3 \n\t" \ - " paddw %%mm0, %%mm5 \n\t" /* mm5 = xC2S6 * irot_input_x */ \ - \ - " paddw %%mm2, %%mm5 \n\t" /* Truncated */ \ - " movq %%mm3, %%mm2 \n\t" \ - \ - " pmulhw %[xC6S2], %%mm3 \n\t" /* mm3 = xC6S2 * irot_input_y */ \ - " psrlw $15, %%mm2 \n\t" \ - \ - " paddw %%mm2, %%mm3 \n\t" /* Truncated */ \ - " psubsw %%mm5, %%mm3 \n\t" \ - \ - " movq %%mm3," #ip6 " \n\t" \ - /* ------------------------------------------------------------------- */ \ - " movq %[xC4S4], %%mm0 \n\t" \ - " movq %%mm1, %%mm2 \n\t" \ - " movq %%mm1, %%mm3 \n\t" \ - \ - " pmulhw %%mm0, %%mm1 \n\t" /* mm0 = xC4S4 * ( is12 - is56 ) - ( is12 - is56 ) */ \ - " psrlw $15, %%mm2 \n\t" \ - \ - " paddw %%mm3, %%mm1 \n\t" /* mm0 = xC4S4 * ( is12 - is56 ) */ \ - " paddw %%mm2, %%mm1 \n\t" /* Truncate mm1, now it is icommon_product1 */ \ - \ - " movq %%mm7, %%mm2 \n\t" \ - " movq %%mm7, %%mm3 \n\t" \ - \ - " pmulhw %%mm0, %%mm7 \n\t" /* mm7 = xC4S4 * ( id12 + id56 ) - ( id12 + id56 ) */ \ - " psrlw $15, %%mm2 \n\t" \ - \ - " paddw %%mm3, %%mm7 \n\t" /* mm7 = xC4S4 * ( id12 + id56 ) */ \ - " paddw %%mm2, %%mm7 \n\t" /* Truncate mm7, now it is icommon_product2 */ \ - /* ------------------------------------------------------------------- */ \ - " pxor %%mm0, %%mm0 \n\t" /* Clear mm0 */ \ - " psubsw %%mm6, %%mm0 \n\t" /* mm0 = - id34 */ \ - \ - " psubsw %%mm7, %%mm0 \n\t" /* mm0 = - ( id34 + idcommon_product2 ) */ \ - " paddsw %%mm6, %%mm6 \n\t" \ - " paddsw %%mm0, %%mm6 \n\t" /* mm6 = id34 - icommon_product2 */ \ - \ - " psubsw %%mm1, %%mm4 \n\t" /* mm4 = id07 - icommon_product1 */ \ - " paddsw %%mm1, %%mm1 \n\t" \ - " paddsw %%mm4, %%mm1 \n\t" /* mm1 = id07 + icommon_product1 */ \ - /* ------------------------------------------------------------------- */ \ - " movq %[xC1S7], %%mm7 \n\t" \ - " movq %%mm1, %%mm2 \n\t" \ - \ - " movq %%mm1, %%mm3 \n\t" \ - " pmulhw %%mm7, %%mm1 \n\t" /* mm1 = xC1S7 * irot_input_x - irot_input_x */ \ - \ - " movq %[xC7S1], %%mm7 \n\t" \ - " psrlw $15, %%mm2 \n\t" \ - \ - " paddw %%mm3, %%mm1 \n\t" /* mm1 = xC1S7 * irot_input_x */ \ - " paddw %%mm2, %%mm1 \n\t" /* Trucated */ \ - \ - " pmulhw %%mm7, %%mm3 \n\t" /* mm3 = xC7S1 * irot_input_x */ \ - " paddw %%mm2, %%mm3 \n\t" /* Truncated */ \ - \ - " movq %%mm0, %%mm5 \n\t" \ - " movq %%mm0, %%mm2 \n\t" \ - \ - " movq %[xC1S7], %%mm7 \n\t" \ - " pmulhw %%mm7, %%mm0 \n\t" /* mm0 = xC1S7 * irot_input_y - irot_input_y */ \ - \ - " movq %[xC7S1], %%mm7 \n\t" \ - " psrlw $15, %%mm2 \n\t" \ - \ - " paddw %%mm5, %%mm0 \n\t" /* mm0 = xC1S7 * irot_input_y */ \ - " paddw %%mm2, %%mm0 \n\t" /* Truncated */ \ - \ - " pmulhw %%mm7, %%mm5 \n\t" /* mm5 = xC7S1 * irot_input_y */ \ - " paddw %%mm2, %%mm5 \n\t" /* Truncated */ \ - \ - " psubsw %%mm5, %%mm1 \n\t" /* mm1 = xC1S7 * irot_input_x - xC7S1 * irot_input_y = ip1 */ \ - " paddsw %%mm0, %%mm3 \n\t" /* mm3 = xC7S1 * irot_input_x - xC1S7 * irot_input_y = ip7 */ \ - \ - " movq %%mm1," #ip1 " \n\t" \ - " movq %%mm3," #ip7 " \n\t" \ - /* ------------------------------------------------------------------- */ \ - " movq %[xC3S5], %%mm0 \n\t" \ - " movq %[xC5S3], %%mm1 \n\t" \ - \ - " movq %%mm6, %%mm5 \n\t" \ - " movq %%mm6, %%mm7 \n\t" \ - \ - " movq %%mm4, %%mm2 \n\t" \ - " movq %%mm4, %%mm3 \n\t" \ - \ - " pmulhw %%mm0, %%mm4 \n\t" /* mm4 = xC3S5 * irot_input_x - irot_input_x */ \ - " pmulhw %%mm1, %%mm6 \n\t" /* mm6 = xC5S3 * irot_input_y - irot_input_y */ \ - \ - " psrlw $15, %%mm2 \n\t" \ - " psrlw $15, %%mm5 \n\t" \ - \ - " paddw %%mm3, %%mm4 \n\t" /* mm4 = xC3S5 * irot_input_x */ \ - " paddw %%mm7, %%mm6 \n\t" /* mm6 = xC5S3 * irot_input_y */ \ - \ - " paddw %%mm2, %%mm4 \n\t" /* Truncated */ \ - " paddw %%mm5, %%mm6 \n\t" /* Truncated */ \ - \ - " psubsw %%mm6, %%mm4 \n\t" /* ip3 */ \ - " movq %%mm4," #ip3 " \n\t" \ - \ - " movq %%mm3, %%mm4 \n\t" \ - " movq %%mm7, %%mm6 \n\t" \ - \ - " pmulhw %%mm1, %%mm3 \n\t" /* mm3 = xC5S3 * irot_input_x - irot_input_x */ \ - " pmulhw %%mm0, %%mm7 \n\t" /* mm7 = xC3S5 * irot_input_y - irot_input_y */ \ - \ - " paddw %%mm2, %%mm4 \n\t" \ - " paddw %%mm5, %%mm6 \n\t" \ - \ - " paddw %%mm4, %%mm3 \n\t" /* mm3 = xC5S3 * irot_input_x */ \ - " paddw %%mm6, %%mm7 \n\t" /* mm7 = xC3S5 * irot_input_y */ \ - \ - " paddw %%mm7, %%mm3 \n\t" /* ip5 */ \ - " movq %%mm3," #ip5 " \n\t" - -#define Transpose_mmx(ip0,ip1,ip2,ip3,ip4,ip5,ip6,ip7, \ - op0,op1,op2,op3,op4,op5,op6,op7) \ - " movq " #ip0 ", %%mm0 \n\t" /* mm0 = a0 a1 a2 a3 */ \ - " movq " #ip4 ", %%mm4 \n\t" /* mm4 = e4 e5 e6 e7 */ \ - " movq " #ip1 ", %%mm1 \n\t" /* mm1 = b0 b1 b2 b3 */ \ - " movq " #ip5 ", %%mm5 \n\t" /* mm5 = f4 f5 f6 f7 */ \ - " movq " #ip2 ", %%mm2 \n\t" /* mm2 = c0 c1 c2 c3 */ \ - " movq " #ip6 ", %%mm6 \n\t" /* mm6 = g4 g5 g6 g7 */ \ - " movq " #ip3 ", %%mm3 \n\t" /* mm3 = d0 d1 d2 d3 */ \ - " movq %%mm1," #op1 " \n\t" /* save b0 b1 b2 b3 */ \ - " movq " #ip7 ", %%mm7 \n\t" /* mm7 = h0 h1 h2 h3 */ \ - /* Transpose 2x8 block */ \ - " movq %%mm4, %%mm1 \n\t" /* mm1 = e3 e2 e1 e0 */ \ - " punpcklwd %%mm5, %%mm4 \n\t" /* mm4 = f1 e1 f0 e0 */ \ - " movq %%mm0," #op0 " \n\t" /* save a3 a2 a1 a0 */ \ - " punpckhwd %%mm5, %%mm1 \n\t" /* mm1 = f3 e3 f2 e2 */ \ - " movq %%mm6, %%mm0 \n\t" /* mm0 = g3 g2 g1 g0 */ \ - " punpcklwd %%mm7, %%mm6 \n\t" /* mm6 = h1 g1 h0 g0 */ \ - " movq %%mm4, %%mm5 \n\t" /* mm5 = f1 e1 f0 e0 */ \ - " punpckldq %%mm6, %%mm4 \n\t" /* mm4 = h0 g0 f0 e0 = MM4 */ \ - " punpckhdq %%mm6, %%mm5 \n\t" /* mm5 = h1 g1 f1 e1 = MM5 */ \ - " movq %%mm1, %%mm6 \n\t" /* mm6 = f3 e3 f2 e2 */ \ - " movq %%mm4," #op4 " \n\t" \ - " punpckhwd %%mm7, %%mm0 \n\t" /* mm0 = h3 g3 h2 g2 */ \ - " movq %%mm5," #op5 " \n\t" \ - " punpckhdq %%mm0, %%mm6 \n\t" /* mm6 = h3 g3 f3 e3 = MM7 */ \ - " movq " #op0 ", %%mm4 \n\t" /* mm4 = a3 a2 a1 a0 */ \ - " punpckldq %%mm0, %%mm1 \n\t" /* mm1 = h2 g2 f2 e2 = MM6 */ \ - " movq " #op1 ", %%mm5 \n\t" /* mm5 = b3 b2 b1 b0 */ \ - " movq %%mm4, %%mm0 \n\t" /* mm0 = a3 a2 a1 a0 */ \ - " movq %%mm6," #op7 " \n\t" \ - " punpcklwd %%mm5, %%mm0 \n\t" /* mm0 = b1 a1 b0 a0 */ \ - " movq %%mm1," #op6 " \n\t" \ - " punpckhwd %%mm5, %%mm4 \n\t" /* mm4 = b3 a3 b2 a2 */ \ - " movq %%mm2, %%mm5 \n\t" /* mm5 = c3 c2 c1 c0 */ \ - " punpcklwd %%mm3, %%mm2 \n\t" /* mm2 = d1 c1 d0 c0 */ \ - " movq %%mm0, %%mm1 \n\t" /* mm1 = b1 a1 b0 a0 */ \ - " punpckldq %%mm2, %%mm0 \n\t" /* mm0 = d0 c0 b0 a0 = MM0 */ \ - " punpckhdq %%mm2, %%mm1 \n\t" /* mm1 = d1 c1 b1 a1 = MM1 */ \ - " movq %%mm4, %%mm2 \n\t" /* mm2 = b3 a3 b2 a2 */ \ - " movq %%mm0," #op0 " \n\t" \ - " punpckhwd %%mm3, %%mm5 \n\t" /* mm5 = d3 c3 d2 c2 */ \ - " movq %%mm1," #op1 " \n\t" \ - " punpckhdq %%mm5, %%mm4 \n\t" /* mm4 = d3 c3 b3 a3 = MM3 */ \ - " punpckldq %%mm5, %%mm2 \n\t" /* mm2 = d2 c2 b2 a2 = MM2 */ \ - " movq %%mm4," #op3 " \n\t" \ - " movq %%mm2," #op2 " \n\t" - - -/* This performs a 2D Forward DCT on an 8x8 block with short - coefficients. We try to do the truncation to match the C - version. */ -static void fdct_short__mmx ( ogg_int16_t *InputData, ogg_int16_t *OutputData) -{ - ogg_int16_t __attribute__((aligned(8))) temp[8*8]; - - __asm__ __volatile__ ( - " .balign 16 \n\t" - /* - * Input data is an 8x8 block. To make processing of the data more efficent - * we will transpose the block of data to two 4x8 blocks??? - */ - Transpose_mmx ( (%0), 16(%0), 32(%0), 48(%0), 8(%0), 24(%0), 40(%0), 56(%0), - (%1), 16(%1), 32(%1), 48(%1), 8(%1), 24(%1), 40(%1), 56(%1)) - Fdct_mmx ( (%1), 16(%1), 32(%1), 48(%1), 8(%1), 24(%1), 40(%1), 56(%1), (%2)) - - Transpose_mmx (64(%0), 80(%0), 96(%0),112(%0), 72(%0), 88(%0),104(%0),120(%0), - 64(%1), 80(%1), 96(%1),112(%1), 72(%1), 88(%1),104(%1),120(%1)) - Fdct_mmx (64(%1), 80(%1), 96(%1),112(%1), 72(%1), 88(%1),104(%1),120(%1), (%2)) - - Transpose_mmx ( 0(%1), 16(%1), 32(%1), 48(%1), 64(%1), 80(%1), 96(%1),112(%1), - 0(%1), 16(%1), 32(%1), 48(%1), 64(%1), 80(%1), 96(%1),112(%1)) - Fdct_mmx ( 0(%1), 16(%1), 32(%1), 48(%1), 64(%1), 80(%1), 96(%1),112(%1), (%2)) - - Transpose_mmx ( 8(%1), 24(%1), 40(%1), 56(%1), 72(%1), 88(%1),104(%1),120(%1), - 8(%1), 24(%1), 40(%1), 56(%1), 72(%1), 88(%1),104(%1),120(%1)) - Fdct_mmx ( 8(%1), 24(%1), 40(%1), 56(%1), 72(%1), 88(%1),104(%1),120(%1), (%2)) - - " emms \n\t" - - : "+r" (InputData), - "+r" (OutputData) - : "r" (temp), - [xC1S7] "m" (xC1S7), /* gcc 3.1+ allows named asm parameters */ - [xC2S6] "m" (xC2S6), - [xC3S5] "m" (xC3S5), - [xC4S4] "m" (xC4S4), - [xC5S3] "m" (xC5S3), - [xC6S2] "m" (xC6S2), - [xC7S1] "m" (xC7S1) - : "memory" - ); -} - -/* install our implementation in the function table */ -void dsp_mmx_fdct_init(DspFunctions *funcs) -{ - funcs->fdct_short = fdct_short__mmx; -} - -#endif /* USE_ASM */ diff --git a/Engine/lib/libtheora/lib/enc/x86_64/idct_mmx.c b/Engine/lib/libtheora/lib/enc/x86_64/idct_mmx.c deleted file mode 100644 index b87db6085..000000000 --- a/Engine/lib/libtheora/lib/enc/x86_64/idct_mmx.c +++ /dev/null @@ -1,27 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: idct_mmx.c 15397 2008-10-14 02:06:24Z tterribe $ - - ********************************************************************/ - -#include "../codec_internal.h" - -#if defined(USE_ASM) - -/* nothing implemented right now */ -void dsp_mmx_idct_init(DspFunctions *funcs) -{ -} - -#endif /* USE_ASM */ diff --git a/Engine/lib/libtheora/lib/enc/x86_64/recon_mmx.c b/Engine/lib/libtheora/lib/enc/x86_64/recon_mmx.c deleted file mode 100644 index b9b86e982..000000000 --- a/Engine/lib/libtheora/lib/enc/x86_64/recon_mmx.c +++ /dev/null @@ -1,184 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: - last mod: $Id: recon_mmx.c 15397 2008-10-14 02:06:24Z tterribe $ - - ********************************************************************/ - -#include "../codec_internal.h" - -#if defined(USE_ASM) - -typedef unsigned long long ogg_uint64_t; - -static const __attribute__ ((aligned(8),used)) ogg_int64_t V128 = 0x8080808080808080LL; - -static void copy8x8__mmx (unsigned char *src, - unsigned char *dest, - ogg_uint32_t stride) -{ - __asm__ __volatile__ ( - " .balign 16 \n\t" - - " lea (%2, %2, 2), %%rdi \n\t" - - " movq (%1), %%mm0 \n\t" - " movq (%1, %2), %%mm1 \n\t" - " movq (%1, %2, 2), %%mm2 \n\t" - " movq (%1, %%rdi), %%mm3 \n\t" - - " lea (%1, %2, 4), %1 \n\t" - - " movq %%mm0, (%0) \n\t" - " movq %%mm1, (%0, %2) \n\t" - " movq %%mm2, (%0, %2, 2) \n\t" - " movq %%mm3, (%0, %%rdi) \n\t" - - " lea (%0, %2, 4), %0 \n\t" - - " movq (%1), %%mm0 \n\t" - " movq (%1, %2), %%mm1 \n\t" - " movq (%1, %2, 2), %%mm2 \n\t" - " movq (%1, %%rdi), %%mm3 \n\t" - - " movq %%mm0, (%0) \n\t" - " movq %%mm1, (%0, %2) \n\t" - " movq %%mm2, (%0, %2, 2) \n\t" - " movq %%mm3, (%0, %%rdi) \n\t" - : "+a" (dest) - : "c" (src), - "d" ((ogg_uint64_t)stride) - : "memory", "rdi" - ); -} - -static void recon_intra8x8__mmx (unsigned char *ReconPtr, ogg_int16_t *ChangePtr, - ogg_uint32_t LineStep) -{ - __asm__ __volatile__ ( - " .balign 16 \n\t" - - " movq %[V128], %%mm0 \n\t" /* Set mm0 to 0x8080808080808080 */ - - " lea 128(%1), %%rdi \n\t" /* Endpoint in input buffer */ - "1: \n\t" - " movq (%1), %%mm2 \n\t" /* First four input values */ - - " packsswb 8(%1), %%mm2 \n\t" /* pack with next(high) four values */ - " por %%mm0, %%mm0 \n\t" - " pxor %%mm0, %%mm2 \n\t" /* Convert result to unsigned (same as add 128) */ - " lea 16(%1), %1 \n\t" /* Step source buffer */ - " cmp %%rdi, %1 \n\t" /* are we done */ - - " movq %%mm2, (%0) \n\t" /* store results */ - - " lea (%0, %2), %0 \n\t" /* Step output buffer */ - " jc 1b \n\t" /* Loop back if we are not done */ - : "+r" (ReconPtr) - : "r" (ChangePtr), - "r" ((ogg_uint64_t)LineStep), - [V128] "m" (V128) - : "memory", "rdi" - ); -} - -static void recon_inter8x8__mmx (unsigned char *ReconPtr, unsigned char *RefPtr, - ogg_int16_t *ChangePtr, ogg_uint32_t LineStep) -{ - __asm__ __volatile__ ( - " .balign 16 \n\t" - - " pxor %%mm0, %%mm0 \n\t" - " lea 128(%1), %%rdi \n\t" - - "1: \n\t" - " movq (%2), %%mm2 \n\t" /* (+3 misaligned) 8 reference pixels */ - - " movq (%1), %%mm4 \n\t" /* first 4 changes */ - " movq %%mm2, %%mm3 \n\t" - " movq 8(%1), %%mm5 \n\t" /* last 4 changes */ - " punpcklbw %%mm0, %%mm2 \n\t" /* turn first 4 refs into positive 16-bit #s */ - " paddsw %%mm4, %%mm2 \n\t" /* add in first 4 changes */ - " punpckhbw %%mm0, %%mm3 \n\t" /* turn last 4 refs into positive 16-bit #s */ - " paddsw %%mm5, %%mm3 \n\t" /* add in last 4 changes */ - " add %3, %2 \n\t" /* next row of reference pixels */ - " packuswb %%mm3, %%mm2 \n\t" /* pack result to unsigned 8-bit values */ - " lea 16(%1), %1 \n\t" /* next row of changes */ - " cmp %%rdi, %1 \n\t" /* are we done? */ - - " movq %%mm2, (%0) \n\t" /* store result */ - - " lea (%0, %3), %0 \n\t" /* next row of output */ - " jc 1b \n\t" - : "+r" (ReconPtr) - : "r" (ChangePtr), - "r" (RefPtr), - "r" ((ogg_uint64_t)LineStep) - : "memory", "rdi" - ); -} - -static void recon_inter8x8_half__mmx (unsigned char *ReconPtr, unsigned char *RefPtr1, - unsigned char *RefPtr2, ogg_int16_t *ChangePtr, - ogg_uint32_t LineStep) -{ - __asm__ __volatile__ ( - " .balign 16 \n\t" - - " pxor %%mm0, %%mm0 \n\t" - " lea 128(%1), %%rdi \n\t" - - "1: \n\t" - " movq (%2), %%mm2 \n\t" /* (+3 misaligned) 8 reference pixels */ - " movq (%3), %%mm4 \n\t" /* (+3 misaligned) 8 reference pixels */ - - " movq %%mm2, %%mm3 \n\t" - " punpcklbw %%mm0, %%mm2 \n\t" /* mm2 = start ref1 as positive 16-bit #s */ - " movq %%mm4, %%mm5 \n\t" - " movq (%1), %%mm6 \n\t" /* first 4 changes */ - " punpckhbw %%mm0, %%mm3 \n\t" /* mm3 = end ref1 as positive 16-bit #s */ - " movq 8(%1), %%mm7 \n\t" /* last 4 changes */ - " punpcklbw %%mm0, %%mm4 \n\t" /* mm4 = start ref2 as positive 16-bit #s */ - " punpckhbw %%mm0, %%mm5 \n\t" /* mm5 = end ref2 as positive 16-bit #s */ - " paddw %%mm4, %%mm2 \n\t" /* mm2 = start (ref1 + ref2) */ - " paddw %%mm5, %%mm3 \n\t" /* mm3 = end (ref1 + ref2) */ - " psrlw $1, %%mm2 \n\t" /* mm2 = start (ref1 + ref2)/2 */ - " psrlw $1, %%mm3 \n\t" /* mm3 = end (ref1 + ref2)/2 */ - " paddw %%mm6, %%mm2 \n\t" /* add changes to start */ - " paddw %%mm7, %%mm3 \n\t" /* add changes to end */ - " lea 16(%1), %1 \n\t" /* next row of changes */ - " packuswb %%mm3, %%mm2 \n\t" /* pack start|end to unsigned 8-bit */ - " add %4, %2 \n\t" /* next row of reference pixels */ - " add %4, %3 \n\t" /* next row of reference pixels */ - " movq %%mm2, (%0) \n\t" /* store result */ - " add %4, %0 \n\t" /* next row of output */ - " cmp %%rdi, %1 \n\t" /* are we done? */ - " jc 1b \n\t" - : "+r" (ReconPtr) - : "r" (ChangePtr), - "r" (RefPtr1), - "r" (RefPtr2), - "r" ((ogg_uint64_t)LineStep) - : "memory", "rdi" - ); -} - -void dsp_mmx_recon_init(DspFunctions *funcs) -{ - funcs->copy8x8 = copy8x8__mmx; - funcs->recon_intra8x8 = recon_intra8x8__mmx; - funcs->recon_inter8x8 = recon_inter8x8__mmx; - funcs->recon_inter8x8_half = recon_inter8x8_half__mmx; -} - -#endif /* USE_ASM */ diff --git a/Engine/lib/libtheora/lib/encapiwrapper.c b/Engine/lib/libtheora/lib/encapiwrapper.c new file mode 100644 index 000000000..874f12442 --- /dev/null +++ b/Engine/lib/libtheora/lib/encapiwrapper.c @@ -0,0 +1,168 @@ +#include +#include +#include +#include "apiwrapper.h" +#include "encint.h" +#include "theora/theoraenc.h" + + + +static void th_enc_api_clear(th_api_wrapper *_api){ + if(_api->encode)th_encode_free(_api->encode); + memset(_api,0,sizeof(*_api)); +} + +static void theora_encode_clear(theora_state *_te){ + if(_te->i!=NULL)theora_info_clear(_te->i); + memset(_te,0,sizeof(*_te)); +} + +static int theora_encode_control(theora_state *_te,int _req, + void *_buf,size_t _buf_sz){ + return th_encode_ctl(((th_api_wrapper *)_te->i->codec_setup)->encode, + _req,_buf,_buf_sz); +} + +static ogg_int64_t theora_encode_granule_frame(theora_state *_te, + ogg_int64_t _gp){ + return th_granule_frame(((th_api_wrapper *)_te->i->codec_setup)->encode,_gp); +} + +static double theora_encode_granule_time(theora_state *_te,ogg_int64_t _gp){ + return th_granule_time(((th_api_wrapper *)_te->i->codec_setup)->encode,_gp); +} + +static const oc_state_dispatch_vtable OC_ENC_DISPATCH_VTBL={ + (oc_state_clear_func)theora_encode_clear, + (oc_state_control_func)theora_encode_control, + (oc_state_granule_frame_func)theora_encode_granule_frame, + (oc_state_granule_time_func)theora_encode_granule_time, +}; + +int theora_encode_init(theora_state *_te,theora_info *_ci){ + th_api_info *apiinfo; + th_info info; + ogg_uint32_t keyframe_frequency_force; + /*Allocate our own combined API wrapper/theora_info struct. + We put them both in one malloc'd block so that when the API wrapper is + freed, the info struct goes with it. + This avoids having to figure out whether or not we need to free the info + struct in either theora_info_clear() or theora_clear().*/ + apiinfo=(th_api_info *)_ogg_malloc(sizeof(*apiinfo)); + if(apiinfo==NULL)return TH_EFAULT; + /*Make our own copy of the info struct, since its lifetime should be + independent of the one we were passed in.*/ + *&apiinfo->info=*_ci; + oc_theora_info2th_info(&info,_ci); + apiinfo->api.encode=th_encode_alloc(&info); + if(apiinfo->api.encode==NULL){ + _ogg_free(apiinfo); + return OC_EINVAL; + } + apiinfo->api.clear=(oc_setup_clear_func)th_enc_api_clear; + /*Provide entry points for ABI compatibility with old decoder shared libs.*/ + _te->internal_encode=(void *)&OC_ENC_DISPATCH_VTBL; + _te->internal_decode=NULL; + _te->granulepos=0; + _te->i=&apiinfo->info; + _te->i->codec_setup=&apiinfo->api; + /*Set the precise requested keyframe frequency.*/ + keyframe_frequency_force=_ci->keyframe_auto_p? + _ci->keyframe_frequency_force:_ci->keyframe_frequency; + th_encode_ctl(apiinfo->api.encode, + TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE, + &keyframe_frequency_force,sizeof(keyframe_frequency_force)); + /*TODO: Additional codec setup using the extra fields in theora_info.*/ + return 0; +} + +int theora_encode_YUVin(theora_state *_te,yuv_buffer *_yuv){ + th_api_wrapper *api; + th_ycbcr_buffer buf; + int ret; + api=(th_api_wrapper *)_te->i->codec_setup; + buf[0].width=_yuv->y_width; + buf[0].height=_yuv->y_height; + buf[0].stride=_yuv->y_stride; + buf[0].data=_yuv->y; + buf[1].width=_yuv->uv_width; + buf[1].height=_yuv->uv_height; + buf[1].stride=_yuv->uv_stride; + buf[1].data=_yuv->u; + buf[2].width=_yuv->uv_width; + buf[2].height=_yuv->uv_height; + buf[2].stride=_yuv->uv_stride; + buf[2].data=_yuv->v; + ret=th_encode_ycbcr_in(api->encode,buf); + if(ret<0)return ret; + _te->granulepos=api->encode->state.granpos; + return ret; +} + +int theora_encode_packetout(theora_state *_te,int _last_p,ogg_packet *_op){ + th_api_wrapper *api; + api=(th_api_wrapper *)_te->i->codec_setup; + return th_encode_packetout(api->encode,_last_p,_op); +} + +int theora_encode_header(theora_state *_te,ogg_packet *_op){ + oc_enc_ctx *enc; + th_api_wrapper *api; + int ret; + api=(th_api_wrapper *)_te->i->codec_setup; + enc=api->encode; + /*If we've already started encoding, fail.*/ + if(enc->packet_state>OC_PACKET_EMPTY||enc->state.granpos!=0){ + return TH_EINVAL; + } + /*Reset the state to make sure we output an info packet.*/ + enc->packet_state=OC_PACKET_INFO_HDR; + ret=th_encode_flushheader(api->encode,NULL,_op); + return ret>=0?0:ret; +} + +int theora_encode_comment(theora_comment *_tc,ogg_packet *_op){ + oggpack_buffer opb; + void *buf; + int packet_state; + int ret; + packet_state=OC_PACKET_COMMENT_HDR; + oggpackB_writeinit(&opb); + ret=oc_state_flushheader(NULL,&packet_state,&opb,NULL,NULL, + th_version_string(),(th_comment *)_tc,_op); + if(ret>=0){ + /*The oggpack_buffer's lifetime ends with this function, so we have to + copy out the packet contents. + Presumably the application knows it is supposed to free this. + This part works nothing like the Vorbis API, and the documentation on it + has been wrong for some time, claiming libtheora owned the memory.*/ + buf=_ogg_malloc(_op->bytes); + if(buf==NULL){ + _op->packet=NULL; + ret=TH_EFAULT; + } + else{ + memcpy(buf,_op->packet,_op->bytes); + _op->packet=buf; + ret=0; + } + } + oggpack_writeclear(&opb); + return ret; +} + +int theora_encode_tables(theora_state *_te,ogg_packet *_op){ + oc_enc_ctx *enc; + th_api_wrapper *api; + int ret; + api=(th_api_wrapper *)_te->i->codec_setup; + enc=api->encode; + /*If we've already started encoding, fail.*/ + if(enc->packet_state>OC_PACKET_EMPTY||enc->state.granpos!=0){ + return TH_EINVAL; + } + /*Reset the state to make sure we output a setup packet.*/ + enc->packet_state=OC_PACKET_SETUP_HDR; + ret=th_encode_flushheader(api->encode,NULL,_op); + return ret>=0?0:ret; +} diff --git a/Engine/lib/libtheora/lib/encfrag.c b/Engine/lib/libtheora/lib/encfrag.c new file mode 100644 index 000000000..bb814c8e4 --- /dev/null +++ b/Engine/lib/libtheora/lib/encfrag.c @@ -0,0 +1,388 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: encfrag.c 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ +#include +#include +#include "encint.h" + + +void oc_enc_frag_sub(const oc_enc_ctx *_enc,ogg_int16_t _diff[64], + const unsigned char *_src,const unsigned char *_ref,int _ystride){ + (*_enc->opt_vtable.frag_sub)(_diff,_src,_ref,_ystride); +} + +void oc_enc_frag_sub_c(ogg_int16_t _diff[64],const unsigned char *_src, + const unsigned char *_ref,int _ystride){ + int i; + for(i=0;i<8;i++){ + int j; + for(j=0;j<8;j++)_diff[i*8+j]=(ogg_int16_t)(_src[j]-_ref[j]); + _src+=_ystride; + _ref+=_ystride; + } +} + +void oc_enc_frag_sub_128(const oc_enc_ctx *_enc,ogg_int16_t _diff[64], + const unsigned char *_src,int _ystride){ + (*_enc->opt_vtable.frag_sub_128)(_diff,_src,_ystride); +} + +void oc_enc_frag_sub_128_c(ogg_int16_t *_diff, + const unsigned char *_src,int _ystride){ + int i; + for(i=0;i<8;i++){ + int j; + for(j=0;j<8;j++)_diff[i*8+j]=(ogg_int16_t)(_src[j]-128); + _src+=_ystride; + } +} + +unsigned oc_enc_frag_sad(const oc_enc_ctx *_enc,const unsigned char *_x, + const unsigned char *_y,int _ystride){ + return (*_enc->opt_vtable.frag_sad)(_x,_y,_ystride); +} + +unsigned oc_enc_frag_sad_c(const unsigned char *_src, + const unsigned char *_ref,int _ystride){ + unsigned sad; + int i; + sad=0; + for(i=8;i-->0;){ + int j; + for(j=0;j<8;j++)sad+=abs(_src[j]-_ref[j]); + _src+=_ystride; + _ref+=_ystride; + } + return sad; +} + +unsigned oc_enc_frag_sad_thresh(const oc_enc_ctx *_enc, + const unsigned char *_src,const unsigned char *_ref,int _ystride, + unsigned _thresh){ + return (*_enc->opt_vtable.frag_sad_thresh)(_src,_ref,_ystride,_thresh); +} + +unsigned oc_enc_frag_sad_thresh_c(const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _thresh){ + unsigned sad; + int i; + sad=0; + for(i=8;i-->0;){ + int j; + for(j=0;j<8;j++)sad+=abs(_src[j]-_ref[j]); + if(sad>_thresh)break; + _src+=_ystride; + _ref+=_ystride; + } + return sad; +} + +unsigned oc_enc_frag_sad2_thresh(const oc_enc_ctx *_enc, + const unsigned char *_src,const unsigned char *_ref1, + const unsigned char *_ref2,int _ystride,unsigned _thresh){ + return (*_enc->opt_vtable.frag_sad2_thresh)(_src,_ref1,_ref2,_ystride, + _thresh); +} + +unsigned oc_enc_frag_sad2_thresh_c(const unsigned char *_src, + const unsigned char *_ref1,const unsigned char *_ref2,int _ystride, + unsigned _thresh){ + unsigned sad; + int i; + sad=0; + for(i=8;i-->0;){ + int j; + for(j=0;j<8;j++)sad+=abs(_src[j]-(_ref1[j]+_ref2[j]>>1)); + if(sad>_thresh)break; + _src+=_ystride; + _ref1+=_ystride; + _ref2+=_ystride; + } + return sad; +} + +static void oc_diff_hadamard(ogg_int16_t _buf[64],const unsigned char *_src, + const unsigned char *_ref,int _ystride){ + int i; + for(i=0;i<8;i++){ + int t0; + int t1; + int t2; + int t3; + int t4; + int t5; + int t6; + int t7; + int r; + /*Hadamard stage 1:*/ + t0=_src[0]-_ref[0]+_src[4]-_ref[4]; + t4=_src[0]-_ref[0]-_src[4]+_ref[4]; + t1=_src[1]-_ref[1]+_src[5]-_ref[5]; + t5=_src[1]-_ref[1]-_src[5]+_ref[5]; + t2=_src[2]-_ref[2]+_src[6]-_ref[6]; + t6=_src[2]-_ref[2]-_src[6]+_ref[6]; + t3=_src[3]-_ref[3]+_src[7]-_ref[7]; + t7=_src[3]-_ref[3]-_src[7]+_ref[7]; + /*Hadamard stage 2:*/ + r=t0; + t0+=t2; + t2=r-t2; + r=t1; + t1+=t3; + t3=r-t3; + r=t4; + t4+=t6; + t6=r-t6; + r=t5; + t5+=t7; + t7=r-t7; + /*Hadamard stage 3:*/ + _buf[0*8+i]=(ogg_int16_t)(t0+t1); + _buf[1*8+i]=(ogg_int16_t)(t0-t1); + _buf[2*8+i]=(ogg_int16_t)(t2+t3); + _buf[3*8+i]=(ogg_int16_t)(t2-t3); + _buf[4*8+i]=(ogg_int16_t)(t4+t5); + _buf[5*8+i]=(ogg_int16_t)(t4-t5); + _buf[6*8+i]=(ogg_int16_t)(t6+t7); + _buf[7*8+i]=(ogg_int16_t)(t6-t7); + _src+=_ystride; + _ref+=_ystride; + } +} + +static void oc_diff_hadamard2(ogg_int16_t _buf[64],const unsigned char *_src, + const unsigned char *_ref1,const unsigned char *_ref2,int _ystride){ + int i; + for(i=0;i<8;i++){ + int t0; + int t1; + int t2; + int t3; + int t4; + int t5; + int t6; + int t7; + int r; + /*Hadamard stage 1:*/ + r=_ref1[0]+_ref2[0]>>1; + t4=_ref1[4]+_ref2[4]>>1; + t0=_src[0]-r+_src[4]-t4; + t4=_src[0]-r-_src[4]+t4; + r=_ref1[1]+_ref2[1]>>1; + t5=_ref1[5]+_ref2[5]>>1; + t1=_src[1]-r+_src[5]-t5; + t5=_src[1]-r-_src[5]+t5; + r=_ref1[2]+_ref2[2]>>1; + t6=_ref1[6]+_ref2[6]>>1; + t2=_src[2]-r+_src[6]-t6; + t6=_src[2]-r-_src[6]+t6; + r=_ref1[3]+_ref2[3]>>1; + t7=_ref1[7]+_ref2[7]>>1; + t3=_src[3]-r+_src[7]-t7; + t7=_src[3]-r-_src[7]+t7; + /*Hadamard stage 2:*/ + r=t0; + t0+=t2; + t2=r-t2; + r=t1; + t1+=t3; + t3=r-t3; + r=t4; + t4+=t6; + t6=r-t6; + r=t5; + t5+=t7; + t7=r-t7; + /*Hadamard stage 3:*/ + _buf[0*8+i]=(ogg_int16_t)(t0+t1); + _buf[1*8+i]=(ogg_int16_t)(t0-t1); + _buf[2*8+i]=(ogg_int16_t)(t2+t3); + _buf[3*8+i]=(ogg_int16_t)(t2-t3); + _buf[4*8+i]=(ogg_int16_t)(t4+t5); + _buf[5*8+i]=(ogg_int16_t)(t4-t5); + _buf[6*8+i]=(ogg_int16_t)(t6+t7); + _buf[7*8+i]=(ogg_int16_t)(t6-t7); + _src+=_ystride; + _ref1+=_ystride; + _ref2+=_ystride; + } +} + +static void oc_intra_hadamard(ogg_int16_t _buf[64],const unsigned char *_src, + int _ystride){ + int i; + for(i=0;i<8;i++){ + int t0; + int t1; + int t2; + int t3; + int t4; + int t5; + int t6; + int t7; + int r; + /*Hadamard stage 1:*/ + t0=_src[0]+_src[4]; + t4=_src[0]-_src[4]; + t1=_src[1]+_src[5]; + t5=_src[1]-_src[5]; + t2=_src[2]+_src[6]; + t6=_src[2]-_src[6]; + t3=_src[3]+_src[7]; + t7=_src[3]-_src[7]; + /*Hadamard stage 2:*/ + r=t0; + t0+=t2; + t2=r-t2; + r=t1; + t1+=t3; + t3=r-t3; + r=t4; + t4+=t6; + t6=r-t6; + r=t5; + t5+=t7; + t7=r-t7; + /*Hadamard stage 3:*/ + _buf[0*8+i]=(ogg_int16_t)(t0+t1); + _buf[1*8+i]=(ogg_int16_t)(t0-t1); + _buf[2*8+i]=(ogg_int16_t)(t2+t3); + _buf[3*8+i]=(ogg_int16_t)(t2-t3); + _buf[4*8+i]=(ogg_int16_t)(t4+t5); + _buf[5*8+i]=(ogg_int16_t)(t4-t5); + _buf[6*8+i]=(ogg_int16_t)(t6+t7); + _buf[7*8+i]=(ogg_int16_t)(t6-t7); + _src+=_ystride; + } +} + +unsigned oc_hadamard_sad_thresh(const ogg_int16_t _buf[64],unsigned _thresh){ + unsigned sad; + int t0; + int t1; + int t2; + int t3; + int t4; + int t5; + int t6; + int t7; + int r; + int i; + sad=0; + for(i=0;i<8;i++){ + /*Hadamard stage 1:*/ + t0=_buf[i*8+0]+_buf[i*8+4]; + t4=_buf[i*8+0]-_buf[i*8+4]; + t1=_buf[i*8+1]+_buf[i*8+5]; + t5=_buf[i*8+1]-_buf[i*8+5]; + t2=_buf[i*8+2]+_buf[i*8+6]; + t6=_buf[i*8+2]-_buf[i*8+6]; + t3=_buf[i*8+3]+_buf[i*8+7]; + t7=_buf[i*8+3]-_buf[i*8+7]; + /*Hadamard stage 2:*/ + r=t0; + t0+=t2; + t2=r-t2; + r=t1; + t1+=t3; + t3=r-t3; + r=t4; + t4+=t6; + t6=r-t6; + r=t5; + t5+=t7; + t7=r-t7; + /*Hadamard stage 3:*/ + r=abs(t0+t1); + r+=abs(t0-t1); + r+=abs(t2+t3); + r+=abs(t2-t3); + r+=abs(t4+t5); + r+=abs(t4-t5); + r+=abs(t6+t7); + r+=abs(t6-t7); + sad+=r; + if(sad>_thresh)break; + } + return sad; +} + +unsigned oc_enc_frag_satd_thresh(const oc_enc_ctx *_enc, + const unsigned char *_src,const unsigned char *_ref,int _ystride, + unsigned _thresh){ + return (*_enc->opt_vtable.frag_satd_thresh)(_src,_ref,_ystride,_thresh); +} + +unsigned oc_enc_frag_satd_thresh_c(const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _thresh){ + ogg_int16_t buf[64]; + oc_diff_hadamard(buf,_src,_ref,_ystride); + return oc_hadamard_sad_thresh(buf,_thresh); +} + +unsigned oc_enc_frag_satd2_thresh(const oc_enc_ctx *_enc, + const unsigned char *_src,const unsigned char *_ref1, + const unsigned char *_ref2,int _ystride,unsigned _thresh){ + return (*_enc->opt_vtable.frag_satd2_thresh)(_src,_ref1,_ref2,_ystride, + _thresh); +} + +unsigned oc_enc_frag_satd2_thresh_c(const unsigned char *_src, + const unsigned char *_ref1,const unsigned char *_ref2,int _ystride, + unsigned _thresh){ + ogg_int16_t buf[64]; + oc_diff_hadamard2(buf,_src,_ref1,_ref2,_ystride); + return oc_hadamard_sad_thresh(buf,_thresh); +} + +unsigned oc_enc_frag_intra_satd(const oc_enc_ctx *_enc, + const unsigned char *_src,int _ystride){ + return (*_enc->opt_vtable.frag_intra_satd)(_src,_ystride); +} + +unsigned oc_enc_frag_intra_satd_c(const unsigned char *_src,int _ystride){ + ogg_int16_t buf[64]; + oc_intra_hadamard(buf,_src,_ystride); + return oc_hadamard_sad_thresh(buf,UINT_MAX) + -abs(buf[0]+buf[1]+buf[2]+buf[3]+buf[4]+buf[5]+buf[6]+buf[7]); +} + +void oc_enc_frag_copy2(const oc_enc_ctx *_enc,unsigned char *_dst, + const unsigned char *_src1,const unsigned char *_src2,int _ystride){ + (*_enc->opt_vtable.frag_copy2)(_dst,_src1,_src2,_ystride); +} + +void oc_enc_frag_copy2_c(unsigned char *_dst, + const unsigned char *_src1,const unsigned char *_src2,int _ystride){ + int i; + int j; + for(i=8;i-->0;){ + for(j=0;j<8;j++)_dst[j]=_src1[j]+_src2[j]>>1; + _dst+=_ystride; + _src1+=_ystride; + _src2+=_ystride; + } +} + +void oc_enc_frag_recon_intra(const oc_enc_ctx *_enc, + unsigned char *_dst,int _ystride,const ogg_int16_t _residue[64]){ + (*_enc->opt_vtable.frag_recon_intra)(_dst,_ystride,_residue); +} + +void oc_enc_frag_recon_inter(const oc_enc_ctx *_enc,unsigned char *_dst, + const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]){ + (*_enc->opt_vtable.frag_recon_inter)(_dst,_src,_ystride,_residue); +} diff --git a/Engine/lib/libtheora/lib/encinfo.c b/Engine/lib/libtheora/lib/encinfo.c new file mode 100644 index 000000000..83be1dae7 --- /dev/null +++ b/Engine/lib/libtheora/lib/encinfo.c @@ -0,0 +1,121 @@ +#include +#include +#include "internal.h" +#include "enquant.h" +#include "huffenc.h" + + + +/*Packs a series of octets from a given byte array into the pack buffer. + _opb: The pack buffer to store the octets in. + _buf: The byte array containing the bytes to pack. + _len: The number of octets to pack.*/ +static void oc_pack_octets(oggpack_buffer *_opb,const char *_buf,int _len){ + int i; + for(i=0;i<_len;i++)oggpackB_write(_opb,_buf[i],8); +} + + + +int oc_state_flushheader(oc_theora_state *_state,int *_packet_state, + oggpack_buffer *_opb,const th_quant_info *_qinfo, + const th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS], + const char *_vendor,th_comment *_tc,ogg_packet *_op){ + unsigned char *packet; + int b_o_s; + if(_op==NULL)return TH_EFAULT; + switch(*_packet_state){ + /*Codec info header.*/ + case OC_PACKET_INFO_HDR:{ + if(_state==NULL)return TH_EFAULT; + oggpackB_reset(_opb); + /*Mark this packet as the info header.*/ + oggpackB_write(_opb,0x80,8); + /*Write the codec string.*/ + oc_pack_octets(_opb,"theora",6); + /*Write the codec bitstream version.*/ + oggpackB_write(_opb,TH_VERSION_MAJOR,8); + oggpackB_write(_opb,TH_VERSION_MINOR,8); + oggpackB_write(_opb,TH_VERSION_SUB,8); + /*Describe the encoded frame.*/ + oggpackB_write(_opb,_state->info.frame_width>>4,16); + oggpackB_write(_opb,_state->info.frame_height>>4,16); + oggpackB_write(_opb,_state->info.pic_width,24); + oggpackB_write(_opb,_state->info.pic_height,24); + oggpackB_write(_opb,_state->info.pic_x,8); + oggpackB_write(_opb,_state->info.pic_y,8); + oggpackB_write(_opb,_state->info.fps_numerator,32); + oggpackB_write(_opb,_state->info.fps_denominator,32); + oggpackB_write(_opb,_state->info.aspect_numerator,24); + oggpackB_write(_opb,_state->info.aspect_denominator,24); + oggpackB_write(_opb,_state->info.colorspace,8); + oggpackB_write(_opb,_state->info.target_bitrate,24); + oggpackB_write(_opb,_state->info.quality,6); + oggpackB_write(_opb,_state->info.keyframe_granule_shift,5); + oggpackB_write(_opb,_state->info.pixel_fmt,2); + /*Spare configuration bits.*/ + oggpackB_write(_opb,0,3); + b_o_s=1; + }break; + /*Comment header.*/ + case OC_PACKET_COMMENT_HDR:{ + int vendor_len; + int i; + if(_tc==NULL)return TH_EFAULT; + vendor_len=strlen(_vendor); + oggpackB_reset(_opb); + /*Mark this packet as the comment header.*/ + oggpackB_write(_opb,0x81,8); + /*Write the codec string.*/ + oc_pack_octets(_opb,"theora",6); + /*Write the vendor string.*/ + oggpack_write(_opb,vendor_len,32); + oc_pack_octets(_opb,_vendor,vendor_len); + oggpack_write(_opb,_tc->comments,32); + for(i=0;i<_tc->comments;i++){ + if(_tc->user_comments[i]!=NULL){ + oggpack_write(_opb,_tc->comment_lengths[i],32); + oc_pack_octets(_opb,_tc->user_comments[i],_tc->comment_lengths[i]); + } + else oggpack_write(_opb,0,32); + } + b_o_s=0; + }break; + /*Codec setup header.*/ + case OC_PACKET_SETUP_HDR:{ + int ret; + oggpackB_reset(_opb); + /*Mark this packet as the setup header.*/ + oggpackB_write(_opb,0x82,8); + /*Write the codec string.*/ + oc_pack_octets(_opb,"theora",6); + /*Write the quantizer tables.*/ + oc_quant_params_pack(_opb,_qinfo); + /*Write the huffman codes.*/ + ret=oc_huff_codes_pack(_opb,_codes); + /*This should never happen, because we validate the tables when they + are set. + If you see, it's a good chance memory is being corrupted.*/ + if(ret<0)return ret; + b_o_s=0; + }break; + /*No more headers to emit.*/ + default:return 0; + } + /*This is kind of fugly: we hand the user a buffer which they do not own. + We will overwrite it when the next packet is output, so the user better be + done with it by then. + Vorbis is little better: it hands back buffers that it will free the next + time the headers are requested, or when the encoder is cleared. + Hopefully libogg2 will make this much cleaner.*/ + packet=oggpackB_get_buffer(_opb); + /*If there's no packet, malloc failed while writing.*/ + if(packet==NULL)return TH_EFAULT; + _op->packet=packet; + _op->bytes=oggpackB_bytes(_opb); + _op->b_o_s=b_o_s; + _op->e_o_s=0; + _op->granulepos=0; + _op->packetno=*_packet_state+3; + return ++(*_packet_state)+3; +} diff --git a/Engine/lib/libtheora/lib/encint.h b/Engine/lib/libtheora/lib/encint.h new file mode 100644 index 000000000..97897d5a0 --- /dev/null +++ b/Engine/lib/libtheora/lib/encint.h @@ -0,0 +1,493 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: encint.h 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ +#if !defined(_encint_H) +# define _encint_H (1) +# if defined(HAVE_CONFIG_H) +# include "config.h" +# endif +# include "theora/theoraenc.h" +# include "internal.h" +# include "ocintrin.h" +# include "mathops.h" +# include "enquant.h" +# include "huffenc.h" +/*# define OC_COLLECT_METRICS*/ + + + +typedef oc_mv oc_mv2[2]; + +typedef struct oc_enc_opt_vtable oc_enc_opt_vtable; +typedef struct oc_mb_enc_info oc_mb_enc_info; +typedef struct oc_mode_scheme_chooser oc_mode_scheme_chooser; +typedef struct oc_iir_filter oc_iir_filter; +typedef struct oc_frame_metrics oc_frame_metrics; +typedef struct oc_rc_state oc_rc_state; +typedef struct th_enc_ctx oc_enc_ctx; +typedef struct oc_token_checkpoint oc_token_checkpoint; + + + +/*Constants for the packet-out state machine specific to the encoder.*/ + +/*Next packet to emit: Data packet, but none are ready yet.*/ +#define OC_PACKET_EMPTY (0) +/*Next packet to emit: Data packet, and one is ready.*/ +#define OC_PACKET_READY (1) + +/*All features enabled.*/ +#define OC_SP_LEVEL_SLOW (0) +/*Enable early skip.*/ +#define OC_SP_LEVEL_EARLY_SKIP (1) +/*Disable motion compensation.*/ +#define OC_SP_LEVEL_NOMC (2) +/*Maximum valid speed level.*/ +#define OC_SP_LEVEL_MAX (2) + + +/*The bits used for each of the MB mode codebooks.*/ +extern const unsigned char OC_MODE_BITS[2][OC_NMODES]; + +/*The bits used for each of the MV codebooks.*/ +extern const unsigned char OC_MV_BITS[2][64]; + +/*The minimum value that can be stored in a SB run for each codeword. + The last entry is the upper bound on the length of a single SB run.*/ +extern const ogg_uint16_t OC_SB_RUN_VAL_MIN[8]; +/*The bits used for each SB run codeword.*/ +extern const unsigned char OC_SB_RUN_CODE_NBITS[7]; + +/*The bits used for each block run length (starting with 1).*/ +extern const unsigned char OC_BLOCK_RUN_CODE_NBITS[30]; + + + +/*Encoder specific functions with accelerated variants.*/ +struct oc_enc_opt_vtable{ + unsigned (*frag_sad)(const unsigned char *_src, + const unsigned char *_ref,int _ystride); + unsigned (*frag_sad_thresh)(const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _thresh); + unsigned (*frag_sad2_thresh)(const unsigned char *_src, + const unsigned char *_ref1,const unsigned char *_ref2,int _ystride, + unsigned _thresh); + unsigned (*frag_satd_thresh)(const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _thresh); + unsigned (*frag_satd2_thresh)(const unsigned char *_src, + const unsigned char *_ref1,const unsigned char *_ref2,int _ystride, + unsigned _thresh); + unsigned (*frag_intra_satd)(const unsigned char *_src,int _ystride); + void (*frag_sub)(ogg_int16_t _diff[64],const unsigned char *_src, + const unsigned char *_ref,int _ystride); + void (*frag_sub_128)(ogg_int16_t _diff[64], + const unsigned char *_src,int _ystride); + void (*frag_copy2)(unsigned char *_dst, + const unsigned char *_src1,const unsigned char *_src2,int _ystride); + void (*frag_recon_intra)(unsigned char *_dst,int _ystride, + const ogg_int16_t _residue[64]); + void (*frag_recon_inter)(unsigned char *_dst, + const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]); + void (*fdct8x8)(ogg_int16_t _y[64],const ogg_int16_t _x[64]); +}; + + +void oc_enc_vtable_init(oc_enc_ctx *_enc); + + + +/*Encoder-specific macroblock information.*/ +struct oc_mb_enc_info{ + /*Neighboring macro blocks that have MVs available from the current frame.*/ + unsigned cneighbors[4]; + /*Neighboring macro blocks to use for MVs from the previous frame.*/ + unsigned pneighbors[4]; + /*The number of current-frame neighbors.*/ + unsigned char ncneighbors; + /*The number of previous-frame neighbors.*/ + unsigned char npneighbors; + /*Flags indicating which MB modes have been refined.*/ + unsigned char refined; + /*Motion vectors for a macro block for the current frame and the + previous two frames. + Each is a set of 2 vectors against OC_FRAME_GOLD and OC_FRAME_PREV, which + can be used to estimate constant velocity and constant acceleration + predictors. + Uninitialized MVs are (0,0).*/ + oc_mv2 analysis_mv[3]; + /*Current unrefined analysis MVs.*/ + oc_mv unref_mv[2]; + /*Unrefined block MVs.*/ + oc_mv block_mv[4]; + /*Refined block MVs.*/ + oc_mv ref_mv[4]; + /*Minimum motion estimation error from the analysis stage.*/ + ogg_uint16_t error[2]; + /*MB error for half-pel refinement for each frame type.*/ + unsigned satd[2]; + /*Block error for half-pel refinement.*/ + unsigned block_satd[4]; +}; + + + +/*State machine to estimate the opportunity cost of coding a MB mode.*/ +struct oc_mode_scheme_chooser{ + /*Pointers to the a list containing the index of each mode in the mode + alphabet used by each scheme. + The first entry points to the dynamic scheme0_ranks, while the remaining 7 + point to the constant entries stored in OC_MODE_SCHEMES.*/ + const unsigned char *mode_ranks[8]; + /*The ranks for each mode when coded with scheme 0. + These are optimized so that the more frequent modes have lower ranks.*/ + unsigned char scheme0_ranks[OC_NMODES]; + /*The list of modes, sorted in descending order of frequency, that + corresponds to the ranks above.*/ + unsigned char scheme0_list[OC_NMODES]; + /*The number of times each mode has been chosen so far.*/ + int mode_counts[OC_NMODES]; + /*The list of mode coding schemes, sorted in ascending order of bit cost.*/ + unsigned char scheme_list[8]; + /*The number of bits used by each mode coding scheme.*/ + ptrdiff_t scheme_bits[8]; +}; + + +void oc_mode_scheme_chooser_init(oc_mode_scheme_chooser *_chooser); + + + +/*A 2nd order low-pass Bessel follower. + We use this for rate control because it has fast reaction time, but is + critically damped.*/ +struct oc_iir_filter{ + ogg_int32_t c[2]; + ogg_int64_t g; + ogg_int32_t x[2]; + ogg_int32_t y[2]; +}; + + + +/*The 2-pass metrics associated with a single frame.*/ +struct oc_frame_metrics{ + /*The log base 2 of the scale factor for this frame in Q24 format.*/ + ogg_int32_t log_scale; + /*The number of application-requested duplicates of this frame.*/ + unsigned dup_count:31; + /*The frame type from pass 1.*/ + unsigned frame_type:1; +}; + + + +/*Rate control state information.*/ +struct oc_rc_state{ + /*The target average bits per frame.*/ + ogg_int64_t bits_per_frame; + /*The current buffer fullness (bits available to be used).*/ + ogg_int64_t fullness; + /*The target buffer fullness. + This is where we'd like to be by the last keyframe the appears in the next + buf_delay frames.*/ + ogg_int64_t target; + /*The maximum buffer fullness (total size of the buffer).*/ + ogg_int64_t max; + /*The log of the number of pixels in a frame in Q57 format.*/ + ogg_int64_t log_npixels; + /*The exponent used in the rate model in Q8 format.*/ + unsigned exp[2]; + /*The number of frames to distribute the buffer usage over.*/ + int buf_delay; + /*The total drop count from the previous frame. + This includes duplicates explicitly requested via the + TH_ENCCTL_SET_DUP_COUNT API as well as frames we chose to drop ourselves.*/ + ogg_uint32_t prev_drop_count; + /*The log of an estimated scale factor used to obtain the real framerate, for + VFR sources or, e.g., 12 fps content doubled to 24 fps, etc.*/ + ogg_int64_t log_drop_scale; + /*The log of estimated scale factor for the rate model in Q57 format.*/ + ogg_int64_t log_scale[2]; + /*The log of the target quantizer level in Q57 format.*/ + ogg_int64_t log_qtarget; + /*Will we drop frames to meet bitrate target?*/ + unsigned char drop_frames; + /*Do we respect the maximum buffer fullness?*/ + unsigned char cap_overflow; + /*Can the reservoir go negative?*/ + unsigned char cap_underflow; + /*Second-order lowpass filters to track scale and VFR.*/ + oc_iir_filter scalefilter[2]; + int inter_count; + int inter_delay; + int inter_delay_target; + oc_iir_filter vfrfilter; + /*Two-pass mode state. + 0 => 1-pass encoding. + 1 => 1st pass of 2-pass encoding. + 2 => 2nd pass of 2-pass encoding.*/ + int twopass; + /*Buffer for current frame metrics.*/ + unsigned char twopass_buffer[48]; + /*The number of bytes in the frame metrics buffer. + When 2-pass encoding is enabled, this is set to 0 after each frame is + submitted, and must be non-zero before the next frame will be accepted.*/ + int twopass_buffer_bytes; + int twopass_buffer_fill; + /*Whether or not to force the next frame to be a keyframe.*/ + unsigned char twopass_force_kf; + /*The metrics for the previous frame.*/ + oc_frame_metrics prev_metrics; + /*The metrics for the current frame.*/ + oc_frame_metrics cur_metrics; + /*The buffered metrics for future frames.*/ + oc_frame_metrics *frame_metrics; + int nframe_metrics; + int cframe_metrics; + /*The index of the current frame in the circular metric buffer.*/ + int frame_metrics_head; + /*The frame count of each type (keyframes, delta frames, and dup frames); + 32 bits limits us to 2.268 years at 60 fps.*/ + ogg_uint32_t frames_total[3]; + /*The number of frames of each type yet to be processed.*/ + ogg_uint32_t frames_left[3]; + /*The sum of the scale values for each frame type.*/ + ogg_int64_t scale_sum[2]; + /*The start of the window over which the current scale sums are taken.*/ + int scale_window0; + /*The end of the window over which the current scale sums are taken.*/ + int scale_window_end; + /*The frame count of each type in the current 2-pass window; this does not + include dup frames.*/ + int nframes[3]; + /*The total accumulated estimation bias.*/ + ogg_int64_t rate_bias; +}; + + +void oc_rc_state_init(oc_rc_state *_rc,oc_enc_ctx *_enc); +void oc_rc_state_clear(oc_rc_state *_rc); + +void oc_enc_rc_resize(oc_enc_ctx *_enc); +int oc_enc_select_qi(oc_enc_ctx *_enc,int _qti,int _clamp); +void oc_enc_calc_lambda(oc_enc_ctx *_enc,int _frame_type); +int oc_enc_update_rc_state(oc_enc_ctx *_enc, + long _bits,int _qti,int _qi,int _trial,int _droppable); +int oc_enc_rc_2pass_out(oc_enc_ctx *_enc,unsigned char **_buf); +int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes); + + + +/*The internal encoder state.*/ +struct th_enc_ctx{ + /*Shared encoder/decoder state.*/ + oc_theora_state state; + /*Buffer in which to assemble packets.*/ + oggpack_buffer opb; + /*Encoder-specific macroblock information.*/ + oc_mb_enc_info *mb_info; + /*DC coefficients after prediction.*/ + ogg_int16_t *frag_dc; + /*The list of coded macro blocks, in coded order.*/ + unsigned *coded_mbis; + /*The number of coded macro blocks.*/ + size_t ncoded_mbis; + /*Whether or not packets are ready to be emitted. + This takes on negative values while there are remaining header packets to + be emitted, reaches 0 when the codec is ready for input, and becomes + positive when a frame has been processed and data packets are ready.*/ + int packet_state; + /*The maximum distance between keyframes.*/ + ogg_uint32_t keyframe_frequency_force; + /*The number of duplicates to produce for the next frame.*/ + ogg_uint32_t dup_count; + /*The number of duplicates remaining to be emitted for the current frame.*/ + ogg_uint32_t nqueued_dups; + /*The number of duplicates emitted for the last frame.*/ + ogg_uint32_t prev_dup_count; + /*The current speed level.*/ + int sp_level; + /*Whether or not VP3 compatibility mode has been enabled.*/ + unsigned char vp3_compatible; + /*Whether or not any INTER frames have been coded.*/ + unsigned char coded_inter_frame; + /*Whether or not previous frame was dropped.*/ + unsigned char prevframe_dropped; + /*Stores most recently chosen Huffman tables for each frame type, DC and AC + coefficients, and luma and chroma tokens. + The actual Huffman table used for a given coefficient depends not only on + the choice made here, but also its index in the zig-zag ordering.*/ + unsigned char huff_idxs[2][2][2]; + /*Current count of bits used by each MV coding mode.*/ + size_t mv_bits[2]; + /*The mode scheme chooser for estimating mode coding costs.*/ + oc_mode_scheme_chooser chooser; + /*The number of vertical super blocks in an MCU.*/ + int mcu_nvsbs; + /*The SSD error for skipping each fragment in the current MCU.*/ + unsigned *mcu_skip_ssd; + /*The DCT token lists for each coefficient and each plane.*/ + unsigned char **dct_tokens[3]; + /*The extra bits associated with each DCT token.*/ + ogg_uint16_t **extra_bits[3]; + /*The number of DCT tokens for each coefficient for each plane.*/ + ptrdiff_t ndct_tokens[3][64]; + /*Pending EOB runs for each coefficient for each plane.*/ + ogg_uint16_t eob_run[3][64]; + /*The offset of the first DCT token for each coefficient for each plane.*/ + unsigned char dct_token_offs[3][64]; + /*The last DC coefficient for each plane and reference frame.*/ + int dc_pred_last[3][3]; +#if defined(OC_COLLECT_METRICS) + /*Fragment SATD statistics for MB mode estimation metrics.*/ + unsigned *frag_satd; + /*Fragment SSD statistics for MB mode estimation metrics.*/ + unsigned *frag_ssd; +#endif + /*The R-D optimization parameter.*/ + int lambda; + /*The huffman tables in use.*/ + th_huff_code huff_codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]; + /*The quantization parameters in use.*/ + th_quant_info qinfo; + oc_iquant *enquant_tables[64][3][2]; + oc_iquant_table enquant_table_data[64][3][2]; + /*An "average" quantizer for each quantizer type (INTRA or INTER) and qi + value. + This is used to paramterize the rate control decisions. + They are kept in the log domain to simplify later processing. + Keep in mind these are DCT domain quantizers, and so are scaled by an + additional factor of 4 from the pixel domain.*/ + ogg_int64_t log_qavg[2][64]; + /*The buffer state used to drive rate control.*/ + oc_rc_state rc; + /*Table for encoder acceleration functions.*/ + oc_enc_opt_vtable opt_vtable; +}; + + +void oc_enc_analyze_intra(oc_enc_ctx *_enc,int _recode); +int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode); +#if defined(OC_COLLECT_METRICS) +void oc_enc_mode_metrics_collect(oc_enc_ctx *_enc); +void oc_enc_mode_metrics_dump(oc_enc_ctx *_enc); +#endif + + + +/*Perform fullpel motion search for a single MB against both reference frames.*/ +void oc_mcenc_search(oc_enc_ctx *_enc,int _mbi); +/*Refine a MB MV for one frame.*/ +void oc_mcenc_refine1mv(oc_enc_ctx *_enc,int _mbi,int _frame); +/*Refine the block MVs.*/ +void oc_mcenc_refine4mv(oc_enc_ctx *_enc,int _mbi); + + + +/*Used to rollback a tokenlog transaction when we retroactively decide to skip + a fragment. + A checkpoint is taken right before each token is added.*/ +struct oc_token_checkpoint{ + /*The color plane the token was added to.*/ + unsigned char pli; + /*The zig-zag index the token was added to.*/ + unsigned char zzi; + /*The outstanding EOB run count before the token was added.*/ + ogg_uint16_t eob_run; + /*The token count before the token was added.*/ + ptrdiff_t ndct_tokens; +}; + + + +void oc_enc_tokenize_start(oc_enc_ctx *_enc); +int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi, + ogg_int16_t *_qdct,const ogg_uint16_t *_dequant,const ogg_int16_t *_dct, + int _zzi,oc_token_checkpoint **_stack,int _acmin); +void oc_enc_tokenlog_rollback(oc_enc_ctx *_enc, + const oc_token_checkpoint *_stack,int _n); +void oc_enc_pred_dc_frag_rows(oc_enc_ctx *_enc, + int _pli,int _fragy0,int _frag_yend); +void oc_enc_tokenize_dc_frag_list(oc_enc_ctx *_enc,int _pli, + const ptrdiff_t *_coded_fragis,ptrdiff_t _ncoded_fragis, + int _prev_ndct_tokens1,int _prev_eob_run1); +void oc_enc_tokenize_finish(oc_enc_ctx *_enc); + + + +/*Utility routine to encode one of the header packets.*/ +int oc_state_flushheader(oc_theora_state *_state,int *_packet_state, + oggpack_buffer *_opb,const th_quant_info *_qinfo, + const th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS], + const char *_vendor,th_comment *_tc,ogg_packet *_op); + + + +/*Encoder-specific accelerated functions.*/ +void oc_enc_frag_sub(const oc_enc_ctx *_enc,ogg_int16_t _diff[64], + const unsigned char *_src,const unsigned char *_ref,int _ystride); +void oc_enc_frag_sub_128(const oc_enc_ctx *_enc,ogg_int16_t _diff[64], + const unsigned char *_src,int _ystride); +unsigned oc_enc_frag_sad(const oc_enc_ctx *_enc,const unsigned char *_src, + const unsigned char *_ref,int _ystride); +unsigned oc_enc_frag_sad_thresh(const oc_enc_ctx *_enc, + const unsigned char *_src,const unsigned char *_ref,int _ystride, + unsigned _thresh); +unsigned oc_enc_frag_sad2_thresh(const oc_enc_ctx *_enc, + const unsigned char *_src,const unsigned char *_ref1, + const unsigned char *_ref2,int _ystride,unsigned _thresh); +unsigned oc_enc_frag_satd_thresh(const oc_enc_ctx *_enc, + const unsigned char *_src,const unsigned char *_ref,int _ystride, + unsigned _thresh); +unsigned oc_enc_frag_satd2_thresh(const oc_enc_ctx *_enc, + const unsigned char *_src,const unsigned char *_ref1, + const unsigned char *_ref2,int _ystride,unsigned _thresh); +unsigned oc_enc_frag_intra_satd(const oc_enc_ctx *_enc, + const unsigned char *_src,int _ystride); +void oc_enc_frag_copy2(const oc_enc_ctx *_enc,unsigned char *_dst, + const unsigned char *_src1,const unsigned char *_src2,int _ystride); +void oc_enc_frag_recon_intra(const oc_enc_ctx *_enc, + unsigned char *_dst,int _ystride,const ogg_int16_t _residue[64]); +void oc_enc_frag_recon_inter(const oc_enc_ctx *_enc,unsigned char *_dst, + const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]); +void oc_enc_fdct8x8(const oc_enc_ctx *_enc,ogg_int16_t _y[64], + const ogg_int16_t _x[64]); + +/*Default pure-C implementations.*/ +void oc_enc_vtable_init_c(oc_enc_ctx *_enc); + +void oc_enc_frag_sub_c(ogg_int16_t _diff[64], + const unsigned char *_src,const unsigned char *_ref,int _ystride); +void oc_enc_frag_sub_128_c(ogg_int16_t _diff[64], + const unsigned char *_src,int _ystride); +void oc_enc_frag_copy2_c(unsigned char *_dst, + const unsigned char *_src1,const unsigned char *_src2,int _ystride); +unsigned oc_enc_frag_sad_c(const unsigned char *_src, + const unsigned char *_ref,int _ystride); +unsigned oc_enc_frag_sad_thresh_c(const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _thresh); +unsigned oc_enc_frag_sad2_thresh_c(const unsigned char *_src, + const unsigned char *_ref1,const unsigned char *_ref2,int _ystride, + unsigned _thresh); +unsigned oc_enc_frag_satd_thresh_c(const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _thresh); +unsigned oc_enc_frag_satd2_thresh_c(const unsigned char *_src, + const unsigned char *_ref1,const unsigned char *_ref2,int _ystride, + unsigned _thresh); +unsigned oc_enc_frag_intra_satd_c(const unsigned char *_src,int _ystride); +void oc_enc_fdct8x8_c(ogg_int16_t _y[64],const ogg_int16_t _x[64]); + +#endif diff --git a/Engine/lib/libtheora/lib/encode.c b/Engine/lib/libtheora/lib/encode.c new file mode 100644 index 000000000..0c5ea6a17 --- /dev/null +++ b/Engine/lib/libtheora/lib/encode.c @@ -0,0 +1,1615 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: encode.c 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ +#include +#include +#include "encint.h" +#if defined(OC_X86_ASM) +# include "x86/x86enc.h" +#endif + + + +/*The default quantization parameters used by VP3.1.*/ +static const int OC_VP31_RANGE_SIZES[1]={63}; +static const th_quant_base OC_VP31_BASES_INTRA_Y[2]={ + { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 58, 68,109,103, 77, + 24, 35, 55, 64, 81,104,113, 92, + 49, 64, 78, 87,103,121,120,101, + 72, 92, 95, 98,112,100,103, 99 + }, + { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 58, 68,109,103, 77, + 24, 35, 55, 64, 81,104,113, 92, + 49, 64, 78, 87,103,121,120,101, + 72, 92, 95, 98,112,100,103, 99 + } +}; +static const th_quant_base OC_VP31_BASES_INTRA_C[2]={ + { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 + }, + { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 + } +}; +static const th_quant_base OC_VP31_BASES_INTER[2]={ + { + 16, 16, 16, 20, 24, 28, 32, 40, + 16, 16, 20, 24, 28, 32, 40, 48, + 16, 20, 24, 28, 32, 40, 48, 64, + 20, 24, 28, 32, 40, 48, 64, 64, + 24, 28, 32, 40, 48, 64, 64, 64, + 28, 32, 40, 48, 64, 64, 64, 96, + 32, 40, 48, 64, 64, 64, 96,128, + 40, 48, 64, 64, 64, 96,128,128 + }, + { + 16, 16, 16, 20, 24, 28, 32, 40, + 16, 16, 20, 24, 28, 32, 40, 48, + 16, 20, 24, 28, 32, 40, 48, 64, + 20, 24, 28, 32, 40, 48, 64, 64, + 24, 28, 32, 40, 48, 64, 64, 64, + 28, 32, 40, 48, 64, 64, 64, 96, + 32, 40, 48, 64, 64, 64, 96,128, + 40, 48, 64, 64, 64, 96,128,128 + } +}; + +const th_quant_info TH_VP31_QUANT_INFO={ + { + 220,200,190,180,170,170,160,160, + 150,150,140,140,130,130,120,120, + 110,110,100,100, 90, 90, 90, 80, + 80, 80, 70, 70, 70, 60, 60, 60, + 60, 50, 50, 50, 50, 40, 40, 40, + 40, 40, 30, 30, 30, 30, 30, 30, + 30, 20, 20, 20, 20, 20, 20, 20, + 20, 10, 10, 10, 10, 10, 10, 10 + }, + { + 500,450,400,370,340,310,285,265, + 245,225,210,195,185,180,170,160, + 150,145,135,130,125,115,110,107, + 100, 96, 93, 89, 85, 82, 75, 74, + 70, 68, 64, 60, 57, 56, 52, 50, + 49, 45, 44, 43, 40, 38, 37, 35, + 33, 32, 30, 29, 28, 25, 24, 22, + 21, 19, 18, 17, 15, 13, 12, 10 + }, + { + 30,25,20,20,15,15,14,14, + 13,13,12,12,11,11,10,10, + 9, 9, 8, 8, 7, 7, 7, 7, + 6, 6, 6, 6, 5, 5, 5, 5, + 4, 4, 4, 4, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }, + { + { + {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTRA_Y}, + {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTRA_C}, + {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTRA_C} + }, + { + {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTER}, + {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTER}, + {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTER} + } + } +}; + +/*The current default quantization parameters.*/ +static const int OC_DEF_QRANGE_SIZES[3]={32,16,15}; +static const th_quant_base OC_DEF_BASES_INTRA_Y[4]={ + { + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + }, + { + 15, 12, 12, 15, 18, 20, 20, 21, + 13, 13, 14, 17, 18, 21, 21, 20, + 14, 14, 15, 18, 20, 21, 21, 21, + 14, 16, 17, 19, 20, 21, 21, 21, + 16, 17, 20, 21, 21, 21, 21, 21, + 18, 19, 20, 21, 21, 21, 21, 21, + 20, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21 + }, + { + 16, 12, 11, 16, 20, 25, 27, 28, + 13, 13, 14, 18, 21, 28, 28, 27, + 14, 13, 16, 20, 25, 28, 28, 28, + 14, 16, 19, 22, 27, 29, 29, 28, + 17, 19, 25, 28, 28, 30, 30, 29, + 20, 24, 27, 28, 29, 30, 30, 29, + 27, 28, 29, 29, 30, 30, 30, 30, + 29, 29, 29, 29, 30, 30, 30, 29 + }, + { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 58, 68,109,103, 77, + 24, 35, 55, 64, 81,104,113, 92, + 49, 64, 78, 87,103,121,120,101, + 72, 92, 95, 98,112,100,103, 99 + } +}; +static const th_quant_base OC_DEF_BASES_INTRA_C[4]={ + { + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19 + }, + { + 18, 18, 21, 25, 26, 26, 26, 26, + 18, 20, 22, 26, 26, 26, 26, 26, + 21, 22, 25, 26, 26, 26, 26, 26, + 25, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26 + }, + { + 17, 18, 22, 31, 36, 36, 36, 36, + 18, 20, 24, 34, 36, 36, 36, 36, + 22, 24, 33, 36, 36, 36, 36, 36, + 31, 34, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36 + }, + { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 + } +}; +static const th_quant_base OC_DEF_BASES_INTER[4]={ + { + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21 + }, + { + 18, 18, 18, 21, 23, 24, 25, 27, + 18, 18, 21, 23, 24, 25, 27, 28, + 18, 21, 23, 24, 25, 27, 28, 29, + 21, 23, 24, 25, 27, 28, 29, 29, + 23, 24, 25, 27, 28, 29, 29, 29, + 24, 25, 27, 28, 29, 29, 29, 30, + 25, 27, 28, 29, 29, 29, 30, 30, + 27, 28, 29, 29, 29, 30, 30, 30 + }, + { + 17, 17, 17, 20, 23, 26, 28, 32, + 17, 17, 20, 23, 26, 28, 32, 34, + 17, 20, 23, 26, 28, 32, 34, 37, + 20, 23, 26, 28, 32, 34, 37, 37, + 23, 26, 28, 32, 34, 37, 37, 37, + 26, 28, 32, 34, 37, 37, 37, 41, + 28, 32, 34, 37, 37, 37, 41, 42, + 32, 34, 37, 37, 37, 41, 42, 42 + }, + { + 16, 16, 16, 20, 24, 28, 32, 40, + 16, 16, 20, 24, 28, 32, 40, 48, + 16, 20, 24, 28, 32, 40, 48, 64, + 20, 24, 28, 32, 40, 48, 64, 64, + 24, 28, 32, 40, 48, 64, 64, 64, + 28, 32, 40, 48, 64, 64, 64, 96, + 32, 40, 48, 64, 64, 64, 96,128, + 40, 48, 64, 64, 64, 96,128,128 + } +}; + +const th_quant_info TH_DEF_QUANT_INFO={ + { + 365,348,333,316,300,287,277,265, + 252,240,229,219,206,197,189,180, + 171,168,160,153,146,139,132,127, + 121,115,110,107,101, 97, 94, 89, + 85, 83, 78, 73, 72, 67, 66, 62, + 60, 59, 56, 53, 52, 48, 47, 43, + 42, 40, 36, 35, 34, 33, 31, 30, + 28, 25, 24, 22, 20, 17, 14, 10 + }, + { + 365,348,333,316,300,287,277,265, + 252,240,229,219,206,197,189,180, + 171,168,160,153,146,139,132,127, + 121,115,110,107,101, 97, 94, 89, + 85, 83, 78, 73, 72, 67, 66, 62, + 60, 59, 56, 53, 52, 48, 47, 43, + 42, 40, 36, 35, 34, 33, 31, 30, + 28, 25, 24, 22, 20, 17, 14, 10 + }, + { + 30,25,20,20,15,15,14,14, + 13,13,12,12,11,11,10,10, + 9, 9, 8, 8, 7, 7, 7, 7, + 6, 6, 6, 6, 5, 5, 5, 5, + 4, 4, 4, 4, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }, + { + { + {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTRA_Y}, + {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTRA_C}, + {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTRA_C} + }, + { + {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTER}, + {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTER}, + {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTER} + } + } +}; + + + +/*The Huffman codes used for macro block modes.*/ + +const unsigned char OC_MODE_BITS[2][OC_NMODES]={ + /*Codebook 0: a maximally skewed prefix code.*/ + {1,2,3,4,5,6,7,7}, + /*Codebook 1: a fixed-length code.*/ + {3,3,3,3,3,3,3,3} +}; + +static const unsigned char OC_MODE_CODES[2][OC_NMODES]={ + /*Codebook 0: a maximally skewed prefix code.*/ + {0x00,0x02,0x06,0x0E,0x1E,0x3E,0x7E,0x7F}, + /*Codebook 1: a fixed-length code.*/ + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07} +}; + + +/*The Huffman codes used for motion vectors.*/ + +const unsigned char OC_MV_BITS[2][64]={ + /*Codebook 0: VLC code.*/ + { + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,7,7,7,7,7,7,7,7,6,6,6,6,4,4,3, + 3, + 3,4,4,6,6,6,6,7,7,7,7,7,7,7,7,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 + }, + /*Codebook 1: (5 bit magnitude, 1 bit sign). + This wastes a code word (0x01, negative zero), or a bit (0x00, positive + zero, requires only 5 bits to uniquely decode), but is hopefully not used + very often.*/ + { + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 + } +}; + +static const unsigned char OC_MV_CODES[2][64]={ + /*Codebook 0: VLC code.*/ + { + 0xFF,0xFD,0xFB,0xF9,0xF7,0xF5,0xF3, + 0xF1,0xEF,0xED,0xEB,0xE9,0xE7,0xE5,0xE3, + 0xE1,0x6F,0x6D,0x6B,0x69,0x67,0x65,0x63, + 0x61,0x2F,0x2D,0x2B,0x29,0x09,0x07,0x02, + 0x00, + 0x01,0x06,0x08,0x28,0x2A,0x2C,0x2E,0x60, + 0x62,0x64,0x66,0x68,0x6A,0x6C,0x6E,0xE0, + 0xE2,0xE4,0xE6,0xE8,0xEA,0xEC,0xEE,0xF0, + 0xF2,0xF4,0xF6,0xF8,0xFA,0xFC,0xFE + }, + /*Codebook 1: (5 bit magnitude, 1 bit sign).*/ + { + 0x3F,0x3D,0x3B,0x39,0x37,0x35,0x33, + 0x31,0x2F,0x2D,0x2B,0x29,0x27,0x25,0x23, + 0x21,0x1F,0x1D,0x1B,0x19,0x17,0x15,0x13, + 0x11,0x0F,0x0D,0x0B,0x09,0x07,0x05,0x03, + 0x00, + 0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,0x10, + 0x12,0x14,0x16,0x18,0x1A,0x1C,0x1E,0x20, + 0x22,0x24,0x26,0x28,0x2A,0x2C,0x2E,0x30, + 0x32,0x34,0x36,0x38,0x3A,0x3C,0x3E + } +}; + + + +/*Super block run coding scheme: + Codeword Run Length + 0 1 + 10x 2-3 + 110x 4-5 + 1110xx 6-9 + 11110xxx 10-17 + 111110xxxx 18-33 + 111111xxxxxxxxxxxx 34-4129*/ +const ogg_uint16_t OC_SB_RUN_VAL_MIN[8]={1,2,4,6,10,18,34,4130}; +static const unsigned OC_SB_RUN_CODE_PREFIX[7]={ + 0,4,0xC,0x38,0xF0,0x3E0,0x3F000 +}; +const unsigned char OC_SB_RUN_CODE_NBITS[7]={1,3,4,6,8,10,18}; + + +/*Writes the bit pattern for the run length of a super block run to the given + oggpack_buffer. + _opb: The buffer to write to. + _run_count: The length of the run, which must be positive. + _flag: The current flag. + _done: Whether or not more flags are to be encoded.*/ +static void oc_sb_run_pack(oggpack_buffer *_opb,ptrdiff_t _run_count, + int _flag,int _done){ + int i; + if(_run_count>=4129){ + do{ + oggpackB_write(_opb,0x3FFFF,18); + _run_count-=4129; + if(_run_count>0)oggpackB_write(_opb,_flag,1); + else if(!_done)oggpackB_write(_opb,!_flag,1); + } + while(_run_count>=4129); + if(_run_count<=0)return; + } + for(i=0;_run_count>=OC_SB_RUN_VAL_MIN[i+1];i++); + oggpackB_write(_opb,OC_SB_RUN_CODE_PREFIX[i]+_run_count-OC_SB_RUN_VAL_MIN[i], + OC_SB_RUN_CODE_NBITS[i]); +} + + + +/*Block run coding scheme: + Codeword Run Length + 0x 1-2 + 10x 3-4 + 110x 5-6 + 1110xx 7-10 + 11110xx 11-14 + 11111xxxx 15-30*/ +const unsigned char OC_BLOCK_RUN_CODE_NBITS[30]={ + 2,2,3,3,4,4,6,6,6,6,7,7,7,7,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9 +}; +static const ogg_uint16_t OC_BLOCK_RUN_CODE_PATTERN[30]={ + 0x000,0x001,0x004,0x005,0x00C,0x00D,0x038, + 0x039,0x03A,0x03B,0x078,0x079,0x07A,0x07B,0x1F0, + 0x1F1,0x1F2,0x1F3,0x1F4,0x1F5,0x1F6,0x1F7,0x1F8, + 0x1F9,0x1FA,0x1FB,0x1FC,0x1FD,0x1FE,0x1FF +}; + + +/*Writes the bit pattern for the run length of a block run to the given + oggpack_buffer. + _opb: The buffer to write to. + _run_count: The length of the run. + This must be positive, and no more than 30.*/ +static void oc_block_run_pack(oggpack_buffer *_opb,int _run_count){ + oggpackB_write(_opb,OC_BLOCK_RUN_CODE_PATTERN[_run_count-1], + OC_BLOCK_RUN_CODE_NBITS[_run_count-1]); +} + + + +static void oc_enc_frame_header_pack(oc_enc_ctx *_enc){ + /*Mark this as a data packet.*/ + oggpackB_write(&_enc->opb,0,1); + /*Output the frame type (key frame or delta frame).*/ + oggpackB_write(&_enc->opb,_enc->state.frame_type,1); + /*Write out the current qi list.*/ + oggpackB_write(&_enc->opb,_enc->state.qis[0],6); + if(_enc->state.nqis>1){ + oggpackB_write(&_enc->opb,1,1); + oggpackB_write(&_enc->opb,_enc->state.qis[1],6); + if(_enc->state.nqis>2){ + oggpackB_write(&_enc->opb,1,1); + oggpackB_write(&_enc->opb,_enc->state.qis[2],6); + } + else oggpackB_write(&_enc->opb,0,1); + } + else oggpackB_write(&_enc->opb,0,1); + if(_enc->state.frame_type==OC_INTRA_FRAME){ + /*Key frames have 3 unused configuration bits, holdovers from the VP3 days. + Most of the other unused bits in the VP3 headers were eliminated. + Monty kept these to leave us some wiggle room for future expansion, + though a single bit in all frames would have been far more useful.*/ + oggpackB_write(&_enc->opb,0,3); + } +} + +/*Writes the bit flags for whether or not each super block is partially coded + or not. + These flags are run-length encoded, with the flag value alternating between + each run. + Return: The number partially coded SBs.*/ +static unsigned oc_enc_partial_sb_flags_pack(oc_enc_ctx *_enc){ + const oc_sb_flags *sb_flags; + unsigned nsbs; + unsigned sbi; + unsigned npartial; + int flag; + sb_flags=_enc->state.sb_flags; + nsbs=_enc->state.nsbs; + flag=sb_flags[0].coded_partially; + oggpackB_write(&_enc->opb,flag,1); + sbi=npartial=0; + do{ + unsigned run_count; + for(run_count=0;sbiopb,run_count,flag,sbi>=nsbs); + flag=!flag; + } + while(sbistate.sb_flags; + nsbs=_enc->state.nsbs; + /*Skip partially coded super blocks; their flags have already been coded.*/ + for(sbi=0;sb_flags[sbi].coded_partially;sbi++); + flag=sb_flags[sbi].coded_fully; + oggpackB_write(&_enc->opb,flag,1); + do{ + unsigned run_count; + for(run_count=0;sbiopb,run_count,flag,sbi>=nsbs); + flag=!flag; + } + while(sbistate.nsbs)oc_enc_coded_sb_flags_pack(_enc); + sb_maps=(const oc_sb_map *)_enc->state.sb_maps; + sb_flags=_enc->state.sb_flags; + nsbs=_enc->state.nsbs; + frags=_enc->state.frags; + for(sbi=0;sbiopb,flag,1); + run_count=0; + nsbs=sbi=0; + for(pli=0;pli<3;pli++){ + nsbs+=_enc->state.fplanes[pli].nsbs; + for(;sbi=0){ + if(frags[fragi].coded!=flag){ + oc_block_run_pack(&_enc->opb,run_count); + flag=!flag; + run_count=1; + } + else run_count++; + } + } + } + } + } + } + /*Flush any trailing block coded run.*/ + if(run_count>0)oc_block_run_pack(&_enc->opb,run_count); + } +} + +static void oc_enc_mb_modes_pack(oc_enc_ctx *_enc){ + const unsigned char *mode_codes; + const unsigned char *mode_bits; + const unsigned char *mode_ranks; + unsigned *coded_mbis; + size_t ncoded_mbis; + const signed char *mb_modes; + unsigned mbii; + int scheme; + int mb_mode; + scheme=_enc->chooser.scheme_list[0]; + /*Encode the best scheme.*/ + oggpackB_write(&_enc->opb,scheme,3); + /*If the chosen scheme is scheme 0, send the mode frequency ordering.*/ + if(scheme==0){ + for(mb_mode=0;mb_modeopb,_enc->chooser.scheme0_ranks[mb_mode],3); + } + } + mode_ranks=_enc->chooser.mode_ranks[scheme]; + mode_bits=OC_MODE_BITS[scheme+1>>3]; + mode_codes=OC_MODE_CODES[scheme+1>>3]; + coded_mbis=_enc->coded_mbis; + ncoded_mbis=_enc->ncoded_mbis; + mb_modes=_enc->state.mb_modes; + for(mbii=0;mbiiopb,mode_codes[rank],mode_bits[rank]); + } +} + +static void oc_enc_mv_pack(oc_enc_ctx *_enc,int _mv_scheme,int _dx,int _dy){ + oggpackB_write(&_enc->opb, + OC_MV_CODES[_mv_scheme][_dx+31],OC_MV_BITS[_mv_scheme][_dx+31]); + oggpackB_write(&_enc->opb, + OC_MV_CODES[_mv_scheme][_dy+31],OC_MV_BITS[_mv_scheme][_dy+31]); +} + +static void oc_enc_mvs_pack(oc_enc_ctx *_enc){ + const unsigned *coded_mbis; + size_t ncoded_mbis; + const oc_mb_map *mb_maps; + const signed char *mb_modes; + const oc_fragment *frags; + const oc_mv *frag_mvs; + unsigned mbii; + int mv_scheme; + /*Choose the coding scheme.*/ + mv_scheme=_enc->mv_bits[1]<_enc->mv_bits[0]; + oggpackB_write(&_enc->opb,mv_scheme,1); + /*Encode the motion vectors. + Macro blocks are iterated in Hilbert scan order, but the MVs within the + macro block are coded in raster order.*/ + coded_mbis=_enc->coded_mbis; + ncoded_mbis=_enc->ncoded_mbis; + mb_modes=_enc->state.mb_modes; + mb_maps=(const oc_mb_map *)_enc->state.mb_maps; + frags=_enc->state.frags; + frag_mvs=(const oc_mv *)_enc->state.frag_mvs; + for(mbii=0;mbiistate.nqis<=1)return; + ncoded_fragis=_enc->state.ntotal_coded_fragis; + if(ncoded_fragis<=0)return; + coded_fragis=_enc->state.coded_fragis; + frags=_enc->state.frags; + flag=!!frags[coded_fragis[0]].qii; + oggpackB_write(&_enc->opb,flag,1); + nqi0=0; + for(fragii=0;fragiiopb,run_count,flag,fragii>=ncoded_fragis); + flag=!flag; + } + if(_enc->state.nqis<3||nqi0>=ncoded_fragis)return; + for(fragii=0;!frags[coded_fragis[fragii]].qii;fragii++); + flag=frags[coded_fragis[fragii]].qii-1; + oggpackB_write(&_enc->opb,flag,1); + while(fragiiopb,run_count,flag,fragii>=ncoded_fragis); + flag=!flag; + } +} + +/*Counts the tokens of each type used for the given range of coefficient + indices in zig-zag order. + _zzi_start: The first zig-zag index to include. + _zzi_end: The first zig-zag index to not include. + _token_counts_y: Returns the token counts for the Y' plane. + _token_counts_c: Returns the token counts for the Cb and Cr planes.*/ +static void oc_enc_count_tokens(oc_enc_ctx *_enc,int _zzi_start,int _zzi_end, + ptrdiff_t _token_counts_y[32],ptrdiff_t _token_counts_c[32]){ + const unsigned char *dct_tokens; + ptrdiff_t ndct_tokens; + int pli; + int zzi; + ptrdiff_t ti; + memset(_token_counts_y,0,32*sizeof(*_token_counts_y)); + memset(_token_counts_c,0,32*sizeof(*_token_counts_c)); + for(zzi=_zzi_start;zzi<_zzi_end;zzi++){ + dct_tokens=_enc->dct_tokens[0][zzi]; + ndct_tokens=_enc->ndct_tokens[0][zzi]; + for(ti=_enc->dct_token_offs[0][zzi];tidct_tokens[pli][zzi]; + ndct_tokens=_enc->ndct_tokens[pli][zzi]; + for(ti=_enc->dct_token_offs[pli][zzi];tihuff_codes[huffi+huff_offs][token].nbits; + } + } +} + +/*Returns the Huffman index using the fewest number of bits.*/ +static int oc_select_huff_idx(size_t _bit_counts[16]){ + int best_huffi; + int huffi; + best_huffi=0; + for(huffi=1;huffi<16;huffi++)if(_bit_counts[huffi]<_bit_counts[best_huffi]){ + best_huffi=huffi; + } + return best_huffi; +} + +static void oc_enc_huff_group_pack(oc_enc_ctx *_enc, + int _zzi_start,int _zzi_end,const int _huff_idxs[2]){ + int zzi; + for(zzi=_zzi_start;zzi<_zzi_end;zzi++){ + int pli; + for(pli=0;pli<3;pli++){ + const unsigned char *dct_tokens; + const ogg_uint16_t *extra_bits; + ptrdiff_t ndct_tokens; + const th_huff_code *huff_codes; + ptrdiff_t ti; + dct_tokens=_enc->dct_tokens[pli][zzi]; + extra_bits=_enc->extra_bits[pli][zzi]; + ndct_tokens=_enc->ndct_tokens[pli][zzi]; + huff_codes=_enc->huff_codes[_huff_idxs[pli+1>>1]]; + for(ti=_enc->dct_token_offs[pli][zzi];tiopb,huff_codes[token].pattern, + huff_codes[token].nbits); + neb=OC_DCT_TOKEN_EXTRA_BITS[token]; + if(neb)oggpackB_write(&_enc->opb,extra_bits[ti],neb); + } + } + } +} + +static void oc_enc_residual_tokens_pack(oc_enc_ctx *_enc){ + static const unsigned char OC_HUFF_GROUP_MIN[6]={0,1,6,15,28,64}; + static const unsigned char *OC_HUFF_GROUP_MAX=OC_HUFF_GROUP_MIN+1; + ptrdiff_t token_counts_y[32]; + ptrdiff_t token_counts_c[32]; + size_t bits_y[16]; + size_t bits_c[16]; + int huff_idxs[2]; + int frame_type; + int hgi; + frame_type=_enc->state.frame_type; + /*Choose which Huffman tables to use for the DC token list.*/ + oc_enc_count_tokens(_enc,0,1,token_counts_y,token_counts_c); + memset(bits_y,0,sizeof(bits_y)); + memset(bits_c,0,sizeof(bits_c)); + oc_enc_count_bits(_enc,0,token_counts_y,bits_y); + oc_enc_count_bits(_enc,0,token_counts_c,bits_c); + huff_idxs[0]=oc_select_huff_idx(bits_y); + huff_idxs[1]=oc_select_huff_idx(bits_c); + /*Write the DC token list with the chosen tables.*/ + oggpackB_write(&_enc->opb,huff_idxs[0],4); + oggpackB_write(&_enc->opb,huff_idxs[1],4); + _enc->huff_idxs[frame_type][0][0]=(unsigned char)huff_idxs[0]; + _enc->huff_idxs[frame_type][0][1]=(unsigned char)huff_idxs[1]; + oc_enc_huff_group_pack(_enc,0,1,huff_idxs); + /*Choose which Huffman tables to use for the AC token lists.*/ + memset(bits_y,0,sizeof(bits_y)); + memset(bits_c,0,sizeof(bits_c)); + for(hgi=1;hgi<5;hgi++){ + oc_enc_count_tokens(_enc,OC_HUFF_GROUP_MIN[hgi],OC_HUFF_GROUP_MAX[hgi], + token_counts_y,token_counts_c); + oc_enc_count_bits(_enc,hgi,token_counts_y,bits_y); + oc_enc_count_bits(_enc,hgi,token_counts_c,bits_c); + } + huff_idxs[0]=oc_select_huff_idx(bits_y); + huff_idxs[1]=oc_select_huff_idx(bits_c); + /*Write the AC token lists using the chosen tables.*/ + oggpackB_write(&_enc->opb,huff_idxs[0],4); + oggpackB_write(&_enc->opb,huff_idxs[1],4); + _enc->huff_idxs[frame_type][1][0]=(unsigned char)huff_idxs[0]; + _enc->huff_idxs[frame_type][1][1]=(unsigned char)huff_idxs[1]; + for(hgi=1;hgi<5;hgi++){ + huff_idxs[0]+=16; + huff_idxs[1]+=16; + oc_enc_huff_group_pack(_enc, + OC_HUFF_GROUP_MIN[hgi],OC_HUFF_GROUP_MAX[hgi],huff_idxs); + } +} + +static void oc_enc_frame_pack(oc_enc_ctx *_enc){ + oggpackB_reset(&_enc->opb); + /*Only proceed if we have some coded blocks. + If there are no coded blocks, we can drop this frame simply by emitting a + 0 byte packet.*/ + if(_enc->state.ntotal_coded_fragis>0){ + oc_enc_frame_header_pack(_enc); + if(_enc->state.frame_type==OC_INTER_FRAME){ + /*Coded block flags, MB modes, and MVs are only needed for delta frames.*/ + oc_enc_coded_flags_pack(_enc); + oc_enc_mb_modes_pack(_enc); + oc_enc_mvs_pack(_enc); + } + oc_enc_block_qis_pack(_enc); + oc_enc_tokenize_finish(_enc); + oc_enc_residual_tokens_pack(_enc); + } + /*Success: Mark the packet as ready to be flushed.*/ + _enc->packet_state=OC_PACKET_READY; +#if defined(OC_COLLECT_METRICS) + oc_enc_mode_metrics_collect(_enc); +#endif +} + + +void oc_enc_vtable_init_c(oc_enc_ctx *_enc){ + /*The implementations prefixed with oc_enc_ are encoder-specific. + The rest we re-use from the decoder.*/ + _enc->opt_vtable.frag_sad=oc_enc_frag_sad_c; + _enc->opt_vtable.frag_sad_thresh=oc_enc_frag_sad_thresh_c; + _enc->opt_vtable.frag_sad2_thresh=oc_enc_frag_sad2_thresh_c; + _enc->opt_vtable.frag_satd_thresh=oc_enc_frag_satd_thresh_c; + _enc->opt_vtable.frag_satd2_thresh=oc_enc_frag_satd2_thresh_c; + _enc->opt_vtable.frag_intra_satd=oc_enc_frag_intra_satd_c; + _enc->opt_vtable.frag_sub=oc_enc_frag_sub_c; + _enc->opt_vtable.frag_sub_128=oc_enc_frag_sub_128_c; + _enc->opt_vtable.frag_copy2=oc_enc_frag_copy2_c; + _enc->opt_vtable.frag_recon_intra=oc_frag_recon_intra_c; + _enc->opt_vtable.frag_recon_inter=oc_frag_recon_inter_c; + _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_c; +} + +/*Initialize the macro block neighbor lists for MC analysis. + This assumes that the entire mb_info memory region has been initialized with + zeros.*/ +static void oc_enc_mb_info_init(oc_enc_ctx *_enc){ + oc_mb_enc_info *embs; + const signed char *mb_modes; + unsigned nhsbs; + unsigned nvsbs; + unsigned nhmbs; + unsigned nvmbs; + unsigned sby; + mb_modes=_enc->state.mb_modes; + embs=_enc->mb_info; + nhsbs=_enc->state.fplanes[0].nhsbs; + nvsbs=_enc->state.fplanes[0].nvsbs; + nhmbs=_enc->state.nhmbs; + nvmbs=_enc->state.nvmbs; + for(sby=0;sby>1); + mby=2*sby+(quadi+1>>1&1); + /*Fill in the neighbors with current motion vectors available.*/ + for(ni=0;ni=nhmbs||nmby<0||nmby>=nvmbs)continue; + nmbi=(nmby&~1)*nhmbs+((nmbx&~1)<<1)+OC_MB_MAP[nmby&1][nmbx&1]; + if(mb_modes[nmbi]==OC_MODE_INVALID)continue; + embs[mbi].cneighbors[embs[mbi].ncneighbors++]=nmbi; + } + /*Fill in the neighbors with previous motion vectors available.*/ + for(ni=0;ni<4;ni++){ + nmbx=mbx+PDX[ni]; + nmby=mby+PDY[ni]; + if(nmbx<0||nmbx>=nhmbs||nmby<0||nmby>=nvmbs)continue; + nmbi=(nmby&~1)*nhmbs+((nmbx&~1)<<1)+OC_MB_MAP[nmby&1][nmbx&1]; + if(mb_modes[nmbi]==OC_MODE_INVALID)continue; + embs[mbi].pneighbors[embs[mbi].npneighbors++]=nmbi; + } + } + } + } +} + +static int oc_enc_set_huffman_codes(oc_enc_ctx *_enc, + const th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]){ + int ret; + if(_enc==NULL)return TH_EFAULT; + if(_enc->packet_state>OC_PACKET_SETUP_HDR)return TH_EINVAL; + if(_codes==NULL)_codes=TH_VP31_HUFF_CODES; + /*Validate the codes.*/ + oggpackB_reset(&_enc->opb); + ret=oc_huff_codes_pack(&_enc->opb,_codes); + if(ret<0)return ret; + memcpy(_enc->huff_codes,_codes,sizeof(_enc->huff_codes)); + return 0; +} + +/*Sets the quantization parameters to use. + This may only be called before the setup header is written. + If it is called multiple times, only the last call has any effect. + _qinfo: The quantization parameters. + These are described in more detail in theoraenc.h. + This can be NULL, in which case the default quantization parameters + will be used.*/ +static int oc_enc_set_quant_params(oc_enc_ctx *_enc, + const th_quant_info *_qinfo){ + int qi; + int pli; + int qti; + if(_enc==NULL)return TH_EFAULT; + if(_enc->packet_state>OC_PACKET_SETUP_HDR)return TH_EINVAL; + if(_qinfo==NULL)_qinfo=&TH_DEF_QUANT_INFO; + /*TODO: Analyze for packing purposes instead of just doing a shallow copy.*/ + memcpy(&_enc->qinfo,_qinfo,sizeof(_enc->qinfo)); + for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){ + _enc->state.dequant_tables[qi][pli][qti]= + _enc->state.dequant_table_data[qi][pli][qti]; + _enc->enquant_tables[qi][pli][qti]=_enc->enquant_table_data[qi][pli][qti]; + } + oc_enquant_tables_init(_enc->state.dequant_tables, + _enc->enquant_tables,_qinfo); + memcpy(_enc->state.loop_filter_limits,_qinfo->loop_filter_limits, + sizeof(_enc->state.loop_filter_limits)); + oc_enquant_qavg_init(_enc->log_qavg,_enc->state.dequant_tables, + _enc->state.info.pixel_fmt); + return 0; +} + +static void oc_enc_clear(oc_enc_ctx *_enc); + +static int oc_enc_init(oc_enc_ctx *_enc,const th_info *_info){ + th_info info; + size_t mcu_nmbs; + ptrdiff_t mcu_nfrags; + int hdec; + int vdec; + int ret; + int pli; + /*Clean up the requested settings.*/ + memcpy(&info,_info,sizeof(info)); + info.version_major=TH_VERSION_MAJOR; + info.version_minor=TH_VERSION_MINOR; + info.version_subminor=TH_VERSION_SUB; + if(info.quality>63)info.quality=63; + if(info.quality<0)info.quality=32; + if(info.target_bitrate<0)info.target_bitrate=0; + /*Initialize the shared encoder/decoder state.*/ + ret=oc_state_init(&_enc->state,&info,4); + if(ret<0)return ret; + _enc->mb_info=_ogg_calloc(_enc->state.nmbs,sizeof(*_enc->mb_info)); + _enc->frag_dc=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_dc)); + _enc->coded_mbis= + (unsigned *)_ogg_malloc(_enc->state.nmbs*sizeof(*_enc->coded_mbis)); + hdec=!(_enc->state.info.pixel_fmt&1); + vdec=!(_enc->state.info.pixel_fmt&2); + /*If chroma is sub-sampled in the vertical direction, we have to encode two + super block rows of Y' for each super block row of Cb and Cr.*/ + _enc->mcu_nvsbs=1<mcu_nvsbs*_enc->state.fplanes[0].nhsbs*(size_t)4; + mcu_nfrags=4*mcu_nmbs+(8*mcu_nmbs>>hdec+vdec); + _enc->mcu_skip_ssd=(unsigned *)_ogg_malloc( + mcu_nfrags*sizeof(*_enc->mcu_skip_ssd)); + for(pli=0;pli<3;pli++){ + _enc->dct_tokens[pli]=(unsigned char **)oc_malloc_2d(64, + _enc->state.fplanes[pli].nfrags,sizeof(**_enc->dct_tokens)); + _enc->extra_bits[pli]=(ogg_uint16_t **)oc_malloc_2d(64, + _enc->state.fplanes[pli].nfrags,sizeof(**_enc->extra_bits)); + } +#if defined(OC_COLLECT_METRICS) + _enc->frag_satd=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_satd)); + _enc->frag_ssd=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_ssd)); +#endif +#if defined(OC_X86_ASM) + oc_enc_vtable_init_x86(_enc); +#else + oc_enc_vtable_init_c(_enc); +#endif + _enc->keyframe_frequency_force=1<<_enc->state.info.keyframe_granule_shift; + _enc->state.qis[0]=_enc->state.info.quality; + _enc->state.nqis=1; + oc_rc_state_init(&_enc->rc,_enc); + oggpackB_writeinit(&_enc->opb); + if(_enc->mb_info==NULL||_enc->frag_dc==NULL||_enc->coded_mbis==NULL|| + _enc->mcu_skip_ssd==NULL||_enc->dct_tokens[0]==NULL|| + _enc->dct_tokens[1]==NULL||_enc->dct_tokens[2]==NULL|| + _enc->extra_bits[0]==NULL||_enc->extra_bits[1]==NULL|| + _enc->extra_bits[2]==NULL +#if defined(OC_COLLECT_METRICS) + ||_enc->frag_satd==NULL||_enc->frag_ssd==NULL +#endif + ){ + oc_enc_clear(_enc); + return TH_EFAULT; + } + oc_mode_scheme_chooser_init(&_enc->chooser); + oc_enc_mb_info_init(_enc); + memset(_enc->huff_idxs,0,sizeof(_enc->huff_idxs)); + /*Reset the packet-out state machine.*/ + _enc->packet_state=OC_PACKET_INFO_HDR; + _enc->dup_count=0; + _enc->nqueued_dups=0; + _enc->prev_dup_count=0; + /*Enable speed optimizations up through early skip by default.*/ + _enc->sp_level=OC_SP_LEVEL_EARLY_SKIP; + /*Disable VP3 compatibility by default.*/ + _enc->vp3_compatible=0; + /*No INTER frames coded yet.*/ + _enc->coded_inter_frame=0; + memcpy(_enc->huff_codes,TH_VP31_HUFF_CODES,sizeof(_enc->huff_codes)); + oc_enc_set_quant_params(_enc,NULL); + return 0; +} + +static void oc_enc_clear(oc_enc_ctx *_enc){ + int pli; + oc_rc_state_clear(&_enc->rc); +#if defined(OC_COLLECT_METRICS) + oc_enc_mode_metrics_dump(_enc); +#endif + oggpackB_writeclear(&_enc->opb); +#if defined(OC_COLLECT_METRICS) + _ogg_free(_enc->frag_ssd); + _ogg_free(_enc->frag_satd); +#endif + for(pli=3;pli-->0;){ + oc_free_2d(_enc->extra_bits[pli]); + oc_free_2d(_enc->dct_tokens[pli]); + } + _ogg_free(_enc->mcu_skip_ssd); + _ogg_free(_enc->coded_mbis); + _ogg_free(_enc->frag_dc); + _ogg_free(_enc->mb_info); + oc_state_clear(&_enc->state); +} + +static void oc_enc_drop_frame(th_enc_ctx *_enc){ + /*Use the previous frame's reconstruction.*/ + _enc->state.ref_frame_idx[OC_FRAME_SELF]= + _enc->state.ref_frame_idx[OC_FRAME_PREV]; + /*Flag motion vector analysis about the frame drop.*/ + _enc->prevframe_dropped=1; + /*Zero the packet.*/ + oggpackB_reset(&_enc->opb); +} + +static void oc_enc_compress_keyframe(oc_enc_ctx *_enc,int _recode){ + if(_enc->state.info.target_bitrate>0){ + _enc->state.qis[0]=oc_enc_select_qi(_enc,OC_INTRA_FRAME, + _enc->state.curframe_num>0); + _enc->state.nqis=1; + } + oc_enc_calc_lambda(_enc,OC_INTRA_FRAME); + oc_enc_analyze_intra(_enc,_recode); + oc_enc_frame_pack(_enc); + /*On the first frame, the previous call was an initial dry-run to prime + feed-forward statistics.*/ + if(!_recode&&_enc->state.curframe_num==0){ + if(_enc->state.info.target_bitrate>0){ + oc_enc_update_rc_state(_enc,oggpackB_bytes(&_enc->opb)<<3, + OC_INTRA_FRAME,_enc->state.qis[0],1,0); + } + oc_enc_compress_keyframe(_enc,1); + } +} + +static void oc_enc_compress_frame(oc_enc_ctx *_enc,int _recode){ + if(_enc->state.info.target_bitrate>0){ + _enc->state.qis[0]=oc_enc_select_qi(_enc,OC_INTER_FRAME,1); + _enc->state.nqis=1; + } + oc_enc_calc_lambda(_enc,OC_INTER_FRAME); + if(oc_enc_analyze_inter(_enc,_enc->rc.twopass!=2,_recode)){ + /*Mode analysis thinks this should have been a keyframe; start over.*/ + oc_enc_compress_keyframe(_enc,1); + } + else{ + oc_enc_frame_pack(_enc); + if(!_enc->coded_inter_frame){ + /*On the first INTER frame, the previous call was an initial dry-run to + prime feed-forward statistics.*/ + _enc->coded_inter_frame=1; + if(_enc->state.info.target_bitrate>0){ + /*Rate control also needs to prime.*/ + oc_enc_update_rc_state(_enc,oggpackB_bytes(&_enc->opb)<<3, + OC_INTER_FRAME,_enc->state.qis[0],1,0); + } + oc_enc_compress_frame(_enc,1); + } + } +} + +/*Set the granule position for the next packet to output based on the current + internal state.*/ +static void oc_enc_set_granpos(oc_enc_ctx *_enc){ + unsigned dup_offs; + /*Add an offset for the number of duplicate frames we've emitted so far.*/ + dup_offs=_enc->prev_dup_count-_enc->nqueued_dups; + /*If the current frame was a keyframe, use it for the high part.*/ + if(_enc->state.frame_type==OC_INTRA_FRAME){ + _enc->state.granpos=(_enc->state.curframe_num+_enc->state.granpos_bias<< + _enc->state.info.keyframe_granule_shift)+dup_offs; + } + /*Otherwise use the last keyframe in the high part and put the current frame + in the low part.*/ + else{ + _enc->state.granpos= + (_enc->state.keyframe_num+_enc->state.granpos_bias<< + _enc->state.info.keyframe_granule_shift) + +_enc->state.curframe_num-_enc->state.keyframe_num+dup_offs; + } +} + + +th_enc_ctx *th_encode_alloc(const th_info *_info){ + oc_enc_ctx *enc; + if(_info==NULL)return NULL; + enc=_ogg_malloc(sizeof(*enc)); + if(enc==NULL||oc_enc_init(enc,_info)<0){ + _ogg_free(enc); + return NULL; + } + return enc; +} + +void th_encode_free(th_enc_ctx *_enc){ + if(_enc!=NULL){ + oc_enc_clear(_enc); + _ogg_free(_enc); + } +} + +int th_encode_ctl(th_enc_ctx *_enc,int _req,void *_buf,size_t _buf_sz){ + switch(_req){ + case TH_ENCCTL_SET_HUFFMAN_CODES:{ + if(_buf==NULL&&_buf_sz!=0|| + _buf!=NULL&&_buf_sz!=sizeof(th_huff_table)*TH_NHUFFMAN_TABLES){ + return TH_EINVAL; + } + return oc_enc_set_huffman_codes(_enc,(const th_huff_table *)_buf); + }break; + case TH_ENCCTL_SET_QUANT_PARAMS:{ + if(_buf==NULL&&_buf_sz!=0|| + _buf!=NULL&&_buf_sz!=sizeof(th_quant_info)){ + return TH_EINVAL; + } + return oc_enc_set_quant_params(_enc,(th_quant_info *)_buf); + }break; + case TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE:{ + ogg_uint32_t keyframe_frequency_force; + if(_enc==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(keyframe_frequency_force))return TH_EINVAL; + keyframe_frequency_force=*(ogg_uint32_t *)_buf; + if(keyframe_frequency_force<=0)keyframe_frequency_force=1; + if(_enc->packet_state==OC_PACKET_INFO_HDR){ + /*It's still early enough to enlarge keyframe_granule_shift.*/ + _enc->state.info.keyframe_granule_shift=OC_CLAMPI( + _enc->state.info.keyframe_granule_shift, + OC_ILOG_32(keyframe_frequency_force-1),31); + } + _enc->keyframe_frequency_force=OC_MINI(keyframe_frequency_force, + (ogg_uint32_t)1U<<_enc->state.info.keyframe_granule_shift); + *(ogg_uint32_t *)_buf=_enc->keyframe_frequency_force; + return 0; + }break; + case TH_ENCCTL_SET_VP3_COMPATIBLE:{ + int vp3_compatible; + if(_enc==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(vp3_compatible))return TH_EINVAL; + vp3_compatible=*(int *)_buf; + _enc->vp3_compatible=vp3_compatible; + if(oc_enc_set_huffman_codes(_enc,TH_VP31_HUFF_CODES)<0)vp3_compatible=0; + if(oc_enc_set_quant_params(_enc,&TH_VP31_QUANT_INFO)<0)vp3_compatible=0; + if(_enc->state.info.pixel_fmt!=TH_PF_420|| + _enc->state.info.pic_width<_enc->state.info.frame_width|| + _enc->state.info.pic_height<_enc->state.info.frame_height|| + /*If we have more than 4095 super blocks, VP3's RLE coding might + overflow. + We could overcome this by ensuring we flip the coded/not-coded flags on + at least one super block in the frame, but we pick the simple solution + of just telling the user the stream will be incompatible instead. + It's unlikely the old VP3 codec would be able to decode streams at this + resolution in real time in the first place.*/ + _enc->state.nsbs>4095){ + vp3_compatible=0; + } + *(int *)_buf=vp3_compatible; + return 0; + }break; + case TH_ENCCTL_GET_SPLEVEL_MAX:{ + if(_enc==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(int))return TH_EINVAL; + *(int *)_buf=OC_SP_LEVEL_MAX; + return 0; + }break; + case TH_ENCCTL_SET_SPLEVEL:{ + int speed; + if(_enc==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(speed))return TH_EINVAL; + speed=*(int *)_buf; + if(speed<0||speed>OC_SP_LEVEL_MAX)return TH_EINVAL; + _enc->sp_level=speed; + return 0; + }break; + case TH_ENCCTL_GET_SPLEVEL:{ + if(_enc==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(int))return TH_EINVAL; + *(int *)_buf=_enc->sp_level; + return 0; + } + case TH_ENCCTL_SET_DUP_COUNT:{ + int dup_count; + if(_enc==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(dup_count))return TH_EINVAL; + dup_count=*(int *)_buf; + if(dup_count>=_enc->keyframe_frequency_force)return TH_EINVAL; + _enc->dup_count=OC_MAXI(dup_count,0); + return 0; + }break; + case TH_ENCCTL_SET_QUALITY:{ + int qi; + if(_enc==NULL||_buf==NULL)return TH_EFAULT; + if(_enc->state.info.target_bitrate>0)return TH_EINVAL; + qi=*(int *)_buf; + if(qi<0||qi>63)return TH_EINVAL; + _enc->state.info.quality=qi; + _enc->state.qis[0]=(unsigned char)qi; + _enc->state.nqis=1; + return 0; + }break; + case TH_ENCCTL_SET_BITRATE:{ + long bitrate; + int reset; + if(_enc==NULL||_buf==NULL)return TH_EFAULT; + bitrate=*(long *)_buf; + if(bitrate<=0)return TH_EINVAL; + reset=_enc->state.info.target_bitrate<=0; + _enc->state.info.target_bitrate=bitrate>INT_MAX?INT_MAX:bitrate; + if(reset)oc_rc_state_init(&_enc->rc,_enc); + else oc_enc_rc_resize(_enc); + return 0; + }break; + case TH_ENCCTL_SET_RATE_FLAGS:{ + int set; + if(_enc==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(set))return TH_EINVAL; + if(_enc->state.info.target_bitrate<=0)return TH_EINVAL; + set=*(int *)_buf; + _enc->rc.drop_frames=set&TH_RATECTL_DROP_FRAMES; + _enc->rc.cap_overflow=set&TH_RATECTL_CAP_OVERFLOW; + _enc->rc.cap_underflow=set&TH_RATECTL_CAP_UNDERFLOW; + return 0; + }break; + case TH_ENCCTL_SET_RATE_BUFFER:{ + int set; + if(_enc==NULL||_buf==NULL)return TH_EFAULT; + if(_buf_sz!=sizeof(set))return TH_EINVAL; + if(_enc->state.info.target_bitrate<=0)return TH_EINVAL; + set=*(int *)_buf; + _enc->rc.buf_delay=set; + oc_enc_rc_resize(_enc); + *(int *)_buf=_enc->rc.buf_delay; + return 0; + }break; + case TH_ENCCTL_2PASS_OUT:{ + if(_enc==NULL||_buf==NULL)return TH_EFAULT; + if(_enc->state.info.target_bitrate<=0|| + _enc->state.curframe_num>=0&&_enc->rc.twopass!=1|| + _buf_sz!=sizeof(unsigned char *)){ + return TH_EINVAL; + } + return oc_enc_rc_2pass_out(_enc,(unsigned char **)_buf); + }break; + case TH_ENCCTL_2PASS_IN:{ + if(_enc==NULL)return TH_EFAULT; + if(_enc->state.info.target_bitrate<=0|| + _enc->state.curframe_num>=0&&_enc->rc.twopass!=2){ + return TH_EINVAL; + } + return oc_enc_rc_2pass_in(_enc,_buf,_buf_sz); + }break; + default:return TH_EIMPL; + } +} + +int th_encode_flushheader(th_enc_ctx *_enc,th_comment *_tc,ogg_packet *_op){ + if(_enc==NULL)return TH_EFAULT; + return oc_state_flushheader(&_enc->state,&_enc->packet_state,&_enc->opb, + &_enc->qinfo,(const th_huff_table *)_enc->huff_codes,th_version_string(), + _tc,_op); +} + +static void oc_img_plane_copy_pad(th_img_plane *_dst,th_img_plane *_src, + ogg_int32_t _pic_x,ogg_int32_t _pic_y, + ogg_int32_t _pic_width,ogg_int32_t _pic_height){ + unsigned char *dst; + int dstride; + ogg_uint32_t frame_width; + ogg_uint32_t frame_height; + ogg_uint32_t y; + frame_width=_dst->width; + frame_height=_dst->height; + /*If we have _no_ data, just encode a dull green.*/ + if(_pic_width==0||_pic_height==0){ + dst=_dst->data; + dstride=_dst->stride; + for(y=0;ystride; + sstride=_src->stride; + dst_data=_dst->data; + src_data=_src->data; + dst=dst_data+_pic_y*(ptrdiff_t)dstride+_pic_x; + src=src_data+_pic_y*(ptrdiff_t)sstride+_pic_x; + for(y=0;y<_pic_height;y++){ + memcpy(dst,src,_pic_width); + dst+=dstride; + src+=sstride; + } + /*Step 2: Perform a low-pass extension into the padding region.*/ + /*Left side.*/ + for(x=_pic_x;x-->0;){ + dst=dst_data+_pic_y*(ptrdiff_t)dstride+x; + for(y=0;y<_pic_height;y++){ + dst[0]=(dst[1]<<1)+(dst-(dstride&-(y>0)))[1] + +(dst+(dstride&-(y+1<_pic_height)))[1]+2>>2; + dst+=dstride; + } + } + /*Right side.*/ + for(x=_pic_x+_pic_width;x0)))[0] + +(dst+(dstride&-(y+1<_pic_height)))[0]+2>>2; + dst+=dstride; + } + } + /*Top.*/ + dst=dst_data+_pic_y*(ptrdiff_t)dstride; + for(y=_pic_y;y-->0;){ + for(x=0;x0)] + +dst[x+(x+1>2; + } + dst-=dstride; + } + /*Bottom.*/ + dst=dst_data+(_pic_y+_pic_height)*(ptrdiff_t)dstride; + for(y=_pic_y+_pic_height;y0)] + +(dst-dstride)[x+(x+1>2; + } + dst+=dstride; + } + } +} + +int th_encode_ycbcr_in(th_enc_ctx *_enc,th_ycbcr_buffer _img){ + th_ycbcr_buffer img; + int cframe_width; + int cframe_height; + int cpic_width; + int cpic_height; + int cpic_x; + int cpic_y; + int hdec; + int vdec; + int pli; + int refi; + int drop; + /*Step 1: validate parameters.*/ + if(_enc==NULL||_img==NULL)return TH_EFAULT; + if(_enc->packet_state==OC_PACKET_DONE)return TH_EINVAL; + if(_enc->rc.twopass&&_enc->rc.twopass_buffer_bytes==0)return TH_EINVAL; + if((ogg_uint32_t)_img[0].width!=_enc->state.info.frame_width|| + (ogg_uint32_t)_img[0].height!=_enc->state.info.frame_height){ + return TH_EINVAL; + } + hdec=!(_enc->state.info.pixel_fmt&1); + vdec=!(_enc->state.info.pixel_fmt&2); + cframe_width=_enc->state.info.frame_width>>hdec; + cframe_height=_enc->state.info.frame_height>>vdec; + if(_img[1].width!=cframe_width||_img[2].width!=cframe_width|| + _img[1].height!=cframe_height||_img[2].height!=cframe_height){ + return TH_EINVAL; + } + /*Step 2: Copy the input to our internal buffer. + This lets us add padding, if necessary, so we don't have to worry about + dereferencing possibly invalid addresses, and allows us to use the same + strides and fragment offsets for both the input frame and the reference + frames.*/ + /*Flip the input buffer upside down.*/ + oc_ycbcr_buffer_flip(img,_img); + oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[OC_FRAME_IO]+0,img+0, + _enc->state.info.pic_x,_enc->state.info.pic_y, + _enc->state.info.pic_width,_enc->state.info.pic_height); + cpic_x=_enc->state.info.pic_x>>hdec; + cpic_y=_enc->state.info.pic_y>>vdec; + cpic_width=(_enc->state.info.pic_x+_enc->state.info.pic_width+hdec>>hdec) + -cpic_x; + cpic_height=(_enc->state.info.pic_y+_enc->state.info.pic_height+vdec>>vdec) + -cpic_y; + for(pli=1;pli<3;pli++){ + oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[OC_FRAME_IO]+pli,img+pli, + cpic_x,cpic_y,cpic_width,cpic_height); + } + /*Step 3: Update the buffer state.*/ + if(_enc->state.ref_frame_idx[OC_FRAME_SELF]>=0){ + _enc->state.ref_frame_idx[OC_FRAME_PREV]= + _enc->state.ref_frame_idx[OC_FRAME_SELF]; + if(_enc->state.frame_type==OC_INTRA_FRAME){ + /*The new frame becomes both the previous and gold reference frames.*/ + _enc->state.keyframe_num=_enc->state.curframe_num; + _enc->state.ref_frame_idx[OC_FRAME_GOLD]= + _enc->state.ref_frame_idx[OC_FRAME_SELF]; + } + } + /*Select a free buffer to use for the reconstructed version of this frame.*/ + for(refi=0;refi==_enc->state.ref_frame_idx[OC_FRAME_GOLD]|| + refi==_enc->state.ref_frame_idx[OC_FRAME_PREV];refi++); + _enc->state.ref_frame_idx[OC_FRAME_SELF]=refi; + _enc->state.curframe_num+=_enc->prev_dup_count+1; + /*Step 4: Compress the frame.*/ + /*Start with a keyframe, and don't allow the generation of invalid files that + overflow the keyframe_granule_shift.*/ + if(_enc->rc.twopass_force_kf||_enc->state.curframe_num==0|| + _enc->state.curframe_num-_enc->state.keyframe_num+_enc->dup_count>= + _enc->keyframe_frequency_force){ + oc_enc_compress_keyframe(_enc,0); + drop=0; + } + else{ + oc_enc_compress_frame(_enc,0); + drop=1; + } + oc_restore_fpu(&_enc->state); + /*drop currently indicates if the frame is droppable.*/ + if(_enc->state.info.target_bitrate>0){ + drop=oc_enc_update_rc_state(_enc,oggpackB_bytes(&_enc->opb)<<3, + _enc->state.frame_type,_enc->state.qis[0],0,drop); + } + else drop=0; + /*drop now indicates if the frame was dropped.*/ + if(drop)oc_enc_drop_frame(_enc); + else _enc->prevframe_dropped=0; + _enc->packet_state=OC_PACKET_READY; + _enc->prev_dup_count=_enc->nqueued_dups=_enc->dup_count; + _enc->dup_count=0; +#if defined(OC_DUMP_IMAGES) + oc_enc_set_granpos(_enc); + oc_state_dump_frame(&_enc->state,OC_FRAME_IO,"src"); + oc_state_dump_frame(&_enc->state,OC_FRAME_SELF,"rec"); +#endif + return 0; +} + +int th_encode_packetout(th_enc_ctx *_enc,int _last_p,ogg_packet *_op){ + if(_enc==NULL||_op==NULL)return TH_EFAULT; + if(_enc->packet_state==OC_PACKET_READY){ + _enc->packet_state=OC_PACKET_EMPTY; + if(_enc->rc.twopass!=1){ + unsigned char *packet; + packet=oggpackB_get_buffer(&_enc->opb); + /*If there's no packet, malloc failed while writing; it's lost forever.*/ + if(packet==NULL)return TH_EFAULT; + _op->packet=packet; + _op->bytes=oggpackB_bytes(&_enc->opb); + } + /*For the first pass in 2-pass mode, don't emit any packet data.*/ + else{ + _op->packet=NULL; + _op->bytes=0; + } + } + else if(_enc->packet_state==OC_PACKET_EMPTY){ + if(_enc->nqueued_dups>0){ + _enc->nqueued_dups--; + _op->packet=NULL; + _op->bytes=0; + } + else{ + if(_last_p)_enc->packet_state=OC_PACKET_DONE; + return 0; + } + } + else return 0; + _last_p=_last_p&&_enc->nqueued_dups<=0; + _op->b_o_s=0; + _op->e_o_s=_last_p; + oc_enc_set_granpos(_enc); + _op->packetno=th_granule_frame(_enc,_enc->state.granpos)+3; + _op->granulepos=_enc->state.granpos; + if(_last_p)_enc->packet_state=OC_PACKET_DONE; + return 1+_enc->nqueued_dups; +} diff --git a/Engine/lib/libtheora/lib/enquant.c b/Engine/lib/libtheora/lib/enquant.c new file mode 100644 index 000000000..3372fed22 --- /dev/null +++ b/Engine/lib/libtheora/lib/enquant.c @@ -0,0 +1,274 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: enquant.c 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ +#include +#include +#include "encint.h" + + + +void oc_quant_params_pack(oggpack_buffer *_opb,const th_quant_info *_qinfo){ + const th_quant_ranges *qranges; + const th_quant_base *base_mats[2*3*64]; + int indices[2][3][64]; + int nbase_mats; + int nbits; + int ci; + int qi; + int qri; + int qti; + int pli; + int qtj; + int plj; + int bmi; + int i; + i=_qinfo->loop_filter_limits[0]; + for(qi=1;qi<64;qi++)i=OC_MAXI(i,_qinfo->loop_filter_limits[qi]); + nbits=OC_ILOG_32(i); + oggpackB_write(_opb,nbits,3); + for(qi=0;qi<64;qi++){ + oggpackB_write(_opb,_qinfo->loop_filter_limits[qi],nbits); + } + /*580 bits for VP3.*/ + i=1; + for(qi=0;qi<64;qi++)i=OC_MAXI(_qinfo->ac_scale[qi],i); + nbits=OC_ILOGNZ_32(i); + oggpackB_write(_opb,nbits-1,4); + for(qi=0;qi<64;qi++)oggpackB_write(_opb,_qinfo->ac_scale[qi],nbits); + /*516 bits for VP3.*/ + i=1; + for(qi=0;qi<64;qi++)i=OC_MAXI(_qinfo->dc_scale[qi],i); + nbits=OC_ILOGNZ_32(i); + oggpackB_write(_opb,nbits-1,4); + for(qi=0;qi<64;qi++)oggpackB_write(_opb,_qinfo->dc_scale[qi],nbits); + /*Consolidate any duplicate base matrices.*/ + nbase_mats=0; + for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){ + qranges=_qinfo->qi_ranges[qti]+pli; + for(qri=0;qri<=qranges->nranges;qri++){ + for(bmi=0;;bmi++){ + if(bmi>=nbase_mats){ + base_mats[bmi]=qranges->base_matrices+qri; + indices[qti][pli][qri]=nbase_mats++; + break; + } + else if(memcmp(base_mats[bmi][0],qranges->base_matrices[qri], + sizeof(base_mats[bmi][0]))==0){ + indices[qti][pli][qri]=bmi; + break; + } + } + } + } + /*Write out the list of unique base matrices. + 1545 bits for VP3 matrices.*/ + oggpackB_write(_opb,nbase_mats-1,9); + for(bmi=0;bmiqi_ranges[qti]+pli; + if(i>0){ + if(qti>0){ + if(qranges->nranges==_qinfo->qi_ranges[qti-1][pli].nranges&& + memcmp(qranges->sizes,_qinfo->qi_ranges[qti-1][pli].sizes, + qranges->nranges*sizeof(qranges->sizes[0]))==0&& + memcmp(indices[qti][pli],indices[qti-1][pli], + (qranges->nranges+1)*sizeof(indices[qti][pli][0]))==0){ + oggpackB_write(_opb,1,2); + continue; + } + } + qtj=(i-1)/3; + plj=(i-1)%3; + if(qranges->nranges==_qinfo->qi_ranges[qtj][plj].nranges&& + memcmp(qranges->sizes,_qinfo->qi_ranges[qtj][plj].sizes, + qranges->nranges*sizeof(qranges->sizes[0]))==0&& + memcmp(indices[qti][pli],indices[qtj][plj], + (qranges->nranges+1)*sizeof(indices[qti][pli][0]))==0){ + oggpackB_write(_opb,0,1+(qti>0)); + continue; + } + oggpackB_write(_opb,1,1); + } + oggpackB_write(_opb,indices[qti][pli][0],nbits); + for(qi=qri=0;qi<63;qri++){ + oggpackB_write(_opb,qranges->sizes[qri]-1,OC_ILOG_32(62-qi)); + qi+=qranges->sizes[qri]; + oggpackB_write(_opb,indices[qti][pli][qri+1],nbits); + } + } +} + +static void oc_iquant_init(oc_iquant *_this,ogg_uint16_t _d){ + ogg_uint32_t t; + int l; + _d<<=1; + l=OC_ILOGNZ_32(_d)-1; + t=1+((ogg_uint32_t)1<<16+l)/_d; + _this->m=(ogg_int16_t)(t-0x10000); + _this->l=l; +} + +/*See comments at oc_dequant_tables_init() for how the quantization tables' + storage should be initialized.*/ +void oc_enquant_tables_init(ogg_uint16_t *_dequant[64][3][2], + oc_iquant *_enquant[64][3][2],const th_quant_info *_qinfo){ + int qi; + int pli; + int qti; + /*Initialize the dequantization tables first.*/ + oc_dequant_tables_init(_dequant,NULL,_qinfo); + /*Derive the quantization tables directly from the dequantization tables.*/ + for(qi=0;qi<64;qi++)for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){ + int zzi; + int plj; + int qtj; + int dupe; + dupe=0; + for(qtj=0;qtj<=qti;qtj++){ + for(plj=0;plj<(qtj>1))/qd; + qp+=rq*(ogg_uint32_t)rq; + } + q2+=OC_PCD[_pixel_fmt][pli]*(ogg_int64_t)qp; + } + /*qavg=1.0/sqrt(q2).*/ + _log_qavg[qti][qi]=OC_Q57(48)-oc_blog64(q2)>>1; + } +} diff --git a/Engine/lib/libtheora/lib/enquant.h b/Engine/lib/libtheora/lib/enquant.h new file mode 100644 index 000000000..d62df10d1 --- /dev/null +++ b/Engine/lib/libtheora/lib/enquant.h @@ -0,0 +1,27 @@ +#if !defined(_enquant_H) +# define _enquant_H (1) +# include "quant.h" + +typedef struct oc_iquant oc_iquant; + +#define OC_QUANT_MAX_LOG (OC_Q57(OC_STATIC_ILOG_32(OC_QUANT_MAX)-1)) + +/*Used to compute x/d via ((x*m>>16)+x>>l)+(x<0)) + (i.e., one 16x16->16 mul, 2 shifts, and 2 adds). + This is not an approximation; for 16-bit x and d, it is exact.*/ +struct oc_iquant{ + ogg_int16_t m; + ogg_int16_t l; +}; + +typedef oc_iquant oc_iquant_table[64]; + + + +void oc_quant_params_pack(oggpack_buffer *_opb,const th_quant_info *_qinfo); +void oc_enquant_tables_init(ogg_uint16_t *_dequant[64][3][2], + oc_iquant *_enquant[64][3][2],const th_quant_info *_qinfo); +void oc_enquant_qavg_init(ogg_int64_t _log_qavg[2][64], + ogg_uint16_t *_dequant[64][3][2],int _pixel_fmt); + +#endif diff --git a/Engine/lib/libtheora/lib/fdct.c b/Engine/lib/libtheora/lib/fdct.c new file mode 100644 index 000000000..dc3a66f24 --- /dev/null +++ b/Engine/lib/libtheora/lib/fdct.c @@ -0,0 +1,422 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: fdct.c 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ +#include "encint.h" +#include "dct.h" + + + +/*Performs a forward 8 point Type-II DCT transform. + The output is scaled by a factor of 2 from the orthonormal version of the + transform. + _y: The buffer to store the result in. + Data will be placed the first 8 entries (e.g., in a row of an 8x8 block). + _x: The input coefficients. + Every 8th entry is used (e.g., from a column of an 8x8 block).*/ +static void oc_fdct8(ogg_int16_t _y[8],const ogg_int16_t *_x){ + int t0; + int t1; + int t2; + int t3; + int t4; + int t5; + int t6; + int t7; + int r; + int s; + int u; + int v; + /*Stage 1:*/ + /*0-7 butterfly.*/ + t0=_x[0<<3]+(int)_x[7<<3]; + t7=_x[0<<3]-(int)_x[7<<3]; + /*1-6 butterfly.*/ + t1=_x[1<<3]+(int)_x[6<<3]; + t6=_x[1<<3]-(int)_x[6<<3]; + /*2-5 butterfly.*/ + t2=_x[2<<3]+(int)_x[5<<3]; + t5=_x[2<<3]-(int)_x[5<<3]; + /*3-4 butterfly.*/ + t3=_x[3<<3]+(int)_x[4<<3]; + t4=_x[3<<3]-(int)_x[4<<3]; + /*Stage 2:*/ + /*0-3 butterfly.*/ + r=t0+t3; + t3=t0-t3; + t0=r; + /*1-2 butterfly.*/ + r=t1+t2; + t2=t1-t2; + t1=r; + /*6-5 butterfly.*/ + r=t6+t5; + t5=t6-t5; + t6=r; + /*Stages 3 and 4 are where all the approximation occurs. + These are chosen to be as close to an exact inverse of the approximations + made in the iDCT as possible, while still using mostly 16-bit arithmetic. + We use some 16x16->32 signed MACs, but those still commonly execute in 1 + cycle on a 16-bit DSP. + For example, s=(27146*t5+0x4000>>16)+t5+(t5!=0) is an exact inverse of + t5=(OC_C4S4*s>>16). + That is, applying the latter to the output of the former will recover t5 + exactly (over the valid input range of t5, -23171...23169). + We increase the rounding bias to 0xB500 in this particular case so that + errors inverting the subsequent butterfly are not one-sided (e.g., the + mean error is very close to zero). + The (t5!=0) term could be replaced simply by 1, but we want to send 0 to 0. + The fDCT of an all-zeros block will still not be zero, because of the + biases we added at the very beginning of the process, but it will be close + enough that it is guaranteed to round to zero.*/ + /*Stage 3:*/ + /*4-5 butterfly.*/ + s=(27146*t5+0xB500>>16)+t5+(t5!=0)>>1; + r=t4+s; + t5=t4-s; + t4=r; + /*7-6 butterfly.*/ + s=(27146*t6+0xB500>>16)+t6+(t6!=0)>>1; + r=t7+s; + t6=t7-s; + t7=r; + /*Stage 4:*/ + /*0-1 butterfly.*/ + r=(27146*t0+0x4000>>16)+t0+(t0!=0); + s=(27146*t1+0xB500>>16)+t1+(t1!=0); + u=r+s>>1; + v=r-u; + _y[0]=u; + _y[4]=v; + /*3-2 rotation by 6pi/16*/ + u=(OC_C6S2*t2+OC_C2S6*t3+0x6CB7>>16)+(t3!=0); + s=(OC_C6S2*u>>16)-t2; + v=(s*21600+0x2800>>18)+s+(s!=0); + _y[2]=u; + _y[6]=v; + /*6-5 rotation by 3pi/16*/ + u=(OC_C5S3*t6+OC_C3S5*t5+0x0E3D>>16)+(t5!=0); + s=t6-(OC_C5S3*u>>16); + v=(s*26568+0x3400>>17)+s+(s!=0); + _y[5]=u; + _y[3]=v; + /*7-4 rotation by 7pi/16*/ + u=(OC_C7S1*t4+OC_C1S7*t7+0x7B1B>>16)+(t7!=0); + s=(OC_C7S1*u>>16)-t4; + v=(s*20539+0x3000>>20)+s+(s!=0); + _y[1]=u; + _y[7]=v; +} + +void oc_enc_fdct8x8(const oc_enc_ctx *_enc,ogg_int16_t _y[64], + const ogg_int16_t _x[64]){ + (*_enc->opt_vtable.fdct8x8)(_y,_x); +} + +/*Performs a forward 8x8 Type-II DCT transform. + The output is scaled by a factor of 4 relative to the orthonormal version + of the transform. + _y: The buffer to store the result in. + This may be the same as _x. + _x: The input coefficients. */ +void oc_enc_fdct8x8_c(ogg_int16_t _y[64],const ogg_int16_t _x[64]){ + const ogg_int16_t *in; + ogg_int16_t *end; + ogg_int16_t *out; + ogg_int16_t w[64]; + int i; + /*Add two extra bits of working precision to improve accuracy; any more and + we could overflow.*/ + for(i=0;i<64;i++)w[i]=_x[i]<<2; + /*These biases correct for some systematic error that remains in the full + fDCT->iDCT round trip.*/ + w[0]+=(w[0]!=0)+1; + w[1]++; + w[8]--; + /*Transform columns of w into rows of _y.*/ + for(in=w,out=_y,end=out+64;out>2; +} + + + +/*This does not seem to outperform simple LFE border padding before MC. + It yields higher PSNR, but much higher bitrate usage.*/ +#if 0 +typedef struct oc_extension_info oc_extension_info; + + + +/*Information needed to pad boundary blocks. + We multiply each row/column by an extension matrix that fills in the padding + values as a linear combination of the active values, so that an equivalent + number of coefficients are forced to zero. + This costs at most 16 multiplies, the same as a 1-D fDCT itself, and as + little as 7 multiplies. + We compute the extension matrices for every possible shape in advance, as + there are only 35. + The coefficients for all matrices are stored in a single array to take + advantage of the overlap and repetitiveness of many of the shapes. + A similar technique is applied to the offsets into this array. + This reduces the required table storage by about 48%. + See tools/extgen.c for details. + We could conceivably do the same for all 256 possible shapes.*/ +struct oc_extension_info{ + /*The mask of the active pixels in the shape.*/ + short mask; + /*The number of active pixels in the shape.*/ + short na; + /*The extension matrix. + This is (8-na)xna*/ + const ogg_int16_t *const *ext; + /*The pixel indices: na active pixels followed by 8-na padding pixels.*/ + unsigned char pi[8]; + /*The coefficient indices: na unconstrained coefficients followed by 8-na + coefficients to be forced to zero.*/ + unsigned char ci[8]; +}; + + +/*The number of shapes we need.*/ +#define OC_NSHAPES (35) + +static const ogg_int16_t OC_EXT_COEFFS[229]={ + 0x7FFF,0xE1F8,0x6903,0xAA79,0x5587,0x7FFF,0x1E08,0x7FFF, + 0x5587,0xAA79,0x6903,0xE1F8,0x7FFF,0x0000,0x0000,0x0000, + 0x7FFF,0x0000,0x0000,0x7FFF,0x8000,0x7FFF,0x0000,0x0000, + 0x7FFF,0xE1F8,0x1E08,0xB0A7,0xAA1D,0x337C,0x7FFF,0x4345, + 0x2267,0x4345,0x7FFF,0x337C,0xAA1D,0xB0A7,0x8A8C,0x4F59, + 0x03B4,0xE2D6,0x7FFF,0x2CF3,0x7FFF,0xE2D6,0x03B4,0x4F59, + 0x8A8C,0x1103,0x7AEF,0x5225,0xDF60,0xC288,0xDF60,0x5225, + 0x7AEF,0x1103,0x668A,0xD6EE,0x3A16,0x0E6C,0xFA07,0x0E6C, + 0x3A16,0xD6EE,0x668A,0x2A79,0x2402,0x980F,0x50F5,0x4882, + 0x50F5,0x980F,0x2402,0x2A79,0xF976,0x2768,0x5F22,0x2768, + 0xF976,0x1F91,0x76C1,0xE9AE,0x76C1,0x1F91,0x7FFF,0xD185, + 0x0FC8,0xD185,0x7FFF,0x4F59,0x4345,0xED62,0x4345,0x4F59, + 0xF574,0x5D99,0x2CF3,0x5D99,0xF574,0x5587,0x3505,0x30FC, + 0xF482,0x953C,0xEAC4,0x7FFF,0x4F04,0x7FFF,0xEAC4,0x953C, + 0xF482,0x30FC,0x4F04,0x273D,0xD8C3,0x273D,0x1E09,0x61F7, + 0x1E09,0x273D,0xD8C3,0x273D,0x4F04,0x30FC,0xA57E,0x153C, + 0x6AC4,0x3C7A,0x1E08,0x3C7A,0x6AC4,0x153C,0xA57E,0x7FFF, + 0xA57E,0x5A82,0x6AC4,0x153C,0xC386,0xE1F8,0xC386,0x153C, + 0x6AC4,0x5A82,0xD8C3,0x273D,0x7FFF,0xE1F7,0x7FFF,0x273D, + 0xD8C3,0x4F04,0x30FC,0xD8C3,0x273D,0xD8C3,0x30FC,0x4F04, + 0x1FC8,0x67AD,0x1853,0xE038,0x1853,0x67AD,0x1FC8,0x4546, + 0xE038,0x1FC8,0x3ABA,0x1FC8,0xE038,0x4546,0x3505,0x5587, + 0xF574,0xBC11,0x78F4,0x4AFB,0xE6F3,0x4E12,0x3C11,0xF8F4, + 0x4AFB,0x3C7A,0xF88B,0x3C11,0x78F4,0xCAFB,0x7FFF,0x08CC, + 0x070C,0x236D,0x5587,0x236D,0x070C,0xF88B,0x3C7A,0x4AFB, + 0xF8F4,0x3C11,0x7FFF,0x153C,0xCAFB,0x153C,0x7FFF,0x1E08, + 0xE1F8,0x7FFF,0x08CC,0x7FFF,0xCAFB,0x78F4,0x3C11,0x4E12, + 0xE6F3,0x4AFB,0x78F4,0xBC11,0xFE3D,0x7FFF,0xFE3D,0x2F3A, + 0x7FFF,0x2F3A,0x89BC,0x7FFF,0x89BC +}; + +static const ogg_int16_t *const OC_EXT_ROWS[96]={ + OC_EXT_COEFFS+ 0,OC_EXT_COEFFS+ 0,OC_EXT_COEFFS+ 0,OC_EXT_COEFFS+ 0, + OC_EXT_COEFFS+ 0,OC_EXT_COEFFS+ 0,OC_EXT_COEFFS+ 0,OC_EXT_COEFFS+ 6, + OC_EXT_COEFFS+ 27,OC_EXT_COEFFS+ 38,OC_EXT_COEFFS+ 43,OC_EXT_COEFFS+ 32, + OC_EXT_COEFFS+ 49,OC_EXT_COEFFS+ 58,OC_EXT_COEFFS+ 67,OC_EXT_COEFFS+ 71, + OC_EXT_COEFFS+ 62,OC_EXT_COEFFS+ 53,OC_EXT_COEFFS+ 12,OC_EXT_COEFFS+ 15, + OC_EXT_COEFFS+ 14,OC_EXT_COEFFS+ 13,OC_EXT_COEFFS+ 76,OC_EXT_COEFFS+ 81, + OC_EXT_COEFFS+ 86,OC_EXT_COEFFS+ 91,OC_EXT_COEFFS+ 96,OC_EXT_COEFFS+ 98, + OC_EXT_COEFFS+ 93,OC_EXT_COEFFS+ 88,OC_EXT_COEFFS+ 83,OC_EXT_COEFFS+ 78, + OC_EXT_COEFFS+ 12,OC_EXT_COEFFS+ 15,OC_EXT_COEFFS+ 15,OC_EXT_COEFFS+ 12, + OC_EXT_COEFFS+ 12,OC_EXT_COEFFS+ 15,OC_EXT_COEFFS+ 12,OC_EXT_COEFFS+ 15, + OC_EXT_COEFFS+ 15,OC_EXT_COEFFS+ 12,OC_EXT_COEFFS+ 103,OC_EXT_COEFFS+ 108, + OC_EXT_COEFFS+ 126,OC_EXT_COEFFS+ 16,OC_EXT_COEFFS+ 137,OC_EXT_COEFFS+ 141, + OC_EXT_COEFFS+ 20,OC_EXT_COEFFS+ 130,OC_EXT_COEFFS+ 113,OC_EXT_COEFFS+ 116, + OC_EXT_COEFFS+ 146,OC_EXT_COEFFS+ 153,OC_EXT_COEFFS+ 160,OC_EXT_COEFFS+ 167, + OC_EXT_COEFFS+ 170,OC_EXT_COEFFS+ 163,OC_EXT_COEFFS+ 156,OC_EXT_COEFFS+ 149, + OC_EXT_COEFFS+ 119,OC_EXT_COEFFS+ 122,OC_EXT_COEFFS+ 174,OC_EXT_COEFFS+ 177, + OC_EXT_COEFFS+ 182,OC_EXT_COEFFS+ 187,OC_EXT_COEFFS+ 192,OC_EXT_COEFFS+ 197, + OC_EXT_COEFFS+ 202,OC_EXT_COEFFS+ 207,OC_EXT_COEFFS+ 210,OC_EXT_COEFFS+ 215, + OC_EXT_COEFFS+ 179,OC_EXT_COEFFS+ 189,OC_EXT_COEFFS+ 24,OC_EXT_COEFFS+ 204, + OC_EXT_COEFFS+ 184,OC_EXT_COEFFS+ 194,OC_EXT_COEFFS+ 212,OC_EXT_COEFFS+ 199, + OC_EXT_COEFFS+ 217,OC_EXT_COEFFS+ 100,OC_EXT_COEFFS+ 134,OC_EXT_COEFFS+ 135, + OC_EXT_COEFFS+ 135,OC_EXT_COEFFS+ 12,OC_EXT_COEFFS+ 15,OC_EXT_COEFFS+ 134, + OC_EXT_COEFFS+ 134,OC_EXT_COEFFS+ 135,OC_EXT_COEFFS+ 220,OC_EXT_COEFFS+ 223, + OC_EXT_COEFFS+ 226,OC_EXT_COEFFS+ 227,OC_EXT_COEFFS+ 224,OC_EXT_COEFFS+ 221 +}; + +static const oc_extension_info OC_EXTENSION_INFO[OC_NSHAPES]={ + {0x7F,7,OC_EXT_ROWS+ 0,{0,1,2,3,4,5,6,7},{0,1,2,4,5,6,7,3}}, + {0xFE,7,OC_EXT_ROWS+ 7,{1,2,3,4,5,6,7,0},{0,1,2,4,5,6,7,3}}, + {0x3F,6,OC_EXT_ROWS+ 8,{0,1,2,3,4,5,7,6},{0,1,3,4,6,7,5,2}}, + {0xFC,6,OC_EXT_ROWS+ 10,{2,3,4,5,6,7,1,0},{0,1,3,4,6,7,5,2}}, + {0x1F,5,OC_EXT_ROWS+ 12,{0,1,2,3,4,7,6,5},{0,2,3,5,7,6,4,1}}, + {0xF8,5,OC_EXT_ROWS+ 15,{3,4,5,6,7,2,1,0},{0,2,3,5,7,6,4,1}}, + {0x0F,4,OC_EXT_ROWS+ 18,{0,1,2,3,7,6,5,4},{0,2,4,6,7,5,3,1}}, + {0xF0,4,OC_EXT_ROWS+ 18,{4,5,6,7,3,2,1,0},{0,2,4,6,7,5,3,1}}, + {0x07,3,OC_EXT_ROWS+ 22,{0,1,2,7,6,5,4,3},{0,3,6,7,5,4,2,1}}, + {0xE0,3,OC_EXT_ROWS+ 27,{5,6,7,4,3,2,1,0},{0,3,6,7,5,4,2,1}}, + {0x03,2,OC_EXT_ROWS+ 32,{0,1,7,6,5,4,3,2},{0,4,7,6,5,3,2,1}}, + {0xC0,2,OC_EXT_ROWS+ 32,{6,7,5,4,3,2,1,0},{0,4,7,6,5,3,2,1}}, + {0x01,1,OC_EXT_ROWS+ 0,{0,7,6,5,4,3,2,1},{0,7,6,5,4,3,2,1}}, + {0x80,1,OC_EXT_ROWS+ 0,{7,6,5,4,3,2,1,0},{0,7,6,5,4,3,2,1}}, + {0x7E,6,OC_EXT_ROWS+ 42,{1,2,3,4,5,6,7,0},{0,1,2,5,6,7,4,3}}, + {0x7C,5,OC_EXT_ROWS+ 44,{2,3,4,5,6,7,1,0},{0,1,4,5,7,6,3,2}}, + {0x3E,5,OC_EXT_ROWS+ 47,{1,2,3,4,5,7,6,0},{0,1,4,5,7,6,3,2}}, + {0x78,4,OC_EXT_ROWS+ 50,{3,4,5,6,7,2,1,0},{0,4,5,7,6,3,2,1}}, + {0x3C,4,OC_EXT_ROWS+ 54,{2,3,4,5,7,6,1,0},{0,3,4,7,6,5,2,1}}, + {0x1E,4,OC_EXT_ROWS+ 58,{1,2,3,4,7,6,5,0},{0,4,5,7,6,3,2,1}}, + {0x70,3,OC_EXT_ROWS+ 62,{4,5,6,7,3,2,1,0},{0,5,7,6,4,3,2,1}}, + {0x38,3,OC_EXT_ROWS+ 67,{3,4,5,7,6,2,1,0},{0,5,6,7,4,3,2,1}}, + {0x1C,3,OC_EXT_ROWS+ 72,{2,3,4,7,6,5,1,0},{0,5,6,7,4,3,2,1}}, + {0x0E,3,OC_EXT_ROWS+ 77,{1,2,3,7,6,5,4,0},{0,5,7,6,4,3,2,1}}, + {0x60,2,OC_EXT_ROWS+ 82,{5,6,7,4,3,2,1,0},{0,2,7,6,5,4,3,1}}, + {0x30,2,OC_EXT_ROWS+ 36,{4,5,7,6,3,2,1,0},{0,4,7,6,5,3,2,1}}, + {0x18,2,OC_EXT_ROWS+ 90,{3,4,7,6,5,2,1,0},{0,1,7,6,5,4,3,2}}, + {0x0C,2,OC_EXT_ROWS+ 34,{2,3,7,6,5,4,1,0},{0,4,7,6,5,3,2,1}}, + {0x06,2,OC_EXT_ROWS+ 84,{1,2,7,6,5,4,3,0},{0,2,7,6,5,4,3,1}}, + {0x40,1,OC_EXT_ROWS+ 0,{6,7,5,4,3,2,1,0},{0,7,6,5,4,3,2,1}}, + {0x20,1,OC_EXT_ROWS+ 0,{5,7,6,4,3,2,1,0},{0,7,6,5,4,3,2,1}}, + {0x10,1,OC_EXT_ROWS+ 0,{4,7,6,5,3,2,1,0},{0,7,6,5,4,3,2,1}}, + {0x08,1,OC_EXT_ROWS+ 0,{3,7,6,5,4,2,1,0},{0,7,6,5,4,3,2,1}}, + {0x04,1,OC_EXT_ROWS+ 0,{2,7,6,5,4,3,1,0},{0,7,6,5,4,3,2,1}}, + {0x02,1,OC_EXT_ROWS+ 0,{1,7,6,5,4,3,2,0},{0,7,6,5,4,3,2,1}} +}; + + + +/*Pads a single column of a partial block and then performs a forward Type-II + DCT on the result. + The input is scaled by a factor of 4 and biased appropriately for the current + fDCT implementation. + The output is scaled by an additional factor of 2 from the orthonormal + version of the transform. + _y: The buffer to store the result in. + Data will be placed the first 8 entries (e.g., in a row of an 8x8 block). + _x: The input coefficients. + Every 8th entry is used (e.g., from a column of an 8x8 block). + _e: The extension information for the shape.*/ +static void oc_fdct8_ext(ogg_int16_t _y[8],ogg_int16_t *_x, + const oc_extension_info *_e){ + const unsigned char *pi; + int na; + na=_e->na; + pi=_e->pi; + if(na==1){ + int ci; + /*While the branch below is still correct for shapes with na==1, we can + perform the entire transform with just 1 multiply in this case instead + of 23.*/ + _y[0]=(ogg_int16_t)(OC_DIV2_16(OC_C4S4*(_x[pi[0]]))); + for(ci=1;ci<8;ci++)_y[ci]=0; + } + else{ + const ogg_int16_t *const *ext; + int zpi; + int api; + int nz; + /*First multiply by the extension matrix to compute the padding values.*/ + nz=8-na; + ext=_e->ext; + for(zpi=0;zpi>16)+1>>1; + } + oc_fdct8(_y,_x); + } +} + +/*Performs a forward 8x8 Type-II DCT transform on blocks which overlap the + border of the picture region. + This method ONLY works with rectangular regions. + _border: A description of which pixels are inside the border. + _y: The buffer to store the result in. + This may be the same as _x. + _x: The input pixel values. + Pixel values outside the border will be ignored.*/ +void oc_fdct8x8_border(const oc_border_info *_border, + ogg_int16_t _y[64],const ogg_int16_t _x[64]){ + ogg_int16_t *in; + ogg_int16_t *out; + ogg_int16_t w[64]; + ogg_int64_t mask; + const oc_extension_info *cext; + const oc_extension_info *rext; + int cmask; + int rmask; + int ri; + int ci; + /*Identify the shapes of the non-zero rows and columns.*/ + rmask=cmask=0; + mask=_border->mask; + for(ri=0;ri<8;ri++){ + /*This aggregation is _only_ correct for rectangular masks.*/ + cmask|=((mask&0xFF)!=0)<>=8; + } + /*Find the associated extension info for these shapes.*/ + if(cmask==0xFF)cext=NULL; + else for(cext=OC_EXTENSION_INFO;cext->mask!=cmask;){ + /*If we somehow can't find the shape, then just do an unpadded fDCT. + It won't be efficient, but it should still be correct.*/ + if(++cext>=OC_EXTENSION_INFO+OC_NSHAPES){ + oc_enc_fdct8x8_c(_y,_x); + return; + } + } + if(rmask==0xFF)rext=NULL; + else for(rext=OC_EXTENSION_INFO;rext->mask!=rmask;){ + /*If we somehow can't find the shape, then just do an unpadded fDCT. + It won't be efficient, but it should still be correct.*/ + if(++rext>=OC_EXTENSION_INFO+OC_NSHAPES){ + oc_enc_fdct8x8_c(_y,_x); + return; + } + } + /*Add two extra bits of working precision to improve accuracy; any more and + we could overflow.*/ + for(ci=0;ci<64;ci++)w[ci]=_x[ci]<<2; + /*These biases correct for some systematic error that remains in the full + fDCT->iDCT round trip. + We can safely add them before padding, since if these pixel values are + overwritten, we didn't care what they were anyway (and the unbiased values + will usually yield smaller DCT coefficient magnitudes).*/ + w[0]+=(w[0]!=0)+1; + w[1]++; + w[8]--; + /*Transform the columns. + We can ignore zero columns without a problem.*/ + in=w; + out=_y; + if(cext==NULL)for(ci=0;ci<8;ci++)oc_fdct8(out+(ci<<3),in+ci); + else for(ci=0;ci<8;ci++)if(rmask&(1<>2; +} +#endif diff --git a/Engine/lib/libtheora/lib/fragment.c b/Engine/lib/libtheora/lib/fragment.c new file mode 100644 index 000000000..15372e9d9 --- /dev/null +++ b/Engine/lib/libtheora/lib/fragment.c @@ -0,0 +1,87 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: fragment.c 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ +#include +#include "internal.h" + +void oc_frag_copy(const oc_theora_state *_state,unsigned char *_dst, + const unsigned char *_src,int _ystride){ + (*_state->opt_vtable.frag_copy)(_dst,_src,_ystride); +} + +void oc_frag_copy_c(unsigned char *_dst,const unsigned char *_src,int _ystride){ + int i; + for(i=8;i-->0;){ + memcpy(_dst,_src,8*sizeof(*_dst)); + _dst+=_ystride; + _src+=_ystride; + } +} + +void oc_frag_recon_intra(const oc_theora_state *_state,unsigned char *_dst, + int _ystride,const ogg_int16_t _residue[64]){ + _state->opt_vtable.frag_recon_intra(_dst,_ystride,_residue); +} + +void oc_frag_recon_intra_c(unsigned char *_dst,int _ystride, + const ogg_int16_t _residue[64]){ + int i; + for(i=0;i<8;i++){ + int j; + for(j=0;j<8;j++)_dst[j]=OC_CLAMP255(_residue[i*8+j]+128); + _dst+=_ystride; + } +} + +void oc_frag_recon_inter(const oc_theora_state *_state,unsigned char *_dst, + const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]){ + _state->opt_vtable.frag_recon_inter(_dst,_src,_ystride,_residue); +} + +void oc_frag_recon_inter_c(unsigned char *_dst, + const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]){ + int i; + for(i=0;i<8;i++){ + int j; + for(j=0;j<8;j++)_dst[j]=OC_CLAMP255(_residue[i*8+j]+_src[j]); + _dst+=_ystride; + _src+=_ystride; + } +} + +void oc_frag_recon_inter2(const oc_theora_state *_state,unsigned char *_dst, + const unsigned char *_src1,const unsigned char *_src2,int _ystride, + const ogg_int16_t _residue[64]){ + _state->opt_vtable.frag_recon_inter2(_dst,_src1,_src2,_ystride,_residue); +} + +void oc_frag_recon_inter2_c(unsigned char *_dst,const unsigned char *_src1, + const unsigned char *_src2,int _ystride,const ogg_int16_t _residue[64]){ + int i; + for(i=0;i<8;i++){ + int j; + for(j=0;j<8;j++)_dst[j]=OC_CLAMP255(_residue[i*8+j]+(_src1[j]+_src2[j]>>1)); + _dst+=_ystride; + _src1+=_ystride; + _src2+=_ystride; + } +} + +void oc_restore_fpu(const oc_theora_state *_state){ + _state->opt_vtable.restore_fpu(); +} + +void oc_restore_fpu_c(void){} diff --git a/Engine/lib/libtheora/lib/huffdec.c b/Engine/lib/libtheora/lib/huffdec.c new file mode 100644 index 000000000..8cf27f034 --- /dev/null +++ b/Engine/lib/libtheora/lib/huffdec.c @@ -0,0 +1,489 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: huffdec.c 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ + +#include +#include +#include +#include "huffdec.h" +#include "decint.h" + + +/*The ANSI offsetof macro is broken on some platforms (e.g., older DECs).*/ +#define _ogg_offsetof(_type,_field)\ + ((size_t)((char *)&((_type *)0)->_field-(char *)0)) + +/*The number of internal tokens associated with each of the spec tokens.*/ +static const unsigned char OC_DCT_TOKEN_MAP_ENTRIES[TH_NDCT_TOKENS]={ + 1,1,1,4,8,1,1,8,1,1,1,1,1,2,2,2,2,4,8,2,2,2,4,2,2,2,2,2,8,2,4,8 +}; + +/*The map from external spec-defined tokens to internal tokens. + This is constructed so that any extra bits read with the original token value + can be masked off the least significant bits of its internal token index. + In addition, all of the tokens which require additional extra bits are placed + at the start of the list, and grouped by type. + OC_DCT_REPEAT_RUN3_TOKEN is placed first, as it is an extra-special case, so + giving it index 0 may simplify comparisons on some architectures. + These requirements require some substantial reordering.*/ +static const unsigned char OC_DCT_TOKEN_MAP[TH_NDCT_TOKENS]={ + /*OC_DCT_EOB1_TOKEN (0 extra bits)*/ + 15, + /*OC_DCT_EOB2_TOKEN (0 extra bits)*/ + 16, + /*OC_DCT_EOB3_TOKEN (0 extra bits)*/ + 17, + /*OC_DCT_REPEAT_RUN0_TOKEN (2 extra bits)*/ + 88, + /*OC_DCT_REPEAT_RUN1_TOKEN (3 extra bits)*/ + 80, + /*OC_DCT_REPEAT_RUN2_TOKEN (4 extra bits)*/ + 1, + /*OC_DCT_REPEAT_RUN3_TOKEN (12 extra bits)*/ + 0, + /*OC_DCT_SHORT_ZRL_TOKEN (3 extra bits)*/ + 48, + /*OC_DCT_ZRL_TOKEN (6 extra bits)*/ + 14, + /*OC_ONE_TOKEN (0 extra bits)*/ + 56, + /*OC_MINUS_ONE_TOKEN (0 extra bits)*/ + 57, + /*OC_TWO_TOKEN (0 extra bits)*/ + 58, + /*OC_MINUS_TWO_TOKEN (0 extra bits)*/ + 59, + /*OC_DCT_VAL_CAT2 (1 extra bit)*/ + 60, + 62, + 64, + 66, + /*OC_DCT_VAL_CAT3 (2 extra bits)*/ + 68, + /*OC_DCT_VAL_CAT4 (3 extra bits)*/ + 72, + /*OC_DCT_VAL_CAT5 (4 extra bits)*/ + 2, + /*OC_DCT_VAL_CAT6 (5 extra bits)*/ + 4, + /*OC_DCT_VAL_CAT7 (6 extra bits)*/ + 6, + /*OC_DCT_VAL_CAT8 (10 extra bits)*/ + 8, + /*OC_DCT_RUN_CAT1A (1 extra bit)*/ + 18, + 20, + 22, + 24, + 26, + /*OC_DCT_RUN_CAT1B (3 extra bits)*/ + 32, + /*OC_DCT_RUN_CAT1C (4 extra bits)*/ + 12, + /*OC_DCT_RUN_CAT2A (2 extra bits)*/ + 28, + /*OC_DCT_RUN_CAT2B (3 extra bits)*/ + 40 +}; + +/*These three functions are really part of the bitpack.c module, but + they are only used here. + Declaring local static versions so they can be inlined saves considerable + function call overhead.*/ + +static oc_pb_window oc_pack_refill(oc_pack_buf *_b,int _bits){ + const unsigned char *ptr; + const unsigned char *stop; + oc_pb_window window; + int available; + window=_b->window; + available=_b->bits; + ptr=_b->ptr; + stop=_b->stop; + /*This version of _refill() doesn't bother setting eof because we won't + check for it after we've started decoding DCT tokens.*/ + if(ptr>=stop)available=OC_LOTS_OF_BITS; + while(available<=OC_PB_WINDOW_SIZE-8){ + available+=8; + window|=(oc_pb_window)*ptr++<=stop)available=OC_LOTS_OF_BITS; + } + _b->ptr=ptr; + if(_bits>available)window|=*ptr>>(available&7); + _b->bits=available; + return window; +} + + +/*Read in bits without advancing the bit pointer. + Here we assume 0<=_bits&&_bits<=32.*/ +static long oc_pack_look(oc_pack_buf *_b,int _bits){ + oc_pb_window window; + int available; + long result; + window=_b->window; + available=_b->bits; + if(_bits==0)return 0; + if(_bits>available)_b->window=window=oc_pack_refill(_b,_bits); + result=window>>OC_PB_WINDOW_SIZE-_bits; + return result; +} + +/*Advance the bit pointer.*/ +static void oc_pack_adv(oc_pack_buf *_b,int _bits){ + /*We ignore the special cases for _bits==0 and _bits==32 here, since they are + never used actually used. + OC_HUFF_SLUSH (defined below) would have to be at least 27 to actually read + 32 bits in a single go, and would require a 32 GB lookup table (assuming + 8 byte pointers, since 4 byte pointers couldn't fit such a table).*/ + _b->window<<=_bits; + _b->bits-=_bits; +} + + +/*The log_2 of the size of a lookup table is allowed to grow to relative to + the number of unique nodes it contains. + E.g., if OC_HUFF_SLUSH is 2, then at most 75% of the space in the tree is + wasted (each node will have an amortized cost of at most 20 bytes when using + 4-byte pointers). + Larger numbers can decode tokens with fewer read operations, while smaller + numbers may save more space (requiring as little as 8 bytes amortized per + node, though there will be more nodes). + With a sample file: + 32233473 read calls are required when no tree collapsing is done (100.0%). + 19269269 read calls are required when OC_HUFF_SLUSH is 0 (59.8%). + 11144969 read calls are required when OC_HUFF_SLUSH is 1 (34.6%). + 10538563 read calls are required when OC_HUFF_SLUSH is 2 (32.7%). + 10192578 read calls are required when OC_HUFF_SLUSH is 3 (31.6%). + Since a value of 1 gets us the vast majority of the speed-up with only a + small amount of wasted memory, this is what we use.*/ +#define OC_HUFF_SLUSH (1) + + +/*Determines the size in bytes of a Huffman tree node that represents a + subtree of depth _nbits. + _nbits: The depth of the subtree. + If this is 0, the node is a leaf node. + Otherwise 1<<_nbits pointers are allocated for children. + Return: The number of bytes required to store the node.*/ +static size_t oc_huff_node_size(int _nbits){ + size_t size; + size=_ogg_offsetof(oc_huff_node,nodes); + if(_nbits>0)size+=sizeof(oc_huff_node *)*(1<<_nbits); + return size; +} + +static oc_huff_node *oc_huff_node_init(char **_storage,size_t _size,int _nbits){ + oc_huff_node *ret; + ret=(oc_huff_node *)*_storage; + ret->nbits=(unsigned char)_nbits; + (*_storage)+=_size; + return ret; +} + + +/*Determines the size in bytes of a Huffman tree. + _nbits: The depth of the subtree. + If this is 0, the node is a leaf node. + Otherwise storage for 1<<_nbits pointers are added for children. + Return: The number of bytes required to store the tree.*/ +static size_t oc_huff_tree_size(const oc_huff_node *_node){ + size_t size; + size=oc_huff_node_size(_node->nbits); + if(_node->nbits){ + int nchildren; + int i; + nchildren=1<<_node->nbits; + for(i=0;inbits-_node->nodes[i]->depth){ + size+=oc_huff_tree_size(_node->nodes[i]); + } + } + return size; +} + + +/*Unpacks a sub-tree from the given buffer. + _opb: The buffer to unpack from. + _binodes: The nodes to store the sub-tree in. + _nbinodes: The number of nodes available for the sub-tree. + Return: 0 on success, or a negative value on error.*/ +static int oc_huff_tree_unpack(oc_pack_buf *_opb, + oc_huff_node *_binodes,int _nbinodes){ + oc_huff_node *binode; + long bits; + int nused; + if(_nbinodes<1)return TH_EBADHEADER; + binode=_binodes; + nused=0; + bits=oc_pack_read1(_opb); + if(oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER; + /*Read an internal node:*/ + if(!bits){ + int ret; + nused++; + binode->nbits=1; + binode->depth=1; + binode->nodes[0]=_binodes+nused; + ret=oc_huff_tree_unpack(_opb,_binodes+nused,_nbinodes-nused); + if(ret>=0){ + nused+=ret; + binode->nodes[1]=_binodes+nused; + ret=oc_huff_tree_unpack(_opb,_binodes+nused,_nbinodes-nused); + } + if(ret<0)return ret; + nused+=ret; + } + /*Read a leaf node:*/ + else{ + int ntokens; + int token; + int i; + bits=oc_pack_read(_opb,OC_NDCT_TOKEN_BITS); + if(oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER; + /*Find out how many internal tokens we translate this external token into.*/ + ntokens=OC_DCT_TOKEN_MAP_ENTRIES[bits]; + if(_nbinodes<2*ntokens-1)return TH_EBADHEADER; + /*Fill in a complete binary tree pointing to the internal tokens.*/ + for(i=1;inbits=0; + binode->depth=1; + binode->token=token+i; + } + } + return nused; +} + +/*Finds the depth of shortest branch of the given sub-tree. + The tree must be binary. + _binode: The root of the given sub-tree. + _binode->nbits must be 0 or 1. + Return: The smallest depth of a leaf node in this sub-tree. + 0 indicates this sub-tree is a leaf node.*/ +static int oc_huff_tree_mindepth(oc_huff_node *_binode){ + int depth0; + int depth1; + if(_binode->nbits==0)return 0; + depth0=oc_huff_tree_mindepth(_binode->nodes[0]); + depth1=oc_huff_tree_mindepth(_binode->nodes[1]); + return OC_MINI(depth0,depth1)+1; +} + +/*Finds the number of internal nodes at a given depth, plus the number of + leaves at that depth or shallower. + The tree must be binary. + _binode: The root of the given sub-tree. + _binode->nbits must be 0 or 1. + Return: The number of entries that would be contained in a jump table of the + given depth.*/ +static int oc_huff_tree_occupancy(oc_huff_node *_binode,int _depth){ + if(_binode->nbits==0||_depth<=0)return 1; + else{ + return oc_huff_tree_occupancy(_binode->nodes[0],_depth-1)+ + oc_huff_tree_occupancy(_binode->nodes[1],_depth-1); + } +} + +/*Makes a copy of the given Huffman tree. + _node: The Huffman tree to copy. + Return: The copy of the Huffman tree.*/ +static oc_huff_node *oc_huff_tree_copy(const oc_huff_node *_node, + char **_storage){ + oc_huff_node *ret; + ret=oc_huff_node_init(_storage,oc_huff_node_size(_node->nbits),_node->nbits); + ret->depth=_node->depth; + if(_node->nbits){ + int nchildren; + int i; + int inext; + nchildren=1<<_node->nbits; + for(i=0;inodes[i]=oc_huff_tree_copy(_node->nodes[i],_storage); + inext=i+(1<<_node->nbits-ret->nodes[i]->depth); + while(++inodes[i]=ret->nodes[i-1]; + } + } + else ret->token=_node->token; + return ret; +} + +static size_t oc_huff_tree_collapse_size(oc_huff_node *_binode,int _depth){ + size_t size; + int mindepth; + int depth; + int loccupancy; + int occupancy; + if(_binode->nbits!=0&&_depth>0){ + return oc_huff_tree_collapse_size(_binode->nodes[0],_depth-1)+ + oc_huff_tree_collapse_size(_binode->nodes[1],_depth-1); + } + depth=mindepth=oc_huff_tree_mindepth(_binode); + occupancy=1<loccupancy&&occupancy>=1<0){ + size+=oc_huff_tree_collapse_size(_binode->nodes[0],depth-1); + size+=oc_huff_tree_collapse_size(_binode->nodes[1],depth-1); + } + return size; +} + +static oc_huff_node *oc_huff_tree_collapse(oc_huff_node *_binode, + char **_storage); + +/*Fills the given nodes table with all the children in the sub-tree at the + given depth. + The nodes in the sub-tree with a depth less than that stored in the table + are freed. + The sub-tree must be binary and complete up until the given depth. + _nodes: The nodes table to fill. + _binode: The root of the sub-tree to fill it with. + _binode->nbits must be 0 or 1. + _level: The current level in the table. + 0 indicates that the current node should be stored, regardless of + whether it is a leaf node or an internal node. + _depth: The depth of the nodes to fill the table with, relative to their + parent.*/ +static void oc_huff_node_fill(oc_huff_node **_nodes, + oc_huff_node *_binode,int _level,int _depth,char **_storage){ + if(_level<=0||_binode->nbits==0){ + int i; + _binode->depth=(unsigned char)(_depth-_level); + _nodes[0]=oc_huff_tree_collapse(_binode,_storage); + for(i=1;i<1<<_level;i++)_nodes[i]=_nodes[0]; + } + else{ + _level--; + oc_huff_node_fill(_nodes,_binode->nodes[0],_level,_depth,_storage); + _nodes+=1<<_level; + oc_huff_node_fill(_nodes,_binode->nodes[1],_level,_depth,_storage); + } +} + +/*Finds the largest complete sub-tree rooted at the current node and collapses + it into a single node. + This procedure is then applied recursively to all the children of that node. + _binode: The root of the sub-tree to collapse. + _binode->nbits must be 0 or 1. + Return: The new root of the collapsed sub-tree.*/ +static oc_huff_node *oc_huff_tree_collapse(oc_huff_node *_binode, + char **_storage){ + oc_huff_node *root; + size_t size; + int mindepth; + int depth; + int loccupancy; + int occupancy; + depth=mindepth=oc_huff_tree_mindepth(_binode); + occupancy=1<loccupancy&&occupancy>=1<depth=_binode->depth; + oc_huff_node_fill(root->nodes,_binode,depth,depth,_storage); + return root; +} + +/*Unpacks a set of Huffman trees, and reduces them to a collapsed + representation. + _opb: The buffer to unpack the trees from. + _nodes: The table to fill with the Huffman trees. + Return: 0 on success, or a negative value on error.*/ +int oc_huff_trees_unpack(oc_pack_buf *_opb, + oc_huff_node *_nodes[TH_NHUFFMAN_TABLES]){ + int i; + for(i=0;i0)_ogg_free(_dst[i]); + return TH_EFAULT; + } + _dst[i]=oc_huff_tree_copy(_src[i],&storage); + } + return 0; +} + +/*Frees the memory used by a set of Huffman trees. + _nodes: The array of trees to free.*/ +void oc_huff_trees_clear(oc_huff_node *_nodes[TH_NHUFFMAN_TABLES]){ + int i; + for(i=0;inbits!=0){ + bits=oc_pack_look(_opb,_node->nbits); + _node=_node->nodes[bits]; + oc_pack_adv(_opb,_node->depth); + } + return _node->token; +} diff --git a/Engine/lib/libtheora/lib/dec/huffdec.h b/Engine/lib/libtheora/lib/huffdec.h similarity index 91% rename from Engine/lib/libtheora/lib/dec/huffdec.h rename to Engine/lib/libtheora/lib/huffdec.h index cc87b4092..d7ffa0e99 100644 --- a/Engine/lib/libtheora/lib/dec/huffdec.h +++ b/Engine/lib/libtheora/lib/huffdec.h @@ -5,19 +5,20 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: huffdec.h 15400 2008-10-15 12:10:58Z tterribe $ + last mod: $Id: huffdec.h 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ #if !defined(_huffdec_H) # define _huffdec_H (1) # include "huffman.h" +# include "bitpack.h" @@ -75,17 +76,17 @@ struct oc_huff_node{ The ACTUAL size of this array is 1< #include -#include "theora/theoraenc.h" -#include "theora/theora.h" -#include "codec_internal.h" -#include "../dec/ocintrin.h" - -/*Wrapper to translate the new API into the old API. - Eventually we need to convert the old functions to support the new API - natively and do the translation the other way. - theora-exp already the necessary code to do so.*/ +#include +#include "huffenc.h" -/*The default Huffman codes used for VP3.1. - It's kind of useless to include this, as TH_ENCCTL_SET_HUFFMAN_CODES is not - actually implemented in the old encoder, but it's part of the public API.*/ +/*The default Huffman codes used for VP3.1.*/ const th_huff_code TH_VP31_HUFF_CODES[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]={ { {0x002D, 6},{0x0026, 7},{0x0166, 9},{0x004E, 8}, @@ -819,323 +811,100 @@ const th_huff_code TH_VP31_HUFF_CODES[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]={ -static void th_info2theora_info(theora_info *_ci,const th_info *_info){ - _ci->version_major=_info->version_major; - _ci->version_minor=_info->version_minor; - _ci->version_subminor=_info->version_subminor; - _ci->width=_info->frame_width; - _ci->height=_info->frame_height; - _ci->frame_width=_info->pic_width; - _ci->frame_height=_info->pic_height; - _ci->offset_x=_info->pic_x; - _ci->offset_y=_info->pic_y; - _ci->fps_numerator=_info->fps_numerator; - _ci->fps_denominator=_info->fps_denominator; - _ci->aspect_numerator=_info->aspect_numerator; - _ci->aspect_denominator=_info->aspect_denominator; - switch(_info->colorspace){ - case TH_CS_ITU_REC_470M:_ci->colorspace=OC_CS_ITU_REC_470M;break; - case TH_CS_ITU_REC_470BG:_ci->colorspace=OC_CS_ITU_REC_470BG;break; - default:_ci->colorspace=OC_CS_UNSPECIFIED;break; - } - switch(_info->pixel_fmt){ - case TH_PF_420:_ci->pixelformat=OC_PF_420;break; - case TH_PF_422:_ci->pixelformat=OC_PF_422;break; - case TH_PF_444:_ci->pixelformat=OC_PF_444;break; - default:_ci->pixelformat=OC_PF_RSVD; - } - _ci->target_bitrate=_info->target_bitrate; - _ci->quality=_info->quality; - _ci->codec_setup=NULL; - /*Defaults from old encoder_example... eventually most of these should go - away when we make the encoder no longer use them.*/ - _ci->dropframes_p=0; - _ci->keyframe_auto_p=1; - _ci->keyframe_frequency=1<<_info->keyframe_granule_shift; - _ci->keyframe_frequency_force=1<<_info->keyframe_granule_shift; - _ci->keyframe_data_target_bitrate= - _info->target_bitrate+(_info->target_bitrate>>1); - _ci->keyframe_auto_threshold=80; - _ci->keyframe_mindistance=8; - _ci->noise_sensitivity=1; - _ci->sharpness=0; - _ci->quick_p=1; +/*A description of a Huffman code value used when encoding the tree.*/ +typedef struct{ + /*The bit pattern, left-shifted so that the MSB of all patterns is + aligned.*/ + ogg_uint32_t pattern; + /*The amount the bit pattern was shifted.*/ + int shift; + /*The token this bit pattern represents.*/ + int token; +}oc_huff_entry; + + + +/*Compares two oc_huff_entry structures by their bit patterns. + _c1: The first entry to compare. + _c2: The second entry to compare. + Return: <0 if _c1<_c2, >0 if _c1>_c2.*/ +static int huff_entry_cmp(const void *_c1,const void *_c2){ + ogg_uint32_t b1; + ogg_uint32_t b2; + b1=((const oc_huff_entry *)_c1)->pattern; + b2=((const oc_huff_entry *)_c2)->pattern; + return b1b2?1:0; } -static int _ilog(unsigned _v){ - int ret; - for(ret=0;_v;ret++)_v>>=1; - return ret; -} - - - -struct th_enc_ctx{ - /*This is required at the start of the struct for the common functions to - work.*/ - th_info info; - /*The actual encoder.*/ - theora_state state; - /*A temporary buffer for input frames. - This is needed if the U and V strides differ, or padding is required.*/ - unsigned char *buf; -}; - - -th_enc_ctx *th_encode_alloc(const th_info *_info){ - theora_info ci; - th_enc_ctx *enc; - th_info2theora_info(&ci,_info); - /*Do a bunch of checks the new API does, but the old one didn't.*/ - if((_info->frame_width&0xF)||(_info->frame_height&0xF)|| - _info->frame_width>=0x100000||_info->frame_height>=0x100000|| - _info->pic_x+_info->pic_width>_info->frame_width|| - _info->pic_y+_info->pic_height>_info->frame_height|| - _info->pic_x>255|| - _info->frame_height-_info->pic_height-_info->pic_y>255|| - _info->colorspace<0||_info->colorspace>=TH_CS_NSPACES|| - _info->pixel_fmt<0||_info->pixel_fmt>=TH_PF_NFORMATS){ - enc=NULL; - } - else{ - enc=(th_enc_ctx *)_ogg_malloc(sizeof(*enc)); - if(theora_encode_init(&enc->state,&ci)<0){ - _ogg_free(enc); - enc=NULL; +/*Encodes a description of the given Huffman tables. + Although the codes are stored in the encoder as flat arrays, in the bit + stream and in the decoder they are structured as a tree. + This function recovers the tree structure from the flat array and then + writes it out. + Note that the codes MUST form a Huffman code, and not merely a prefix-free + code, since the binary tree is assumed to be full. + _opb: The buffer to store the tree in. + _codes: The Huffman tables to pack. + Return: 0 on success, or a negative value if one of the given Huffman tables + does not form a full, prefix-free code.*/ +int oc_huff_codes_pack(oggpack_buffer *_opb, + const th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]){ + int i; + for(i=0;iframe_width>_info->pic_width|| - _info->frame_height>_info->pic_height){ - enc->buf=_ogg_malloc((_info->frame_width*_info->frame_height+ - ((_info->frame_width>>!(_info->pixel_fmt&1))* - (_info->frame_height>>!(_info->pixel_fmt&2))<<1))*sizeof(*enc->buf)); - } - else enc->buf=NULL; - memcpy(&enc->info,_info,sizeof(enc->info)); - /*Overwrite values theora_encode_init() can change; don't trust the user.*/ - enc->info.version_major=ci.version_major; - enc->info.version_minor=ci.version_minor; - enc->info.version_subminor=ci.version_subminor; - enc->info.quality=ci.quality; - enc->info.target_bitrate=ci.target_bitrate; - enc->info.fps_numerator=ci.fps_numerator; - enc->info.fps_denominator=ci.fps_denominator; - enc->info.keyframe_granule_shift=_ilog(ci.keyframe_frequency_force-1); + mask=(1<<(maxlen>>1)<<(maxlen+1>>1))-1; + /*Copy over the codes into our temporary workspace. + The bit patterns are aligned, and the original entry each code is from + is stored as well.*/ + for(j=0;jstate,_req,_buf,_buf_sz); -} - -int th_encode_flushheader(th_enc_ctx *_enc,th_comment *_comments, - ogg_packet *_op){ - theora_state *te; - CP_INSTANCE *cpi; - if(_enc==NULL||_op==NULL)return OC_FAULT; - te=&_enc->state; - cpi=(CP_INSTANCE *)te->internal_encode; - switch(cpi->doneflag){ - case -3:{ - theora_encode_header(te,_op); - return -cpi->doneflag++; - }break; - case -2:{ - if(_comments==NULL)return OC_FAULT; - theora_encode_comment((theora_comment *)_comments,_op); - /*The old API does not require a theora_state struct when writing the - comment header, so it can't use its internal buffer and relies on the - application to free it. - The old documentation is wrong on this subject, and this breaks on - Windows when linking against multiple versions of libc (which is - almost always done when, e.g., using DLLs built with mingw32). - The new API _does_ require a th_enc_ctx, and states that libtheora owns - the memory. - Thus we move the contents of this packet into our internal - oggpack_buffer so it can be properly reclaimed.*/ - oggpackB_reset(cpi->oggbuffer); - oggpackB_writecopy(cpi->oggbuffer,_op->packet,_op->bytes*8); - _ogg_free(_op->packet); - _op->packet=oggpackB_get_buffer(cpi->oggbuffer); - return -cpi->doneflag++; - }break; - case -1:{ - theora_encode_tables(te,_op); - return -cpi->doneflag++; - }break; - case 0:return 0; - default:return OC_EINVAL; - } -} - -/*Copies the picture region of the _src image plane into _dst and pads the rest - of _dst using a diffusion extension method. - We could do much better (e.g., the DCT-based low frequency extension method - in theora-exp's fdct.c) if we were to pad after motion compensation, but - that would require significant changes to the encoder.*/ -static unsigned char *th_encode_copy_pad_plane(th_img_plane *_dst, - unsigned char *_buf,th_img_plane *_src, - ogg_uint32_t _pic_x,ogg_uint32_t _pic_y, - ogg_uint32_t _pic_width,ogg_uint32_t _pic_height){ - size_t buf_sz; - _dst->width=_src->width; - _dst->height=_src->height; - _dst->stride=_src->width; - _dst->data=_buf; - buf_sz=_dst->width*_dst->height*sizeof(*_dst->data); - /*If we have _no_ data, just encode a dull green.*/ - if(_pic_width==0||_pic_height==0)memset(_dst->data,0,buf_sz); - else{ - unsigned char *dst; - unsigned char *src; - ogg_uint32_t x; - ogg_uint32_t y; - int dstride; - int sstride; - /*Step 1: Copy the data we do have.*/ - dstride=_dst->stride; - sstride=_src->stride; - dst=_dst->data+_pic_y*dstride+_pic_x; - src=_src->data+_pic_y*sstride+_pic_x; - for(y=0;y<_pic_height;y++){ - memcpy(dst,src,_pic_width); - dst+=dstride; - src+=sstride; - } - /*Step 2: Copy the border into any blocks that are 100% padding. - There's probably smarter things we could do than this.*/ - /*Left side.*/ - for(x=_pic_x;x-->0;){ - dst=_dst->data+_pic_y*dstride+x; - for(y=0;y<_pic_height;y++){ - dst[0]=(dst[1]<<1)+(dst-(dstride&-(y>0)))[1]+ - (dst+(dstride&-(y+1<_pic_height)))[1]+2>>2; - dst+=dstride; + /*Sort the codes into ascending order. + This is the order the leaves of the tree will be traversed.*/ + qsort(entries,TH_NDCT_TOKENS,sizeof(entries[0]),huff_entry_cmp); + /*For each leaf of the tree:*/ + bpos=maxlen; + for(j=0;jentries[j].shift;bpos--)oggpackB_write(_opb,0,1); + /*Mark this as a leaf node, and write its value.*/ + oggpackB_write(_opb,1,1); + oggpackB_write(_opb,entries[j].token,5); + /*For each 1 branch we've descended, back up the tree until we reach a + 0 branch.*/ + bit=1<width;x++){ - dst=_dst->data+_pic_y*dstride+x-1; - for(y=0;y<_pic_height;y++){ - dst[1]=(dst[0]<<1)+(dst-(dstride&-(y>0)))[0]+ - (dst+(dstride&-(y+1<_pic_height)))[0]+2>>2; - dst+=dstride; - } - } - /*Top.*/ - dst=_dst->data+_pic_y*dstride; - for(y=_pic_y;y-->0;){ - for(x=0;x<_dst->width;x++){ - (dst-dstride)[x]=(dst[x]<<1)+dst[x-(x>0)]+dst[x+(x+1<_dst->width)]+2>>2; - } - dst-=dstride; - } - /*Bottom.*/ - dst=_dst->data+(_pic_y+_pic_height)*dstride; - for(y=_pic_y+_pic_height;y<_dst->height;y++){ - for(x=0;x<_dst->width;x++){ - dst[x]=((dst-dstride)[x]<<1)+(dst-dstride)[x-(x>0)]+ - (dst-dstride)[x+(x+1<_dst->width)]+2>>2; - } - dst+=dstride; - } - } - _buf+=buf_sz; - return _buf; -} - -int th_encode_ycbcr_in(th_enc_ctx *_enc,th_ycbcr_buffer _ycbcr){ - CP_INSTANCE *cpi; - theora_state *te; - th_img_plane *pycbcr; - th_ycbcr_buffer ycbcr; - yuv_buffer yuv; - ogg_uint32_t pic_width; - ogg_uint32_t pic_height; - int hdec; - int vdec; - int ret; - if(_enc==NULL||_ycbcr==NULL)return OC_FAULT; - te=&_enc->state; - /*theora_encode_YUVin() does not bother to check uv_width and uv_height, and - then uses them. - This is arguably okay (it will most likely lead to a crash if they're - wrong, which will make the developer who passed them fix the problem), but - our API promises to return an error code instead.*/ - cpi=(CP_INSTANCE *)te->internal_encode; - hdec=!(cpi->pb.info.pixelformat&1); - vdec=!(cpi->pb.info.pixelformat&2); - if(_ycbcr[0].width!=cpi->pb.info.width|| - _ycbcr[0].height!=cpi->pb.info.height|| - _ycbcr[1].width!=_ycbcr[0].width>>hdec|| - _ycbcr[1].height!=_ycbcr[0].height>>vdec|| - _ycbcr[2].width!=_ycbcr[1].width||_ycbcr[2].height!=_ycbcr[1].height){ - return OC_EINVAL; - } - pic_width=cpi->pb.info.frame_width; - pic_height=cpi->pb.info.frame_height; - /*We can only directly use the input buffer if no padding is required (since - the new API is documented not to use values outside the picture region) - and if the strides for the Cb and Cr planes are the same, since the old - API had no way to specify different ones.*/ - if(_ycbcr[0].width==pic_width&&_ycbcr[0].height==pic_height&& - _ycbcr[1].stride==_ycbcr[2].stride){ - pycbcr=_ycbcr; - } - else{ - unsigned char *buf; - int pic_x; - int pic_y; - int pli; - pic_x=cpi->pb.info.offset_x; - pic_y=cpi->pb.info.offset_y; - if(_ycbcr[0].width>pic_width||_ycbcr[0].height>pic_height){ - buf=th_encode_copy_pad_plane(ycbcr+0,_enc->buf,_ycbcr+0, - pic_x,pic_y,pic_width,pic_height); - } - else{ - /*If only the strides differ, we can still avoid copying the luma plane.*/ - memcpy(ycbcr+0,_ycbcr+0,sizeof(ycbcr[0])); - if(_enc->buf==NULL){ - _enc->buf=(unsigned char *)_ogg_malloc( - (_ycbcr[1].width*_ycbcr[1].height<<1)*sizeof(*_enc->buf)); - } - buf=_enc->buf; - } - for(pli=1;pli<3;pli++){ - int x0; - int y0; - x0=pic_x>>hdec; - y0=pic_y>>vdec; - buf=th_encode_copy_pad_plane(ycbcr+pli,buf,_ycbcr+pli, - x0,y0,(pic_x+pic_width+hdec>>hdec)-x0,(pic_y+pic_height+vdec>>vdec)-y0); - } - pycbcr=ycbcr; - } - yuv.y_width=pycbcr[0].width; - yuv.y_height=pycbcr[0].height; - yuv.uv_width=pycbcr[1].width; - yuv.uv_height=pycbcr[1].height; - yuv.y_stride=pycbcr[0].stride; - yuv.y=pycbcr[0].data; - yuv.uv_stride=pycbcr[1].stride; - yuv.u=pycbcr[1].data; - yuv.v=pycbcr[2].data; - ret=theora_encode_YUVin(te,&yuv); - return ret; -} - -int th_encode_packetout(th_enc_ctx *_enc,int _last,ogg_packet *_op){ - if(_enc==NULL)return OC_FAULT; - return theora_encode_packetout(&_enc->state,_last,_op); -} - -void th_encode_free(th_enc_ctx *_enc){ - if(_enc!=NULL){ - theora_clear(&_enc->state); - _ogg_free(_enc->buf); - _ogg_free(_enc); } + return 0; } diff --git a/Engine/lib/libtheora/lib/huffenc.h b/Engine/lib/libtheora/lib/huffenc.h new file mode 100644 index 000000000..c5a3956f1 --- /dev/null +++ b/Engine/lib/libtheora/lib/huffenc.h @@ -0,0 +1,19 @@ +#if !defined(_huffenc_H) +# define _huffenc_H (1) +# include "huffman.h" + + + +typedef th_huff_code th_huff_table[TH_NDCT_TOKENS]; + + + +extern const th_huff_code + TH_VP31_HUFF_CODES[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]; + + + +int oc_huff_codes_pack(oggpack_buffer *_opb, + const th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]); + +#endif diff --git a/Engine/lib/libtheora/lib/dec/huffman.h b/Engine/lib/libtheora/lib/huffman.h similarity index 92% rename from Engine/lib/libtheora/lib/dec/huffman.h rename to Engine/lib/libtheora/lib/huffman.h index 59096e1e8..36cf7572e 100644 --- a/Engine/lib/libtheora/lib/dec/huffman.h +++ b/Engine/lib/libtheora/lib/huffman.h @@ -5,13 +5,13 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: huffman.h 15400 2008-10-15 12:10:58Z tterribe $ + last mod: $Id: huffman.h 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ @@ -65,6 +65,6 @@ #define OC_NDCT_RUN_MAX (32) #define OC_NDCT_RUN_CAT1A_MAX (28) -extern const int OC_DCT_TOKEN_EXTRA_BITS[TH_NDCT_TOKENS]; +extern const unsigned char OC_DCT_TOKEN_EXTRA_BITS[TH_NDCT_TOKENS]; #endif diff --git a/Engine/lib/libtheora/lib/dec/idct.c b/Engine/lib/libtheora/lib/idct.c similarity index 70% rename from Engine/lib/libtheora/lib/dec/idct.c rename to Engine/lib/libtheora/lib/idct.c index 21ac83f14..0e68ac765 100644 --- a/Engine/lib/libtheora/lib/dec/idct.c +++ b/Engine/lib/libtheora/lib/idct.c @@ -5,20 +5,19 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: idct.c 15400 2008-10-15 12:10:58Z tterribe $ + last mod: $Id: idct.c 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ #include -#include +#include "internal.h" #include "dct.h" -#include "idct.h" /*Performs an inverse 8 point Type-II DCT transform. The output is scaled by a factor of 2 relative to the orthonormal version of @@ -220,19 +219,29 @@ static void idct8_1(ogg_int16_t *_y,const ogg_int16_t _x[1]){ /*Performs an inverse 8x8 Type-II DCT transform. The input is assumed to be scaled by a factor of 4 relative to orthonormal version of the transform. + All coefficients but the first 3 in zig-zag scan order are assumed to be 0: + x x 0 0 0 0 0 0 + x 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 _y: The buffer to store the result in. This may be the same as _x. - _x: The input coefficients. */ -void oc_idct8x8_c(ogg_int16_t _y[64],const ogg_int16_t _x[64]){ + _x: The input coefficients.*/ +static void oc_idct8x8_3(ogg_int16_t _y[64],const ogg_int16_t _x[64]){ const ogg_int16_t *in; ogg_int16_t *end; ogg_int16_t *out; ogg_int16_t w[64]; /*Transform rows of x into columns of w.*/ - for(in=_x,out=w,end=out+8;out>4); } @@ -250,8 +259,8 @@ void oc_idct8x8_c(ogg_int16_t _y[64],const ogg_int16_t _x[64]){ 0 0 0 0 0 0 0 0 _y: The buffer to store the result in. This may be the same as _x. - _x: The input coefficients. */ -void oc_idct8x8_10_c(ogg_int16_t _y[64],const ogg_int16_t _x[64]){ + _x: The input coefficients.*/ +static void oc_idct8x8_10(ogg_int16_t _y[64],const ogg_int16_t _x[64]){ const ogg_int16_t *in; ogg_int16_t *end; ogg_int16_t *out; @@ -263,6 +272,64 @@ void oc_idct8x8_10_c(ogg_int16_t _y[64],const ogg_int16_t _x[64]){ idct8_1(w+3,_x+24); /*Transform rows of w into columns of y.*/ for(in=w,out=_y,end=out+8;out>4); } + +/*Performs an inverse 8x8 Type-II DCT transform. + The input is assumed to be scaled by a factor of 4 relative to orthonormal + version of the transform. + _y: The buffer to store the result in. + This may be the same as _x. + _x: The input coefficients.*/ +static void oc_idct8x8_slow(ogg_int16_t _y[64],const ogg_int16_t _x[64]){ + const ogg_int16_t *in; + ogg_int16_t *end; + ogg_int16_t *out; + ogg_int16_t w[64]; + /*Transform rows of x into columns of w.*/ + for(in=_x,out=w,end=out+8;out>4); +} + +void oc_idct8x8(const oc_theora_state *_state,ogg_int16_t _y[64], + int _last_zzi){ + (*_state->opt_vtable.idct8x8)(_y,_last_zzi); +} + +/*Performs an inverse 8x8 Type-II DCT transform. + The input is assumed to be scaled by a factor of 4 relative to orthonormal + version of the transform.*/ +void oc_idct8x8_c(ogg_int16_t _y[64],int _last_zzi){ + /*_last_zzi is subtly different from an actual count of the number of + coefficients we decoded for this block. + It contains the value of zzi BEFORE the final token in the block was + decoded. + In most cases this is an EOB token (the continuation of an EOB run from a + previous block counts), and so this is the same as the coefficient count. + However, in the case that the last token was NOT an EOB token, but filled + the block up with exactly 64 coefficients, _last_zzi will be less than 64. + Provided the last token was not a pure zero run, the minimum value it can + be is 46, and so that doesn't affect any of the cases in this routine. + However, if the last token WAS a pure zero run of length 63, then _last_zzi + will be 1 while the number of coefficients decoded is 64. + Thus, we will trigger the following special case, where the real + coefficient count would not. + Note also that a zero run of length 64 will give _last_zzi a value of 0, + but we still process the DC coefficient, which might have a non-zero value + due to DC prediction. + Although convoluted, this is arguably the correct behavior: it allows us to + use a smaller transform when the block ends with a long zero run instead + of a normal EOB token. + It could be smarter... multiple separate zero runs at the end of a block + will fool it, but an encoder that generates these really deserves what it + gets. + Needless to say we inherited this approach from VP3.*/ + /*Then perform the iDCT.*/ + if(_last_zzi<3)oc_idct8x8_3(_y,_y); + else if(_last_zzi<10)oc_idct8x8_10(_y,_y); + else oc_idct8x8_slow(_y,_y); +} diff --git a/Engine/lib/libtheora/lib/dec/info.c b/Engine/lib/libtheora/lib/info.c similarity index 83% rename from Engine/lib/libtheora/lib/dec/info.c rename to Engine/lib/libtheora/lib/info.c index 26e7f42a9..6b9762978 100644 --- a/Engine/lib/libtheora/lib/dec/info.c +++ b/Engine/lib/libtheora/lib/info.c @@ -5,20 +5,20 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: info.c 15400 2008-10-15 12:10:58Z tterribe $ + last mod: $Id: info.c 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ #include #include #include -#include "../internal.h" +#include "internal.h" @@ -55,14 +55,21 @@ void th_comment_init(th_comment *_tc){ } void th_comment_add(th_comment *_tc,char *_comment){ - int comment_len; - _tc->user_comments=_ogg_realloc(_tc->user_comments, + char **user_comments; + int *comment_lengths; + int comment_len; + user_comments=_ogg_realloc(_tc->user_comments, (_tc->comments+2)*sizeof(*_tc->user_comments)); - _tc->comment_lengths=_ogg_realloc(_tc->comment_lengths, + if(user_comments==NULL)return; + _tc->user_comments=user_comments; + comment_lengths=_ogg_realloc(_tc->comment_lengths, (_tc->comments+2)*sizeof(*_tc->comment_lengths)); + if(comment_lengths==NULL)return; + _tc->comment_lengths=comment_lengths; comment_len=strlen(_comment); - _tc->comment_lengths[_tc->comments]=comment_len; - _tc->user_comments[_tc->comments]=_ogg_malloc(comment_len+1); + comment_lengths[_tc->comments]=comment_len; + user_comments[_tc->comments]=_ogg_malloc(comment_len+1); + if(user_comments[_tc->comments]==NULL)return; memcpy(_tc->user_comments[_tc->comments],_comment,comment_len+1); _tc->comments++; _tc->user_comments[_tc->comments]=NULL; @@ -76,6 +83,7 @@ void th_comment_add_tag(th_comment *_tc,char *_tag,char *_val){ val_len=strlen(_val); /*+2 for '=' and '\0'.*/ comment=_ogg_malloc(tag_len+val_len+2); + if(comment==NULL)return; memcpy(comment,_tag,tag_len); comment[tag_len]='='; memcpy(comment+tag_len+1,_val,val_len+1); diff --git a/Engine/lib/libtheora/lib/dec/internal.c b/Engine/lib/libtheora/lib/internal.c similarity index 62% rename from Engine/lib/libtheora/lib/dec/internal.c rename to Engine/lib/libtheora/lib/internal.c index 3fe62e55b..0fe4f63e7 100644 --- a/Engine/lib/libtheora/lib/dec/internal.c +++ b/Engine/lib/libtheora/lib/internal.c @@ -5,21 +5,20 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: internal.c 15400 2008-10-15 12:10:58Z tterribe $ + last mod: $Id: internal.c 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ #include #include #include -#include "../internal.h" -#include "idct.h" +#include "internal.h" @@ -27,7 +26,7 @@ block. All zig zag indices beyond 63 are sent to coefficient 64, so that zero runs past the end of a block in bogus streams get mapped to a known location.*/ -const int OC_FZIG_ZAG[128]={ +const unsigned char OC_FZIG_ZAG[128]={ 0, 1, 8,16, 9, 2, 3,10, 17,24,32,25,18,11, 4, 5, 12,19,26,33,40,48,41,34, @@ -48,7 +47,7 @@ const int OC_FZIG_ZAG[128]={ /*A map from the coefficient number in a block to its index in the zig zag scan.*/ -const int OC_IZIG_ZAG[64]={ +const unsigned char OC_IZIG_ZAG[64]={ 0, 1, 5, 6,14,15,27,28, 2, 4, 7,13,16,26,29,42, 3, 8,12,17,25,30,41,43, @@ -59,33 +58,13 @@ const int OC_IZIG_ZAG[64]={ 35,36,48,49,57,58,62,63 }; -/*The predictor frame to use for each macro block mode.*/ -const int OC_FRAME_FOR_MODE[8]={ - /*OC_MODE_INTER_NOMV*/ - OC_FRAME_PREV, - /*OC_MODE_INTRA*/ - OC_FRAME_SELF, - /*OC_MODE_INTER_MV*/ - OC_FRAME_PREV, - /*OC_MODE_INTER_MV_LAST*/ - OC_FRAME_PREV, - /*OC_MODE_INTER_MV_LAST2*/ - OC_FRAME_PREV, - /*OC_MODE_GOLDEN*/ - OC_FRAME_GOLD, - /*OC_MODE_GOLDEN_MV*/ - OC_FRAME_GOLD, - /*OC_MODE_INTER_MV_FOUR*/ - OC_FRAME_PREV, -}; - /*A map from physical macro block ordering to bitstream macro block ordering within a super block.*/ -const int OC_MB_MAP[2][2]={{0,3},{1,2}}; +const unsigned char OC_MB_MAP[2][2]={{0,3},{1,2}}; /*A list of the indices in the oc_mb.map array that can be valid for each of the various chroma decimation types.*/ -const int OC_MB_MAP_IDXS[TH_PF_NFORMATS][12]={ +const unsigned char OC_MB_MAP_IDXS[TH_PF_NFORMATS][12]={ {0,1,2,3,4,8}, {0,1,2,3,4,5,8,9}, {0,1,2,3,4,6,8,10}, @@ -94,13 +73,13 @@ const int OC_MB_MAP_IDXS[TH_PF_NFORMATS][12]={ /*The number of indices in the oc_mb.map array that can be valid for each of the various chroma decimation types.*/ -const int OC_MB_MAP_NIDXS[TH_PF_NFORMATS]={6,8,8,12}; +const unsigned char OC_MB_MAP_NIDXS[TH_PF_NFORMATS]={6,8,8,12}; /*The number of extra bits that are coded with each of the DCT tokens. Each DCT token has some fixed number of additional bits (possibly 0) stored after the token itself, containing, for example, coefficient magnitude, sign bits, etc.*/ -const int OC_DCT_TOKEN_EXTRA_BITS[TH_NDCT_TOKENS]={ +const unsigned char OC_DCT_TOKEN_EXTRA_BITS[TH_NDCT_TOKENS]={ 0,0,0,2,3,4,12,3,6, 0,0,0,0, 1,1,1,1,2,3,4,5,6,10, @@ -118,113 +97,10 @@ int oc_ilog(unsigned _v){ -/*Determines the number of blocks or coefficients to be skipped for a given - token value. - _token: The token value to skip. - _extra_bits: The extra bits attached to this token. - Return: A positive value indicates that number of coefficients are to be - skipped in the current block. - Otherwise, the negative of the return value indicates that number of - blocks are to be ended.*/ -typedef int (*oc_token_skip_func)(int _token,int _extra_bits); - -/*Handles the simple end of block tokens.*/ -static int oc_token_skip_eob(int _token,int _extra_bits){ - static const int NBLOCKS_ADJUST[OC_NDCT_EOB_TOKEN_MAX]={1,2,3,4,8,16,0}; - return -_extra_bits-NBLOCKS_ADJUST[_token]; -} - -/*The last EOB token has a special case, where an EOB run of size zero ends all - the remaining blocks in the frame.*/ -static int oc_token_skip_eob6(int _token,int _extra_bits){ - if(!_extra_bits)return -INT_MAX; - return -_extra_bits; -} - -/*Handles the pure zero run tokens.*/ -static int oc_token_skip_zrl(int _token,int _extra_bits){ - return _extra_bits+1; -} - -/*Handles a normal coefficient value token.*/ -static int oc_token_skip_val(void){ - return 1; -} - -/*Handles a category 1A zero run/coefficient value combo token.*/ -static int oc_token_skip_run_cat1a(int _token){ - return _token-OC_DCT_RUN_CAT1A+2; -} - -/*Handles category 1b and 2 zero run/coefficient value combo tokens.*/ -static int oc_token_skip_run(int _token,int _extra_bits){ - static const int NCOEFFS_ADJUST[OC_NDCT_RUN_MAX-OC_DCT_RUN_CAT1B]={ - 7,11,2,3 - }; - static const int NCOEFFS_MASK[OC_NDCT_RUN_MAX-OC_DCT_RUN_CAT1B]={ - 3,7,0,1 - }; - _token-=OC_DCT_RUN_CAT1B; - return (_extra_bits&NCOEFFS_MASK[_token])+NCOEFFS_ADJUST[_token]; -} - -/*A jump table for computing the number of coefficients or blocks to skip for - a given token value. - This reduces all the conditional branches, etc., needed to parse these token - values down to one indirect jump.*/ -static const oc_token_skip_func OC_TOKEN_SKIP_TABLE[TH_NDCT_TOKENS]={ - oc_token_skip_eob, - oc_token_skip_eob, - oc_token_skip_eob, - oc_token_skip_eob, - oc_token_skip_eob, - oc_token_skip_eob, - oc_token_skip_eob6, - oc_token_skip_zrl, - oc_token_skip_zrl, - (oc_token_skip_func)oc_token_skip_val, - (oc_token_skip_func)oc_token_skip_val, - (oc_token_skip_func)oc_token_skip_val, - (oc_token_skip_func)oc_token_skip_val, - (oc_token_skip_func)oc_token_skip_val, - (oc_token_skip_func)oc_token_skip_val, - (oc_token_skip_func)oc_token_skip_val, - (oc_token_skip_func)oc_token_skip_val, - (oc_token_skip_func)oc_token_skip_val, - (oc_token_skip_func)oc_token_skip_val, - (oc_token_skip_func)oc_token_skip_val, - (oc_token_skip_func)oc_token_skip_val, - (oc_token_skip_func)oc_token_skip_val, - (oc_token_skip_func)oc_token_skip_val, - (oc_token_skip_func)oc_token_skip_run_cat1a, - (oc_token_skip_func)oc_token_skip_run_cat1a, - (oc_token_skip_func)oc_token_skip_run_cat1a, - (oc_token_skip_func)oc_token_skip_run_cat1a, - (oc_token_skip_func)oc_token_skip_run_cat1a, - oc_token_skip_run, - oc_token_skip_run, - oc_token_skip_run, - oc_token_skip_run -}; - -/*Determines the number of blocks or coefficients to be skipped for a given - token value. - _token: The token value to skip. - _extra_bits: The extra bits attached to this token. - Return: A positive value indicates that number of coefficients are to be - skipped in the current block. - Otherwise, the negative of the return value indicates that number of - blocks are to be ended. - 0 will never be returned, so that at least one coefficient in one - block will always be decoded for every token.*/ -int oc_dct_token_skip(int _token,int _extra_bits){ - return (*OC_TOKEN_SKIP_TABLE[_token])(_token,_extra_bits); -} - - /*The function used to fill in the chroma plane motion vectors for a macro block when 4 different motion vectors are specified in the luma plane. - This version is for use with chroma decimated in the X and Y directions. + This version is for use with chroma decimated in the X and Y directions + (4:2:0). _cbmvs: The chroma block-level motion vectors to fill in. _lbmvs: The luma block-level motion vectors.*/ static void oc_set_chroma_mvs00(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){ @@ -256,7 +132,7 @@ static void oc_set_chroma_mvs01(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){ /*The function used to fill in the chroma plane motion vectors for a macro block when 4 different motion vectors are specified in the luma plane. - This version is for use with chroma decimated in the X direction. + This version is for use with chroma decimated in the X direction (4:2:2). _cbmvs: The chroma block-level motion vectors to fill in. _lbmvs: The luma block-level motion vectors.*/ static void oc_set_chroma_mvs10(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){ @@ -274,7 +150,7 @@ static void oc_set_chroma_mvs10(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){ /*The function used to fill in the chroma plane motion vectors for a macro block when 4 different motion vectors are specified in the luma plane. - This version is for use with no chroma decimation. + This version is for use with no chroma decimation (4:4:4). _cbmvs: The chroma block-level motion vectors to fill in. _lmbmv: The luma macro-block level motion vector to fill in for use in prediction. @@ -305,6 +181,7 @@ void **oc_malloc_2d(size_t _height,size_t _width,size_t _sz){ datsz=rowsz*_height; /*Alloc array and row pointers.*/ ret=(char *)_ogg_malloc(datsz+colsz); + if(ret==NULL)return NULL; /*Initialize the array.*/ if(ret!=NULL){ size_t i; @@ -327,6 +204,7 @@ void **oc_calloc_2d(size_t _height,size_t _width,size_t _sz){ datsz=rowsz*_height; /*Alloc array and row pointers.*/ ret=(char *)_ogg_calloc(datsz+colsz,1); + if(ret==NULL)return NULL; /*Initialize the array.*/ if(ret!=NULL){ size_t i; @@ -355,7 +233,8 @@ void oc_ycbcr_buffer_flip(th_ycbcr_buffer _dst, _dst[pli].width=_src[pli].width; _dst[pli].height=_src[pli].height; _dst[pli].stride=-_src[pli].stride; - _dst[pli].data=_src[pli].data+(1-_dst[pli].height)*_dst[pli].stride; + _dst[pli].data=_src[pli].data + +(1-_dst[pli].height)*(ptrdiff_t)_dst[pli].stride; } } @@ -364,7 +243,7 @@ const char *th_version_string(void){ } ogg_uint32_t th_version_number(void){ - return (TH_VERSION_MAJOR<<16)+(TH_VERSION_MINOR<<8)+(TH_VERSION_SUB); + return (TH_VERSION_MAJOR<<16)+(TH_VERSION_MINOR<<8)+TH_VERSION_SUB; } /*Determines the packet type. diff --git a/Engine/lib/libtheora/lib/internal.h b/Engine/lib/libtheora/lib/internal.h index 0413a355a..d81263e13 100644 --- a/Engine/lib/libtheora/lib/internal.h +++ b/Engine/lib/libtheora/lib/internal.h @@ -5,36 +5,74 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: internal.h 15469 2008-10-30 12:49:42Z tterribe $ + last mod: $Id: internal.h 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ - #if !defined(_internal_H) # define _internal_H (1) # include +# include # if defined(HAVE_CONFIG_H) # include # endif # include "theora/codec.h" # include "theora/theora.h" -# include "dec/ocintrin.h" -# include "dec/huffman.h" -# include "dec/quant.h" -/*Thank you Microsoft, I know the order of operations.*/ # if defined(_MSC_VER) -# pragma warning(disable:4554) /* order of operations */ -# pragma warning(disable:4799) /* disable missing EMMS warnings */ +/*Disable missing EMMS warnings.*/ +# pragma warning(disable:4799) +/*Thank you Microsoft, I know the order of operations.*/ +# pragma warning(disable:4554) +# endif +/*You, too, gcc.*/ +# if defined(__GNUC_PREREQ) +# if __GNUC_PREREQ(4,2) +# pragma GCC diagnostic ignored "-Wparentheses" +# endif # endif +# include "ocintrin.h" +# include "huffman.h" +# include "quant.h" + +/*Some assembly constructs require aligned operands.*/ +# if defined(OC_X86_ASM) +# if defined(__GNUC__) +# define OC_ALIGN8(expr) expr __attribute__((aligned(8))) +# define OC_ALIGN16(expr) expr __attribute__((aligned(16))) +# elif defined(_MSC_VER) +# define OC_ALIGN8(expr) __declspec (align(8)) expr +# define OC_ALIGN16(expr) __declspec (align(16)) expr +# endif +# endif +# if !defined(OC_ALIGN8) +# define OC_ALIGN8(expr) expr +# endif +# if !defined(OC_ALIGN16) +# define OC_ALIGN16(expr) expr +# endif + + + +typedef struct oc_sb_flags oc_sb_flags; +typedef struct oc_border_info oc_border_info; +typedef struct oc_fragment oc_fragment; +typedef struct oc_fragment_plane oc_fragment_plane; +typedef struct oc_base_opt_vtable oc_base_opt_vtable; +typedef struct oc_base_opt_data oc_base_opt_data; +typedef struct oc_state_dispatch_vtable oc_state_dispatch_vtable; +typedef struct oc_theora_state oc_theora_state; + + + /*This library's version.*/ -# define OC_VENDOR_STRING "Xiph.Org libTheora I 20081020 3 2 1" +# define OC_VENDOR_STRING "Xiph.Org libtheora 1.1 20090822 (Thusnelda)" /*Theora bitstream version.*/ # define TH_VERSION_MAJOR (3) @@ -97,18 +135,10 @@ /*The number of (coded) modes.*/ #define OC_NMODES (8) -/*Macro block is not coded.*/ -#define OC_MODE_NOT_CODED (8) - -/*Predictor bit flags.*/ -/*Left.*/ -#define OC_PL (1) -/*Upper-left.*/ -#define OC_PUL (2) -/*Up.*/ -#define OC_PU (4) -/*Upper-right.*/ -#define OC_PUR (8) +/*Determines the reference frame used for a given MB mode.*/ +#define OC_FRAME_FOR_MODE(_x) \ + OC_UNIBBLE_TABLE32(OC_FRAME_PREV,OC_FRAME_SELF,OC_FRAME_PREV,OC_FRAME_PREV, \ + OC_FRAME_PREV,OC_FRAME_GOLD,OC_FRAME_GOLD,OC_FRAME_PREV,(_x)) /*Constants for the packet state machine common between encoder and decoder.*/ @@ -123,21 +153,7 @@ -typedef struct oc_theora_state oc_theora_state; - - - -/*A map from a super block to fragment numbers.*/ -typedef int oc_sb_map[4][4]; -/*A map from a macro block to fragment numbers.*/ -typedef int oc_mb_map[3][4]; -/*A motion vector.*/ -typedef signed char oc_mv[2]; - - - -/*Super block information. - Super blocks are 32x32 segments of pixels in a single color plane indexed +/*Super blocks are 32x32 segments of pixels in a single color plane indexed in image order. Internally, super blocks are broken up into four quadrants, each of which contains a 2x2 pattern of blocks, each of which is an 8x8 block of pixels. @@ -148,194 +164,201 @@ typedef signed char oc_mv[2]; the regular image order indexing strategy, blocks indexed in image order are called "fragments". Fragments are indexed in image order, left to right, then bottom to top, - from Y plane to Cb plane to Cr plane.*/ -typedef struct{ - unsigned coded_fully:1; - unsigned coded_partially:1; - unsigned quad_valid:4; - oc_sb_map map; -}oc_sb; + from Y' plane to Cb plane to Cr plane. - - -/*Macro block information. - The co-located fragments in all image planes corresponding to the location of - a single luma plane super block quadrant forms a macro block. - Thus there is only a single set of macro blocks for all planes, which + The co-located fragments in all image planes corresponding to the location + of a single quadrant of a luma plane super block form a macro block. + Thus there is only a single set of macro blocks for all planes, each of which contains between 6 and 12 fragments, depending on the pixel format. - Therefore macro block information is kept in a separate array from super - blocks, to avoid unused space in the other planes.*/ -typedef struct{ - /*The current macro block mode. - A negative number indicates the macro block lies entirely outside the - coded frame.*/ - int mode; - /*The X location of the macro block's upper-left hand pixel.*/ - int x; - /*The Y location of the macro block's upper-right hand pixel.*/ - int y; - /*The fragments that belong to this macro block in each color plane. - Fragments are stored in image order (left to right then top to bottom). - When chroma components are decimated, the extra fragments have an index of - -1.*/ - oc_mb_map map; -}oc_mb; + Therefore macro block information is kept in a separate set of arrays from + super blocks to avoid unused space in the other planes. + The lists are indexed in super block order. + That is, the macro block corresponding to the macro block mbi in (luma plane) + super block sbi is at index (sbi<<2|mbi). + Thus the number of macro blocks in each dimension is always twice the number + of super blocks, even when only an odd number fall inside the coded frame. + These "extra" macro blocks are just an artifact of our internal data layout, + and not part of the coded stream; they are flagged with a negative MB mode.*/ + + + +/*A single quadrant of the map from a super block to fragment numbers.*/ +typedef ptrdiff_t oc_sb_map_quad[4]; +/*A map from a super block to fragment numbers.*/ +typedef oc_sb_map_quad oc_sb_map[4]; +/*A single plane of the map from a macro block to fragment numbers.*/ +typedef ptrdiff_t oc_mb_map_plane[4]; +/*A map from a macro block to fragment numbers.*/ +typedef oc_mb_map_plane oc_mb_map[3]; +/*A motion vector.*/ +typedef signed char oc_mv[2]; + + + +/*Super block information.*/ +struct oc_sb_flags{ + unsigned char coded_fully:1; + unsigned char coded_partially:1; + unsigned char quad_valid:4; +}; /*Information about a fragment which intersects the border of the displayable region. - This marks which pixels belong to the displayable region, and is used to - ensure that pixels outside of this region are never referenced. - This allows applications to pass in buffers that are really the size of the - displayable region without causing a seg fault.*/ -typedef struct{ + This marks which pixels belong to the displayable region.*/ +struct oc_border_info{ /*A bit mask marking which pixels are in the displayable region. Pixel (x,y) corresponds to bit (y<<3|x).*/ ogg_int64_t mask; /*The number of pixels in the displayable region. This is always positive, and always less than 64.*/ int npixels; -}oc_border_info; +}; /*Fragment information.*/ -typedef struct{ +struct oc_fragment{ /*A flag indicating whether or not this fragment is coded.*/ - unsigned coded:1; - /*A flag indicating that all of this fragment lies outside the displayable + unsigned coded:1; + /*A flag indicating that this entire fragment lies outside the displayable region of the frame. Note the contrast with an invalid macro block, which is outside the coded - frame, not just the displayable one.*/ - unsigned invalid:1; - /*The quality index used for this fragment's AC coefficients.*/ - unsigned qi:6; - /*The mode of the macroblock this fragment belongs to. + frame, not just the displayable one. + There are no fragments outside the coded frame by construction.*/ + unsigned invalid:1; + /*The index of the quality index used for this fragment's AC coefficients.*/ + unsigned qii:6; + /*The mode of the macroblock this fragment belongs to.*/ + unsigned mb_mode:3; + /*The index of the associated border information for fragments which lie + partially outside the displayable region. + For fragments completely inside or outside this region, this is -1. Note that the C standard requires an explicit signed keyword for bitfield types, since some compilers may treat them as unsigned without it.*/ - signed int mbmode:8; + signed int borderi:5; /*The prediction-corrected DC component. Note that the C standard requires an explicit signed keyword for bitfield types, since some compilers may treat them as unsigned without it.*/ - signed int dc:16; - /*A pointer to the portion of an image covered by this fragment in several - images. - The first three are reconstructed frame buffers, while the last is the - input image buffer. - The appropriate stride value is determined by the color plane the fragment - belongs in.*/ - unsigned char *buffer[4]; - /*Information for fragments which lie partially outside the displayable - region. - For fragments completely inside or outside this region, this is NULL.*/ - oc_border_info *border; - /*The motion vector used for this fragment.*/ - oc_mv mv; -}oc_fragment; + signed int dc:16; +}; /*A description of each fragment plane.*/ -typedef struct{ +struct oc_fragment_plane{ /*The number of fragments in the horizontal direction.*/ - int nhfrags; + int nhfrags; /*The number of fragments in the vertical direction.*/ - int nvfrags; + int nvfrags; /*The offset of the first fragment in the plane.*/ - int froffset; + ptrdiff_t froffset; /*The total number of fragments in the plane.*/ - int nfrags; + ptrdiff_t nfrags; /*The number of super blocks in the horizontal direction.*/ - int nhsbs; + unsigned nhsbs; /*The number of super blocks in the vertical direction.*/ - int nvsbs; + unsigned nvsbs; /*The offset of the first super block in the plane.*/ - int sboffset; + unsigned sboffset; /*The total number of super blocks in the plane.*/ - int nsbs; -}oc_fragment_plane; + unsigned nsbs; +}; /*The shared (encoder and decoder) functions that have accelerated variants.*/ -typedef struct{ - void (*frag_recon_intra)(unsigned char *_dst,int _dst_ystride, - const ogg_int16_t *_residue); - void (*frag_recon_inter)(unsigned char *_dst,int _dst_ystride, - const unsigned char *_src,int _src_ystride,const ogg_int16_t *_residue); - void (*frag_recon_inter2)(unsigned char *_dst,int _dst_ystride, - const unsigned char *_src1,int _src1_ystride,const unsigned char *_src2, - int _src2_ystride,const ogg_int16_t *_residue); - void (*state_frag_copy)(const oc_theora_state *_state, - const int *_fragis,int _nfragis,int _dst_frame,int _src_frame,int _pli); - void (*state_frag_recon)(oc_theora_state *_state,oc_fragment *_frag, - int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,int _ncoefs, - ogg_uint16_t _dc_iquant,const ogg_uint16_t _ac_iquant[64]); +struct oc_base_opt_vtable{ + void (*frag_copy)(unsigned char *_dst, + const unsigned char *_src,int _ystride); + void (*frag_recon_intra)(unsigned char *_dst,int _ystride, + const ogg_int16_t _residue[64]); + void (*frag_recon_inter)(unsigned char *_dst, + const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]); + void (*frag_recon_inter2)(unsigned char *_dst,const unsigned char *_src1, + const unsigned char *_src2,int _ystride,const ogg_int16_t _residue[64]); + void (*idct8x8)(ogg_int16_t _y[64],int _last_zzi); + void (*state_frag_recon)(const oc_theora_state *_state,ptrdiff_t _fragi, + int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant); + void (*state_frag_copy_list)(const oc_theora_state *_state, + const ptrdiff_t *_fragis,ptrdiff_t _nfragis, + int _dst_frame,int _src_frame,int _pli); + void (*state_loop_filter_frag_rows)(const oc_theora_state *_state, + int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end); void (*restore_fpu)(void); - void (*state_loop_filter_frag_rows)(oc_theora_state *_state,int *_bv, - int _refi,int _pli,int _fragy0,int _fragy_end); -}oc_base_opt_vtable; +}; + +/*The shared (encoder and decoder) tables that vary according to which variants + of the above functions are used.*/ +struct oc_base_opt_data{ + const unsigned char *dct_fzig_zag; +}; - -/*Common state information between the encoder and decoder.*/ +/*State information common to both the encoder and decoder.*/ struct oc_theora_state{ /*The stream information.*/ th_info info; /*Table for shared accelerated functions.*/ oc_base_opt_vtable opt_vtable; + /*Table for shared data used by accelerated functions.*/ + oc_base_opt_data opt_data; /*CPU flags to detect the presence of extended instruction sets.*/ ogg_uint32_t cpu_flags; /*The fragment plane descriptions.*/ oc_fragment_plane fplanes[3]; - /*The total number of fragments in a single frame.*/ - int nfrags; /*The list of fragments, indexed in image order.*/ oc_fragment *frags; + /*The the offset into the reference frame buffer to the upper-left pixel of + each fragment.*/ + ptrdiff_t *frag_buf_offs; + /*The motion vector for each fragment.*/ + oc_mv *frag_mvs; + /*The total number of fragments in a single frame.*/ + ptrdiff_t nfrags; + /*The list of super block maps, indexed in image order.*/ + oc_sb_map *sb_maps; + /*The list of super block flags, indexed in image order.*/ + oc_sb_flags *sb_flags; /*The total number of super blocks in a single frame.*/ - int nsbs; - /*The list of super blocks, indexed in image order.*/ - oc_sb *sbs; + unsigned nsbs; + /*The fragments from each color plane that belong to each macro block. + Fragments are stored in image order (left to right then top to bottom). + When chroma components are decimated, the extra fragments have an index of + -1.*/ + oc_mb_map *mb_maps; + /*The list of macro block modes. + A negative number indicates the macro block lies entirely outside the + coded frame.*/ + signed char *mb_modes; /*The number of macro blocks in the X direction.*/ - int nhmbs; + unsigned nhmbs; /*The number of macro blocks in the Y direction.*/ - int nvmbs; + unsigned nvmbs; /*The total number of macro blocks.*/ - int nmbs; - /*The list of macro blocks, indexed in super block order. - That is, the macro block corresponding to the macro block mbi in (luma - plane) super block sbi is (sbi<<2|mbi).*/ - oc_mb *mbs; - /*The list of coded fragments, in coded order.*/ - int *coded_fragis; + size_t nmbs; + /*The list of coded fragments, in coded order. + Uncoded fragments are stored in reverse order from the end of the list.*/ + ptrdiff_t *coded_fragis; /*The number of coded fragments in each plane.*/ - int ncoded_fragis[3]; - /*The list of uncoded fragments. - This just past the end of the list, which is in reverse order, and - uses the same block of allocated storage as the coded_fragis list.*/ - int *uncoded_fragis; - /*The number of uncoded fragments in each plane.*/ - int nuncoded_fragis[3]; - /*The list of coded macro blocks in the Y plane, in coded order.*/ - int *coded_mbis; - /*The number of coded macro blocks in the Y plane.*/ - int ncoded_mbis; - /*A copy of the image data used to fill the input pointers in each fragment. - If the data pointers or strides change, these input pointers must be - re-populated.*/ - th_ycbcr_buffer input; + ptrdiff_t ncoded_fragis[3]; + /*The total number of coded fragments.*/ + ptrdiff_t ntotal_coded_fragis; + /*The index of the buffers being used for each OC_FRAME_* reference frame.*/ + int ref_frame_idx[4]; + /*The actual buffers used for the previously decoded frames.*/ + th_ycbcr_buffer ref_frame_bufs[4]; + /*The storage for the reference frame buffers.*/ + unsigned char *ref_frame_data[4]; + /*The strides for each plane in the reference frames.*/ + int ref_ystride[3]; /*The number of unique border patterns.*/ int nborders; - /*The storage for the border info for all border fragments. - This data is pointed to from the appropriate fragments.*/ + /*The unique border patterns for all border fragments. + The borderi field of fragments which straddle the border indexes this + list.*/ oc_border_info borders[16]; - /*The index of the buffers being used for each OC_FRAME_* reference frame.*/ - int ref_frame_idx[3]; - /*The actual buffers used for the previously decoded frames.*/ - th_ycbcr_buffer ref_frame_bufs[3]; - /*The storage for the reference frame buffers.*/ - unsigned char *ref_frame_data; /*The frame number of the last keyframe.*/ ogg_int64_t keyframe_num; /*The frame number of the current frame.*/ @@ -343,14 +366,17 @@ struct oc_theora_state{ /*The granpos of the current frame.*/ ogg_int64_t granpos; /*The type of the current frame.*/ - int frame_type; - /*The quality indices of the current frame.*/ - int qis[3]; + unsigned char frame_type; + /*The bias to add to the frame count when computing granule positions.*/ + unsigned char granpos_bias; /*The number of quality indices used in the current frame.*/ - int nqis; - /*The dequantization tables.*/ - oc_quant_table *dequant_tables[2][3]; - oc_quant_tables dequant_table_data[2][3]; + unsigned char nqis; + /*The quality indices of the current frame.*/ + unsigned char qis[3]; + /*The dequantization tables, stored in zig-zag order, and indexed by + qi, pli, qti, and zzi.*/ + ogg_uint16_t *dequant_tables[64][3][2]; + OC_ALIGN16(oc_quant_table dequant_table_data[64][3][2]); /*Loop filter strength parameters.*/ unsigned char loop_filter_limits[64]; }; @@ -369,25 +395,20 @@ typedef void (*oc_set_chroma_mvs_func)(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]); /*A map from the index in the zig zag scan to the coefficient number in a - block. - The extra 64 entries send out of bounds indexes to index 64. - This is used to safely ignore invalid zero runs when decoding - coefficients.*/ -extern const int OC_FZIG_ZAG[128]; + block.*/ +extern const unsigned char OC_FZIG_ZAG[128]; /*A map from the coefficient number in a block to its index in the zig zag scan.*/ -extern const int OC_IZIG_ZAG[64]; -/*The predictor frame to use for each macro block mode.*/ -extern const int OC_FRAME_FOR_MODE[OC_NMODES]; +extern const unsigned char OC_IZIG_ZAG[64]; /*A map from physical macro block ordering to bitstream macro block ordering within a super block.*/ -extern const int OC_MB_MAP[2][2]; -/*A list of the indices in the oc_mb.map array that can be valid for each of +extern const unsigned char OC_MB_MAP[2][2]; +/*A list of the indices in the oc_mb_map array that can be valid for each of the various chroma decimation types.*/ -extern const int OC_MB_MAP_IDXS[TH_PF_NFORMATS][12]; -/*The number of indices in the oc_mb.map array that can be valid for each of +extern const unsigned char OC_MB_MAP_IDXS[TH_PF_NFORMATS][12]; +/*The number of indices in the oc_mb_map array that can be valid for each of the various chroma decimation types.*/ -extern const int OC_MB_MAP_NIDXS[TH_PF_NFORMATS]; +extern const unsigned char OC_MB_MAP_NIDXS[TH_PF_NFORMATS]; /*A table of functions used to fill in the Cb,Cr plane motion vectors for a macro block when 4 different motion vectors are specified in the luma plane.*/ @@ -403,12 +424,7 @@ void oc_free_2d(void *_ptr); void oc_ycbcr_buffer_flip(th_ycbcr_buffer _dst, const th_ycbcr_buffer _src); -int oc_dct_token_skip(int _token,int _extra_bits); - -int oc_frag_pred_dc(const oc_fragment *_frag, - const oc_fragment_plane *_fplane,int _x,int _y,int _pred_last[3]); - -int oc_state_init(oc_theora_state *_state,const th_info *_info); +int oc_state_init(oc_theora_state *_state,const th_info *_info,int _nrefs); void oc_state_clear(oc_theora_state *_state); void oc_state_vtable_init_c(oc_theora_state *_state); void oc_state_borders_fill_rows(oc_theora_state *_state,int _refi,int _pli, @@ -418,8 +434,8 @@ void oc_state_borders_fill(oc_theora_state *_state,int _refi); void oc_state_fill_buffer_ptrs(oc_theora_state *_state,int _buf_idx, th_ycbcr_buffer _img); int oc_state_mbi_for_pos(oc_theora_state *_state,int _mbx,int _mby); -int oc_state_get_mv_offsets(oc_theora_state *_state,int *_offsets, - int _dx,int _dy,int _ystride,int _pli); +int oc_state_get_mv_offsets(const oc_theora_state *_state,int _offsets[2], + int _pli,int _dx,int _dy); int oc_state_loop_filter_init(oc_theora_state *_state,int *_bv); void oc_state_loop_filter(oc_theora_state *_state,int _frame); @@ -429,39 +445,42 @@ int oc_state_dump_frame(const oc_theora_state *_state,int _frame, #endif /*Shared accelerated functions.*/ +void oc_frag_copy(const oc_theora_state *_state,unsigned char *_dst, + const unsigned char *_src,int _ystride); void oc_frag_recon_intra(const oc_theora_state *_state, - unsigned char *_dst,int _dst_ystride,const ogg_int16_t *_residue); -void oc_frag_recon_inter(const oc_theora_state *_state, - unsigned char *_dst,int _dst_ystride, - const unsigned char *_src,int _src_ystride,const ogg_int16_t *_residue); + unsigned char *_dst,int _dst_ystride,const ogg_int16_t _residue[64]); +void oc_frag_recon_inter(const oc_theora_state *_state,unsigned char *_dst, + const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]); void oc_frag_recon_inter2(const oc_theora_state *_state, - unsigned char *_dst,int _dst_ystride, - const unsigned char *_src1,int _src1_ystride,const unsigned char *_src2, - int _src2_ystride,const ogg_int16_t *_residue); -void oc_state_frag_copy(const oc_theora_state *_state,const int *_fragis, - int _nfragis,int _dst_frame,int _src_frame,int _pli); -void oc_state_frag_recon(oc_theora_state *_state,oc_fragment *_frag, - int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,int _ncoefs, - ogg_uint16_t _dc_iquant,const ogg_uint16_t _ac_iquant[64]); -void oc_state_loop_filter_frag_rows(oc_theora_state *_state,int *_bv, - int _refi,int _pli,int _fragy0,int _fragy_end); + unsigned char *_dst,const unsigned char *_src1,const unsigned char *_src2, + int _ystride,const ogg_int16_t _residue[64]); +void oc_idct8x8(const oc_theora_state *_state,ogg_int16_t _y[64],int _last_zzi); +void oc_state_frag_recon(const oc_theora_state *_state,ptrdiff_t _fragi, + int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant); +void oc_state_frag_copy_list(const oc_theora_state *_state, + const ptrdiff_t *_fragis,ptrdiff_t _nfragis, + int _dst_frame,int _src_frame,int _pli); +void oc_state_loop_filter_frag_rows(const oc_theora_state *_state, + int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end); void oc_restore_fpu(const oc_theora_state *_state); /*Default pure-C implementations.*/ +void oc_frag_copy_c(unsigned char *_dst, + const unsigned char *_src,int _src_ystride); void oc_frag_recon_intra_c(unsigned char *_dst,int _dst_ystride, - const ogg_int16_t *_residue); -void oc_frag_recon_inter_c(unsigned char *_dst,int _dst_ystride, - const unsigned char *_src,int _src_ystride,const ogg_int16_t *_residue); -void oc_frag_recon_inter2_c(unsigned char *_dst,int _dst_ystride, - const unsigned char *_src1,int _src1_ystride,const unsigned char *_src2, - int _src2_ystride,const ogg_int16_t *_residue); -void oc_state_frag_copy_c(const oc_theora_state *_state,const int *_fragis, - int _nfragis,int _dst_frame,int _src_frame,int _pli); -void oc_state_frag_recon_c(oc_theora_state *_state,oc_fragment *_frag, - int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,int _ncoefs, - ogg_uint16_t _dc_iquant,const ogg_uint16_t _ac_iquant[64]); -void oc_state_loop_filter_frag_rows_c(oc_theora_state *_state,int *_bv, - int _refi,int _pli,int _fragy0,int _fragy_end); + const ogg_int16_t _residue[64]); +void oc_frag_recon_inter_c(unsigned char *_dst, + const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]); +void oc_frag_recon_inter2_c(unsigned char *_dst,const unsigned char *_src1, + const unsigned char *_src2,int _ystride,const ogg_int16_t _residue[64]); +void oc_idct8x8_c(ogg_int16_t _y[64],int _last_zzi); +void oc_state_frag_recon_c(const oc_theora_state *_state,ptrdiff_t _fragi, + int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant); +void oc_state_frag_copy_list_c(const oc_theora_state *_state, + const ptrdiff_t *_fragis,ptrdiff_t _nfragis, + int _dst_frame,int _src_frame,int _pli); +void oc_state_loop_filter_frag_rows_c(const oc_theora_state *_state, + int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end); void oc_restore_fpu_c(void); /*We need a way to call a few encoder functions without introducing a link-time @@ -472,16 +491,15 @@ void oc_restore_fpu_c(void); We do a similar thing for the decoder in case we ever decide to split off a common base library.*/ typedef void (*oc_state_clear_func)(theora_state *_th); -typedef int (*oc_state_control_func)(theora_state *th,int req, - void *buf,size_t buf_sz); +typedef int (*oc_state_control_func)(theora_state *th,int _req, + void *_buf,size_t _buf_sz); typedef ogg_int64_t (*oc_state_granule_frame_func)(theora_state *_th, ogg_int64_t _granulepos); typedef double (*oc_state_granule_time_func)(theora_state *_th, ogg_int64_t _granulepos); -typedef struct oc_state_dispatch_vtbl oc_state_dispatch_vtbl; -struct oc_state_dispatch_vtbl{ +struct oc_state_dispatch_vtable{ oc_state_clear_func clear; oc_state_control_func control; oc_state_granule_frame_func granule_frame; diff --git a/Engine/lib/libtheora/lib/mathops.c b/Engine/lib/libtheora/lib/mathops.c new file mode 100644 index 000000000..d3fb90919 --- /dev/null +++ b/Engine/lib/libtheora/lib/mathops.c @@ -0,0 +1,296 @@ +#include "mathops.h" +#include + +/*The fastest fallback strategy for platforms with fast multiplication appears + to be based on de Bruijn sequences~\cite{LP98}. + Tests confirmed this to be true even on an ARM11, where it is actually faster + than using the native clz instruction. + Define OC_ILOG_NODEBRUIJN to use a simpler fallback on platforms where + multiplication or table lookups are too expensive. + + @UNPUBLISHED{LP98, + author="Charles E. Leiserson and Harald Prokop", + title="Using de {Bruijn} Sequences to Index a 1 in a Computer Word", + month=Jun, + year=1998, + note="\url{http://supertech.csail.mit.edu/papers/debruijn.pdf}" + }*/ +#if !defined(OC_ILOG_NODEBRUIJN)&& \ + !defined(OC_CLZ32)||!defined(OC_CLZ64)&&LONG_MAX<9223372036854775807LL +static const unsigned char OC_DEBRUIJN_IDX32[32]={ + 0, 1,28, 2,29,14,24, 3,30,22,20,15,25,17, 4, 8, + 31,27,13,23,21,19,16, 7,26,12,18, 6,11, 5,10, 9 +}; +#endif + +int oc_ilog32(ogg_uint32_t _v){ +#if defined(OC_CLZ32) + return (OC_CLZ32_OFFS-OC_CLZ32(_v))&-!!_v; +#else +/*On a Pentium M, this branchless version tested as the fastest version without + multiplications on 1,000,000,000 random 32-bit integers, edging out a + similar version with branches, and a 256-entry LUT version.*/ +# if defined(OC_ILOG_NODEBRUIJN) + int ret; + int m; + ret=_v>0; + m=(_v>0xFFFFU)<<4; + _v>>=m; + ret|=m; + m=(_v>0xFFU)<<3; + _v>>=m; + ret|=m; + m=(_v>0xFU)<<2; + _v>>=m; + ret|=m; + m=(_v>3)<<1; + _v>>=m; + ret|=m; + ret+=_v>1; + return ret; +/*This de Bruijn sequence version is faster if you have a fast multiplier.*/ +# else + int ret; + ret=_v>0; + _v|=_v>>1; + _v|=_v>>2; + _v|=_v>>4; + _v|=_v>>8; + _v|=_v>>16; + _v=(_v>>1)+1; + ret+=OC_DEBRUIJN_IDX32[_v*0x77CB531U>>27&0x1F]; + return ret; +# endif +#endif +} + +int oc_ilog64(ogg_int64_t _v){ +#if defined(OC_CLZ64) + return (OC_CLZ64_OFFS-OC_CLZ64(_v))&-!!_v; +#else +# if defined(OC_ILOG_NODEBRUIJN) + ogg_uint32_t v; + int ret; + int m; + ret=_v>0; + m=(_v>0xFFFFFFFFU)<<5; + v=(ogg_uint32_t)(_v>>m); + ret|=m; + m=(v>0xFFFFU)<<4; + v>>=m; + ret|=m; + m=(v>0xFFU)<<3; + v>>=m; + ret|=m; + m=(v>0xFU)<<2; + v>>=m; + ret|=m; + m=(v>3)<<1; + v>>=m; + ret|=m; + ret+=v>1; + return ret; +# else +/*If we don't have a 64-bit word, split it into two 32-bit halves.*/ +# if LONG_MAX<9223372036854775807LL + ogg_uint32_t v; + int ret; + int m; + ret=_v>0; + m=(_v>0xFFFFFFFFU)<<5; + v=(ogg_uint32_t)(_v>>m); + ret|=m; + v|=v>>1; + v|=v>>2; + v|=v>>4; + v|=v>>8; + v|=v>>16; + v=(v>>1)+1; + ret+=OC_DEBRUIJN_IDX32[v*0x77CB531U>>27&0x1F]; + return ret; +/*Otherwise do it in one 64-bit operation.*/ +# else + static const unsigned char OC_DEBRUIJN_IDX64[64]={ + 0, 1, 2, 7, 3,13, 8,19, 4,25,14,28, 9,34,20,40, + 5,17,26,38,15,46,29,48,10,31,35,54,21,50,41,57, + 63, 6,12,18,24,27,33,39,16,37,45,47,30,53,49,56, + 62,11,23,32,36,44,52,55,61,22,43,51,60,42,59,58 + }; + int ret; + ret=_v>0; + _v|=_v>>1; + _v|=_v>>2; + _v|=_v>>4; + _v|=_v>>8; + _v|=_v>>16; + _v|=_v>>32; + _v=(_v>>1)+1; + ret+=OC_DEBRUIJN_IDX64[_v*0x218A392CD3D5DBF>>58&0x3F]; + return ret; +# endif +# endif +#endif +} + +/*round(2**(62+i)*atanh(2**(-(i+1)))/log(2))*/ +static const ogg_int64_t OC_ATANH_LOG2[32]={ + 0x32B803473F7AD0F4LL,0x2F2A71BD4E25E916LL,0x2E68B244BB93BA06LL, + 0x2E39FB9198CE62E4LL,0x2E2E683F68565C8FLL,0x2E2B850BE2077FC1LL, + 0x2E2ACC58FE7B78DBLL,0x2E2A9E2DE52FD5F2LL,0x2E2A92A338D53EECLL, + 0x2E2A8FC08F5E19B6LL,0x2E2A8F07E51A485ELL,0x2E2A8ED9BA8AF388LL, + 0x2E2A8ECE2FE7384ALL,0x2E2A8ECB4D3E4B1ALL,0x2E2A8ECA94940FE8LL, + 0x2E2A8ECA6669811DLL,0x2E2A8ECA5ADEDD6ALL,0x2E2A8ECA57FC347ELL, + 0x2E2A8ECA57438A43LL,0x2E2A8ECA57155FB4LL,0x2E2A8ECA5709D510LL, + 0x2E2A8ECA5706F267LL,0x2E2A8ECA570639BDLL,0x2E2A8ECA57060B92LL, + 0x2E2A8ECA57060008LL,0x2E2A8ECA5705FD25LL,0x2E2A8ECA5705FC6CLL, + 0x2E2A8ECA5705FC3ELL,0x2E2A8ECA5705FC33LL,0x2E2A8ECA5705FC30LL, + 0x2E2A8ECA5705FC2FLL,0x2E2A8ECA5705FC2FLL +}; + +/*Computes the binary exponential of _z, a log base 2 in Q57 format.*/ +ogg_int64_t oc_bexp64(ogg_int64_t _z){ + ogg_int64_t w; + ogg_int64_t z; + int ipart; + ipart=(int)(_z>>57); + if(ipart<0)return 0; + if(ipart>=63)return 0x7FFFFFFFFFFFFFFFLL; + z=_z-OC_Q57(ipart); + if(z){ + ogg_int64_t mask; + long wlo; + int i; + /*C doesn't give us 64x64->128 muls, so we use CORDIC. + This is not particularly fast, but it's not being used in time-critical + code; it is very accurate.*/ + /*z is the fractional part of the log in Q62 format. + We need 1 bit of headroom since the magnitude can get larger than 1 + during the iteration, and a sign bit.*/ + z<<=5; + /*w is the exponential in Q61 format (since it also needs headroom and can + get as large as 2.0); we could get another bit if we dropped the sign, + but we'll recover that bit later anyway. + Ideally this should start out as + \lim_{n->\infty} 2^{61}/\product_{i=1}^n \sqrt{1-2^{-2i}} + but in order to guarantee convergence we have to repeat iterations 4, + 13 (=3*4+1), and 40 (=3*13+1, etc.), so it winds up somewhat larger.*/ + w=0x26A3D0E401DD846DLL; + for(i=0;;i++){ + mask=-(z<0); + w+=(w>>i+1)+mask^mask; + z-=OC_ATANH_LOG2[i]+mask^mask; + /*Repeat iteration 4.*/ + if(i>=3)break; + z<<=1; + } + for(;;i++){ + mask=-(z<0); + w+=(w>>i+1)+mask^mask; + z-=OC_ATANH_LOG2[i]+mask^mask; + /*Repeat iteration 13.*/ + if(i>=12)break; + z<<=1; + } + for(;i<32;i++){ + mask=-(z<0); + w+=(w>>i+1)+mask^mask; + z=z-(OC_ATANH_LOG2[i]+mask^mask)<<1; + } + wlo=0; + /*Skip the remaining iterations unless we really require that much + precision. + We could have bailed out earlier for smaller iparts, but that would + require initializing w from a table, as the limit doesn't converge to + 61-bit precision until n=30.*/ + if(ipart>30){ + /*For these iterations, we just update the low bits, as the high bits + can't possibly be affected. + OC_ATANH_LOG2 has also converged (it actually did so one iteration + earlier, but that's no reason for an extra special case).*/ + for(;;i++){ + mask=-(z<0); + wlo+=(w>>i)+mask^mask; + z-=OC_ATANH_LOG2[31]+mask^mask; + /*Repeat iteration 40.*/ + if(i>=39)break; + z<<=1; + } + for(;i<61;i++){ + mask=-(z<0); + wlo+=(w>>i)+mask^mask; + z=z-(OC_ATANH_LOG2[31]+mask^mask)<<1; + } + } + w=(w<<1)+wlo; + } + else w=(ogg_int64_t)1<<62; + if(ipart<62)w=(w>>61-ipart)+1>>1; + return w; +} + +/*Computes the binary logarithm of _w, returned in Q57 format.*/ +ogg_int64_t oc_blog64(ogg_int64_t _w){ + ogg_int64_t z; + int ipart; + if(_w<=0)return -1; + ipart=OC_ILOGNZ_64(_w)-1; + if(ipart>61)_w>>=ipart-61; + else _w<<=61-ipart; + z=0; + if(_w&_w-1){ + ogg_int64_t x; + ogg_int64_t y; + ogg_int64_t u; + ogg_int64_t mask; + int i; + /*C doesn't give us 64x64->128 muls, so we use CORDIC. + This is not particularly fast, but it's not being used in time-critical + code; it is very accurate.*/ + /*z is the fractional part of the log in Q61 format.*/ + /*x and y are the cosh() and sinh(), respectively, in Q61 format. + We are computing z=2*atanh(y/x)=2*atanh((_w-1)/(_w+1)).*/ + x=_w+((ogg_int64_t)1<<61); + y=_w-((ogg_int64_t)1<<61); + for(i=0;i<4;i++){ + mask=-(y<0); + z+=(OC_ATANH_LOG2[i]>>i)+mask^mask; + u=x>>i+1; + x-=(y>>i+1)+mask^mask; + y-=u+mask^mask; + } + /*Repeat iteration 4.*/ + for(i--;i<13;i++){ + mask=-(y<0); + z+=(OC_ATANH_LOG2[i]>>i)+mask^mask; + u=x>>i+1; + x-=(y>>i+1)+mask^mask; + y-=u+mask^mask; + } + /*Repeat iteration 13.*/ + for(i--;i<32;i++){ + mask=-(y<0); + z+=(OC_ATANH_LOG2[i]>>i)+mask^mask; + u=x>>i+1; + x-=(y>>i+1)+mask^mask; + y-=u+mask^mask; + } + /*OC_ATANH_LOG2 has converged.*/ + for(;i<40;i++){ + mask=-(y<0); + z+=(OC_ATANH_LOG2[31]>>i)+mask^mask; + u=x>>i+1; + x-=(y>>i+1)+mask^mask; + y-=u+mask^mask; + } + /*Repeat iteration 40.*/ + for(i--;i<62;i++){ + mask=-(y<0); + z+=(OC_ATANH_LOG2[31]>>i)+mask^mask; + u=x>>i+1; + x-=(y>>i+1)+mask^mask; + y-=u+mask^mask; + } + z=z+8>>4; + } + return OC_Q57(ipart)+z; +} diff --git a/Engine/lib/libtheora/lib/mathops.h b/Engine/lib/libtheora/lib/mathops.h new file mode 100644 index 000000000..efbc5377b --- /dev/null +++ b/Engine/lib/libtheora/lib/mathops.h @@ -0,0 +1,141 @@ +#if !defined(_mathops_H) +# define _mathops_H (1) +# include + +# ifdef __GNUC_PREREQ +# if __GNUC_PREREQ(3,4) +# include +/*Note the casts to (int) below: this prevents OC_CLZ{32|64}_OFFS from + "upgrading" the type of an entire expression to an (unsigned) size_t.*/ +# if INT_MAX>=2147483647 +# define OC_CLZ32_OFFS ((int)sizeof(unsigned)*CHAR_BIT) +# define OC_CLZ32(_x) (__builtin_clz(_x)) +# elif LONG_MAX>=2147483647L +# define OC_CLZ32_OFFS ((int)sizeof(unsigned long)*CHAR_BIT) +# define OC_CLZ32(_x) (__builtin_clzl(_x)) +# endif +# if INT_MAX>=9223372036854775807LL +# define OC_CLZ64_OFFS ((int)sizeof(unsigned)*CHAR_BIT) +# define OC_CLZ64(_x) (__builtin_clz(_x)) +# elif LONG_MAX>=9223372036854775807LL +# define OC_CLZ64_OFFS ((int)sizeof(unsigned long)*CHAR_BIT) +# define OC_CLZ64(_x) (__builtin_clzl(_x)) +# elif LLONG_MAX>=9223372036854775807LL|| \ + __LONG_LONG_MAX__>=9223372036854775807LL +# define OC_CLZ64_OFFS ((int)sizeof(unsigned long long)*CHAR_BIT) +# define OC_CLZ64(_x) (__builtin_clzll(_x)) +# endif +# endif +# endif + + + +/** + * oc_ilog32 - Integer binary logarithm of a 32-bit value. + * @_v: A 32-bit value. + * Returns floor(log2(_v))+1, or 0 if _v==0. + * This is the number of bits that would be required to represent _v in two's + * complement notation with all of the leading zeros stripped. + * The OC_ILOG_32() or OC_ILOGNZ_32() macros may be able to use a builtin + * function instead, which should be faster. + */ +int oc_ilog32(ogg_uint32_t _v); +/** + * oc_ilog64 - Integer binary logarithm of a 64-bit value. + * @_v: A 64-bit value. + * Returns floor(log2(_v))+1, or 0 if _v==0. + * This is the number of bits that would be required to represent _v in two's + * complement notation with all of the leading zeros stripped. + * The OC_ILOG_64() or OC_ILOGNZ_64() macros may be able to use a builtin + * function instead, which should be faster. + */ +int oc_ilog64(ogg_int64_t _v); + + +# if defined(OC_CLZ32) +/** + * OC_ILOGNZ_32 - Integer binary logarithm of a non-zero 32-bit value. + * @_v: A non-zero 32-bit value. + * Returns floor(log2(_v))+1. + * This is the number of bits that would be required to represent _v in two's + * complement notation with all of the leading zeros stripped. + * If _v is zero, the return value is undefined; use OC_ILOG_32() instead. + */ +# define OC_ILOGNZ_32(_v) (OC_CLZ32_OFFS-OC_CLZ32(_v)) +/** + * OC_ILOG_32 - Integer binary logarithm of a 32-bit value. + * @_v: A 32-bit value. + * Returns floor(log2(_v))+1, or 0 if _v==0. + * This is the number of bits that would be required to represent _v in two's + * complement notation with all of the leading zeros stripped. + */ +# define OC_ILOG_32(_v) (OC_ILOGNZ_32(_v)&-!!(_v)) +# else +# define OC_ILOGNZ_32(_v) (oc_ilog32(_v)) +# define OC_ILOG_32(_v) (oc_ilog32(_v)) +# endif + +# if defined(CLZ64) +/** + * OC_ILOGNZ_64 - Integer binary logarithm of a non-zero 64-bit value. + * @_v: A non-zero 64-bit value. + * Returns floor(log2(_v))+1. + * This is the number of bits that would be required to represent _v in two's + * complement notation with all of the leading zeros stripped. + * If _v is zero, the return value is undefined; use OC_ILOG_64() instead. + */ +# define OC_ILOGNZ_64(_v) (CLZ64_OFFS-CLZ64(_v)) +/** + * OC_ILOG_64 - Integer binary logarithm of a 64-bit value. + * @_v: A 64-bit value. + * Returns floor(log2(_v))+1, or 0 if _v==0. + * This is the number of bits that would be required to represent _v in two's + * complement notation with all of the leading zeros stripped. + */ +# define OC_ILOG_64(_v) (OC_ILOGNZ_64(_v)&-!!(_v)) +# else +# define OC_ILOGNZ_64(_v) (oc_ilog64(_v)) +# define OC_ILOG_64(_v) (oc_ilog64(_v)) +# endif + +# define OC_STATIC_ILOG0(_v) (!!(_v)) +# define OC_STATIC_ILOG1(_v) (((_v)&0x2)?2:OC_STATIC_ILOG0(_v)) +# define OC_STATIC_ILOG2(_v) \ + (((_v)&0xC)?2+OC_STATIC_ILOG1((_v)>>2):OC_STATIC_ILOG1(_v)) +# define OC_STATIC_ILOG3(_v) \ + (((_v)&0xF0)?4+OC_STATIC_ILOG2((_v)>>4):OC_STATIC_ILOG2(_v)) +# define OC_STATIC_ILOG4(_v) \ + (((_v)&0xFF00)?8+OC_STATIC_ILOG3((_v)>>8):OC_STATIC_ILOG3(_v)) +# define OC_STATIC_ILOG5(_v) \ + (((_v)&0xFFFF0000)?16+OC_STATIC_ILOG4((_v)>>16):OC_STATIC_ILOG4(_v)) +# define OC_STATIC_ILOG6(_v) \ + (((_v)&0xFFFFFFFF00000000ULL)?32+OC_STATIC_ILOG5((_v)>>32):OC_STATIC_ILOG5(_v)) +/** + * OC_STATIC_ILOG_32 - The integer logarithm of an (unsigned, 32-bit) constant. + * @_v: A non-negative 32-bit constant. + * Returns floor(log2(_v))+1, or 0 if _v==0. + * This is the number of bits that would be required to represent _v in two's + * complement notation with all of the leading zeros stripped. + * This macro is suitable for evaluation at compile time, but it should not be + * used on values that can change at runtime, as it operates via exhaustive + * search. + */ +# define OC_STATIC_ILOG_32(_v) (OC_STATIC_ILOG5((ogg_uint32_t)(_v))) +/** + * OC_STATIC_ILOG_64 - The integer logarithm of an (unsigned, 64-bit) constant. + * @_v: A non-negative 64-bit constant. + * Returns floor(log2(_v))+1, or 0 if _v==0. + * This is the number of bits that would be required to represent _v in two's + * complement notation with all of the leading zeros stripped. + * This macro is suitable for evaluation at compile time, but it should not be + * used on values that can change at runtime, as it operates via exhaustive + * search. + */ +# define OC_STATIC_ILOG_64(_v) (OC_STATIC_ILOG6((ogg_int64_t)(_v))) + +#define OC_Q57(_v) ((ogg_int64_t)(_v)<<57) + +ogg_int64_t oc_bexp64(ogg_int64_t _z); +ogg_int64_t oc_blog64(ogg_int64_t _w); + +#endif diff --git a/Engine/lib/libtheora/lib/mcenc.c b/Engine/lib/libtheora/lib/mcenc.c new file mode 100644 index 000000000..797e81f4f --- /dev/null +++ b/Engine/lib/libtheora/lib/mcenc.c @@ -0,0 +1,767 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id$ + + ********************************************************************/ +#include +#include +#include +#include "encint.h" + + + +typedef struct oc_mcenc_ctx oc_mcenc_ctx; + + + +/*Temporary state used for motion estimation.*/ +struct oc_mcenc_ctx{ + /*The candidate motion vectors.*/ + int candidates[13][2]; + /*The start of the Set B candidates.*/ + int setb0; + /*The total number of candidates.*/ + int ncandidates; +}; + + + +/*The maximum Y plane SAD value for accepting the median predictor.*/ +#define OC_YSAD_THRESH1 (256) +/*The amount to right shift the minimum error by when inflating it for + computing the second maximum Y plane SAD threshold.*/ +#define OC_YSAD_THRESH2_SCALE_BITS (4) +/*The amount to add to the second maximum Y plane threshold when inflating + it.*/ +#define OC_YSAD_THRESH2_OFFSET (64) + +/*The vector offsets in the X direction for each search site in the square + pattern.*/ +static const int OC_SQUARE_DX[9]={-1,0,1,-1,0,1,-1,0,1}; +/*The vector offsets in the Y direction for each search site in the square + pattern.*/ +static const int OC_SQUARE_DY[9]={-1,-1,-1,0,0,0,1,1,1}; +/*The number of sites to search for each boundary condition in the square + pattern. + Bit flags for the boundary conditions are as follows: + 1: -16==dx + 2: dx==15(.5) + 4: -16==dy + 8: dy==15(.5)*/ +static const int OC_SQUARE_NSITES[11]={8,5,5,0,5,3,3,0,5,3,3}; +/*The list of sites to search for each boundary condition in the square + pattern.*/ +static const int OC_SQUARE_SITES[11][8]={ + /* -15.5mb_info; + /*Skip a position to store the median predictor in.*/ + ncandidates=1; + if(embs[_mbi].ncneighbors>0){ + /*Fill in the first part of set A: the vectors from adjacent blocks.*/ + for(i=0;icandidates[ncandidates][0]=embs[nmbi].analysis_mv[0][_frame][0]; + _mcenc->candidates[ncandidates][1]=embs[nmbi].analysis_mv[0][_frame][1]; + ncandidates++; + } + } + /*Add a few additional vectors to set A: the vectors used in the previous + frames and the (0,0) vector.*/ + _mcenc->candidates[ncandidates][0]=OC_CLAMPI(-31,_accum[0],31); + _mcenc->candidates[ncandidates][1]=OC_CLAMPI(-31,_accum[1],31); + ncandidates++; + _mcenc->candidates[ncandidates][0]=OC_CLAMPI(-31, + embs[_mbi].analysis_mv[1][_frame][0]+_accum[0],31); + _mcenc->candidates[ncandidates][1]=OC_CLAMPI(-31, + embs[_mbi].analysis_mv[1][_frame][1]+_accum[1],31); + ncandidates++; + _mcenc->candidates[ncandidates][0]=0; + _mcenc->candidates[ncandidates][1]=0; + ncandidates++; + /*Use the first three vectors of set A to find our best predictor: their + median.*/ + memcpy(a,_mcenc->candidates+1,sizeof(a)); + OC_SORT2I(a[0][0],a[1][0]); + OC_SORT2I(a[0][1],a[1][1]); + OC_SORT2I(a[1][0],a[2][0]); + OC_SORT2I(a[1][1],a[2][1]); + OC_SORT2I(a[0][0],a[1][0]); + OC_SORT2I(a[0][1],a[1][1]); + _mcenc->candidates[0][0]=a[1][0]; + _mcenc->candidates[0][1]=a[1][1]; + /*Fill in set B: accelerated predictors for this and adjacent macro blocks.*/ + _mcenc->setb0=ncandidates; + /*The first time through the loop use the current macro block.*/ + nmbi=_mbi; + for(i=0;;i++){ + _mcenc->candidates[ncandidates][0]=OC_CLAMPI(-31, + 2*embs[_mbi].analysis_mv[1][_frame][0] + -embs[_mbi].analysis_mv[2][_frame][0]+_accum[0],31); + _mcenc->candidates[ncandidates][1]=OC_CLAMPI(-31, + 2*embs[_mbi].analysis_mv[1][_frame][1] + -embs[_mbi].analysis_mv[2][_frame][1]+_accum[1],31); + ncandidates++; + if(i>=embs[_mbi].npneighbors)break; + nmbi=embs[_mbi].pneighbors[i]; + } + /*Truncate to full-pel positions.*/ + for(i=0;icandidates[i][0]=OC_DIV2(_mcenc->candidates[i][0]); + _mcenc->candidates[i][1]=OC_DIV2(_mcenc->candidates[i][1]); + } + _mcenc->ncandidates=ncandidates; +} + +#if 0 +static unsigned oc_sad16_halfpel(const oc_enc_ctx *_enc, + const ptrdiff_t *_frag_buf_offs,const ptrdiff_t _fragis[4], + int _mvoffset0,int _mvoffset1,const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _best_err){ + unsigned err; + int bi; + err=0; + for(bi=0;bi<4;bi++){ + ptrdiff_t frag_offs; + frag_offs=_frag_buf_offs[_fragis[bi]]; + err+=oc_enc_frag_sad2_thresh(_enc,_src+frag_offs,_ref+frag_offs+_mvoffset0, + _ref+frag_offs+_mvoffset1,_ystride,_best_err-err); + } + return err; +} +#endif + +static unsigned oc_satd16_halfpel(const oc_enc_ctx *_enc, + const ptrdiff_t *_frag_buf_offs,const ptrdiff_t _fragis[4], + int _mvoffset0,int _mvoffset1,const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _best_err){ + unsigned err; + int bi; + err=0; + for(bi=0;bi<4;bi++){ + ptrdiff_t frag_offs; + frag_offs=_frag_buf_offs[_fragis[bi]]; + err+=oc_enc_frag_satd2_thresh(_enc,_src+frag_offs,_ref+frag_offs+_mvoffset0, + _ref+frag_offs+_mvoffset1,_ystride,_best_err-err); + } + return err; +} + +static unsigned oc_mcenc_ysad_check_mbcandidate_fullpel(const oc_enc_ctx *_enc, + const ptrdiff_t *_frag_buf_offs,const ptrdiff_t _fragis[4],int _dx,int _dy, + const unsigned char *_src,const unsigned char *_ref,int _ystride, + unsigned _block_err[4]){ + unsigned err; + int mvoffset; + int bi; + mvoffset=_dx+_dy*_ystride; + err=0; + for(bi=0;bi<4;bi++){ + ptrdiff_t frag_offs; + unsigned block_err; + frag_offs=_frag_buf_offs[_fragis[bi]]; + block_err=oc_enc_frag_sad(_enc, + _src+frag_offs,_ref+frag_offs+mvoffset,_ystride); + _block_err[bi]=block_err; + err+=block_err; + } + return err; +} + +static int oc_mcenc_ysatd_check_mbcandidate_fullpel(const oc_enc_ctx *_enc, + const ptrdiff_t *_frag_buf_offs,const ptrdiff_t _fragis[4],int _dx,int _dy, + const unsigned char *_src,const unsigned char *_ref,int _ystride){ + int mvoffset; + int err; + int bi; + mvoffset=_dx+_dy*_ystride; + err=0; + for(bi=0;bi<4;bi++){ + ptrdiff_t frag_offs; + frag_offs=_frag_buf_offs[_fragis[bi]]; + err+=oc_enc_frag_satd_thresh(_enc, + _src+frag_offs,_ref+frag_offs+mvoffset,_ystride,UINT_MAX); + } + return err; +} + +static unsigned oc_mcenc_ysatd_check_bcandidate_fullpel(const oc_enc_ctx *_enc, + ptrdiff_t _frag_offs,int _dx,int _dy, + const unsigned char *_src,const unsigned char *_ref,int _ystride){ + return oc_enc_frag_satd_thresh(_enc, + _src+_frag_offs,_ref+_frag_offs+_dx+_dy*_ystride,_ystride,UINT_MAX); +} + +/*Perform a motion vector search for this macro block against a single + reference frame. + As a bonus, individual block motion vectors are computed as well, as much of + the work can be shared. + The actual motion vector is stored in the appropriate place in the + oc_mb_enc_info structure. + _mcenc: The motion compensation context. + _accum: Drop frame/golden MV accumulators. + _mbi: The macro block index. + _frame: The frame to search, either OC_FRAME_PREV or OC_FRAME_GOLD.*/ +void oc_mcenc_search_frame(oc_enc_ctx *_enc,int _accum[2],int _mbi,int _frame){ + /*Note: Traditionally this search is done using a rate-distortion objective + function of the form D+lambda*R. + However, xiphmont tested this and found it produced a small degredation, + while requiring extra computation. + This is most likely due to Theora's peculiar MV encoding scheme: MVs are + not coded relative to a predictor, and the only truly cheap way to use a + MV is in the LAST or LAST2 MB modes, which are not being considered here. + Therefore if we use the MV found here, it's only because both LAST and + LAST2 performed poorly, and therefore the MB is not likely to be uniform + or suffer from the aperture problem. + Furthermore we would like to re-use the MV found here for as many MBs as + possible, so picking a slightly sub-optimal vector to save a bit or two + may cause increased degredation in many blocks to come. + We could artificially reduce lambda to compensate, but it's faster to just + disable it entirely, and use D (the distortion) as the sole criterion.*/ + oc_mcenc_ctx mcenc; + const ptrdiff_t *frag_buf_offs; + const ptrdiff_t *fragis; + const unsigned char *src; + const unsigned char *ref; + int ystride; + oc_mb_enc_info *embs; + ogg_int32_t hit_cache[31]; + ogg_int32_t hitbit; + unsigned best_block_err[4]; + unsigned block_err[4]; + unsigned best_err; + int best_vec[2]; + int best_block_vec[4][2]; + int candx; + int candy; + int bi; + embs=_enc->mb_info; + /*Find some candidate motion vectors.*/ + oc_mcenc_find_candidates(_enc,&mcenc,_accum,_mbi,_frame); + /*Clear the cache of locations we've examined.*/ + memset(hit_cache,0,sizeof(hit_cache)); + /*Start with the median predictor.*/ + candx=mcenc.candidates[0][0]; + candy=mcenc.candidates[0][1]; + hit_cache[candy+15]|=(ogg_int32_t)1<state.frag_buf_offs; + fragis=_enc->state.mb_maps[_mbi][0]; + src=_enc->state.ref_frame_data[OC_FRAME_IO]; + ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[_frame]]; + ystride=_enc->state.ref_ystride[0]; + /*TODO: customize error function for speed/(quality+size) tradeoff.*/ + best_err=oc_mcenc_ysad_check_mbcandidate_fullpel(_enc, + frag_buf_offs,fragis,candx,candy,src,ref,ystride,block_err); + best_vec[0]=candx; + best_vec[1]=candy; + if(_frame==OC_FRAME_PREV){ + for(bi=0;bi<4;bi++){ + best_block_err[bi]=block_err[bi]; + best_block_vec[bi][0]=candx; + best_block_vec[bi][1]=candy; + } + } + /*If this predictor fails, move on to set A.*/ + if(best_err>OC_YSAD_THRESH1){ + unsigned err; + unsigned t2; + int ncs; + int ci; + /*Compute the early termination threshold for set A.*/ + t2=embs[_mbi].error[_frame]; + ncs=OC_MINI(3,embs[_mbi].ncneighbors); + for(ci=0;ci>OC_YSAD_THRESH2_SCALE_BITS)+OC_YSAD_THRESH2_OFFSET; + /*Examine the candidates in set A.*/ + for(ci=1;cit2){ + /*Examine the candidates in set B.*/ + for(;cit2){ + int best_site; + int nsites; + int sitei; + int site; + int b; + /*Square pattern search.*/ + for(;;){ + best_site=4; + /*Compose the bit flags for boundary conditions.*/ + b=OC_DIV16(-best_vec[0]+1)|OC_DIV16(best_vec[0]+1)<<1| + OC_DIV16(-best_vec[1]+1)<<2|OC_DIV16(best_vec[1]+1)<<3; + nsites=OC_SQUARE_NSITES[b]; + for(sitei=0;sitei>=2; + for(bi=0;bi<4;bi++){ + if(best_block_err[bi]>t2){ + /*Square pattern search. + We do this in a slightly interesting manner. + We continue to check the SAD of all four blocks in the + macro block. + This gives us two things: + 1) We can continue to use the hit_cache to avoid duplicate + checks. + Otherwise we could continue to read it, but not write to it + without saving and restoring it for each block. + Note that we could still eliminate a large number of + duplicate checks by taking into account the site we came + from when choosing the site list. + We can still do that to avoid extra hit_cache queries, and + it might even be a speed win. + 2) It gives us a slightly better chance of escaping local + minima. + We would not be here if we weren't doing a fairly bad job + in finding a good vector, and checking these vectors can + save us from 100 to several thousand points off our SAD 1 + in 15 times. + TODO: Is this a good idea? + Who knows. + It needs more testing.*/ + for(;;){ + int bestx; + int besty; + int bj; + bestx=best_block_vec[bi][0]; + besty=best_block_vec[bi][1]; + /*Compose the bit flags for boundary conditions.*/ + b=OC_DIV16(-bestx+1)|OC_DIV16(bestx+1)<<1| + OC_DIV16(-besty+1)<<2|OC_DIV16(besty+1)<<3; + nsites=OC_SQUARE_NSITES[b]; + for(sitei=0;siteimb_info[_mbi].analysis_mv; + if(_enc->prevframe_dropped){ + accum_p[0]=mvs[0][OC_FRAME_PREV][0]; + accum_p[1]=mvs[0][OC_FRAME_PREV][1]; + } + else accum_p[1]=accum_p[0]=0; + accum_g[0]=mvs[2][OC_FRAME_GOLD][0]; + accum_g[1]=mvs[2][OC_FRAME_GOLD][1]; + mvs[0][OC_FRAME_PREV][0]-=mvs[2][OC_FRAME_PREV][0]; + mvs[0][OC_FRAME_PREV][1]-=mvs[2][OC_FRAME_PREV][1]; + /*Move the motion vector predictors back a frame.*/ + memmove(mvs+1,mvs,2*sizeof(*mvs)); + /*Search the last frame.*/ + oc_mcenc_search_frame(_enc,accum_p,_mbi,OC_FRAME_PREV); + mvs[2][OC_FRAME_PREV][0]=accum_p[0]; + mvs[2][OC_FRAME_PREV][1]=accum_p[1]; + /*GOLDEN MVs are different from PREV MVs in that they're each absolute + offsets from some frame in the past rather than relative offsets from the + frame before. + For predictor calculation to make sense, we need them to be in the same + form as PREV MVs.*/ + mvs[1][OC_FRAME_GOLD][0]-=mvs[2][OC_FRAME_GOLD][0]; + mvs[1][OC_FRAME_GOLD][1]-=mvs[2][OC_FRAME_GOLD][1]; + mvs[2][OC_FRAME_GOLD][0]-=accum_g[0]; + mvs[2][OC_FRAME_GOLD][1]-=accum_g[1]; + /*Search the golden frame.*/ + oc_mcenc_search_frame(_enc,accum_g,_mbi,OC_FRAME_GOLD); + /*Put GOLDEN MVs back into absolute offset form. + The newest MV is already an absolute offset.*/ + mvs[2][OC_FRAME_GOLD][0]+=accum_g[0]; + mvs[2][OC_FRAME_GOLD][1]+=accum_g[1]; + mvs[1][OC_FRAME_GOLD][0]+=mvs[2][OC_FRAME_GOLD][0]; + mvs[1][OC_FRAME_GOLD][1]+=mvs[2][OC_FRAME_GOLD][1]; +} + +#if 0 +static int oc_mcenc_ysad_halfpel_mbrefine(const oc_enc_ctx *_enc,int _mbi, + int _vec[2],int _best_err,int _frame){ + const unsigned char *src; + const unsigned char *ref; + const ptrdiff_t *frag_buf_offs; + const ptrdiff_t *fragis; + int offset_y[9]; + int ystride; + int mvoffset_base; + int best_site; + int sitei; + int err; + src=_enc->state.ref_frame_data[OC_FRAME_IO]; + ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[_framei]]; + frag_buf_offs=_enc->state.frag_buf_offs; + fragis=_enc->state.mb_maps[_mbi][0]; + ystride=_enc->state.ref_ystride[0]; + mvoffset_base=_vec[0]+_vec[1]*ystride; + offset_y[0]=offset_y[1]=offset_y[2]=-ystride; + offset_y[3]=offset_y[5]=0; + offset_y[6]=offset_y[7]=offset_y[8]=ystride; + best_site=4; + for(sitei=0;sitei<8;sitei++){ + int site; + int xmask; + int ymask; + int dx; + int dy; + int mvoffset0; + int mvoffset1; + site=OC_SQUARE_SITES[0][sitei]; + dx=OC_SQUARE_DX[site]; + dy=OC_SQUARE_DY[site]; + /*The following code SHOULD be equivalent to + oc_state_get_mv_offsets(&_mcenc->enc.state,&mvoffset0,&mvoffset1, + (_vec[0]<<1)+dx,(_vec[1]<<1)+dy,ref_ystride,0); + However, it should also be much faster, as it involves no multiplies and + doesn't have to handle chroma vectors.*/ + xmask=OC_SIGNMASK(((_vec[0]<<1)+dx)^dx); + ymask=OC_SIGNMASK(((_vec[1]<<1)+dy)^dy); + mvoffset0=mvoffset_base+(dx&xmask)+(offset_y[site]&ymask); + mvoffset1=mvoffset_base+(dx&~xmask)+(offset_y[site]&~ymask); + err=oc_sad16_halfpel(_enc,frag_buf_offs,fragis, + mvoffset0,mvoffset1,src,ref,ystride,_best_err); + if(err<_best_err){ + _best_err=err; + best_site=site; + } + } + _vec[0]=(_vec[0]<<1)+OC_SQUARE_DX[best_site]; + _vec[1]=(_vec[1]<<1)+OC_SQUARE_DY[best_site]; + return _best_err; +} +#endif + +static unsigned oc_mcenc_ysatd_halfpel_mbrefine(const oc_enc_ctx *_enc, + int _mbi,int _vec[2],unsigned _best_err,int _frame){ + const unsigned char *src; + const unsigned char *ref; + const ptrdiff_t *frag_buf_offs; + const ptrdiff_t *fragis; + int offset_y[9]; + int ystride; + int mvoffset_base; + int best_site; + int sitei; + int err; + src=_enc->state.ref_frame_data[OC_FRAME_IO]; + ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[_frame]]; + frag_buf_offs=_enc->state.frag_buf_offs; + fragis=_enc->state.mb_maps[_mbi][0]; + ystride=_enc->state.ref_ystride[0]; + mvoffset_base=_vec[0]+_vec[1]*ystride; + offset_y[0]=offset_y[1]=offset_y[2]=-ystride; + offset_y[3]=offset_y[5]=0; + offset_y[6]=offset_y[7]=offset_y[8]=ystride; + best_site=4; + for(sitei=0;sitei<8;sitei++){ + int site; + int xmask; + int ymask; + int dx; + int dy; + int mvoffset0; + int mvoffset1; + site=OC_SQUARE_SITES[0][sitei]; + dx=OC_SQUARE_DX[site]; + dy=OC_SQUARE_DY[site]; + /*The following code SHOULD be equivalent to + oc_state_get_mv_offsets(&_mcenc->enc.state,&mvoffset0,&mvoffset1, + (_vec[0]<<1)+dx,(_vec[1]<<1)+dy,ref_ystride,0); + However, it should also be much faster, as it involves no multiplies and + doesn't have to handle chroma vectors.*/ + xmask=OC_SIGNMASK(((_vec[0]<<1)+dx)^dx); + ymask=OC_SIGNMASK(((_vec[1]<<1)+dy)^dy); + mvoffset0=mvoffset_base+(dx&xmask)+(offset_y[site]&ymask); + mvoffset1=mvoffset_base+(dx&~xmask)+(offset_y[site]&~ymask); + err=oc_satd16_halfpel(_enc,frag_buf_offs,fragis, + mvoffset0,mvoffset1,src,ref,ystride,_best_err); + if(err<_best_err){ + _best_err=err; + best_site=site; + } + } + _vec[0]=(_vec[0]<<1)+OC_SQUARE_DX[best_site]; + _vec[1]=(_vec[1]<<1)+OC_SQUARE_DY[best_site]; + return _best_err; +} + +void oc_mcenc_refine1mv(oc_enc_ctx *_enc,int _mbi,int _frame){ + oc_mb_enc_info *embs; + int vec[2]; + embs=_enc->mb_info; + vec[0]=OC_DIV2(embs[_mbi].analysis_mv[0][_frame][0]); + vec[1]=OC_DIV2(embs[_mbi].analysis_mv[0][_frame][1]); + embs[_mbi].satd[_frame]=oc_mcenc_ysatd_halfpel_mbrefine(_enc, + _mbi,vec,embs[_mbi].satd[_frame],_frame); + embs[_mbi].analysis_mv[0][_frame][0]=(signed char)vec[0]; + embs[_mbi].analysis_mv[0][_frame][1]=(signed char)vec[1]; +} + +#if 0 +static int oc_mcenc_ysad_halfpel_brefine(const oc_enc_ctx *_enc, + int _vec[2],const unsigned char *_src,const unsigned char *_ref,int _ystride, + int _offset_y[9],unsigned _best_err){ + int mvoffset_base; + int best_site; + int sitei; + mvoffset_base=_vec[0]+_vec[1]*_ystride; + best_site=4; + for(sitei=0;sitei<8;sitei++){ + unsigned err; + int site; + int xmask; + int ymask; + int dx; + int dy; + int mvoffset0; + int mvoffset1; + site=OC_SQUARE_SITES[0][sitei]; + dx=OC_SQUARE_DX[site]; + dy=OC_SQUARE_DY[site]; + /*The following code SHOULD be equivalent to + oc_state_get_mv_offsets(&_mcenc->enc.state,&mvoffset0,&mvoffset1, + (_vec[0]<<1)+dx,(_vec[1]<<1)+dy,ref_ystride,0); + However, it should also be much faster, as it involves no multiplies and + doesn't have to handle chroma vectors.*/ + xmask=OC_SIGNMASK(((_vec[0]<<1)+dx)^dx); + ymask=OC_SIGNMASK(((_vec[1]<<1)+dy)^dy); + mvoffset0=mvoffset_base+(dx&xmask)+(_offset_y[site]&ymask); + mvoffset1=mvoffset_base+(dx&~xmask)+(_offset_y[site]&~ymask); + err=oc_enc_frag_sad2_thresh(_enc,_src, + _ref+mvoffset0,_ref+mvoffset1,ystride,_best_err); + if(err<_best_err){ + _best_err=err; + best_site=site; + } + } + _vec[0]=(_vec[0]<<1)+OC_SQUARE_DX[best_site]; + _vec[1]=(_vec[1]<<1)+OC_SQUARE_DY[best_site]; + return _best_err; +} +#endif + +static unsigned oc_mcenc_ysatd_halfpel_brefine(const oc_enc_ctx *_enc, + int _vec[2],const unsigned char *_src,const unsigned char *_ref,int _ystride, + int _offset_y[9],unsigned _best_err){ + int mvoffset_base; + int best_site; + int sitei; + mvoffset_base=_vec[0]+_vec[1]*_ystride; + best_site=4; + for(sitei=0;sitei<8;sitei++){ + unsigned err; + int site; + int xmask; + int ymask; + int dx; + int dy; + int mvoffset0; + int mvoffset1; + site=OC_SQUARE_SITES[0][sitei]; + dx=OC_SQUARE_DX[site]; + dy=OC_SQUARE_DY[site]; + /*The following code SHOULD be equivalent to + oc_state_get_mv_offsets(&_enc->state,&mvoffsets,0, + (_vec[0]<<1)+dx,(_vec[1]<<1)+dy); + However, it should also be much faster, as it involves no multiplies and + doesn't have to handle chroma vectors.*/ + xmask=OC_SIGNMASK(((_vec[0]<<1)+dx)^dx); + ymask=OC_SIGNMASK(((_vec[1]<<1)+dy)^dy); + mvoffset0=mvoffset_base+(dx&xmask)+(_offset_y[site]&ymask); + mvoffset1=mvoffset_base+(dx&~xmask)+(_offset_y[site]&~ymask); + err=oc_enc_frag_satd2_thresh(_enc,_src, + _ref+mvoffset0,_ref+mvoffset1,_ystride,_best_err); + if(err<_best_err){ + _best_err=err; + best_site=site; + } + } + _vec[0]=(_vec[0]<<1)+OC_SQUARE_DX[best_site]; + _vec[1]=(_vec[1]<<1)+OC_SQUARE_DY[best_site]; + return _best_err; +} + +void oc_mcenc_refine4mv(oc_enc_ctx *_enc,int _mbi){ + oc_mb_enc_info *embs; + const ptrdiff_t *frag_buf_offs; + const ptrdiff_t *fragis; + const unsigned char *src; + const unsigned char *ref; + int offset_y[9]; + int ystride; + int bi; + ystride=_enc->state.ref_ystride[0]; + frag_buf_offs=_enc->state.frag_buf_offs; + fragis=_enc->state.mb_maps[_mbi][0]; + src=_enc->state.ref_frame_data[OC_FRAME_IO]; + ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_PREV]]; + offset_y[0]=offset_y[1]=offset_y[2]=-ystride; + offset_y[3]=offset_y[5]=0; + offset_y[6]=offset_y[7]=offset_y[8]=ystride; + embs=_enc->mb_info; + for(bi=0;bi<4;bi++){ + ptrdiff_t frag_offs; + int vec[2]; + frag_offs=frag_buf_offs[fragis[bi]]; + vec[0]=OC_DIV2(embs[_mbi].block_mv[bi][0]); + vec[1]=OC_DIV2(embs[_mbi].block_mv[bi][1]); + embs[_mbi].block_satd[bi]=oc_mcenc_ysatd_halfpel_brefine(_enc,vec, + src+frag_offs,ref+frag_offs,ystride,offset_y,embs[_mbi].block_satd[bi]); + embs[_mbi].ref_mv[bi][0]=(signed char)vec[0]; + embs[_mbi].ref_mv[bi][1]=(signed char)vec[1]; + } +} diff --git a/Engine/lib/libtheora/lib/modedec.h b/Engine/lib/libtheora/lib/modedec.h new file mode 100644 index 000000000..ea12c64af --- /dev/null +++ b/Engine/lib/libtheora/lib/modedec.h @@ -0,0 +1,4027 @@ +/*File generated by libtheora with OC_COLLECT_METRICS defined at compile time.*/ +#if !defined(_modedec_H) +# define _modedec_H (1) + + + +# if defined(OC_COLLECT_METRICS) +typedef struct oc_mode_metrics oc_mode_metrics; +# endif +typedef struct oc_mode_rd oc_mode_rd; + + + +/*The number of extra bits of precision at which to store rate metrics.*/ +# define OC_BIT_SCALE (6) +/*The number of extra bits of precision at which to store RMSE metrics. + This must be at least half OC_BIT_SCALE (rounded up).*/ +# define OC_RMSE_SCALE (5) +/*The number of bins to partition statistics into.*/ +# define OC_SAD_BINS (24) +/*The number of bits of precision to drop from SAD scores to assign them to a + bin.*/ +# define OC_SAD_SHIFT (9) + + + +# if defined(OC_COLLECT_METRICS) +struct oc_mode_metrics{ + double fragw; + double satd; + double rate; + double rmse; + double satd2; + double satdrate; + double rate2; + double satdrmse; + double rmse2; +}; + + +int oc_has_mode_metrics; +oc_mode_metrics OC_MODE_METRICS[64][3][2][OC_SAD_BINS]; +# endif + + + +struct oc_mode_rd{ + ogg_int16_t rate; + ogg_int16_t rmse; +}; + + +# if !defined(OC_COLLECT_METRICS) +static const +# endif +oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={ + { + { + /*Y' qi=0 INTRA*/ + { + { 87, -66},{ 132, 1611},{ 197, 3474},{ 285, 5130}, + { 376, 6419},{ 450, 7545},{ 521, 8587},{ 600, 9587}, + { 689,10498},{ 790,11348},{ 899,12158},{ 1030,12855}, + { 1166,13459},{ 1276,14052},{ 1353,14732},{ 1444,15425}, + { 1535,16101},{ 1609,16856},{ 1697,17532},{ 1823,17995}, + { 1962,18426},{ 2085,18919},{ 2201,19503},{ 2304,20307} + }, + /*Y' qi=0 INTER*/ + { + { 32, -105},{ 40, 1268},{ 54, 2919},{ 91, 4559}, + { 118, 6244},{ 132, 7932},{ 142, 9514},{ 149,10989}, + { 155,12375},{ 161,13679},{ 168,14958},{ 176,16215}, + { 187,17431},{ 196,18623},{ 207,19790},{ 218,20941}, + { 230,22083},{ 246,23213},{ 265,24333},{ 292,25439}, + { 328,26512},{ 372,27538},{ 427,28522},{ 494,29479} + } + }, + { + /*Cb qi=0 INTRA*/ + { + { 1, 6},{ 27, 368},{ 52, 738},{ 67, 1171}, + { 80, 1642},{ 99, 2134},{ 110, 2642},{ 112, 3144}, + { 126, 3578},{ 154, 3967},{ 167, 4387},{ 172, 4839}, + { 191, 5278},{ 208, 5666},{ 220, 6036},{ 223, 6398}, + { 227, 6814},{ 253, 7157},{ 284, 7403},{ 292, 7699}, + { 314, 7983},{ 339, 8203},{ 363, 8460},{ 399, 8919} + }, + /*Cb qi=0 INTER*/ + { + { 68, -55},{ 63, 275},{ 58, 602},{ 53, 936}, + { 50, 1290},{ 54, 1691},{ 58, 2116},{ 62, 2553}, + { 67, 2992},{ 72, 3422},{ 78, 3843},{ 84, 4253}, + { 89, 4658},{ 94, 5062},{ 98, 5455},{ 100, 5848}, + { 102, 6231},{ 104, 6604},{ 104, 6982},{ 105, 7359}, + { 105, 7733},{ 104, 8104},{ 105, 8465},{ 111, 8828} + } + }, + { + /*Cr qi=0 INTRA*/ + { + { 1, 8},{ 23, 375},{ 47, 759},{ 63, 1220}, + { 71, 1693},{ 82, 2171},{ 94, 2652},{ 109, 3103}, + { 125, 3567},{ 133, 3995},{ 151, 4375},{ 168, 4819}, + { 174, 5244},{ 190, 5635},{ 215, 6005},{ 242, 6347}, + { 257, 6758},{ 280, 7068},{ 311, 7336},{ 326, 7652}, + { 346, 7968},{ 372, 8213},{ 388, 8515},{ 408, 9060} + }, + /*Cr qi=0 INTER*/ + { + { 69, 0},{ 60, 314},{ 49, 624},{ 45, 943}, + { 45, 1285},{ 49, 1691},{ 55, 2130},{ 62, 2560}, + { 71, 2973},{ 79, 3385},{ 85, 3800},{ 89, 4207}, + { 92, 4620},{ 95, 5037},{ 96, 5436},{ 97, 5839}, + { 98, 6252},{ 99, 6653},{ 99, 7038},{ 103, 7426}, + { 107, 7810},{ 108, 8178},{ 107, 8539},{ 106, 8937} + } + } + }, + { + { + /*Y' qi=1 INTRA*/ + { + { 81, -71},{ 133, 1610},{ 203, 3460},{ 296, 5083}, + { 392, 6342},{ 467, 7454},{ 541, 8486},{ 625, 9466}, + { 716,10352},{ 823,11181},{ 940,11961},{ 1074,12643}, + { 1211,13233},{ 1324,13807},{ 1408,14489},{ 1504,15167}, + { 1598,15824},{ 1679,16544},{ 1788,17161},{ 1928,17579}, + { 2070,17991},{ 2202,18456},{ 2324,19021},{ 2425,19894} + }, + /*Y' qi=1 INTER*/ + { + { 34, 4},{ 40, 1307},{ 55, 2914},{ 93, 4555}, + { 120, 6243},{ 134, 7912},{ 144, 9468},{ 152,10918}, + { 158,12275},{ 164,13569},{ 171,14846},{ 180,16098}, + { 191,17310},{ 204,18484},{ 216,19636},{ 228,20779}, + { 242,21912},{ 261,23036},{ 286,24146},{ 320,25221}, + { 363,26265},{ 418,27261},{ 485,28203},{ 551,29148} + } + }, + { + /*Cb qi=1 INTRA*/ + { + { 1, 6},{ 28, 367},{ 52, 738},{ 68, 1172}, + { 86, 1644},{ 106, 2135},{ 115, 2642},{ 119, 3141}, + { 132, 3569},{ 157, 3951},{ 172, 4366},{ 177, 4819}, + { 194, 5258},{ 211, 5638},{ 224, 6006},{ 233, 6367}, + { 236, 6784},{ 258, 7121},{ 299, 7357},{ 319, 7637}, + { 337, 7921},{ 358, 8141},{ 381, 8367},{ 401, 8768} + }, + /*Cb qi=1 INTER*/ + { + { 95, -31},{ 81, 295},{ 67, 614},{ 53, 953}, + { 48, 1305},{ 51, 1700},{ 56, 2125},{ 61, 2563}, + { 67, 3008},{ 73, 3435},{ 79, 3844},{ 85, 4251}, + { 90, 4663},{ 95, 5073},{ 98, 5458},{ 100, 5844}, + { 101, 6231},{ 102, 6606},{ 102, 6980},{ 103, 7347}, + { 104, 7726},{ 105, 8096},{ 105, 8453},{ 105, 8789} + } + }, + { + /*Cr qi=1 INTRA*/ + { + { 1, 8},{ 25, 375},{ 50, 759},{ 65, 1221}, + { 74, 1695},{ 86, 2172},{ 101, 2651},{ 117, 3101}, + { 129, 3561},{ 135, 3985},{ 153, 4368},{ 171, 4807}, + { 182, 5223},{ 202, 5608},{ 225, 5964},{ 251, 6300}, + { 271, 6697},{ 295, 6978},{ 324, 7235},{ 348, 7558}, + { 367, 7877},{ 394, 8101},{ 413, 8386},{ 409, 8945} + }, + /*Cr qi=1 INTER*/ + { + { 66, 11},{ 59, 323},{ 51, 631},{ 44, 949}, + { 44, 1292},{ 49, 1703},{ 56, 2140},{ 62, 2566}, + { 69, 2991},{ 77, 3397},{ 84, 3799},{ 89, 4211}, + { 93, 4634},{ 94, 5049},{ 95, 5444},{ 96, 5854}, + { 94, 6260},{ 95, 6640},{ 96, 7032},{ 101, 7423}, + { 104, 7790},{ 105, 8158},{ 109, 8527},{ 108, 8872} + } + } + }, + { + { + /*Y' qi=2 INTRA*/ + { + { 87, -72},{ 139, 1607},{ 213, 3426},{ 315, 4992}, + { 416, 6217},{ 495, 7315},{ 574, 8317},{ 666, 9265}, + { 763,10124},{ 875,10906},{ 1001,11654},{ 1147,12305}, + { 1289,12865},{ 1407,13424},{ 1503,14076},{ 1610,14724}, + { 1720,15342},{ 1815,16020},{ 1937,16579},{ 2084,16981}, + { 2236,17371},{ 2385,17779},{ 2536,18250},{ 2689,18931} + }, + /*Y' qi=2 INTER*/ + { + { 30, -2},{ 40, 1308},{ 57, 2921},{ 96, 4567}, + { 122, 6260},{ 136, 7902},{ 148, 9418},{ 156,10826}, + { 162,12157},{ 169,13448},{ 177,14709},{ 188,15938}, + { 200,17133},{ 213,18295},{ 228,19433},{ 245,20564}, + { 264,21685},{ 289,22790},{ 323,23876},{ 368,24916}, + { 427,25906},{ 499,26837},{ 585,27700},{ 680,28514} + } + }, + { + /*Cb qi=2 INTRA*/ + { + { 1, 6},{ 30, 367},{ 58, 738},{ 77, 1172}, + { 93, 1645},{ 111, 2137},{ 123, 2642},{ 126, 3133}, + { 136, 3553},{ 162, 3934},{ 178, 4352},{ 183, 4803}, + { 199, 5231},{ 220, 5596},{ 235, 5957},{ 245, 6314}, + { 256, 6718},{ 286, 7048},{ 320, 7285},{ 336, 7568}, + { 366, 7829},{ 387, 8045},{ 405, 8261},{ 445, 8550} + }, + /*Cb qi=2 INTER*/ + { + { 115, -61},{ 93, 277},{ 71, 609},{ 54, 963}, + { 49, 1329},{ 53, 1715},{ 58, 2138},{ 63, 2583}, + { 69, 3017},{ 75, 3442},{ 81, 3857},{ 88, 4263}, + { 93, 4667},{ 96, 5065},{ 101, 5451},{ 101, 5832}, + { 102, 6213},{ 103, 6593},{ 103, 6968},{ 104, 7336}, + { 104, 7710},{ 105, 8076},{ 106, 8440},{ 106, 8822} + } + }, + { + /*Cr qi=2 INTRA*/ + { + { 1, 8},{ 27, 375},{ 54, 759},{ 70, 1222}, + { 79, 1696},{ 89, 2173},{ 106, 2652},{ 123, 3098}, + { 135, 3553},{ 143, 3972},{ 161, 4348},{ 181, 4782}, + { 194, 5189},{ 213, 5565},{ 235, 5907},{ 266, 6229}, + { 286, 6618},{ 311, 6897},{ 339, 7152},{ 362, 7454}, + { 392, 7721},{ 416, 7946},{ 429, 8227},{ 458, 8540} + }, + /*Cr qi=2 INTER*/ + { + { 74, 20},{ 63, 330},{ 51, 635},{ 44, 942}, + { 47, 1287},{ 54, 1710},{ 59, 2147},{ 65, 2571}, + { 72, 2996},{ 79, 3413},{ 86, 3820},{ 91, 4230}, + { 93, 4642},{ 95, 5046},{ 95, 5442},{ 95, 5839}, + { 96, 6243},{ 97, 6641},{ 99, 7021},{ 101, 7396}, + { 103, 7764},{ 106, 8138},{ 109, 8507},{ 114, 8851} + } + } + }, + { + { + /*Y' qi=3 INTRA*/ + { + { 91, -67},{ 141, 1606},{ 219, 3405},{ 328, 4929}, + { 433, 6122},{ 515, 7209},{ 598, 8204},{ 693, 9145}, + { 796, 9986},{ 912,10756},{ 1045,11471},{ 1200,12079}, + { 1345,12640},{ 1471,13179},{ 1571,13809},{ 1678,14450}, + { 1798,15047},{ 1905,15701},{ 2043,16205},{ 2202,16569}, + { 2351,16971},{ 2501,17393},{ 2660,17851},{ 2825,18455} + }, + /*Y' qi=3 INTER*/ + { + { 53, -164},{ 38, 1314},{ 59, 2917},{ 99, 4563}, + { 124, 6253},{ 139, 7882},{ 150, 9375},{ 159,10749}, + { 166,12059},{ 173,13349},{ 183,14608},{ 194,15826}, + { 208,17003},{ 223,18150},{ 240,19287},{ 259,20411}, + { 284,21508},{ 317,22593},{ 359,23656},{ 414,24671}, + { 483,25634},{ 569,26519},{ 670,27332},{ 786,28072} + } + }, + { + /*Cb qi=3 INTRA*/ + { + { 1, 5},{ 31, 367},{ 58, 739},{ 78, 1173}, + { 96, 1645},{ 113, 2134},{ 125, 2638},{ 133, 3127}, + { 148, 3542},{ 171, 3915},{ 184, 4328},{ 192, 4776}, + { 209, 5197},{ 230, 5556},{ 245, 5909},{ 252, 6261}, + { 272, 6641},{ 304, 6942},{ 330, 7184},{ 342, 7477}, + { 380, 7736},{ 404, 7962},{ 428, 8151},{ 469, 8430} + }, + /*Cb qi=3 INTER*/ + { + { 86, -29},{ 72, 296},{ 58, 618},{ 46, 964}, + { 47, 1338},{ 51, 1743},{ 56, 2158},{ 63, 2594}, + { 69, 3035},{ 77, 3455},{ 84, 3859},{ 89, 4266}, + { 94, 4673},{ 98, 5074},{ 101, 5460},{ 101, 5842}, + { 101, 6217},{ 101, 6593},{ 102, 6964},{ 104, 7325}, + { 103, 7696},{ 103, 8056},{ 104, 8430},{ 103, 8792} + } + }, + { + /*Cr qi=3 INTRA*/ + { + { 1, 8},{ 27, 374},{ 56, 759},{ 74, 1221}, + { 83, 1696},{ 96, 2173},{ 113, 2650},{ 127, 3091}, + { 140, 3542},{ 151, 3960},{ 164, 4334},{ 188, 4764}, + { 208, 5144},{ 224, 5493},{ 250, 5841},{ 278, 6162}, + { 298, 6548},{ 334, 6816},{ 365, 7045},{ 388, 7343}, + { 419, 7613},{ 443, 7836},{ 455, 8105},{ 484, 8445} + }, + /*Cr qi=3 INTER*/ + { + { 76, 26},{ 65, 332},{ 53, 638},{ 45, 945}, + { 45, 1304},{ 53, 1725},{ 60, 2153},{ 68, 2584}, + { 74, 3007},{ 81, 3425},{ 87, 3844},{ 91, 4253}, + { 94, 4657},{ 95, 5061},{ 94, 5462},{ 94, 5856}, + { 95, 6250},{ 96, 6635},{ 97, 7014},{ 101, 7393}, + { 104, 7761},{ 106, 8137},{ 109, 8506},{ 111, 8823} + } + } + }, + { + { + /*Y' qi=4 INTRA*/ + { + { 80, -67},{ 143, 1603},{ 227, 3378},{ 344, 4861}, + { 454, 6026},{ 537, 7104},{ 626, 8089},{ 725, 9006}, + { 830, 9827},{ 950,10581},{ 1089,11270},{ 1257,11826}, + { 1409,12366},{ 1535,12912},{ 1640,13528},{ 1753,14173}, + { 1884,14756},{ 2007,15368},{ 2148,15852},{ 2307,16212}, + { 2464,16591},{ 2614,17019},{ 2785,17455},{ 2970,17963} + }, + /*Y' qi=4 INTER*/ + { + { 50, -145},{ 38, 1324},{ 61, 2921},{ 102, 4566}, + { 127, 6248},{ 142, 7845},{ 154, 9300},{ 163,10656}, + { 169,11965},{ 177,13246},{ 188,14495},{ 202,15702}, + { 218,16864},{ 236,18003},{ 256,19124},{ 278,20233}, + { 307,21330},{ 347,22398},{ 398,23437},{ 463,24429}, + { 546,25343},{ 649,26170},{ 767,26935},{ 888,27674} + } + }, + { + /*Cb qi=4 INTRA*/ + { + { 1, 5},{ 33, 367},{ 61, 739},{ 80, 1173}, + { 98, 1646},{ 114, 2136},{ 126, 2639},{ 137, 3124}, + { 152, 3535},{ 176, 3903},{ 194, 4307},{ 206, 4753}, + { 222, 5165},{ 242, 5508},{ 260, 5857},{ 272, 6205}, + { 294, 6559},{ 332, 6848},{ 356, 7104},{ 364, 7389}, + { 396, 7637},{ 415, 7878},{ 446, 8064},{ 506, 8294} + }, + /*Cb qi=4 INTER*/ + { + { 86, -15},{ 73, 308},{ 60, 627},{ 46, 967}, + { 47, 1343},{ 51, 1754},{ 56, 2183},{ 63, 2615}, + { 70, 3044},{ 79, 3459},{ 85, 3866},{ 90, 4276}, + { 94, 4686},{ 97, 5088},{ 100, 5467},{ 102, 5837}, + { 102, 6205},{ 101, 6569},{ 103, 6939},{ 104, 7317}, + { 105, 7690},{ 107, 8043},{ 107, 8394},{ 111, 8736} + } + }, + { + /*Cr qi=4 INTRA*/ + { + { 1, 7},{ 28, 375},{ 57, 759},{ 79, 1221}, + { 92, 1697},{ 105, 2174},{ 122, 2648},{ 135, 3085}, + { 146, 3530},{ 157, 3947},{ 171, 4316},{ 195, 4737}, + { 218, 5117},{ 239, 5445},{ 268, 5767},{ 295, 6074}, + { 315, 6460},{ 355, 6735},{ 392, 6933},{ 418, 7218}, + { 448, 7495},{ 471, 7688},{ 481, 7954},{ 504, 8313} + }, + /*Cr qi=4 INTER*/ + { + { 68, 28},{ 57, 334},{ 47, 639},{ 43, 953}, + { 48, 1314},{ 54, 1736},{ 59, 2169},{ 69, 2592}, + { 78, 3017},{ 84, 3434},{ 88, 3850},{ 92, 4260}, + { 95, 4663},{ 96, 5068},{ 95, 5455},{ 95, 5839}, + { 96, 6243},{ 97, 6626},{ 98, 7006},{ 101, 7390}, + { 104, 7755},{ 108, 8115},{ 111, 8471},{ 110, 8825} + } + } + }, + { + { + /*Y' qi=5 INTRA*/ + { + { 84, -69},{ 147, 1599},{ 237, 3350},{ 360, 4796}, + { 475, 5934},{ 562, 6992},{ 657, 7953},{ 765, 8837}, + { 874, 9641},{ 998,10384},{ 1146,11047},{ 1322,11572}, + { 1484,12076},{ 1617,12609},{ 1731,13203},{ 1856,13806}, + { 1995,14367},{ 2132,14936},{ 2289,15386},{ 2460,15721}, + { 2635,16066},{ 2802,16442},{ 2980,16805},{ 3177,17272} + }, + /*Y' qi=5 INTER*/ + { + { 38, -86},{ 37, 1349},{ 64, 2920},{ 105, 4563}, + { 129, 6236},{ 145, 7809},{ 158, 9236},{ 167,10572}, + { 174,11871},{ 182,13141},{ 195,14368},{ 212,15558}, + { 230,16706},{ 250,17828},{ 274,18944},{ 303,20041}, + { 342,21116},{ 394,22152},{ 460,23144},{ 543,24073}, + { 648,24919},{ 773,25673},{ 922,26323},{ 1084,26924} + } + }, + { + /*Cb qi=5 INTRA*/ + { + { 1, 5},{ 34, 367},{ 63, 739},{ 82, 1174}, + { 102, 1647},{ 119, 2137},{ 134, 2639},{ 145, 3121}, + { 161, 3529},{ 189, 3891},{ 207, 4290},{ 216, 4721}, + { 232, 5113},{ 258, 5455},{ 277, 5798},{ 294, 6124}, + { 322, 6427},{ 352, 6697},{ 370, 6982},{ 384, 7283}, + { 423, 7529},{ 448, 7766},{ 478, 7943},{ 527, 8151} + }, + /*Cb qi=5 INTER*/ + { + { 83, -49},{ 69, 284},{ 55, 611},{ 48, 961}, + { 49, 1355},{ 52, 1769},{ 58, 2191},{ 65, 2616}, + { 73, 3041},{ 80, 3460},{ 87, 3868},{ 92, 4276}, + { 95, 4682},{ 98, 5077},{ 100, 5459},{ 102, 5827}, + { 102, 6200},{ 102, 6568},{ 103, 6930},{ 103, 7303}, + { 104, 7672},{ 106, 8032},{ 106, 8391},{ 106, 8727} + } + }, + { + /*Cr qi=5 INTRA*/ + { + { 1, 8},{ 28, 375},{ 57, 760},{ 81, 1222}, + { 99, 1696},{ 111, 2175},{ 125, 2648},{ 140, 3079}, + { 152, 3520},{ 162, 3927},{ 179, 4294},{ 203, 4714}, + { 225, 5080},{ 254, 5389},{ 286, 5703},{ 318, 5997}, + { 342, 6364},{ 380, 6640},{ 416, 6837},{ 445, 7103}, + { 473, 7370},{ 497, 7562},{ 514, 7811},{ 549, 8148} + }, + /*Cr qi=5 INTER*/ + { + { 60, 6},{ 54, 323},{ 46, 638},{ 43, 958}, + { 45, 1329},{ 54, 1749},{ 61, 2175},{ 70, 2600}, + { 79, 3021},{ 85, 3437},{ 89, 3847},{ 93, 4254}, + { 95, 4660},{ 96, 5065},{ 95, 5456},{ 95, 5849}, + { 96, 6243},{ 96, 6621},{ 97, 6996},{ 101, 7366}, + { 104, 7722},{ 107, 8088},{ 111, 8448},{ 119, 8816} + } + } + }, + { + { + /*Y' qi=6 INTRA*/ + { + { 88, -69},{ 151, 1593},{ 251, 3294},{ 387, 4681}, + { 507, 5790},{ 601, 6837},{ 702, 7787},{ 813, 8648}, + { 927, 9427},{ 1059,10152},{ 1213,10787},{ 1399,11284}, + { 1568,11781},{ 1705,12312},{ 1823,12890},{ 1957,13482}, + { 2106,14036},{ 2249,14600},{ 2411,15042},{ 2588,15359}, + { 2772,15699},{ 2947,16062},{ 3127,16429},{ 3320,16849} + }, + /*Y' qi=6 INTER*/ + { + { 44, -80},{ 36, 1346},{ 69, 2919},{ 111, 4563}, + { 136, 6216},{ 154, 7746},{ 168, 9139},{ 178,10461}, + { 185,11747},{ 195,13007},{ 211,14229},{ 230,15408}, + { 250,16547},{ 274,17663},{ 302,18769},{ 339,19851}, + { 386,20907},{ 446,21933},{ 527,22884},{ 631,23746}, + { 760,24512},{ 914,25178},{ 1087,25758},{ 1278,26262} + } + }, + { + /*Cb qi=6 INTRA*/ + { + { 1, 4},{ 36, 367},{ 66, 739},{ 84, 1174}, + { 105, 1648},{ 126, 2139},{ 140, 2639},{ 149, 3116}, + { 164, 3523},{ 194, 3880},{ 217, 4271},{ 226, 4694}, + { 243, 5077},{ 270, 5407},{ 291, 5742},{ 310, 6061}, + { 340, 6340},{ 373, 6609},{ 394, 6890},{ 409, 7189}, + { 444, 7434},{ 469, 7652},{ 499, 7853},{ 559, 8135} + }, + /*Cb qi=6 INTER*/ + { + { 68, -46},{ 60, 291},{ 50, 623},{ 49, 971}, + { 50, 1357},{ 55, 1781},{ 61, 2211},{ 69, 2634}, + { 78, 3052},{ 86, 3466},{ 91, 3882},{ 95, 4292}, + { 98, 4691},{ 101, 5080},{ 102, 5458},{ 103, 5830}, + { 103, 6192},{ 104, 6554},{ 104, 6916},{ 106, 7278}, + { 108, 7641},{ 110, 8004},{ 112, 8371},{ 112, 8758} + } + }, + { + /*Cr qi=6 INTRA*/ + { + { 1, 8},{ 29, 375},{ 59, 760},{ 84, 1223}, + { 99, 1698},{ 112, 2176},{ 129, 2647},{ 143, 3076}, + { 156, 3510},{ 168, 3906},{ 189, 4269},{ 220, 4682}, + { 241, 5047},{ 266, 5342},{ 299, 5649},{ 331, 5954}, + { 357, 6309},{ 393, 6579},{ 431, 6765},{ 467, 6997}, + { 501, 7276},{ 520, 7488},{ 525, 7749},{ 548, 8146} + }, + /*Cr qi=6 INTER*/ + { + { 94, 31},{ 69, 335},{ 47, 641},{ 43, 967}, + { 50, 1350},{ 57, 1772},{ 65, 2197},{ 74, 2625}, + { 83, 3043},{ 90, 3454},{ 94, 3867},{ 97, 4273}, + { 98, 4671},{ 99, 5068},{ 99, 5461},{ 98, 5857}, + { 98, 6245},{ 99, 6610},{ 103, 6975},{ 105, 7345}, + { 108, 7712},{ 111, 8073},{ 113, 8415},{ 119, 8768} + } + } + }, + { + { + /*Y' qi=7 INTRA*/ + { + { 92, -70},{ 156, 1590},{ 261, 3267},{ 403, 4618}, + { 529, 5704},{ 628, 6730},{ 736, 7657},{ 856, 8491}, + { 978, 9246},{ 1118, 9943},{ 1281,10550},{ 1472,11028}, + { 1645,11507},{ 1793,12008},{ 1924,12565},{ 2067,13130}, + { 2229,13638},{ 2388,14160},{ 2558,14584},{ 2744,14886}, + { 2932,15194},{ 3116,15531},{ 3311,15858},{ 3538,16197} + }, + /*Y' qi=7 INTER*/ + { + { 43, -8},{ 36, 1351},{ 71, 2923},{ 112, 4568}, + { 138, 6201},{ 157, 7705},{ 171, 9083},{ 181,10390}, + { 189,11664},{ 202,12910},{ 220,14121},{ 241,15281}, + { 266,16401},{ 295,17507},{ 328,18608},{ 371,19677}, + { 430,20701},{ 508,21676},{ 604,22588},{ 727,23397}, + { 878,24093},{ 1055,24690},{ 1263,25151},{ 1496,25504} + } + }, + { + /*Cb qi=7 INTRA*/ + { + { 1, 5},{ 40, 367},{ 72, 740},{ 89, 1175}, + { 108, 1649},{ 129, 2140},{ 143, 2637},{ 154, 3110}, + { 169, 3507},{ 198, 3860},{ 224, 4237},{ 235, 4652}, + { 253, 5037},{ 282, 5358},{ 307, 5674},{ 329, 5986}, + { 361, 6273},{ 393, 6527},{ 419, 6777},{ 435, 7078}, + { 467, 7342},{ 495, 7554},{ 529, 7757},{ 591, 8053} + }, + /*Cb qi=7 INTER*/ + { + { 79, -33},{ 68, 299},{ 56, 627},{ 50, 978}, + { 51, 1366},{ 55, 1786},{ 61, 2213},{ 70, 2642}, + { 80, 3062},{ 87, 3474},{ 92, 3886},{ 96, 4292}, + { 99, 4684},{ 102, 5072},{ 103, 5450},{ 104, 5814}, + { 104, 6176},{ 104, 6538},{ 107, 6905},{ 110, 7270}, + { 110, 7625},{ 110, 7978},{ 111, 8340},{ 117, 8674} + } + }, + { + /*Cr qi=7 INTRA*/ + { + { 2, 7},{ 31, 375},{ 62, 760},{ 87, 1223}, + { 103, 1698},{ 115, 2175},{ 131, 2644},{ 147, 3066}, + { 161, 3494},{ 175, 3889},{ 199, 4250},{ 229, 4653}, + { 250, 5001},{ 279, 5275},{ 311, 5577},{ 343, 5889}, + { 376, 6227},{ 417, 6486},{ 457, 6689},{ 484, 6925}, + { 518, 7174},{ 544, 7393},{ 549, 7662},{ 577, 8050} + }, + /*Cr qi=7 INTER*/ + { + { 89, 22},{ 62, 332},{ 45, 641},{ 47, 976}, + { 52, 1363},{ 59, 1779},{ 67, 2203},{ 76, 2628}, + { 84, 3046},{ 90, 3460},{ 94, 3875},{ 98, 4272}, + { 99, 4666},{ 98, 5063},{ 98, 5459},{ 98, 5849}, + { 99, 6226},{ 101, 6594},{ 104, 6957},{ 109, 7324}, + { 109, 7686},{ 111, 8042},{ 115, 8379},{ 119, 8699} + } + } + }, + { + { + /*Y' qi=8 INTRA*/ + { + { 91, -69},{ 160, 1585},{ 274, 3226},{ 423, 4538}, + { 557, 5596},{ 664, 6595},{ 778, 7506},{ 905, 8319}, + { 1038, 9035},{ 1186, 9701},{ 1355,10292},{ 1554,10754}, + { 1739,11196},{ 1904,11639},{ 2047,12184},{ 2194,12763}, + { 2361,13256},{ 2529,13753},{ 2709,14155},{ 2902,14433}, + { 3100,14723},{ 3292,15026},{ 3489,15327},{ 3714,15705} + }, + /*Y' qi=8 INTER*/ + { + { 32, -157},{ 33, 1346},{ 74, 2914},{ 116, 4554}, + { 142, 6172},{ 162, 7648},{ 177, 9004},{ 186,10300}, + { 196,11570},{ 210,12808},{ 231,14001},{ 256,15150}, + { 285,16259},{ 319,17352},{ 359,18435},{ 415,19475}, + { 489,20470},{ 584,21400},{ 703,22246},{ 852,22968}, + { 1038,23556},{ 1253,24032},{ 1503,24367},{ 1778,24628} + } + }, + { + /*Cb qi=8 INTRA*/ + { + { 1, 4},{ 42, 367},{ 75, 740},{ 93, 1176}, + { 111, 1649},{ 128, 2139},{ 144, 2635},{ 157, 3103}, + { 174, 3494},{ 206, 3844},{ 233, 4207},{ 251, 4605}, + { 277, 4980},{ 304, 5284},{ 335, 5584},{ 359, 5888}, + { 393, 6152},{ 432, 6398},{ 455, 6656},{ 471, 6956}, + { 502, 7193},{ 528, 7405},{ 562, 7630},{ 603, 7922} + }, + /*Cb qi=8 INTER*/ + { + { 77, -37},{ 68, 299},{ 58, 632},{ 50, 991}, + { 50, 1382},{ 55, 1799},{ 62, 2226},{ 73, 2647}, + { 82, 3066},{ 90, 3480},{ 94, 3891},{ 96, 4296}, + { 98, 4687},{ 101, 5073},{ 103, 5456},{ 104, 5817}, + { 105, 6170},{ 106, 6523},{ 107, 6886},{ 108, 7250}, + { 109, 7600},{ 110, 7955},{ 111, 8305},{ 112, 8641} + } + }, + { + /*Cr qi=8 INTRA*/ + { + { 2, 7},{ 33, 375},{ 64, 760},{ 92, 1224}, + { 111, 1700},{ 122, 2173},{ 137, 2637},{ 156, 3055}, + { 172, 3476},{ 186, 3856},{ 211, 4211},{ 242, 4597}, + { 263, 4939},{ 292, 5214},{ 335, 5489},{ 376, 5772}, + { 406, 6099},{ 440, 6378},{ 483, 6578},{ 517, 6797}, + { 550, 7049},{ 571, 7283},{ 583, 7560},{ 618, 7967} + }, + /*Cr qi=8 INTER*/ + { + { 74, 25},{ 58, 328},{ 43, 637},{ 45, 980}, + { 51, 1371},{ 59, 1788},{ 69, 2207},{ 79, 2630}, + { 86, 3051},{ 91, 3470},{ 95, 3880},{ 97, 4280}, + { 98, 4680},{ 97, 5074},{ 96, 5456},{ 97, 5839}, + { 99, 6219},{ 101, 6583},{ 103, 6945},{ 106, 7312}, + { 110, 7671},{ 114, 8009},{ 115, 8345},{ 117, 8686} + } + } + }, + { + { + /*Y' qi=9 INTRA*/ + { + { 104, -68},{ 164, 1580},{ 288, 3173},{ 448, 4439}, + { 587, 5485},{ 702, 6465},{ 824, 7351},{ 958, 8148}, + { 1096, 8845},{ 1253, 9480},{ 1432,10047},{ 1640,10494}, + { 1835,10926},{ 2015,11350},{ 2166,11871},{ 2321,12428}, + { 2508,12876},{ 2684,13345},{ 2866,13741},{ 3069,13991}, + { 3281,14243},{ 3487,14518},{ 3689,14813},{ 3911,15175} + }, + /*Y' qi=9 INTER*/ + { + { 47, -140},{ 34, 1348},{ 77, 2915},{ 119, 4552}, + { 145, 6150},{ 166, 7600},{ 182, 8936},{ 192,10221}, + { 203,11482},{ 220,12711},{ 244,13886},{ 274,15012}, + { 308,16111},{ 349,17190},{ 401,18244},{ 470,19257}, + { 561,20209},{ 680,21069},{ 830,21822},{ 1010,22463}, + { 1227,22971},{ 1482,23328},{ 1769,23544},{ 2077,23655} + } + }, + { + /*Cb qi=9 INTRA*/ + { + { 1, 5},{ 43, 367},{ 76, 740},{ 95, 1176}, + { 114, 1649},{ 135, 2138},{ 153, 2629},{ 165, 3091}, + { 184, 3481},{ 217, 3831},{ 244, 4187},{ 260, 4572}, + { 290, 4930},{ 320, 5231},{ 351, 5521},{ 379, 5812}, + { 414, 6055},{ 452, 6307},{ 483, 6564},{ 502, 6848}, + { 525, 7115},{ 554, 7321},{ 589, 7533},{ 626, 7833} + }, + /*Cb qi=9 INTER*/ + { + { 101, -43},{ 81, 298},{ 62, 637},{ 49, 989}, + { 51, 1381},{ 56, 1806},{ 65, 2231},{ 74, 2653}, + { 84, 3071},{ 91, 3482},{ 95, 3892},{ 97, 4293}, + { 99, 4684},{ 101, 5066},{ 103, 5437},{ 103, 5793}, + { 103, 6148},{ 104, 6511},{ 105, 6867},{ 107, 7221}, + { 110, 7572},{ 111, 7926},{ 112, 8283},{ 116, 8625} + } + }, + { + /*Cr qi=9 INTRA*/ + { + { 2, 7},{ 35, 375},{ 66, 761},{ 93, 1224}, + { 112, 1700},{ 126, 2173},{ 144, 2633},{ 165, 3047}, + { 183, 3458},{ 199, 3835},{ 224, 4191},{ 257, 4558}, + { 283, 4887},{ 309, 5176},{ 351, 5446},{ 397, 5713}, + { 433, 6017},{ 469, 6283},{ 508, 6480},{ 546, 6687}, + { 579, 6945},{ 600, 7182},{ 610, 7434},{ 623, 7793} + }, + /*Cr qi=9 INTER*/ + { + { 77, 15},{ 57, 330},{ 45, 640},{ 48, 980}, + { 54, 1380},{ 61, 1802},{ 70, 2220},{ 80, 2639}, + { 87, 3057},{ 92, 3474},{ 94, 3882},{ 98, 4282}, + { 98, 4675},{ 97, 5062},{ 97, 5450},{ 98, 5829}, + { 100, 6197},{ 101, 6561},{ 104, 6927},{ 107, 7289}, + { 113, 7638},{ 117, 7978},{ 119, 8311},{ 117, 8629} + } + } + }, + { + { + /*Y' qi=10 INTRA*/ + { + { 101, -69},{ 168, 1574},{ 299, 3143},{ 465, 4386}, + { 610, 5410},{ 736, 6353},{ 866, 7207},{ 1006, 7982}, + { 1153, 8655},{ 1319, 9261},{ 1504, 9812},{ 1719,10248}, + { 1928,10653},{ 2116,11056},{ 2282,11550},{ 2458,12070}, + { 2654,12492},{ 2846,12923},{ 3043,13291},{ 3249,13537}, + { 3466,13764},{ 3682,13999},{ 3896,14268},{ 4145,14548} + }, + /*Y' qi=10 INTER*/ + { + { 48, -94},{ 34, 1355},{ 81, 2920},{ 124, 4545}, + { 151, 6113},{ 174, 7532},{ 190, 8850},{ 201,10125}, + { 214,11379},{ 235,12591},{ 264,13745},{ 299,14859}, + { 338,15948},{ 388,17008},{ 456,18029},{ 546,18988}, + { 661,19877},{ 808,20666},{ 993,21321},{ 1218,21835}, + { 1481,22203},{ 1783,22420},{ 2117,22504},{ 2469,22481} + } + }, + { + /*Cb qi=10 INTRA*/ + { + { 2, 4},{ 44, 367},{ 79, 740},{ 99, 1178}, + { 117, 1652},{ 137, 2141},{ 156, 2630},{ 170, 3089}, + { 192, 3474},{ 227, 3813},{ 259, 4157},{ 282, 4526}, + { 310, 4860},{ 342, 5140},{ 377, 5425},{ 400, 5714}, + { 436, 5952},{ 475, 6194},{ 496, 6468},{ 522, 6748}, + { 559, 6996},{ 587, 7216},{ 617, 7433},{ 673, 7678} + }, + /*Cb qi=10 INTER*/ + { + { 87, -37},{ 72, 301},{ 58, 636},{ 49, 995}, + { 51, 1394},{ 57, 1819},{ 66, 2241},{ 78, 2660}, + { 87, 3074},{ 93, 3482},{ 97, 3891},{ 99, 4294}, + { 101, 4678},{ 103, 5050},{ 105, 5414},{ 106, 5773}, + { 107, 6134},{ 108, 6485},{ 110, 6832},{ 113, 7187}, + { 113, 7547},{ 114, 7887},{ 117, 8230},{ 112, 8590} + } + }, + { + /*Cr qi=10 INTRA*/ + { + { 2, 7},{ 38, 375},{ 69, 761},{ 96, 1224}, + { 116, 1701},{ 131, 2175},{ 148, 2634},{ 168, 3041}, + { 190, 3439},{ 211, 3802},{ 238, 4151},{ 271, 4506}, + { 297, 4824},{ 331, 5103},{ 373, 5360},{ 415, 5632}, + { 459, 5928},{ 500, 6176},{ 535, 6386},{ 573, 6586}, + { 608, 6834},{ 629, 7079},{ 642, 7337},{ 686, 7680} + }, + /*Cr qi=10 INTER*/ + { + { 81, 34},{ 63, 333},{ 50, 633},{ 48, 987}, + { 53, 1397},{ 61, 1820},{ 71, 2237},{ 83, 2651}, + { 91, 3065},{ 95, 3479},{ 98, 3882},{ 100, 4279}, + { 101, 4673},{ 101, 5054},{ 100, 5429},{ 101, 5801}, + { 102, 6173},{ 104, 6541},{ 108, 6904},{ 110, 7264}, + { 114, 7609},{ 119, 7945},{ 123, 8275},{ 128, 8615} + } + } + }, + { + { + /*Y' qi=11 INTRA*/ + { + { 110, -66},{ 176, 1564},{ 316, 3087},{ 492, 4296}, + { 645, 5299},{ 781, 6217},{ 924, 7039},{ 1075, 7776}, + { 1232, 8421},{ 1410, 9005},{ 1607, 9532},{ 1834, 9929}, + { 2053,10300},{ 2249,10697},{ 2427,11184},{ 2619,11682}, + { 2826,12083},{ 3019,12508},{ 3225,12869},{ 3452,13064}, + { 3670,13280},{ 3890,13519},{ 4123,13750},{ 4367,14059} + }, + /*Y' qi=11 INTER*/ + { + { 72, -115},{ 32, 1354},{ 83, 2911},{ 126, 4534}, + { 154, 6080},{ 178, 7475},{ 194, 8779},{ 205,10047}, + { 222,11290},{ 246,12488},{ 281,13621},{ 322,14714}, + { 372,15786},{ 436,16821},{ 519,17813},{ 628,18728}, + { 770,19549},{ 950,20254},{ 1175,20800},{ 1443,21197}, + { 1752,21446},{ 2095,21555},{ 2457,21553},{ 2808,21544} + } + }, + { + /*Cb qi=11 INTRA*/ + { + { 2, 4},{ 45, 367},{ 81, 740},{ 101, 1177}, + { 121, 1650},{ 142, 2136},{ 159, 2621},{ 174, 3075}, + { 199, 3451},{ 234, 3778},{ 265, 4117},{ 297, 4473}, + { 333, 4789},{ 367, 5054},{ 402, 5319},{ 427, 5613}, + { 462, 5871},{ 503, 6107},{ 532, 6336},{ 560, 6584}, + { 601, 6842},{ 631, 7092},{ 662, 7292},{ 721, 7497} + }, + /*Cb qi=11 INTER*/ + { + { 117, -24},{ 93, 308},{ 69, 638},{ 52, 993}, + { 52, 1395},{ 58, 1822},{ 68, 2246},{ 80, 2665}, + { 89, 3082},{ 94, 3492},{ 96, 3900},{ 98, 4299}, + { 101, 4679},{ 103, 5047},{ 104, 5405},{ 106, 5763}, + { 106, 6120},{ 107, 6474},{ 109, 6823},{ 112, 7163}, + { 115, 7516},{ 117, 7868},{ 118, 8213},{ 119, 8561} + } + }, + { + /*Cr qi=11 INTRA*/ + { + { 2, 7},{ 40, 375},{ 75, 761},{ 100, 1224}, + { 119, 1700},{ 137, 2169},{ 154, 2622},{ 178, 3025}, + { 198, 3416},{ 220, 3770},{ 255, 4114},{ 294, 4459}, + { 323, 4756},{ 359, 5028},{ 399, 5292},{ 438, 5556}, + { 483, 5827},{ 518, 6073},{ 551, 6298},{ 598, 6501}, + { 634, 6754},{ 652, 6997},{ 670, 7211},{ 689, 7560} + }, + /*Cr qi=11 INTER*/ + { + { 75, 30},{ 61, 334},{ 51, 639},{ 49, 995}, + { 53, 1403},{ 62, 1821},{ 73, 2237},{ 84, 2654}, + { 91, 3070},{ 95, 3485},{ 96, 3890},{ 98, 4287}, + { 98, 4672},{ 99, 5050},{ 99, 5427},{ 100, 5798}, + { 103, 6169},{ 105, 6528},{ 107, 6881},{ 113, 7233}, + { 118, 7580},{ 121, 7916},{ 125, 8240},{ 130, 8551} + } + } + }, + { + { + /*Y' qi=12 INTRA*/ + { + { 104, -69},{ 182, 1557},{ 335, 3040},{ 521, 4205}, + { 684, 5178},{ 831, 6068},{ 986, 6854},{ 1151, 7559}, + { 1323, 8169},{ 1523, 8704},{ 1736, 9192},{ 1978, 9558}, + { 2213, 9908},{ 2421,10298},{ 2613,10757},{ 2822,11208}, + { 3042,11585},{ 3250,11991},{ 3474,12308},{ 3710,12480}, + { 3939,12687},{ 4174,12902},{ 4416,13102},{ 4672,13369} + }, + /*Y' qi=12 INTER*/ + { + { 52, -91},{ 34, 1355},{ 86, 2911},{ 129, 4518}, + { 159, 6037},{ 184, 7405},{ 200, 8694},{ 213, 9955}, + { 232,11185},{ 263,12360},{ 304,13479},{ 354,14555}, + { 415,15601},{ 495,16608},{ 601,17549},{ 738,18400}, + { 915,19136},{ 1139,19724},{ 1414,20150},{ 1731,20412}, + { 2090,20520},{ 2473,20509},{ 2851,20442},{ 3227,20328} + } + }, + { + /*Cb qi=12 INTRA*/ + { + { 1, 4},{ 46, 367},{ 85, 740},{ 109, 1178}, + { 126, 1650},{ 145, 2134},{ 165, 2617},{ 182, 3061}, + { 209, 3428},{ 245, 3749},{ 281, 4077},{ 316, 4417}, + { 354, 4718},{ 392, 4970},{ 430, 5217},{ 456, 5501}, + { 490, 5771},{ 534, 5996},{ 571, 6207},{ 600, 6458}, + { 644, 6697},{ 675, 6942},{ 707, 7151},{ 766, 7342} + }, + /*Cb qi=12 INTER*/ + { + { 84, -24},{ 73, 311},{ 60, 644},{ 52, 998}, + { 53, 1398},{ 60, 1825},{ 71, 2249},{ 83, 2665}, + { 90, 3081},{ 94, 3490},{ 97, 3893},{ 99, 4286}, + { 102, 4663},{ 104, 5032},{ 105, 5393},{ 106, 5751}, + { 107, 6102},{ 108, 6445},{ 111, 6788},{ 113, 7136}, + { 114, 7483},{ 117, 7828},{ 121, 8163},{ 122, 8496} + } + }, + { + /*Cr qi=12 INTRA*/ + { + { 3, 7},{ 41, 375},{ 78, 761},{ 106, 1225}, + { 124, 1700},{ 140, 2167},{ 163, 2616},{ 188, 3010}, + { 213, 3385},{ 240, 3718},{ 271, 4062},{ 309, 4406}, + { 345, 4691},{ 387, 4956},{ 430, 5212},{ 469, 5467}, + { 513, 5729},{ 554, 5970},{ 587, 6176},{ 633, 6395}, + { 673, 6659},{ 692, 6868},{ 712, 7061},{ 758, 7259} + }, + /*Cr qi=12 INTER*/ + { + { 73, 31},{ 59, 335},{ 48, 638},{ 50, 998}, + { 56, 1410},{ 65, 1827},{ 75, 2240},{ 85, 2657}, + { 92, 3073},{ 95, 3485},{ 97, 3888},{ 99, 4279}, + { 98, 4663},{ 99, 5042},{ 101, 5412},{ 102, 5779}, + { 105, 6142},{ 107, 6498},{ 108, 6848},{ 113, 7198}, + { 118, 7540},{ 121, 7867},{ 127, 8188},{ 132, 8508} + } + } + }, + { + { + /*Y' qi=13 INTRA*/ + { + { 109, -68},{ 187, 1551},{ 347, 3010},{ 541, 4153}, + { 709, 5107},{ 864, 5975},{ 1026, 6745},{ 1194, 7433}, + { 1375, 8021},{ 1581, 8550},{ 1803, 9026},{ 2054, 9371}, + { 2301, 9713},{ 2522,10082},{ 2728,10515},{ 2949,10956}, + { 3184,11297},{ 3408,11653},{ 3643,11946},{ 3886,12100}, + { 4124,12277},{ 4377,12459},{ 4632,12635},{ 4898,12861} + }, + /*Y' qi=13 INTER*/ + { + { 48, -78},{ 35, 1357},{ 89, 2914},{ 133, 4512}, + { 164, 6004},{ 190, 7348},{ 207, 8627},{ 222, 9881}, + { 247,11096},{ 284,12251},{ 333,13350},{ 392,14407}, + { 466,15426},{ 565,16391},{ 696,17279},{ 865,18058}, + { 1085,18689},{ 1358,19156},{ 1684,19456},{ 2050,19605}, + { 2447,19614},{ 2855,19524},{ 3243,19398},{ 3611,19201} + } + }, + { + /*Cb qi=13 INTRA*/ + { + { 2, 4},{ 47, 367},{ 86, 741},{ 108, 1179}, + { 127, 1651},{ 150, 2133},{ 173, 2611},{ 194, 3050}, + { 222, 3417},{ 262, 3733},{ 303, 4048},{ 337, 4375}, + { 378, 4657},{ 420, 4897},{ 456, 5148},{ 486, 5422}, + { 518, 5682},{ 558, 5903},{ 592, 6113},{ 623, 6372}, + { 662, 6628},{ 700, 6833},{ 751, 6989},{ 805, 7147} + }, + /*Cb qi=13 INTER*/ + { + { 94, -34},{ 78, 303},{ 60, 638},{ 51, 994}, + { 54, 1406},{ 61, 1836},{ 73, 2253},{ 84, 2668}, + { 92, 3082},{ 96, 3492},{ 99, 3894},{ 101, 4284}, + { 103, 4659},{ 105, 5023},{ 106, 5376},{ 108, 5726}, + { 109, 6070},{ 110, 6418},{ 113, 6765},{ 117, 7105}, + { 119, 7448},{ 122, 7784},{ 126, 8119},{ 131, 8463} + } + }, + { + /*Cr qi=13 INTRA*/ + { + { 3, 7},{ 43, 375},{ 80, 762},{ 110, 1226}, + { 131, 1701},{ 149, 2166},{ 172, 2610},{ 196, 2999}, + { 221, 3359},{ 254, 3679},{ 292, 4005},{ 332, 4329}, + { 369, 4612},{ 408, 4880},{ 456, 5139},{ 500, 5388}, + { 544, 5631},{ 581, 5877},{ 615, 6101},{ 660, 6316}, + { 692, 6594},{ 714, 6795},{ 736, 6997},{ 789, 7290} + }, + /*Cr qi=13 INTER*/ + { + { 73, 28},{ 61, 336},{ 46, 642},{ 50, 1003}, + { 58, 1414},{ 67, 1832},{ 79, 2245},{ 87, 2660}, + { 93, 3075},{ 97, 3484},{ 99, 3888},{ 100, 4277}, + { 100, 4651},{ 100, 5027},{ 101, 5403},{ 102, 5765}, + { 105, 6116},{ 109, 6470},{ 113, 6825},{ 119, 7163}, + { 124, 7497},{ 127, 7827},{ 131, 8137},{ 135, 8437} + } + } + }, + { + { + /*Y' qi=14 INTRA*/ + { + { 113, -68},{ 191, 1545},{ 358, 2981},{ 559, 4104}, + { 733, 5044},{ 896, 5890},{ 1066, 6636},{ 1241, 7304}, + { 1428, 7886},{ 1642, 8402},{ 1872, 8871},{ 2128, 9219}, + { 2380, 9547},{ 2609, 9908},{ 2825,10321},{ 3055,10728}, + { 3294,11076},{ 3523,11425},{ 3766,11689},{ 4013,11845}, + { 4254,12022},{ 4506,12209},{ 4759,12383},{ 5013,12637} + }, + /*Y' qi=14 INTER*/ + { + { 58, -82},{ 38, 1362},{ 93, 2914},{ 138, 4492}, + { 171, 5962},{ 198, 7289},{ 216, 8559},{ 234, 9804}, + { 263,11005},{ 306,12143},{ 363,13222},{ 434,14259}, + { 523,15255},{ 639,16188},{ 794,17021},{ 1000,17717}, + { 1262,18260},{ 1575,18645},{ 1943,18841},{ 2356,18872}, + { 2782,18802},{ 3194,18682},{ 3576,18559},{ 3923,18447} + } + }, + { + /*Cb qi=14 INTRA*/ + { + { 2, 3},{ 50, 367},{ 91, 741},{ 114, 1180}, + { 134, 1651},{ 157, 2131},{ 181, 2601},{ 208, 3028}, + { 239, 3391},{ 279, 3706},{ 322, 4000},{ 361, 4309}, + { 406, 4587},{ 445, 4822},{ 482, 5067},{ 515, 5344}, + { 546, 5612},{ 589, 5821},{ 626, 6020},{ 655, 6276}, + { 701, 6523},{ 748, 6717},{ 796, 6876},{ 815, 7151} + }, + /*Cb qi=14 INTER*/ + { + { 80, -43},{ 68, 301},{ 56, 644},{ 50, 1004}, + { 54, 1412},{ 63, 1836},{ 75, 2253},{ 87, 2670}, + { 94, 3083},{ 98, 3487},{ 101, 3885},{ 103, 4271}, + { 106, 4645},{ 107, 5004},{ 108, 5358},{ 109, 5705}, + { 112, 6047},{ 115, 6388},{ 118, 6731},{ 121, 7081}, + { 126, 7421},{ 129, 7747},{ 132, 8076},{ 137, 8419} + } + }, + { + /*Cr qi=14 INTRA*/ + { + { 3, 6},{ 45, 375},{ 85, 762},{ 116, 1226}, + { 138, 1700},{ 158, 2163},{ 180, 2602},{ 206, 2985}, + { 236, 3333},{ 270, 3639},{ 310, 3956},{ 359, 4258}, + { 397, 4524},{ 430, 4802},{ 478, 5068},{ 527, 5316}, + { 572, 5560},{ 613, 5802},{ 654, 6012},{ 699, 6216}, + { 734, 6489},{ 755, 6707},{ 775, 6898},{ 841, 7111} + }, + /*Cr qi=14 INTER*/ + { + { 78, 0},{ 59, 322},{ 46, 649},{ 51, 1016}, + { 58, 1422},{ 68, 1839},{ 81, 2253},{ 90, 2666}, + { 95, 3080},{ 98, 3486},{ 101, 3881},{ 102, 4268}, + { 102, 4644},{ 103, 5017},{ 105, 5382},{ 106, 5743}, + { 108, 6093},{ 112, 6442},{ 118, 6791},{ 124, 7130}, + { 127, 7463},{ 133, 7784},{ 138, 8085},{ 142, 8395} + } + } + }, + { + { + /*Y' qi=15 INTRA*/ + { + { 111, -66},{ 197, 1538},{ 370, 2949},{ 579, 4050}, + { 762, 4968},{ 933, 5798},{ 1112, 6520},{ 1299, 7161}, + { 1497, 7725},{ 1723, 8219},{ 1967, 8654},{ 2234, 8990}, + { 2499, 9302},{ 2740, 9637},{ 2968,10039},{ 3215,10414}, + { 3473,10709},{ 3721,11015},{ 3971,11270},{ 4228,11402}, + { 4487,11543},{ 4752,11707},{ 5011,11871},{ 5290,12099} + }, + /*Y' qi=15 INTER*/ + { + { 59, -113},{ 37, 1349},{ 95, 2904},{ 139, 4478}, + { 174, 5929},{ 201, 7244},{ 220, 8505},{ 241, 9736}, + { 275,10922},{ 327,12040},{ 395,13097},{ 477,14114}, + { 585,15071},{ 730,15947},{ 917,16714},{ 1162,17326}, + { 1468,17770},{ 1833,18029},{ 2251,18111},{ 2694,18068}, + { 3125,17968},{ 3529,17845},{ 3908,17713},{ 4260,17587} + } + }, + { + /*Cb qi=15 INTRA*/ + { + { 2, 3},{ 51, 367},{ 94, 741},{ 120, 1180}, + { 140, 1651},{ 160, 2129},{ 184, 2591},{ 213, 3010}, + { 246, 3371},{ 289, 3680},{ 335, 3969},{ 374, 4274}, + { 418, 4546},{ 460, 4783},{ 498, 5019},{ 532, 5280}, + { 565, 5553},{ 608, 5765},{ 647, 5958},{ 683, 6193}, + { 732, 6433},{ 782, 6620},{ 832, 6769},{ 848, 7027} + }, + /*Cb qi=15 INTER*/ + { + { 71, -52},{ 63, 296},{ 54, 644},{ 50, 1010}, + { 53, 1417},{ 64, 1837},{ 77, 2253},{ 88, 2666}, + { 95, 3079},{ 98, 3487},{ 100, 3882},{ 103, 4264}, + { 106, 4633},{ 108, 4991},{ 109, 5343},{ 109, 5693}, + { 112, 6038},{ 114, 6371},{ 119, 6709},{ 123, 7051}, + { 125, 7385},{ 130, 7716},{ 135, 8050},{ 140, 8374} + } + }, + { + /*Cr qi=15 INTRA*/ + { + { 2, 6},{ 47, 375},{ 87, 763},{ 119, 1225}, + { 143, 1699},{ 162, 2158},{ 185, 2595},{ 213, 2971}, + { 246, 3315},{ 279, 3618},{ 320, 3920},{ 372, 4210}, + { 409, 4480},{ 446, 4756},{ 496, 5017},{ 542, 5263}, + { 590, 5487},{ 639, 5721},{ 687, 5923},{ 724, 6132}, + { 753, 6417},{ 781, 6622},{ 805, 6806},{ 856, 6977} + }, + /*Cr qi=15 INTER*/ + { + { 71, 3},{ 61, 326},{ 52, 651},{ 50, 1017}, + { 58, 1422},{ 69, 1837},{ 82, 2251},{ 90, 2668}, + { 95, 3080},{ 98, 3484},{ 101, 3877},{ 102, 4257}, + { 102, 4632},{ 101, 5005},{ 103, 5370},{ 106, 5733}, + { 110, 6082},{ 116, 6424},{ 120, 6774},{ 124, 7106}, + { 130, 7427},{ 135, 7748},{ 141, 8052},{ 147, 8333} + } + } + }, + { + { + /*Y' qi=16 INTRA*/ + { + { 114, -63},{ 206, 1525},{ 396, 2887},{ 618, 3945}, + { 816, 4832},{ 1002, 5626},{ 1196, 6319},{ 1401, 6923}, + { 1616, 7458},{ 1857, 7928},{ 2121, 8334},{ 2405, 8645}, + { 2685, 8934},{ 2938, 9255},{ 3175, 9638},{ 3433, 9990}, + { 3707,10263},{ 3958,10577},{ 4218,10807},{ 4488,10906}, + { 4760,11028},{ 5037,11148},{ 5306,11286},{ 5625,11463} + }, + /*Y' qi=16 INTER*/ + { + { 69, -153},{ 39, 1348},{ 98, 2894},{ 144, 4448}, + { 181, 5872},{ 209, 7167},{ 228, 8422},{ 254, 9644}, + { 297,10810},{ 359,11908},{ 438,12944},{ 539,13930}, + { 672,14842},{ 850,15650},{ 1085,16318},{ 1391,16793}, + { 1769,17082},{ 2200,17198},{ 2659,17174},{ 3116,17072}, + { 3547,16948},{ 3943,16819},{ 4299,16701},{ 4611,16644} + } + }, + { + /*Cb qi=16 INTRA*/ + { + { 3, 4},{ 54, 367},{ 97, 742},{ 122, 1181}, + { 143, 1651},{ 168, 2123},{ 197, 2575},{ 226, 2985}, + { 263, 3338},{ 314, 3631},{ 367, 3903},{ 409, 4200}, + { 453, 4468},{ 491, 4703},{ 528, 4932},{ 566, 5188}, + { 601, 5459},{ 647, 5672},{ 693, 5844},{ 734, 6058}, + { 784, 6305},{ 836, 6460},{ 882, 6602},{ 905, 6891} + }, + /*Cb qi=16 INTER*/ + { + { 75, -64},{ 67, 292},{ 56, 645},{ 51, 1016}, + { 54, 1421},{ 66, 1842},{ 79, 2257},{ 89, 2670}, + { 95, 3082},{ 98, 3488},{ 101, 3879},{ 104, 4258}, + { 106, 4623},{ 108, 4974},{ 109, 5321},{ 113, 5664}, + { 116, 6001},{ 117, 6341},{ 123, 6677},{ 128, 7004}, + { 130, 7336},{ 136, 7671},{ 143, 7996},{ 148, 8310} + } + }, + { + /*Cr qi=16 INTRA*/ + { + { 4, 7},{ 50, 375},{ 90, 763},{ 124, 1225}, + { 148, 1698},{ 168, 2154},{ 195, 2582},{ 227, 2948}, + { 263, 3279},{ 302, 3575},{ 343, 3865},{ 394, 4137}, + { 439, 4402},{ 482, 4672},{ 533, 4925},{ 579, 5165}, + { 626, 5382},{ 675, 5616},{ 725, 5812},{ 769, 5991}, + { 810, 6242},{ 848, 6430},{ 868, 6615},{ 944, 6732} + }, + /*Cr qi=16 INTER*/ + { + { 78, 11},{ 62, 327},{ 49, 650},{ 50, 1025}, + { 59, 1431},{ 72, 1841},{ 83, 2253},{ 90, 2671}, + { 95, 3084},{ 98, 3487},{ 100, 3879},{ 101, 4254}, + { 102, 4625},{ 103, 4994},{ 106, 5355},{ 108, 5708}, + { 111, 6058},{ 115, 6400},{ 121, 6733},{ 128, 7058}, + { 134, 7374},{ 140, 7691},{ 146, 7993},{ 146, 8317} + } + } + }, + { + { + /*Y' qi=17 INTRA*/ + { + { 112, -59},{ 210, 1515},{ 409, 2850},{ 640, 3882}, + { 844, 4748},{ 1038, 5529},{ 1240, 6206},{ 1452, 6803}, + { 1676, 7330},{ 1925, 7792},{ 2194, 8201},{ 2483, 8512}, + { 2766, 8801},{ 3027, 9121},{ 3279, 9482},{ 3548, 9810}, + { 3825,10069},{ 4088,10345},{ 4362,10544},{ 4638,10644}, + { 4915,10744},{ 5196,10850},{ 5471,10981},{ 5802,11136} + }, + /*Y' qi=17 INTER*/ + { + { 70, -147},{ 45, 1349},{ 106, 2894},{ 155, 4425}, + { 195, 5818},{ 225, 7099},{ 247, 8348},{ 278, 9565}, + { 328,10717},{ 399,11794},{ 491,12807},{ 609,13760}, + { 766,14623},{ 984,15349},{ 1274,15902},{ 1642,16256}, + { 2082,16411},{ 2563,16409},{ 3048,16315},{ 3508,16194}, + { 3924,16064},{ 4306,15938},{ 4656,15828},{ 4966,15733} + } + }, + { + /*Cb qi=17 INTRA*/ + { + { 3, 4},{ 57, 367},{ 101, 742},{ 126, 1182}, + { 148, 1650},{ 175, 2118},{ 207, 2565},{ 241, 2966}, + { 279, 3307},{ 331, 3588},{ 389, 3845},{ 435, 4132}, + { 474, 4408},{ 517, 4641},{ 560, 4869},{ 602, 5122}, + { 638, 5389},{ 672, 5610},{ 716, 5787},{ 758, 6002}, + { 817, 6226},{ 869, 6393},{ 916, 6530},{ 950, 6799} + }, + /*Cb qi=17 INTER*/ + { + { 105, -65},{ 86, 288},{ 66, 638},{ 54, 1014}, + { 59, 1427},{ 71, 1844},{ 86, 2257},{ 95, 2668}, + { 100, 3075},{ 103, 3476},{ 106, 3867},{ 110, 4241}, + { 112, 4598},{ 114, 4948},{ 117, 5294},{ 121, 5633}, + { 123, 5968},{ 126, 6301},{ 131, 6637},{ 136, 6968}, + { 144, 7287},{ 152, 7606},{ 158, 7931},{ 162, 8262} + } + }, + { + /*Cr qi=17 INTRA*/ + { + { 4, 6},{ 55, 376},{ 97, 765},{ 128, 1226}, + { 152, 1696},{ 175, 2144},{ 204, 2568},{ 241, 2928}, + { 282, 3250},{ 323, 3530},{ 368, 3811},{ 420, 4089}, + { 463, 4347},{ 505, 4609},{ 562, 4860},{ 609, 5094}, + { 655, 5303},{ 709, 5535},{ 759, 5740},{ 803, 5913}, + { 844, 6153},{ 879, 6350},{ 905, 6527},{ 972, 6637} + }, + /*Cr qi=17 INTER*/ + { + { 88, 8},{ 68, 330},{ 51, 653},{ 54, 1028}, + { 65, 1433},{ 77, 1845},{ 89, 2257},{ 96, 2669}, + { 100, 3081},{ 102, 3481},{ 105, 3867},{ 106, 4245}, + { 108, 4613},{ 110, 4971},{ 112, 5328},{ 115, 5679}, + { 120, 6019},{ 127, 6355},{ 133, 6686},{ 140, 7007}, + { 149, 7316},{ 158, 7618},{ 166, 7924},{ 170, 8232} + } + } + }, + { + { + /*Y' qi=18 INTRA*/ + { + { 122, -58},{ 216, 1506},{ 425, 2815},{ 665, 3822}, + { 882, 4666},{ 1088, 5425},{ 1301, 6084},{ 1529, 6653}, + { 1766, 7162},{ 2026, 7611},{ 2312, 7987},{ 2612, 8278}, + { 2913, 8551},{ 3196, 8840},{ 3454, 9184},{ 3734, 9490}, + { 4030, 9725},{ 4305, 9973},{ 4585,10162},{ 4864,10251}, + { 5150,10324},{ 5443,10420},{ 5727,10536},{ 6053,10682} + }, + /*Y' qi=18 INTER*/ + { + { 66, -143},{ 47, 1351},{ 108, 2886},{ 158, 4401}, + { 200, 5775},{ 232, 7044},{ 256, 8288},{ 292, 9493}, + { 351,10625},{ 434,11679},{ 541,12665},{ 681,13578}, + { 875,14379},{ 1136,15025},{ 1483,15475},{ 1914,15709}, + { 2399,15767},{ 2907,15699},{ 3400,15579},{ 3852,15453}, + { 4259,15332},{ 4630,15221},{ 4976,15121},{ 5294,15061} + } + }, + { + /*Cb qi=18 INTRA*/ + { + { 2, 3},{ 61, 367},{ 107, 743},{ 131, 1182}, + { 155, 1648},{ 183, 2110},{ 220, 2542},{ 260, 2927}, + { 303, 3265},{ 359, 3540},{ 416, 3785},{ 462, 4063}, + { 506, 4334},{ 553, 4567},{ 595, 4797},{ 636, 5049}, + { 676, 5304},{ 717, 5516},{ 759, 5698},{ 801, 5904}, + { 861, 6133},{ 911, 6311},{ 962, 6443},{ 1021, 6645} + }, + /*Cb qi=18 INTER*/ + { + { 126, 5},{ 95, 326},{ 66, 643},{ 55, 1015}, + { 60, 1427},{ 73, 1843},{ 87, 2256},{ 96, 2667}, + { 101, 3073},{ 104, 3470},{ 108, 3853},{ 111, 4226}, + { 114, 4584},{ 117, 4928},{ 119, 5274},{ 122, 5612}, + { 126, 5942},{ 130, 6271},{ 136, 6606},{ 141, 6931}, + { 148, 7247},{ 156, 7568},{ 164, 7891},{ 173, 8211} + } + }, + { + /*Cr qi=18 INTRA*/ + { + { 4, 6},{ 59, 376},{ 104, 765},{ 133, 1226}, + { 156, 1692},{ 184, 2136},{ 218, 2548},{ 260, 2893}, + { 308, 3204},{ 348, 3481},{ 397, 3751},{ 448, 4024}, + { 490, 4281},{ 541, 4523},{ 593, 4776},{ 634, 5022}, + { 685, 5236},{ 748, 5455},{ 812, 5638},{ 856, 5818}, + { 891, 6048},{ 928, 6230},{ 961, 6405},{ 1055, 6449} + }, + /*Cr qi=18 INTER*/ + { + { 81, 34},{ 68, 342},{ 57, 652},{ 59, 1027}, + { 67, 1439},{ 80, 1848},{ 91, 2257},{ 97, 2670}, + { 100, 3076},{ 103, 3473},{ 106, 3857},{ 108, 4231}, + { 109, 4599},{ 110, 4958},{ 113, 5307},{ 119, 5650}, + { 125, 5991},{ 130, 6325},{ 138, 6651},{ 147, 6971}, + { 153, 7278},{ 162, 7578},{ 172, 7874},{ 177, 8156} + } + } + }, + { + { + /*Y' qi=19 INTRA*/ + { + { 128, -55},{ 228, 1495},{ 448, 2775},{ 699, 3758}, + { 931, 4571},{ 1154, 5296},{ 1386, 5914},{ 1636, 6450}, + { 1894, 6930},{ 2177, 7342},{ 2479, 7698},{ 2792, 7976}, + { 3099, 8235},{ 3392, 8517},{ 3658, 8853},{ 3938, 9155}, + { 4242, 9371},{ 4527, 9605},{ 4810, 9781},{ 5089, 9853}, + { 5378, 9920},{ 5674,10009},{ 5972,10110},{ 6336,10196} + }, + /*Y' qi=19 INTER*/ + { + { 69, -147},{ 49, 1353},{ 111, 2883},{ 162, 4381}, + { 205, 5737},{ 237, 6996},{ 264, 8232},{ 307, 9421}, + { 376,10534},{ 472,11567},{ 596,12525},{ 761,13395}, + { 990,14130},{ 1298,14694},{ 1695,15053},{ 2172,15195}, + { 2696,15173},{ 3213,15075},{ 3696,14948},{ 4141,14829}, + { 4541,14721},{ 4910,14609},{ 5245,14506},{ 5536,14399} + } + }, + { + /*Cb qi=19 INTRA*/ + { + { 3, 3},{ 61, 367},{ 109, 743},{ 135, 1182}, + { 161, 1646},{ 191, 2101},{ 229, 2524},{ 273, 2898}, + { 318, 3221},{ 376, 3490},{ 436, 3731},{ 487, 3994}, + { 539, 4251},{ 584, 4485},{ 621, 4721},{ 664, 4967}, + { 709, 5225},{ 752, 5431},{ 801, 5595},{ 846, 5796}, + { 912, 6011},{ 959, 6193},{ 1015, 6321},{ 1121, 6504} + }, + /*Cb qi=19 INTER*/ + { + { 126, 4},{ 97, 329},{ 69, 649},{ 56, 1017}, + { 61, 1432},{ 74, 1846},{ 88, 2255},{ 98, 2663}, + { 103, 3065},{ 106, 3460},{ 110, 3844},{ 114, 4211}, + { 117, 4564},{ 120, 4911},{ 122, 5253},{ 125, 5588}, + { 129, 5916},{ 135, 6241},{ 142, 6567},{ 149, 6885}, + { 155, 7206},{ 163, 7527},{ 174, 7843},{ 188, 8145} + } + }, + { + /*Cr qi=19 INTRA*/ + { + { 5, 6},{ 61, 376},{ 106, 765},{ 135, 1225}, + { 160, 1689},{ 192, 2126},{ 229, 2531},{ 271, 2869}, + { 321, 3168},{ 370, 3433},{ 421, 3704},{ 476, 3965}, + { 520, 4212},{ 572, 4452},{ 629, 4691},{ 671, 4939}, + { 724, 5152},{ 792, 5347},{ 858, 5510},{ 895, 5696}, + { 939, 5905},{ 991, 6056},{ 1027, 6244},{ 1127, 6333} + }, + /*Cr qi=19 INTER*/ + { + { 80, 45},{ 66, 344},{ 55, 654},{ 56, 1030}, + { 66, 1440},{ 80, 1850},{ 91, 2259},{ 98, 2668}, + { 102, 3072},{ 104, 3466},{ 107, 3845},{ 109, 4215}, + { 110, 4578},{ 112, 4933},{ 116, 5283},{ 122, 5625}, + { 129, 5963},{ 136, 6287},{ 143, 6611},{ 151, 6927}, + { 160, 7229},{ 170, 7528},{ 181, 7818},{ 191, 8092} + } + } + }, + { + { + /*Y' qi=20 INTRA*/ + { + { 129, -50},{ 238, 1481},{ 469, 2728},{ 730, 3684}, + { 974, 4473},{ 1213, 5171},{ 1463, 5763},{ 1729, 6281}, + { 2002, 6744},{ 2299, 7146},{ 2613, 7492},{ 2940, 7746}, + { 3265, 7978},{ 3571, 8228},{ 3853, 8543},{ 4156, 8815}, + { 4476, 9001},{ 4775, 9218},{ 5070, 9373},{ 5352, 9446}, + { 5649, 9510},{ 5956, 9580},{ 6268, 9660},{ 6647, 9705} + }, + /*Y' qi=20 INTER*/ + { + { 64, -93},{ 52, 1340},{ 116, 2862},{ 170, 4344}, + { 216, 5678},{ 249, 6928},{ 281, 8155},{ 333, 9326}, + { 418,10410},{ 533,11411},{ 683,12329},{ 890,13127}, + { 1183,13750},{ 1579,14162},{ 2066,14357},{ 2611,14370}, + { 3159,14284},{ 3675,14167},{ 4142,14053},{ 4568,13953}, + { 4961,13852},{ 5320,13755},{ 5649,13675},{ 5933,13610} + } + }, + { + /*Cb qi=20 INTRA*/ + { + { 3, 3},{ 62, 367},{ 112, 743},{ 140, 1183}, + { 165, 1646},{ 196, 2099},{ 235, 2517},{ 284, 2883}, + { 334, 3198},{ 393, 3460},{ 457, 3690},{ 509, 3945}, + { 560, 4198},{ 605, 4435},{ 647, 4658},{ 699, 4888}, + { 742, 5155},{ 788, 5350},{ 835, 5517},{ 880, 5730}, + { 956, 5914},{ 1007, 6060},{ 1053, 6199},{ 1158, 6358} + }, + /*Cb qi=20 INTER*/ + { + { 128, -6},{ 96, 322},{ 66, 653},{ 54, 1025}, + { 63, 1431},{ 79, 1844},{ 91, 2256},{ 99, 2665}, + { 104, 3065},{ 107, 3455},{ 111, 3831},{ 115, 4189}, + { 120, 4539},{ 123, 4885},{ 126, 5219},{ 130, 5548}, + { 135, 5876},{ 141, 6199},{ 149, 6519},{ 156, 6837}, + { 166, 7153},{ 179, 7468},{ 189, 7784},{ 194, 8102} + } + }, + { + /*Cr qi=20 INTRA*/ + { + { 4, 6},{ 63, 376},{ 109, 765},{ 139, 1225}, + { 165, 1689},{ 199, 2124},{ 239, 2523},{ 285, 2852}, + { 340, 3140},{ 388, 3398},{ 438, 3662},{ 499, 3914}, + { 547, 4155},{ 596, 4392},{ 652, 4634},{ 699, 4877}, + { 759, 5074},{ 824, 5257},{ 883, 5428},{ 936, 5589}, + { 986, 5790},{ 1030, 5960},{ 1074, 6119},{ 1172, 6191} + }, + /*Cr qi=20 INTER*/ + { + { 92, 40},{ 70, 345},{ 55, 658},{ 57, 1034}, + { 69, 1441},{ 84, 1852},{ 94, 2261},{ 98, 2669}, + { 102, 3074},{ 105, 3465},{ 107, 3841},{ 110, 4206}, + { 112, 4562},{ 116, 4915},{ 121, 5260},{ 127, 5591}, + { 134, 5920},{ 142, 6246},{ 153, 6562},{ 163, 6870}, + { 173, 7170},{ 186, 7463},{ 198, 7746},{ 199, 8030} + } + } + }, + { + { + /*Y' qi=21 INTRA*/ + { + { 130, -51},{ 244, 1476},{ 483, 2705},{ 756, 3635}, + { 1013, 4396},{ 1266, 5070},{ 1530, 5647},{ 1806, 6153}, + { 2093, 6600},{ 2411, 6976},{ 2739, 7299},{ 3079, 7534}, + { 3422, 7744},{ 3738, 7987},{ 4032, 8274},{ 4348, 8533}, + { 4675, 8721},{ 4989, 8909},{ 5291, 9051},{ 5577, 9111}, + { 5879, 9163},{ 6190, 9228},{ 6506, 9286},{ 6899, 9295} + }, + /*Y' qi=21 INTER*/ + { + { 64, -56},{ 55, 1341},{ 119, 2859},{ 174, 4324}, + { 223, 5640},{ 258, 6880},{ 295, 8096},{ 359, 9246}, + { 460,10302},{ 595,11268},{ 778,12131},{ 1032,12857}, + { 1387,13385},{ 1850,13683},{ 2399,13774},{ 2976,13729}, + { 3527,13619},{ 4034,13504},{ 4492,13401},{ 4912,13291}, + { 5298,13209},{ 5648,13137},{ 5974,13046},{ 6308,12977} + } + }, + { + /*Cb qi=21 INTRA*/ + { + { 4, 3},{ 64, 367},{ 114, 743},{ 141, 1183}, + { 166, 1645},{ 201, 2092},{ 247, 2502},{ 299, 2856}, + { 352, 3158},{ 413, 3412},{ 480, 3642},{ 536, 3893}, + { 588, 4137},{ 637, 4367},{ 678, 4598},{ 725, 4834}, + { 774, 5083},{ 827, 5269},{ 883, 5420},{ 930, 5633}, + { 999, 5829},{ 1057, 5959},{ 1113, 6082},{ 1200, 6265} + }, + /*Cb qi=21 INTER*/ + { + { 109, -8},{ 84, 321},{ 62, 654},{ 54, 1028}, + { 64, 1434},{ 80, 1847},{ 92, 2259},{ 100, 2664}, + { 105, 3060},{ 109, 3445},{ 114, 3815},{ 118, 4172}, + { 122, 4519},{ 126, 4861},{ 128, 5194},{ 133, 5520}, + { 139, 5847},{ 146, 6169},{ 155, 6487},{ 166, 6801}, + { 177, 7114},{ 189, 7423},{ 201, 7729},{ 208, 8035} + } + }, + { + /*Cr qi=21 INTRA*/ + { + { 4, 6},{ 64, 377},{ 111, 766},{ 144, 1225}, + { 174, 1683},{ 206, 2114},{ 248, 2506},{ 302, 2824}, + { 357, 3099},{ 404, 3357},{ 455, 3622},{ 519, 3867}, + { 573, 4098},{ 625, 4331},{ 683, 4571},{ 733, 4802}, + { 793, 4994},{ 863, 5173},{ 926, 5337},{ 978, 5492}, + { 1030, 5685},{ 1079, 5856},{ 1126, 6027},{ 1217, 6159} + }, + /*Cr qi=21 INTER*/ + { + { 82, 29},{ 67, 341},{ 55, 660},{ 58, 1038}, + { 71, 1443},{ 85, 1851},{ 95, 2258},{ 99, 2666}, + { 103, 3069},{ 107, 3456},{ 110, 3826},{ 112, 4188}, + { 114, 4544},{ 118, 4891},{ 124, 5231},{ 132, 5567}, + { 139, 5894},{ 148, 6210},{ 159, 6520},{ 171, 6822}, + { 185, 7111},{ 196, 7403},{ 209, 7691},{ 225, 7945} + } + } + }, + { + { + /*Y' qi=22 INTRA*/ + { + { 128, -45},{ 254, 1463},{ 507, 2662},{ 794, 3562}, + { 1070, 4292},{ 1340, 4941},{ 1622, 5492},{ 1920, 5968}, + { 2229, 6387},{ 2565, 6742},{ 2911, 7047},{ 3263, 7264}, + { 3615, 7464},{ 3944, 7689},{ 4258, 7950},{ 4591, 8183}, + { 4934, 8347},{ 5259, 8517},{ 5573, 8634},{ 5870, 8683}, + { 6186, 8723},{ 6508, 8762},{ 6831, 8801},{ 7232, 8830} + }, + /*Y' qi=22 INTER*/ + { + { 77, -48},{ 57, 1343},{ 122, 2853},{ 180, 4299}, + { 231, 5597},{ 269, 6826},{ 314, 8025},{ 393, 9150}, + { 512,10179},{ 673,11103},{ 894,11908},{ 1207,12542}, + { 1635,12956},{ 2166,13148},{ 2755,13167},{ 3345,13088}, + { 3895,12966},{ 4386,12848},{ 4832,12746},{ 5252,12647}, + { 5634,12563},{ 5978,12497},{ 6299,12412},{ 6633,12338} + } + }, + { + /*Cb qi=22 INTRA*/ + { + { 4, 3},{ 66, 367},{ 122, 744},{ 153, 1182}, + { 177, 1640},{ 213, 2080},{ 263, 2475},{ 323, 2811}, + { 382, 3103},{ 451, 3346},{ 522, 3568},{ 581, 3814}, + { 633, 4054},{ 674, 4288},{ 719, 4523},{ 768, 4756}, + { 823, 4979},{ 883, 5162},{ 937, 5325},{ 996, 5510}, + { 1070, 5687},{ 1129, 5807},{ 1193, 5929},{ 1311, 6099} + }, + /*Cb qi=22 INTER*/ + { + { 107, -5},{ 83, 322},{ 61, 653},{ 55, 1030}, + { 66, 1436},{ 81, 1845},{ 94, 2253},{ 102, 2656}, + { 107, 3050},{ 111, 3435},{ 115, 3804},{ 119, 4158}, + { 124, 4501},{ 128, 4835},{ 132, 5164},{ 138, 5490}, + { 146, 5812},{ 154, 6128},{ 163, 6442},{ 174, 6754}, + { 188, 7060},{ 205, 7361},{ 219, 7662},{ 233, 7953} + } + }, + { + /*Cr qi=22 INTRA*/ + { + { 4, 6},{ 67, 378},{ 118, 767},{ 151, 1222}, + { 182, 1675},{ 221, 2097},{ 269, 2476},{ 329, 2774}, + { 389, 3039},{ 444, 3292},{ 500, 3545},{ 560, 3788}, + { 615, 4020},{ 671, 4251},{ 734, 4484},{ 781, 4712}, + { 850, 4887},{ 925, 5060},{ 981, 5229},{ 1031, 5369}, + { 1092, 5549},{ 1148, 5715},{ 1200, 5861},{ 1291, 5943} + }, + /*Cr qi=22 INTER*/ + { + { 88, 34},{ 69, 340},{ 57, 657},{ 60, 1039}, + { 73, 1445},{ 87, 1851},{ 96, 2257},{ 100, 2662}, + { 103, 3058},{ 107, 3442},{ 111, 3812},{ 115, 4172}, + { 118, 4524},{ 123, 4864},{ 129, 5199},{ 136, 5531}, + { 145, 5855},{ 156, 6168},{ 170, 6468},{ 184, 6765}, + { 193, 7066},{ 207, 7353},{ 222, 7628},{ 230, 7900} + } + } + }, + { + { + /*Y' qi=23 INTRA*/ + { + { 126, -40},{ 257, 1458},{ 521, 2636},{ 825, 3501}, + { 1111, 4207},{ 1391, 4842},{ 1684, 5385},{ 1992, 5858}, + { 2311, 6277},{ 2653, 6626},{ 3005, 6929},{ 3366, 7134}, + { 3729, 7311},{ 4071, 7526},{ 4396, 7770},{ 4734, 7986}, + { 5086, 8131},{ 5421, 8286},{ 5735, 8404},{ 6033, 8456}, + { 6357, 8486},{ 6682, 8525},{ 7003, 8573},{ 7387, 8604} + }, + /*Y' qi=23 INTER*/ + { + { 64, -57},{ 60, 1345},{ 124, 2853},{ 185, 4284}, + { 239, 5565},{ 282, 6783},{ 336, 7967},{ 429, 9069}, + { 568,10063},{ 758,10943},{ 1028,11679},{ 1407,12216}, + { 1909,12520},{ 2502,12616},{ 3126,12573},{ 3722,12461}, + { 4258,12344},{ 4742,12236},{ 5185,12136},{ 5590,12052}, + { 5970,11980},{ 6315,11901},{ 6631,11826},{ 6954,11769} + } + }, + { + /*Cb qi=23 INTRA*/ + { + { 3, 3},{ 70, 367},{ 124, 744},{ 151, 1182}, + { 181, 1637},{ 222, 2071},{ 276, 2460},{ 343, 2785}, + { 403, 3072},{ 468, 3317},{ 542, 3534},{ 605, 3773}, + { 659, 4009},{ 703, 4243},{ 747, 4479},{ 795, 4707}, + { 852, 4923},{ 908, 5105},{ 972, 5254},{ 1043, 5423}, + { 1118, 5594},{ 1172, 5731},{ 1240, 5853},{ 1365, 6005} + }, + /*Cb qi=23 INTER*/ + { + { 109, -10},{ 87, 325},{ 63, 650},{ 57, 1031}, + { 67, 1439},{ 83, 1847},{ 96, 2253},{ 103, 2652}, + { 109, 3041},{ 114, 3421},{ 117, 3789},{ 122, 4141}, + { 128, 4480},{ 134, 4811},{ 139, 5138},{ 144, 5463}, + { 152, 5781},{ 161, 6096},{ 174, 6404},{ 185, 6714}, + { 198, 7023},{ 216, 7320},{ 233, 7621},{ 245, 7935} + } + }, + { + /*Cr qi=23 INTRA*/ + { + { 5, 6},{ 70, 379},{ 122, 768},{ 155, 1222}, + { 187, 1671},{ 231, 2088},{ 283, 2459},{ 346, 2750}, + { 411, 3009},{ 465, 3261},{ 523, 3509},{ 585, 3746}, + { 639, 3980},{ 695, 4219},{ 754, 4449},{ 803, 4671}, + { 873, 4840},{ 953, 5001},{ 1015, 5156},{ 1071, 5286}, + { 1137, 5464},{ 1191, 5629},{ 1249, 5782},{ 1359, 5885} + }, + /*Cr qi=23 INTER*/ + { + { 84, 29},{ 69, 343},{ 58, 660},{ 62, 1041}, + { 75, 1448},{ 88, 1853},{ 97, 2258},{ 102, 2659}, + { 105, 3050},{ 108, 3430},{ 113, 3799},{ 116, 4155}, + { 121, 4505},{ 126, 4845},{ 132, 5176},{ 142, 5504}, + { 153, 5826},{ 165, 6133},{ 180, 6432},{ 197, 6722}, + { 212, 7005},{ 226, 7287},{ 244, 7555},{ 258, 7828} + } + } + }, + { + { + /*Y' qi=24 INTRA*/ + { + { 125, -34},{ 268, 1444},{ 547, 2590},{ 866, 3422}, + { 1172, 4098},{ 1476, 4702},{ 1790, 5222},{ 2117, 5678}, + { 2453, 6080},{ 2811, 6418},{ 3178, 6700},{ 3552, 6895}, + { 3928, 7055},{ 4286, 7243},{ 4627, 7477},{ 4981, 7674}, + { 5344, 7802},{ 5683, 7944},{ 6009, 8043},{ 6313, 8082}, + { 6633, 8111},{ 6959, 8151},{ 7280, 8197},{ 7660, 8221} + }, + /*Y' qi=24 INTER*/ + { + { 62, -63},{ 68, 1345},{ 134, 2840},{ 199, 4245}, + { 256, 5508},{ 304, 6715},{ 371, 7880},{ 484, 8950}, + { 652, 9899},{ 892,10709},{ 1238,11334},{ 1722,11722}, + { 2326,11875},{ 2983,11864},{ 3616,11783},{ 4189,11678}, + { 4707,11570},{ 5178,11476},{ 5617,11395},{ 6017,11319}, + { 6380,11252},{ 6720,11185},{ 7044,11126},{ 7377,11118} + } + }, + { + /*Cb qi=24 INTRA*/ + { + { 4, 3},{ 75, 367},{ 132, 745},{ 159, 1182}, + { 187, 1634},{ 230, 2061},{ 289, 2439},{ 361, 2753}, + { 425, 3034},{ 492, 3278},{ 566, 3490},{ 630, 3720}, + { 686, 3956},{ 732, 4190},{ 777, 4420},{ 829, 4637}, + { 894, 4840},{ 958, 5012},{ 1023, 5155},{ 1090, 5326}, + { 1165, 5502},{ 1226, 5622},{ 1299, 5717},{ 1408, 5887} + }, + /*Cb qi=24 INTER*/ + { + { 110, 35},{ 92, 337},{ 70, 651},{ 63, 1033}, + { 74, 1440},{ 91, 1846},{ 102, 2248},{ 109, 2644}, + { 114, 3031},{ 120, 3404},{ 127, 3762},{ 133, 4109}, + { 138, 4445},{ 144, 4772},{ 151, 5094},{ 159, 5411}, + { 168, 5728},{ 180, 6037},{ 195, 6338},{ 210, 6640}, + { 227, 6944},{ 249, 7236},{ 272, 7528},{ 299, 7809} + } + }, + { + /*Cr qi=24 INTRA*/ + { + { 5, 6},{ 72, 380},{ 124, 770},{ 158, 1222}, + { 195, 1668},{ 240, 2079},{ 297, 2438},{ 367, 2715}, + { 433, 2966},{ 488, 3218},{ 549, 3467},{ 609, 3701}, + { 664, 3935},{ 728, 4165},{ 792, 4379},{ 845, 4586}, + { 917, 4744},{ 995, 4898},{ 1063, 5049},{ 1120, 5187}, + { 1190, 5359},{ 1249, 5522},{ 1304, 5672},{ 1397, 5806} + }, + /*Cr qi=24 INTER*/ + { + { 91, 56},{ 73, 353},{ 61, 664},{ 66, 1045}, + { 80, 1449},{ 95, 1851},{ 103, 2250},{ 107, 2648}, + { 111, 3038},{ 116, 3413},{ 120, 3774},{ 124, 4128}, + { 130, 4471},{ 138, 4802},{ 145, 5130},{ 156, 5453}, + { 171, 5764},{ 187, 6061},{ 204, 6355},{ 220, 6643}, + { 238, 6923},{ 254, 7204},{ 275, 7475},{ 289, 7752} + } + } + }, + { + { + /*Y' qi=25 INTRA*/ + { + { 125, -28},{ 285, 1426},{ 582, 2540},{ 917, 3351}, + { 1244, 3997},{ 1569, 4570},{ 1903, 5071},{ 2258, 5498}, + { 2626, 5866},{ 3002, 6182},{ 3382, 6448},{ 3770, 6623}, + { 4162, 6760},{ 4528, 6934},{ 4882, 7144},{ 5249, 7328}, + { 5610, 7453},{ 5958, 7578},{ 6291, 7672},{ 6597, 7708}, + { 6928, 7715},{ 7258, 7737},{ 7575, 7781},{ 7950, 7829} + }, + /*Y' qi=25 INTER*/ + { + { 64, -16},{ 72, 1348},{ 139, 2832},{ 206, 4218}, + { 268, 5465},{ 322, 6659},{ 403, 7803},{ 540, 8838}, + { 747, 9734},{ 1044,10465},{ 1473,10981},{ 2048,11249}, + { 2717,11311},{ 3397,11257},{ 4025,11161},{ 4589,11052}, + { 5099,10947},{ 5560,10859},{ 5989,10786},{ 6389,10717}, + { 6753,10652},{ 7078,10592},{ 7389,10535},{ 7697,10460} + } + }, + { + /*Cb qi=25 INTRA*/ + { + { 3, 3},{ 78, 368},{ 133, 745},{ 159, 1180}, + { 193, 1627},{ 242, 2046},{ 304, 2411},{ 381, 2714}, + { 456, 2983},{ 527, 3224},{ 598, 3437},{ 667, 3655}, + { 726, 3888},{ 776, 4117},{ 826, 4333},{ 883, 4543}, + { 954, 4727},{ 1019, 4878},{ 1095, 5014},{ 1171, 5187}, + { 1255, 5342},{ 1319, 5458},{ 1396, 5546},{ 1536, 5678} + }, + /*Cb qi=25 INTER*/ + { + { 117, 32},{ 89, 342},{ 67, 660},{ 64, 1037}, + { 77, 1441},{ 93, 1845},{ 105, 2243},{ 113, 2633}, + { 120, 3016},{ 125, 3387},{ 131, 3739},{ 137, 4080}, + { 144, 4416},{ 152, 4741},{ 160, 5057},{ 169, 5369}, + { 180, 5680},{ 193, 5990},{ 209, 6294},{ 227, 6594}, + { 249, 6888},{ 269, 7180},{ 294, 7467},{ 317, 7768} + } + }, + { + /*Cr qi=25 INTRA*/ + { + { 6, 6},{ 74, 380},{ 129, 770},{ 165, 1220}, + { 201, 1658},{ 253, 2061},{ 315, 2410},{ 388, 2676}, + { 462, 2920},{ 523, 3166},{ 584, 3404},{ 647, 3637}, + { 701, 3870},{ 769, 4086},{ 838, 4296},{ 898, 4491}, + { 980, 4627},{ 1065, 4759},{ 1126, 4920},{ 1187, 5058}, + { 1283, 5180},{ 1347, 5332},{ 1404, 5475},{ 1527, 5534} + }, + /*Cr qi=25 INTER*/ + { + { 92, 41},{ 75, 347},{ 64, 664},{ 70, 1045}, + { 85, 1448},{ 98, 1849},{ 105, 2245},{ 110, 2637}, + { 115, 3023},{ 120, 3395},{ 126, 3753},{ 131, 4102}, + { 136, 4439},{ 145, 4768},{ 156, 5094},{ 168, 5410}, + { 184, 5717},{ 203, 6010},{ 221, 6300},{ 239, 6577}, + { 262, 6847},{ 282, 7123},{ 303, 7390},{ 322, 7665} + } + } + }, + { + { + /*Y' qi=26 INTRA*/ + { + { 130, -24},{ 292, 1423},{ 594, 2525},{ 943, 3307}, + { 1289, 3921},{ 1633, 4467},{ 1991, 4943},{ 2368, 5348}, + { 2753, 5696},{ 3148, 5991},{ 3545, 6247},{ 3942, 6415}, + { 4342, 6535},{ 4726, 6690},{ 5093, 6883},{ 5466, 7047}, + { 5840, 7159},{ 6202, 7274},{ 6545, 7351},{ 6855, 7375}, + { 7186, 7384},{ 7517, 7416},{ 7840, 7447},{ 8238, 7450} + }, + /*Y' qi=26 INTER*/ + { + { 52, 16},{ 75, 1336},{ 143, 2815},{ 213, 4191}, + { 278, 5427},{ 339, 6611},{ 436, 7734},{ 600, 8732}, + { 843, 9579},{ 1195,10243},{ 1702,10660},{ 2355,10825}, + { 3070,10820},{ 3755,10743},{ 4372,10643},{ 4925,10538}, + { 5426,10440},{ 5882,10354},{ 6296,10290},{ 6686,10224}, + { 7049,10163},{ 7380,10113},{ 7672,10062},{ 7937,10021} + } + }, + { + /*Cb qi=26 INTRA*/ + { + { 4, 3},{ 79, 368},{ 138, 745},{ 167, 1180}, + { 200, 1623},{ 252, 2034},{ 322, 2389},{ 403, 2682}, + { 480, 2941},{ 558, 3176},{ 631, 3393},{ 700, 3608}, + { 766, 3825},{ 819, 4046},{ 868, 4265},{ 926, 4472}, + { 1002, 4645},{ 1070, 4800},{ 1151, 4924},{ 1242, 5063}, + { 1325, 5221},{ 1393, 5338},{ 1464, 5431},{ 1595, 5559} + }, + /*Cb qi=26 INTER*/ + { + { 98, 33},{ 83, 343},{ 65, 662},{ 65, 1037}, + { 80, 1437},{ 96, 1839},{ 107, 2238},{ 115, 2628}, + { 122, 3007},{ 128, 3373},{ 134, 3722},{ 142, 4060}, + { 149, 4390},{ 158, 4713},{ 167, 5029},{ 178, 5341}, + { 191, 5647},{ 208, 5948},{ 227, 6244},{ 247, 6539}, + { 269, 6833},{ 295, 7114},{ 328, 7388},{ 369, 7658} + } + }, + { + /*Cr qi=26 INTRA*/ + { + { 5, 6},{ 75, 380},{ 133, 769},{ 172, 1217}, + { 212, 1652},{ 266, 2048},{ 333, 2384},{ 412, 2643}, + { 490, 2880},{ 552, 3124},{ 616, 3365},{ 681, 3594}, + { 739, 3816},{ 810, 4024},{ 880, 4224},{ 945, 4405}, + { 1029, 4538},{ 1114, 4674},{ 1183, 4822},{ 1254, 4946}, + { 1346, 5063},{ 1417, 5201},{ 1478, 5345},{ 1597, 5411} + }, + /*Cr qi=26 INTER*/ + { + { 97, 29},{ 75, 342},{ 62, 667},{ 70, 1047}, + { 87, 1447},{ 100, 1846},{ 107, 2242},{ 113, 2633}, + { 118, 3016},{ 123, 3382},{ 128, 3737},{ 135, 4082}, + { 142, 4417},{ 151, 4746},{ 162, 5066},{ 176, 5377}, + { 194, 5679},{ 217, 5963},{ 239, 6244},{ 260, 6522}, + { 284, 6789},{ 309, 7052},{ 335, 7313},{ 355, 7582} + } + } + }, + { + { + /*Y' qi=27 INTRA*/ + { + { 118, -10},{ 308, 1404},{ 630, 2473},{ 997, 3227}, + { 1360, 3819},{ 1719, 4354},{ 2086, 4829},{ 2470, 5233}, + { 2863, 5576},{ 3267, 5870},{ 3677, 6117},{ 4085, 6268}, + { 4499, 6376},{ 4888, 6521},{ 5257, 6705},{ 5638, 6865}, + { 6020, 6962},{ 6394, 7056},{ 6744, 7130},{ 7051, 7158}, + { 7386, 7164},{ 7717, 7185},{ 8042, 7209},{ 8444, 7206} + }, + /*Y' qi=27 INTER*/ + { + { 54, 19},{ 77, 1333},{ 147, 2806},{ 221, 4166}, + { 290, 5390},{ 360, 6564},{ 474, 7665},{ 664, 8630}, + { 949, 9423},{ 1370,10002},{ 1958,10323},{ 2670,10414}, + { 3406,10375},{ 4086,10285},{ 4691,10182},{ 5233,10085}, + { 5724, 9994},{ 6169, 9918},{ 6582, 9863},{ 6962, 9813}, + { 7316, 9759},{ 7645, 9707},{ 7948, 9660},{ 8262, 9623} + } + }, + { + /*Cb qi=27 INTRA*/ + { + { 4, 3},{ 79, 368},{ 137, 745},{ 166, 1180}, + { 200, 1622},{ 253, 2030},{ 324, 2381},{ 407, 2671}, + { 487, 2925},{ 567, 3156},{ 640, 3372},{ 712, 3580}, + { 782, 3792},{ 833, 4015},{ 887, 4227},{ 954, 4422}, + { 1031, 4592},{ 1103, 4738},{ 1187, 4856},{ 1280, 4990}, + { 1371, 5135},{ 1442, 5244},{ 1520, 5321},{ 1684, 5398} + }, + /*Cb qi=27 INTER*/ + { + { 113, 20},{ 90, 338},{ 66, 661},{ 67, 1034}, + { 82, 1438},{ 97, 1842},{ 108, 2238},{ 115, 2624}, + { 123, 3000},{ 130, 3361},{ 138, 3708},{ 146, 4040}, + { 155, 4367},{ 164, 4688},{ 174, 4999},{ 186, 5306}, + { 203, 5609},{ 222, 5908},{ 243, 6202},{ 268, 6494}, + { 295, 6781},{ 326, 7058},{ 367, 7319},{ 420, 7551} + } + }, + { + /*Cr qi=27 INTRA*/ + { + { 5, 6},{ 75, 380},{ 133, 770},{ 173, 1217}, + { 214, 1650},{ 268, 2040},{ 337, 2375},{ 418, 2631}, + { 496, 2862},{ 558, 3104},{ 625, 3346},{ 692, 3571}, + { 753, 3786},{ 825, 3989},{ 896, 4182},{ 969, 4352}, + { 1059, 4479},{ 1144, 4614},{ 1212, 4757},{ 1284, 4871}, + { 1380, 4982},{ 1457, 5125},{ 1528, 5267},{ 1651, 5346} + }, + /*Cr qi=27 INTER*/ + { + { 92, 24},{ 74, 341},{ 61, 669},{ 71, 1049}, + { 88, 1448},{ 100, 1849},{ 107, 2243},{ 113, 2631}, + { 119, 3010},{ 125, 3373},{ 131, 3723},{ 137, 4064}, + { 146, 4396},{ 159, 4720},{ 172, 5033},{ 189, 5340}, + { 210, 5636},{ 233, 5920},{ 256, 6197},{ 282, 6465}, + { 310, 6730},{ 332, 7000},{ 359, 7259},{ 385, 7515} + } + } + }, + { + { + /*Y' qi=28 INTRA*/ + { + { 116, -8},{ 314, 1400},{ 640, 2458},{ 1013, 3197}, + { 1386, 3768},{ 1762, 4279},{ 2151, 4733},{ 2558, 5117}, + { 2970, 5442},{ 3393, 5714},{ 3820, 5935},{ 4243, 6069}, + { 4671, 6161},{ 5074, 6289},{ 5456, 6457},{ 5849, 6598}, + { 6244, 6689},{ 6632, 6777},{ 6984, 6833},{ 7294, 6855}, + { 7625, 6862},{ 7961, 6875},{ 8302, 6890},{ 8720, 6883} + }, + /*Y' qi=28 INTER*/ + { + { 54, 8},{ 81, 1333},{ 154, 2793},{ 231, 4138}, + { 304, 5352},{ 384, 6512},{ 519, 7585},{ 743, 8508}, + { 1082, 9236},{ 1587, 9717},{ 2267, 9928},{ 3034, 9944}, + { 3775, 9878},{ 4438, 9786},{ 5031, 9686},{ 5563, 9601}, + { 6042, 9523},{ 6481, 9456},{ 6890, 9405},{ 7266, 9356}, + { 7614, 9313},{ 7933, 9265},{ 8238, 9220},{ 8545, 9193} + } + }, + { + /*Cb qi=28 INTRA*/ + { + { 3, 3},{ 80, 368},{ 138, 746},{ 168, 1179}, + { 208, 1615},{ 268, 2014},{ 345, 2354},{ 432, 2637}, + { 515, 2884},{ 595, 3108},{ 669, 3323},{ 745, 3533}, + { 818, 3740},{ 876, 3953},{ 932, 4160},{ 1003, 4349}, + { 1088, 4501},{ 1154, 4648},{ 1241, 4768},{ 1349, 4889}, + { 1441, 5023},{ 1524, 5113},{ 1611, 5187},{ 1783, 5283} + }, + /*Cb qi=28 INTER*/ + { + { 117, 29},{ 91, 341},{ 65, 663},{ 68, 1038}, + { 85, 1440},{ 100, 1841},{ 110, 2234},{ 119, 2616}, + { 127, 2985},{ 135, 3342},{ 142, 3685},{ 151, 4015}, + { 162, 4337},{ 174, 4652},{ 186, 4960},{ 201, 5264}, + { 218, 5567},{ 239, 5863},{ 266, 6149},{ 295, 6434}, + { 328, 6715},{ 371, 6976},{ 409, 7239},{ 460, 7477} + } + }, + { + /*Cr qi=28 INTRA*/ + { + { 6, 7},{ 79, 381},{ 138, 771},{ 178, 1215}, + { 222, 1644},{ 285, 2026},{ 359, 2347},{ 441, 2597}, + { 521, 2827},{ 588, 3066},{ 655, 3303},{ 725, 3523}, + { 791, 3728},{ 870, 3920},{ 950, 4103},{ 1030, 4265}, + { 1121, 4388},{ 1198, 4520},{ 1266, 4659},{ 1356, 4759}, + { 1461, 4865},{ 1540, 4993},{ 1619, 5115},{ 1786, 5160} + }, + /*Cr qi=28 INTER*/ + { + { 96, 18},{ 78, 340},{ 66, 672},{ 74, 1051}, + { 90, 1450},{ 103, 1845},{ 110, 2235},{ 116, 2619}, + { 122, 2995},{ 129, 3356},{ 137, 3702},{ 146, 4038}, + { 156, 4365},{ 168, 4684},{ 182, 4995},{ 203, 5297}, + { 227, 5588},{ 253, 5866},{ 282, 6131},{ 311, 6394}, + { 339, 6664},{ 366, 6918},{ 400, 7171},{ 424, 7450} + } + } + }, + { + { + /*Y' qi=29 INTRA*/ + { + { 112, 7},{ 334, 1382},{ 681, 2410},{ 1081, 3112}, + { 1484, 3650},{ 1894, 4128},{ 2316, 4547},{ 2749, 4905}, + { 3188, 5208},{ 3634, 5458},{ 4079, 5666},{ 4517, 5791}, + { 4952, 5870},{ 5359, 5983},{ 5754, 6137},{ 6165, 6268}, + { 6568, 6351},{ 6958, 6423},{ 7320, 6471},{ 7638, 6490}, + { 7979, 6490},{ 8313, 6499},{ 8651, 6517},{ 9085, 6499} + }, + /*Y' qi=29 INTER*/ + { + { 55, 15},{ 85, 1336},{ 160, 2780},{ 242, 4104}, + { 323, 5302},{ 418, 6443},{ 586, 7480},{ 859, 8342}, + { 1278, 8982},{ 1888, 9347},{ 2658, 9457},{ 3457, 9425}, + { 4192, 9343},{ 4842, 9247},{ 5417, 9162},{ 5935, 9086}, + { 6404, 9011},{ 6841, 8952},{ 7241, 8907},{ 7609, 8867}, + { 7953, 8832},{ 8267, 8792},{ 8562, 8740},{ 8836, 8701} + } + }, + { + /*Cb qi=29 INTRA*/ + { + { 5, 3},{ 84, 368},{ 144, 746},{ 176, 1175}, + { 219, 1604},{ 285, 1991},{ 372, 2318},{ 462, 2591}, + { 546, 2833},{ 628, 3058},{ 704, 3274},{ 788, 3473}, + { 870, 3664},{ 935, 3865},{ 995, 4059},{ 1072, 4239}, + { 1167, 4388},{ 1248, 4518},{ 1334, 4634},{ 1429, 4765}, + { 1536, 4884},{ 1628, 4964},{ 1716, 5038},{ 1885, 5128} + }, + /*Cb qi=29 INTER*/ + { + { 126, 25},{ 95, 340},{ 69, 662},{ 71, 1039}, + { 88, 1440},{ 102, 1839},{ 113, 2227},{ 122, 2604}, + { 132, 2969},{ 141, 3320},{ 151, 3659},{ 161, 3985}, + { 172, 4301},{ 186, 4612},{ 200, 4917},{ 219, 5213}, + { 241, 5509},{ 265, 5800},{ 296, 6081},{ 329, 6360}, + { 369, 6633},{ 414, 6899},{ 465, 7148},{ 520, 7387} + } + }, + { + /*Cr qi=29 INTRA*/ + { + { 6, 7},{ 82, 382},{ 142, 772},{ 185, 1211}, + { 233, 1632},{ 303, 2000},{ 388, 2306},{ 475, 2550}, + { 556, 2779},{ 627, 3007},{ 707, 3237},{ 778, 3459}, + { 843, 3654},{ 927, 3834},{ 1012, 4012},{ 1101, 4152}, + { 1197, 4262},{ 1275, 4399},{ 1359, 4511},{ 1455, 4596}, + { 1562, 4708},{ 1644, 4833},{ 1719, 4954},{ 1888, 4988} + }, + /*Cr qi=29 INTER*/ + { + { 101, 28},{ 81, 343},{ 67, 673},{ 75, 1053}, + { 93, 1450},{ 106, 1844},{ 113, 2230},{ 119, 2610}, + { 127, 2980},{ 135, 3334},{ 143, 3676},{ 153, 4007}, + { 165, 4330},{ 180, 4645},{ 201, 4951},{ 224, 5243}, + { 253, 5522},{ 284, 5794},{ 314, 6060},{ 345, 6322}, + { 381, 6578},{ 419, 6828},{ 455, 7073},{ 495, 7316} + } + } + }, + { + { + /*Y' qi=30 INTRA*/ + { + { 112, 8},{ 335, 1380},{ 682, 2401},{ 1083, 3093}, + { 1489, 3619},{ 1902, 4092},{ 2332, 4511},{ 2777, 4865}, + { 3231, 5156},{ 3693, 5394},{ 4153, 5585},{ 4605, 5689}, + { 5049, 5764},{ 5468, 5871},{ 5875, 6004},{ 6295, 6120}, + { 6706, 6201},{ 7099, 6273},{ 7461, 6311},{ 7785, 6320}, + { 8128, 6322},{ 8469, 6331},{ 8806, 6342},{ 9220, 6338} + }, + /*Y' qi=30 INTER*/ + { + { 58, 8},{ 90, 1340},{ 169, 2771},{ 257, 4079}, + { 345, 5266},{ 459, 6387},{ 660, 7383},{ 990, 8180}, + { 1496, 8726},{ 2203, 8992},{ 3029, 9038},{ 3833, 8984}, + { 4549, 8900},{ 5183, 8813},{ 5745, 8735},{ 6250, 8674}, + { 6715, 8619},{ 7138, 8565},{ 7529, 8528},{ 7899, 8495}, + { 8234, 8465},{ 8550, 8429},{ 8856, 8395},{ 9160, 8374} + } + }, + { + /*Cb qi=30 INTRA*/ + { + { 7, 3},{ 88, 369},{ 149, 747},{ 185, 1175}, + { 232, 1599},{ 304, 1976},{ 392, 2293},{ 486, 2557}, + { 573, 2797},{ 656, 3027},{ 735, 3243},{ 819, 3442}, + { 903, 3629},{ 966, 3828},{ 1025, 4027},{ 1105, 4204}, + { 1201, 4343},{ 1282, 4469},{ 1379, 4575},{ 1486, 4689}, + { 1588, 4813},{ 1678, 4900},{ 1767, 4969},{ 1911, 5080} + }, + /*Cb qi=30 INTER*/ + { + { 120, 23},{ 96, 336},{ 72, 661},{ 75, 1043}, + { 91, 1441},{ 105, 1837},{ 117, 2221},{ 127, 2592}, + { 137, 2953},{ 148, 3301},{ 159, 3635},{ 170, 3959}, + { 184, 4271},{ 199, 4578},{ 216, 4879},{ 238, 5175}, + { 262, 5466},{ 294, 5750},{ 332, 6027},{ 373, 6298}, + { 421, 6559},{ 473, 6805},{ 526, 7053},{ 587, 7298} + } + }, + { + /*Cr qi=30 INTRA*/ + { + { 10, 7},{ 89, 384},{ 147, 773},{ 192, 1211}, + { 245, 1627},{ 322, 1984},{ 412, 2280},{ 501, 2520}, + { 583, 2750},{ 654, 2982},{ 736, 3207},{ 810, 3419}, + { 873, 3614},{ 957, 3794},{ 1048, 3965},{ 1139, 4102}, + { 1237, 4208},{ 1327, 4328},{ 1408, 4448},{ 1496, 4545}, + { 1604, 4652},{ 1699, 4760},{ 1780, 4877},{ 1937, 4942} + }, + /*Cr qi=30 INTER*/ + { + { 115, 26},{ 89, 342},{ 70, 672},{ 79, 1055}, + { 96, 1451},{ 108, 1841},{ 116, 2222},{ 124, 2599}, + { 132, 2965},{ 141, 3316},{ 151, 3655},{ 163, 3984}, + { 178, 4301},{ 197, 4609},{ 219, 4909},{ 247, 5195}, + { 280, 5469},{ 317, 5734},{ 351, 5991},{ 383, 6248}, + { 423, 6500},{ 467, 6744},{ 502, 6995},{ 558, 7226} + } + } + }, + { + { + /*Y' qi=31 INTRA*/ + { + { 116, 20},{ 359, 1361},{ 732, 2350},{ 1162, 3010}, + { 1597, 3507},{ 2042, 3950},{ 2503, 4339},{ 2974, 4670}, + { 3446, 4951},{ 3922, 5179},{ 4394, 5357},{ 4858, 5454}, + { 5313, 5519},{ 5734, 5626},{ 6154, 5755},{ 6585, 5859}, + { 7004, 5928},{ 7408, 5998},{ 7775, 6039},{ 8102, 6048}, + { 8442, 6051},{ 8790, 6054},{ 9136, 6057},{ 9554, 6041} + }, + /*Y' qi=31 INTER*/ + { + { 53, 12},{ 90, 1340},{ 169, 2765},{ 259, 4062}, + { 353, 5236},{ 483, 6340},{ 713, 7305},{ 1086, 8059}, + { 1651, 8548},{ 2423, 8751},{ 3288, 8754},{ 4106, 8674}, + { 4827, 8572},{ 5451, 8482},{ 6007, 8407},{ 6514, 8344}, + { 6970, 8282},{ 7397, 8225},{ 7795, 8193},{ 8159, 8161}, + { 8498, 8120},{ 8814, 8093},{ 9127, 8066},{ 9432, 8040} + } + }, + { + /*Cb qi=31 INTRA*/ + { + { 7, 3},{ 88, 369},{ 149, 746},{ 185, 1173}, + { 234, 1595},{ 308, 1967},{ 399, 2278},{ 494, 2537}, + { 583, 2774},{ 669, 2997},{ 755, 3204},{ 847, 3390}, + { 936, 3569},{ 1008, 3759},{ 1078, 3942},{ 1162, 4104}, + { 1262, 4238},{ 1352, 4364},{ 1442, 4470},{ 1557, 4567}, + { 1676, 4674},{ 1759, 4781},{ 1850, 4853},{ 2043, 4897} + }, + /*Cb qi=31 INTER*/ + { + { 121, 23},{ 96, 335},{ 72, 660},{ 74, 1043}, + { 90, 1440},{ 105, 1834},{ 116, 2217},{ 127, 2586}, + { 138, 2945},{ 148, 3293},{ 159, 3626},{ 172, 3945}, + { 185, 4256},{ 202, 4559},{ 223, 4856},{ 245, 5150}, + { 272, 5440},{ 306, 5719},{ 346, 5989},{ 391, 6253}, + { 443, 6511},{ 510, 6743},{ 583, 6965},{ 651, 7182} + } + }, + { + /*Cr qi=31 INTRA*/ + { + { 10, 7},{ 88, 384},{ 147, 773},{ 192, 1209}, + { 247, 1622},{ 326, 1974},{ 417, 2262},{ 509, 2500}, + { 596, 2726},{ 670, 2949},{ 754, 3170},{ 836, 3370}, + { 912, 3548},{ 999, 3724},{ 1093, 3888},{ 1198, 4000}, + { 1304, 4095},{ 1384, 4230},{ 1470, 4347},{ 1577, 4422}, + { 1696, 4513},{ 1798, 4620},{ 1869, 4746},{ 1991, 4798} + }, + /*Cr qi=31 INTER*/ + { + { 113, 32},{ 88, 345},{ 69, 674},{ 79, 1055}, + { 96, 1451},{ 108, 1839},{ 115, 2218},{ 123, 2592}, + { 132, 2957},{ 141, 3308},{ 151, 3643},{ 163, 3968}, + { 179, 4285},{ 200, 4590},{ 225, 4886},{ 254, 5169}, + { 291, 5436},{ 330, 5696},{ 368, 5951},{ 409, 6200}, + { 452, 6448},{ 493, 6695},{ 536, 6940},{ 571, 7204} + } + } + }, + { + { + /*Y' qi=32 INTRA*/ + { + { 123, 26},{ 370, 1356},{ 756, 2321},{ 1211, 2944}, + { 1674, 3408},{ 2148, 3826},{ 2639, 4193},{ 3138, 4504}, + { 3634, 4765},{ 4133, 4973},{ 4625, 5137},{ 5101, 5225}, + { 5567, 5274},{ 6002, 5363},{ 6437, 5482},{ 6885, 5566}, + { 7312, 5625},{ 7723, 5686},{ 8101, 5721},{ 8429, 5732}, + { 8769, 5728},{ 9120, 5726},{ 9472, 5723},{ 9918, 5700} + }, + /*Y' qi=32 INTER*/ + { + { 54, -3},{ 95, 1343},{ 179, 2750},{ 276, 4027}, + { 382, 5185},{ 543, 6256},{ 830, 7161},{ 1301, 7815}, + { 2003, 8172},{ 2883, 8266},{ 3779, 8217},{ 4578, 8127}, + { 5274, 8035},{ 5886, 7952},{ 6430, 7887},{ 6929, 7835}, + { 7380, 7779},{ 7796, 7737},{ 8190, 7705},{ 8552, 7672}, + { 8896, 7640},{ 9210, 7612},{ 9510, 7589},{ 9746, 7552} + } + }, + { + /*Cb qi=32 INTRA*/ + { + { 6, 3},{ 89, 369},{ 153, 746},{ 193, 1167}, + { 247, 1577},{ 330, 1935},{ 429, 2236},{ 528, 2494}, + { 620, 2732},{ 712, 2948},{ 801, 3146},{ 898, 3325}, + { 999, 3489},{ 1078, 3664},{ 1155, 3832},{ 1251, 3985}, + { 1360, 4115},{ 1451, 4236},{ 1549, 4338},{ 1667, 4433}, + { 1797, 4522},{ 1891, 4613},{ 1989, 4687},{ 2162, 4776} + }, + /*Cb qi=32 INTER*/ + { + { 116, -1},{ 98, 321},{ 80, 656},{ 80, 1042}, + { 96, 1438},{ 110, 1827},{ 122, 2205},{ 133, 2570}, + { 144, 2925},{ 157, 3268},{ 170, 3597},{ 185, 3911}, + { 202, 4216},{ 221, 4516},{ 244, 4809},{ 273, 5096}, + { 308, 5376},{ 350, 5644},{ 401, 5907},{ 459, 6160}, + { 520, 6401},{ 592, 6630},{ 676, 6837},{ 758, 7050} + } + }, + { + /*Cr qi=32 INTRA*/ + { + { 12, 7},{ 91, 386},{ 152, 773},{ 201, 1202}, + { 261, 1603},{ 347, 1942},{ 447, 2223},{ 540, 2460}, + { 626, 2684},{ 711, 2901},{ 801, 3115},{ 887, 3312}, + { 969, 3480},{ 1068, 3633},{ 1176, 3779},{ 1283, 3885}, + { 1392, 3969},{ 1485, 4090},{ 1573, 4206},{ 1686, 4274}, + { 1813, 4354},{ 1911, 4459},{ 2004, 4563},{ 2162, 4590} + }, + /*Cr qi=32 INTER*/ + { + { 129, 5},{ 98, 334},{ 75, 673},{ 84, 1055}, + { 101, 1448},{ 113, 1832},{ 121, 2206},{ 129, 2577}, + { 140, 2937},{ 151, 3282},{ 163, 3614},{ 179, 3932}, + { 198, 4240},{ 221, 4542},{ 252, 4830},{ 290, 5102}, + { 329, 5364},{ 373, 5618},{ 420, 5864},{ 468, 6105}, + { 513, 6351},{ 564, 6587},{ 624, 6810},{ 697, 7017} + } + } + }, + { + { + /*Y' qi=33 INTRA*/ + { + { 115, 36},{ 388, 1338},{ 791, 2289},{ 1258, 2899}, + { 1732, 3352},{ 2220, 3760},{ 2730, 4117},{ 3244, 4415}, + { 3751, 4662},{ 4261, 4858},{ 4766, 5012},{ 5249, 5094}, + { 5719, 5141},{ 6159, 5225},{ 6597, 5333},{ 7044, 5416}, + { 7474, 5472},{ 7893, 5531},{ 8268, 5570},{ 8591, 5580}, + { 8931, 5578},{ 9283, 5579},{ 9634, 5582},{10067, 5560} + }, + /*Y' qi=33 INTER*/ + { + { 65, -14},{ 102, 1345},{ 190, 2736},{ 294, 3999}, + { 411, 5146},{ 597, 6192},{ 934, 7045},{ 1488, 7622}, + { 2281, 7895},{ 3213, 7937},{ 4108, 7871},{ 4883, 7784}, + { 5556, 7709},{ 6150, 7643},{ 6685, 7585},{ 7176, 7539}, + { 7620, 7502},{ 8034, 7466},{ 8427, 7435},{ 8793, 7409}, + { 9136, 7386},{ 9446, 7364},{ 9743, 7339},{10025, 7303} + } + }, + { + /*Cb qi=33 INTRA*/ + { + { 5, 3},{ 92, 369},{ 159, 746},{ 203, 1163}, + { 263, 1564},{ 353, 1911},{ 458, 2204},{ 557, 2460}, + { 650, 2697},{ 744, 2913},{ 836, 3110},{ 934, 3292}, + { 1036, 3454},{ 1125, 3616},{ 1204, 3781},{ 1298, 3932}, + { 1410, 4058},{ 1507, 4170},{ 1606, 4265},{ 1725, 4358}, + { 1853, 4445},{ 1955, 4535},{ 2067, 4597},{ 2258, 4663} + }, + /*Cb qi=33 INTER*/ + { + { 109, 37},{ 94, 343},{ 81, 662},{ 85, 1042}, + { 102, 1436},{ 116, 1823},{ 128, 2195},{ 141, 2554}, + { 154, 2906},{ 167, 3246},{ 183, 3570},{ 202, 3881}, + { 220, 4185},{ 241, 4482},{ 268, 4772},{ 302, 5053}, + { 341, 5328},{ 388, 5592},{ 446, 5846},{ 507, 6096}, + { 581, 6328},{ 670, 6534},{ 762, 6731},{ 842, 6922} + } + }, + { + /*Cr qi=33 INTRA*/ + { + { 11, 7},{ 93, 387},{ 158, 774},{ 211, 1197}, + { 278, 1589},{ 372, 1917},{ 475, 2191},{ 569, 2429}, + { 658, 2655},{ 744, 2868},{ 835, 3083},{ 926, 3271}, + { 1010, 3430},{ 1110, 3586},{ 1224, 3724},{ 1336, 3826}, + { 1449, 3908},{ 1547, 4021},{ 1636, 4136},{ 1751, 4200}, + { 1886, 4277},{ 1977, 4384},{ 2070, 4474},{ 2232, 4510} + }, + /*Cr qi=33 INTER*/ + { + { 77, 9},{ 90, 347},{ 80, 674},{ 91, 1053}, + { 107, 1444},{ 119, 1825},{ 127, 2196},{ 137, 2563}, + { 149, 2919},{ 161, 3259},{ 176, 3588},{ 194, 3905}, + { 217, 4209},{ 246, 4504},{ 280, 4786},{ 320, 5055}, + { 364, 5316},{ 409, 5565},{ 460, 5804},{ 517, 6039}, + { 578, 6264},{ 640, 6489},{ 701, 6721},{ 772, 6948} + } + } + }, + { + { + /*Y' qi=34 INTRA*/ + { + { 124, 40},{ 401, 1333},{ 823, 2262},{ 1318, 2842}, + { 1823, 3265},{ 2339, 3650},{ 2872, 3991},{ 3405, 4274}, + { 3926, 4513},{ 4448, 4704},{ 4961, 4845},{ 5450, 4921}, + { 5925, 4971},{ 6372, 5053},{ 6813, 5160},{ 7264, 5242}, + { 7704, 5291},{ 8124, 5346},{ 8500, 5382},{ 8831, 5384}, + { 9178, 5380},{ 9525, 5387},{ 9869, 5389},{10310, 5356} + }, + /*Y' qi=34 INTER*/ + { + { 64, -17},{ 101, 1344},{ 190, 2730},{ 299, 3981}, + { 430, 5110},{ 648, 6127},{ 1036, 6933},{ 1664, 7445}, + { 2535, 7652},{ 3504, 7653},{ 4402, 7572},{ 5173, 7479}, + { 5843, 7400},{ 6441, 7334},{ 6976, 7280},{ 7464, 7231}, + { 7910, 7189},{ 8332, 7157},{ 8730, 7125},{ 9091, 7103}, + { 9422, 7086},{ 9753, 7061},{10067, 7036},{10316, 7029} + } + }, + { + /*Cb qi=34 INTRA*/ + { + { 5, 3},{ 91, 369},{ 158, 746},{ 204, 1162}, + { 266, 1561},{ 358, 1903},{ 466, 2189},{ 570, 2439}, + { 665, 2671},{ 765, 2880},{ 864, 3069},{ 970, 3238}, + { 1079, 3392},{ 1174, 3545},{ 1265, 3693},{ 1360, 3841}, + { 1471, 3968},{ 1572, 4083},{ 1675, 4181},{ 1804, 4255}, + { 1939, 4332},{ 2048, 4411},{ 2155, 4484},{ 2339, 4584} + }, + /*Cb qi=34 INTER*/ + { + { 99, 44},{ 92, 345},{ 82, 661},{ 86, 1043}, + { 101, 1436},{ 116, 1821},{ 128, 2191},{ 140, 2549}, + { 154, 2898},{ 168, 3235},{ 185, 3556},{ 203, 3865}, + { 224, 4166},{ 248, 4457},{ 278, 4741},{ 315, 5021}, + { 361, 5289},{ 416, 5546},{ 483, 5792},{ 559, 6025}, + { 651, 6237},{ 752, 6432},{ 849, 6626},{ 967, 6790} + } + }, + { + /*Cr qi=34 INTRA*/ + { + { 11, 7},{ 93, 387},{ 158, 773},{ 212, 1195}, + { 282, 1584},{ 378, 1909},{ 483, 2179},{ 578, 2414}, + { 671, 2633},{ 766, 2837},{ 866, 3038},{ 960, 3223}, + { 1049, 3376},{ 1158, 3520},{ 1285, 3644},{ 1400, 3740}, + { 1505, 3828},{ 1616, 3928},{ 1713, 4030},{ 1820, 4104}, + { 1957, 4185},{ 2063, 4280},{ 2160, 4355},{ 2320, 4341} + }, + /*Cr qi=34 INTER*/ + { + { 78, 11},{ 89, 347},{ 79, 674},{ 90, 1053}, + { 106, 1444},{ 117, 1823},{ 127, 2192},{ 137, 2558}, + { 149, 2912},{ 163, 3249},{ 178, 3574},{ 197, 3888}, + { 222, 4189},{ 252, 4481},{ 293, 4755},{ 341, 5013}, + { 386, 5268},{ 436, 5512},{ 498, 5743},{ 563, 5970}, + { 622, 6200},{ 694, 6415},{ 776, 6622},{ 871, 6818} + } + } + }, + { + { + /*Y' qi=35 INTRA*/ + { + { 116, 51},{ 433, 1312},{ 881, 2221},{ 1406, 2771}, + { 1948, 3156},{ 2511, 3501},{ 3085, 3811},{ 3654, 4066}, + { 4212, 4273},{ 4763, 4444},{ 5298, 4572},{ 5799, 4638}, + { 6285, 4678},{ 6747, 4746},{ 7203, 4838},{ 7673, 4905}, + { 8124, 4950},{ 8552, 5003},{ 8938, 5027},{ 9275, 5026}, + { 9628, 5019},{ 9981, 5024},{10331, 5030},{10795, 5000} + }, + /*Y' qi=35 INTER*/ + { + { 71, -10},{ 108, 1348},{ 203, 2710},{ 325, 3938}, + { 485, 5040},{ 766, 6000},{ 1267, 6706},{ 2048, 7089}, + { 3037, 7191},{ 4032, 7146},{ 4903, 7061},{ 5648, 6977}, + { 6301, 6912},{ 6884, 6857},{ 7413, 6812},{ 7898, 6775}, + { 8342, 6739},{ 8764, 6710},{ 9160, 6688},{ 9519, 6668}, + { 9859, 6646},{10190, 6625},{10492, 6612},{10755, 6595} + } + }, + { + /*Cb qi=35 INTRA*/ + { + { 6, 3},{ 95, 369},{ 164, 746},{ 214, 1156}, + { 287, 1542},{ 390, 1869},{ 504, 2143},{ 611, 2388}, + { 712, 2613},{ 822, 2811},{ 937, 2987},{ 1055, 3147}, + { 1174, 3285},{ 1286, 3420},{ 1386, 3560},{ 1488, 3698}, + { 1604, 3814},{ 1714, 3916},{ 1825, 4008},{ 1958, 4088}, + { 2101, 4159},{ 2224, 4226},{ 2339, 4292},{ 2538, 4383} + }, + /*Cb qi=35 INTER*/ + { + { 98, 41},{ 90, 348},{ 86, 665},{ 92, 1042}, + { 108, 1432},{ 122, 1812},{ 136, 2175},{ 151, 2528}, + { 165, 2872},{ 182, 3202},{ 202, 3516},{ 225, 3819}, + { 251, 4112},{ 281, 4398},{ 320, 4675},{ 367, 4944}, + { 421, 5204},{ 493, 5450},{ 579, 5679},{ 672, 5892}, + { 785, 6082},{ 906, 6258},{ 1026, 6432},{ 1153, 6592} + } + }, + { + /*Cr qi=35 INTRA*/ + { + { 12, 7},{ 98, 388},{ 166, 773},{ 226, 1187}, + { 306, 1563},{ 411, 1874},{ 524, 2134},{ 622, 2365}, + { 721, 2577},{ 826, 2768},{ 947, 2946},{ 1066, 3106}, + { 1163, 3250},{ 1274, 3395},{ 1417, 3508},{ 1539, 3590}, + { 1639, 3671},{ 1754, 3765},{ 1865, 3855},{ 1979, 3921}, + { 2127, 3998},{ 2249, 4085},{ 2346, 4172},{ 2473, 4210} + }, + /*Cr qi=35 INTER*/ + { + { 86, 12},{ 94, 354},{ 85, 677},{ 96, 1052}, + { 113, 1439},{ 125, 1811},{ 135, 2177},{ 147, 2537}, + { 160, 2884},{ 177, 3215},{ 195, 3535},{ 219, 3842}, + { 252, 4133},{ 292, 4413},{ 339, 4680},{ 396, 4928}, + { 455, 5169},{ 514, 5408},{ 588, 5626},{ 672, 5835}, + { 750, 6051},{ 837, 6257},{ 943, 6442},{ 1073, 6595} + } + } + }, + { + { + /*Y' qi=36 INTRA*/ + { + { 116, 52},{ 432, 1312},{ 881, 2215},{ 1407, 2759}, + { 1948, 3140},{ 2511, 3484},{ 3090, 3789},{ 3672, 4036}, + { 4243, 4236},{ 4803, 4397},{ 5346, 4517},{ 5856, 4581}, + { 6350, 4614},{ 6821, 4675},{ 7286, 4763},{ 7754, 4832}, + { 8201, 4875},{ 8631, 4922},{ 9015, 4948},{ 9351, 4945}, + { 9706, 4941},{10061, 4948},{10408, 4949},{10878, 4923} + }, + /*Y' qi=36 INTER*/ + { + { 63, -16},{ 114, 1332},{ 216, 2690},{ 343, 3914}, + { 515, 5009},{ 829, 5939},{ 1399, 6586},{ 2263, 6901}, + { 3290, 6967},{ 4272, 6920},{ 5115, 6847},{ 5839, 6779}, + { 6478, 6726},{ 7051, 6685},{ 7571, 6649},{ 8050, 6614}, + { 8495, 6587},{ 8908, 6567},{ 9298, 6550},{ 9673, 6530}, + {10005, 6512},{10324, 6499},{10640, 6483},{10936, 6487} + } + }, + { + /*Cb qi=36 INTRA*/ + { + { 6, 3},{ 98, 370},{ 170, 746},{ 225, 1150}, + { 306, 1527},{ 416, 1845},{ 534, 2116},{ 642, 2363}, + { 743, 2591},{ 851, 2794},{ 964, 2972},{ 1081, 3133}, + { 1198, 3275},{ 1311, 3410},{ 1411, 3547},{ 1519, 3680}, + { 1642, 3789},{ 1750, 3892},{ 1860, 3982},{ 1998, 4054}, + { 2141, 4129},{ 2256, 4204},{ 2372, 4278},{ 2567, 4356} + }, + /*Cb qi=36 INTER*/ + { + { 107, 30},{ 96, 346},{ 88, 667},{ 100, 1039}, + { 115, 1426},{ 128, 1804},{ 142, 2164},{ 158, 2512}, + { 176, 2851},{ 195, 3178},{ 218, 3491},{ 243, 3791}, + { 270, 4084},{ 307, 4365},{ 348, 4638},{ 397, 4908}, + { 464, 5157},{ 545, 5392},{ 635, 5620},{ 734, 5831}, + { 854, 6015},{ 993, 6170},{ 1124, 6327},{ 1234, 6502} + } + }, + { + /*Cr qi=36 INTRA*/ + { + { 12, 7},{ 102, 388},{ 172, 773},{ 239, 1182}, + { 328, 1546},{ 439, 1848},{ 554, 2106},{ 651, 2341}, + { 747, 2561},{ 850, 2757},{ 972, 2934},{ 1086, 3097}, + { 1182, 3245},{ 1302, 3382},{ 1447, 3491},{ 1572, 3567}, + { 1677, 3641},{ 1793, 3733},{ 1899, 3828},{ 2013, 3894}, + { 2163, 3967},{ 2283, 4059},{ 2387, 4142},{ 2559, 4145} + }, + /*Cr qi=36 INTER*/ + { + { 98, -10},{ 96, 347},{ 89, 676},{ 102, 1048}, + { 118, 1433},{ 130, 1804},{ 141, 2167},{ 154, 2523}, + { 171, 2866},{ 190, 3194},{ 212, 3508},{ 240, 3809}, + { 276, 4099},{ 320, 4377},{ 372, 4638},{ 428, 4887}, + { 492, 5122},{ 560, 5353},{ 638, 5572},{ 725, 5779}, + { 814, 5985},{ 902, 6192},{ 1013, 6377},{ 1155, 6527} + } + } + }, + { + { + /*Y' qi=37 INTRA*/ + { + { 109, 58},{ 445, 1302},{ 927, 2177},{ 1489, 2689}, + { 2053, 3052},{ 2632, 3387},{ 3230, 3683},{ 3830, 3922}, + { 4417, 4114},{ 4992, 4266},{ 5546, 4375},{ 6067, 4430}, + { 6571, 4459},{ 7046, 4516},{ 7513, 4599},{ 7991, 4663}, + { 8445, 4706},{ 8883, 4749},{ 9273, 4771},{ 9612, 4770}, + { 9970, 4765},{10325, 4773},{10672, 4778},{11106, 4758} + }, + /*Y' qi=37 INTER*/ + { + { 56, -14},{ 114, 1333},{ 218, 2683},{ 354, 3894}, + { 550, 4966},{ 916, 5854},{ 1569, 6437},{ 2520, 6685}, + { 3596, 6704},{ 4585, 6635},{ 5424, 6556},{ 6147, 6489}, + { 6787, 6437},{ 7358, 6395},{ 7876, 6358},{ 8361, 6325}, + { 8807, 6294},{ 9229, 6271},{ 9631, 6253},{10002, 6238}, + {10356, 6228},{10678, 6212},{10975, 6197},{11274, 6185} + } + }, + { + /*Cb qi=37 INTRA*/ + { + { 6, 3},{ 99, 370},{ 171, 746},{ 227, 1149}, + { 309, 1522},{ 421, 1836},{ 541, 2104},{ 652, 2347}, + { 757, 2572},{ 871, 2768},{ 989, 2936},{ 1111, 3087}, + { 1238, 3223},{ 1357, 3352},{ 1465, 3486},{ 1576, 3612}, + { 1709, 3705},{ 1828, 3801},{ 1937, 3895},{ 2076, 3967}, + { 2220, 4035},{ 2345, 4104},{ 2466, 4173},{ 2680, 4265} + }, + /*Cb qi=37 INTER*/ + { + { 111, 27},{ 97, 344},{ 87, 667},{ 99, 1038}, + { 115, 1425},{ 128, 1802},{ 143, 2160},{ 159, 2506}, + { 176, 2843},{ 198, 3167},{ 220, 3477},{ 247, 3774}, + { 280, 4061},{ 321, 4338},{ 368, 4608},{ 427, 4867}, + { 501, 5109},{ 595, 5332},{ 701, 5544},{ 818, 5738}, + { 956, 5905},{ 1105, 6066},{ 1248, 6217},{ 1381, 6353} + } + }, + { + /*Cr qi=37 INTRA*/ + { + { 12, 7},{ 102, 388},{ 173, 773},{ 242, 1180}, + { 331, 1541},{ 444, 1839},{ 562, 2095},{ 662, 2326}, + { 763, 2540},{ 871, 2728},{ 1003, 2892},{ 1130, 3045}, + { 1230, 3188},{ 1350, 3321},{ 1503, 3418},{ 1634, 3492}, + { 1737, 3568},{ 1856, 3653},{ 1970, 3744},{ 2091, 3802}, + { 2247, 3871},{ 2371, 3962},{ 2477, 4041},{ 2655, 4052} + }, + /*Cr qi=37 INTER*/ + { + { 89, -9},{ 97, 347},{ 88, 677},{ 102, 1048}, + { 118, 1432},{ 130, 1802},{ 141, 2163},{ 154, 2517}, + { 172, 2857},{ 192, 3181},{ 216, 3494},{ 246, 3793}, + { 286, 4074},{ 337, 4343},{ 395, 4600},{ 464, 4837}, + { 534, 5066},{ 608, 5289},{ 694, 5501},{ 788, 5704}, + { 893, 5901},{ 1010, 6088},{ 1151, 6249},{ 1331, 6374} + } + } + }, + { + { + /*Y' qi=38 INTRA*/ + { + { 107, 65},{ 476, 1286},{ 968, 2148},{ 1548, 2641}, + { 2141, 2979},{ 2757, 3289},{ 3390, 3564},{ 4020, 3784}, + { 4632, 3957},{ 5224, 4097},{ 5794, 4201},{ 6326, 4250}, + { 6828, 4274},{ 7309, 4322},{ 7790, 4401},{ 8271, 4463}, + { 8729, 4498},{ 9165, 4540},{ 9552, 4566},{ 9901, 4560}, + {10266, 4552},{10617, 4563},{10964, 4572},{11393, 4567} + }, + /*Y' qi=38 INTER*/ + { + { 57, -13},{ 118, 1332},{ 233, 2665},{ 386, 3856}, + { 620, 4899},{ 1070, 5722},{ 1849, 6211},{ 2898, 6384}, + { 3989, 6376},{ 4947, 6311},{ 5754, 6249},{ 6454, 6199}, + { 7077, 6161},{ 7640, 6132},{ 8159, 6101},{ 8639, 6076}, + { 9081, 6054},{ 9502, 6037},{ 9900, 6027},{10274, 6012}, + {10621, 5999},{10938, 5991},{11237, 5977},{11557, 5966} + } + }, + { + /*Cb qi=38 INTRA*/ + { + { 8, 3},{ 104, 370},{ 179, 744},{ 243, 1139}, + { 338, 1498},{ 458, 1801},{ 584, 2060},{ 700, 2297}, + { 812, 2514},{ 935, 2699},{ 1061, 2858},{ 1189, 3007}, + { 1321, 3141},{ 1446, 3266},{ 1563, 3388},{ 1684, 3512}, + { 1816, 3614},{ 1942, 3702},{ 2055, 3793},{ 2201, 3857}, + { 2357, 3923},{ 2477, 3994},{ 2593, 4061},{ 2768, 4178} + }, + /*Cb qi=38 INTER*/ + { + { 118, 24},{ 102, 342},{ 91, 663},{ 101, 1040}, + { 116, 1427},{ 131, 1799},{ 147, 2152},{ 168, 2491}, + { 191, 2822},{ 215, 3139},{ 244, 3441},{ 276, 3731}, + { 316, 4013},{ 363, 4286},{ 423, 4546},{ 495, 4795}, + { 584, 5028},{ 691, 5242},{ 814, 5439},{ 959, 5608}, + { 1119, 5759},{ 1277, 5906},{ 1449, 6035},{ 1655, 6144} + } + }, + { + /*Cr qi=38 INTRA*/ + { + { 12, 6},{ 106, 387},{ 182, 771},{ 261, 1168}, + { 364, 1514},{ 483, 1802},{ 603, 2053},{ 707, 2282}, + { 817, 2489},{ 933, 2670},{ 1074, 2825},{ 1210, 2967}, + { 1320, 3104},{ 1444, 3229},{ 1599, 3324},{ 1735, 3396}, + { 1846, 3464},{ 1971, 3547},{ 2086, 3646},{ 2206, 3711}, + { 2366, 3773},{ 2499, 3859},{ 2603, 3945},{ 2766, 3952} + }, + /*Cr qi=38 INTER*/ + { + { 86, -9},{ 91, 352},{ 85, 680},{ 102, 1053}, + { 119, 1435},{ 132, 1799},{ 146, 2153},{ 162, 2501}, + { 183, 2835},{ 209, 3154},{ 240, 3458},{ 278, 3751}, + { 327, 4025},{ 388, 4284},{ 455, 4532},{ 529, 4766}, + { 616, 4980},{ 711, 5188},{ 815, 5386},{ 920, 5583}, + { 1042, 5770},{ 1186, 5936},{ 1348, 6080},{ 1542, 6196} + } + } + }, + { + { + /*Y' qi=39 INTRA*/ + { + { 103, 66},{ 479, 1283},{ 998, 2125},{ 1610, 2591}, + { 2223, 2913},{ 2855, 3214},{ 3501, 3482},{ 4146, 3698}, + { 4772, 3868},{ 5376, 3999},{ 5956, 4095},{ 6496, 4140}, + { 7008, 4162},{ 7499, 4209},{ 7987, 4282},{ 8478, 4338}, + { 8947, 4374},{ 9385, 4417},{ 9783, 4437},{10143, 4433}, + {10504, 4424},{10866, 4435},{11225, 4444},{11665, 4430} + }, + /*Y' qi=39 INTER*/ + { + { 56, 2},{ 118, 1332},{ 235, 2660},{ 395, 3843}, + { 653, 4867},{ 1153, 5652},{ 2003, 6089},{ 3113, 6214}, + { 4228, 6178},{ 5189, 6102},{ 6002, 6031},{ 6707, 5976}, + { 7336, 5936},{ 7901, 5900},{ 8424, 5870},{ 8915, 5844}, + { 9361, 5822},{ 9784, 5807},{10187, 5794},{10571, 5778}, + {10931, 5763},{11264, 5751},{11582, 5742},{11916, 5730} + } + }, + { + /*Cb qi=39 INTRA*/ + { + { 8, 3},{ 104, 370},{ 179, 744},{ 244, 1138}, + { 340, 1496},{ 461, 1796},{ 588, 2053},{ 705, 2288}, + { 820, 2503},{ 945, 2684},{ 1073, 2840},{ 1210, 2981}, + { 1352, 3106},{ 1480, 3225},{ 1603, 3342},{ 1728, 3464}, + { 1865, 3559},{ 1990, 3645},{ 2106, 3734},{ 2258, 3796}, + { 2413, 3856},{ 2540, 3920},{ 2667, 3986},{ 2887, 4060} + }, + /*Cb qi=39 INTER*/ + { + { 119, 19},{ 103, 340},{ 90, 664},{ 100, 1040}, + { 115, 1426},{ 131, 1797},{ 148, 2148},{ 169, 2486}, + { 192, 2816},{ 217, 3131},{ 247, 3432},{ 282, 3721}, + { 324, 3999},{ 374, 4268},{ 435, 4526},{ 520, 4766}, + { 621, 4990},{ 738, 5194},{ 878, 5376},{ 1035, 5543}, + { 1202, 5686},{ 1374, 5819},{ 1545, 5950},{ 1729, 6064} + } + }, + { + /*Cr qi=39 INTRA*/ + { + { 12, 6},{ 106, 387},{ 182, 771},{ 262, 1167}, + { 365, 1512},{ 486, 1798},{ 608, 2047},{ 713, 2274}, + { 824, 2479},{ 945, 2655},{ 1091, 2804},{ 1231, 2941}, + { 1346, 3073},{ 1475, 3194},{ 1633, 3282},{ 1778, 3345}, + { 1891, 3414},{ 2013, 3501},{ 2138, 3584},{ 2266, 3640}, + { 2428, 3701},{ 2568, 3782},{ 2674, 3863},{ 2816, 3894} + }, + /*Cr qi=39 INTER*/ + { + { 88, -7},{ 92, 352},{ 85, 680},{ 102, 1053}, + { 119, 1434},{ 132, 1797},{ 146, 2151},{ 163, 2498}, + { 185, 2830},{ 211, 3147},{ 243, 3451},{ 285, 3735}, + { 337, 4005},{ 401, 4260},{ 477, 4499},{ 565, 4721}, + { 655, 4937},{ 749, 5148},{ 858, 5344},{ 979, 5529}, + { 1110, 5710},{ 1264, 5871},{ 1460, 5990},{ 1677, 6086} + } + } + }, + { + { + /*Y' qi=40 INTRA*/ + { + { 98, 71},{ 491, 1274},{ 1023, 2103},{ 1641, 2559}, + { 2257, 2877},{ 2898, 3171},{ 3566, 3429},{ 4233, 3629}, + { 4881, 3784},{ 5499, 3906},{ 6088, 3997},{ 6631, 4040}, + { 7145, 4060},{ 7640, 4107},{ 8128, 4178},{ 8618, 4233}, + { 9077, 4267},{ 9514, 4304},{ 9919, 4324},{10277, 4317}, + {10635, 4312},{10985, 4324},{11338, 4331},{11792, 4334} + }, + /*Y' qi=40 INTER*/ + { + { 63, -26},{ 125, 1331},{ 256, 2640},{ 439, 3801}, + { 757, 4782},{ 1391, 5474},{ 2399, 5805},{ 3582, 5870}, + { 4678, 5824},{ 5600, 5763},{ 6386, 5710},{ 7076, 5667}, + { 7693, 5637},{ 8252, 5610},{ 8775, 5586},{ 9255, 5571}, + { 9694, 5556},{10115, 5541},{10530, 5530},{10903, 5522}, + {11242, 5515},{11596, 5501},{11904, 5482},{12205, 5475} + } + }, + { + /*Cb qi=40 INTRA*/ + { + { 8, 3},{ 108, 371},{ 189, 743},{ 265, 1128}, + { 371, 1475},{ 499, 1767},{ 628, 2022},{ 746, 2256}, + { 864, 2467},{ 991, 2647},{ 1124, 2801},{ 1270, 2933}, + { 1412, 3054},{ 1547, 3165},{ 1677, 3277},{ 1804, 3393}, + { 1946, 3483},{ 2078, 3569},{ 2201, 3651},{ 2352, 3711}, + { 2513, 3766},{ 2643, 3826},{ 2775, 3880},{ 3025, 3919} + }, + /*Cb qi=40 INTER*/ + { + { 114, 35},{ 104, 349},{ 96, 667},{ 106, 1040}, + { 121, 1423},{ 138, 1789},{ 158, 2132},{ 184, 2464}, + { 212, 2787},{ 242, 3095},{ 279, 3389},{ 321, 3671}, + { 374, 3941},{ 438, 4199},{ 517, 4446},{ 617, 4673}, + { 740, 4881},{ 891, 5064},{ 1058, 5225},{ 1239, 5372}, + { 1441, 5499},{ 1638, 5610},{ 1840, 5719},{ 2076, 5814} + } + }, + { + /*Cr qi=40 INTRA*/ + { + { 14, 7},{ 114, 389},{ 193, 771},{ 283, 1156}, + { 399, 1488},{ 523, 1768},{ 643, 2018},{ 752, 2245}, + { 865, 2450},{ 984, 2626},{ 1139, 2763},{ 1290, 2887}, + { 1413, 3014},{ 1550, 3128},{ 1711, 3211},{ 1865, 3268}, + { 1981, 3334},{ 2103, 3415},{ 2237, 3486},{ 2365, 3543}, + { 2529, 3610},{ 2666, 3700},{ 2775, 3779},{ 2929, 3803} + }, + /*Cr qi=40 INTER*/ + { + { 89, -8},{ 95, 353},{ 90, 681},{ 107, 1053}, + { 124, 1430},{ 139, 1787},{ 156, 2136},{ 177, 2477}, + { 203, 2803},{ 237, 3112},{ 276, 3406},{ 329, 3683}, + { 395, 3942},{ 475, 4182},{ 567, 4407},{ 665, 4624}, + { 767, 4834},{ 879, 5032},{ 1011, 5213},{ 1169, 5375}, + { 1348, 5525},{ 1547, 5654},{ 1785, 5743},{ 2066, 5787} + } + } + }, + { + { + /*Y' qi=41 INTRA*/ + { + { 98, 71},{ 495, 1272},{ 1040, 2090},{ 1675, 2533}, + { 2302, 2842},{ 2953, 3132},{ 3631, 3381},{ 4309, 3574}, + { 4966, 3726},{ 5593, 3846},{ 6189, 3934},{ 6738, 3972}, + { 7256, 3991},{ 7754, 4036},{ 8250, 4099},{ 8747, 4150}, + { 9207, 4185},{ 9650, 4222},{10057, 4242},{10411, 4237}, + {10771, 4230},{11127, 4244},{11486, 4254},{11933, 4252} + }, + /*Y' qi=41 INTER*/ + { + { 65, -25},{ 125, 1331},{ 260, 2633},{ 457, 3782}, + { 807, 4740},{ 1499, 5397},{ 2562, 5693},{ 3766, 5743}, + { 4859, 5695},{ 5776, 5638},{ 6556, 5590},{ 7243, 5554}, + { 7859, 5529},{ 8417, 5506},{ 8935, 5486},{ 9419, 5473}, + { 9869, 5460},{10296, 5446},{10711, 5436},{11089, 5430}, + {11445, 5421},{11802, 5412},{12129, 5404},{12465, 5393} + } + }, + { + /*Cb qi=41 INTRA*/ + { + { 8, 3},{ 108, 371},{ 189, 743},{ 267, 1126}, + { 374, 1471},{ 504, 1760},{ 635, 2011},{ 758, 2241}, + { 881, 2447},{ 1013, 2621},{ 1147, 2773},{ 1293, 2906}, + { 1441, 3023},{ 1580, 3131},{ 1712, 3243},{ 1844, 3360}, + { 1985, 3451},{ 2114, 3532},{ 2240, 3613},{ 2390, 3680}, + { 2550, 3740},{ 2687, 3800},{ 2825, 3862},{ 3052, 3944} + }, + /*Cb qi=41 INTER*/ + { + { 104, 39},{ 100, 350},{ 95, 667},{ 105, 1040}, + { 121, 1422},{ 137, 1787},{ 159, 2129},{ 185, 2459}, + { 216, 2778},{ 249, 3083},{ 287, 3374},{ 335, 3653}, + { 393, 3920},{ 462, 4175},{ 549, 4414},{ 660, 4636}, + { 791, 4839},{ 952, 5014},{ 1135, 5166},{ 1337, 5297}, + { 1552, 5411},{ 1752, 5530},{ 1972, 5634},{ 2224, 5724} + } + }, + { + /*Cr qi=41 INTRA*/ + { + { 15, 7},{ 115, 389},{ 193, 770},{ 284, 1154}, + { 401, 1484},{ 528, 1761},{ 652, 2005},{ 764, 2228}, + { 882, 2427},{ 1008, 2599},{ 1167, 2734},{ 1320, 2859}, + { 1443, 2990},{ 1580, 3103},{ 1743, 3181},{ 1894, 3241}, + { 2012, 3309},{ 2141, 3385},{ 2272, 3459},{ 2398, 3519}, + { 2566, 3584},{ 2707, 3680},{ 2816, 3762},{ 2991, 3770} + }, + /*Cr qi=41 INTER*/ + { + { 92, -9},{ 98, 354},{ 90, 682},{ 107, 1052}, + { 124, 1429},{ 139, 1786},{ 156, 2132},{ 178, 2471}, + { 207, 2794},{ 241, 3100},{ 285, 3391},{ 345, 3662}, + { 417, 3915},{ 503, 4151},{ 600, 4375},{ 703, 4589}, + { 815, 4791},{ 942, 4981},{ 1088, 5155},{ 1250, 5316}, + { 1432, 5462},{ 1653, 5575},{ 1930, 5639},{ 2250, 5655} + } + } + }, + { + { + /*Y' qi=42 INTRA*/ + { + { 109, 75},{ 534, 1257},{ 1114, 2047},{ 1793, 2456}, + { 2461, 2735},{ 3157, 2994},{ 3879, 3221},{ 4595, 3396}, + { 5282, 3531},{ 5931, 3638},{ 6546, 3714},{ 7105, 3749}, + { 7633, 3766},{ 8147, 3803},{ 8652, 3865},{ 9148, 3915}, + { 9613, 3946},{10075, 3976},{10489, 3997},{10835, 3994}, + {11195, 3985},{11553, 3997},{11909, 4004},{12369, 3990} + }, + /*Y' qi=42 INTER*/ + { + { 69, -23},{ 134, 1332},{ 287, 2611},{ 521, 3730}, + { 970, 4624},{ 1827, 5176},{ 3028, 5382},{ 4262, 5389}, + { 5325, 5338},{ 6214, 5291},{ 6976, 5255},{ 7651, 5228}, + { 8260, 5206},{ 8821, 5190},{ 9343, 5177},{ 9823, 5165}, + {10273, 5152},{10709, 5143},{11121, 5136},{11502, 5129}, + {11857, 5125},{12193, 5115},{12520, 5107},{12802, 5097} + } + }, + { + /*Cb qi=42 INTRA*/ + { + { 9, 3},{ 113, 371},{ 199, 743},{ 279, 1123}, + { 390, 1462},{ 525, 1743},{ 662, 1986},{ 789, 2208}, + { 916, 2406},{ 1057, 2571},{ 1204, 2712},{ 1362, 2835}, + { 1524, 2943},{ 1676, 3040},{ 1815, 3145},{ 1959, 3249}, + { 2117, 3325},{ 2249, 3406},{ 2377, 3488},{ 2537, 3547}, + { 2706, 3597},{ 2854, 3646},{ 2999, 3705},{ 3236, 3759} + }, + /*Cb qi=42 INTER*/ + { + { 114, 44},{ 107, 353},{ 101, 670},{ 111, 1041}, + { 129, 1418},{ 148, 1775},{ 174, 2110},{ 208, 2432}, + { 244, 2746},{ 283, 3046},{ 330, 3330},{ 388, 3602}, + { 460, 3858},{ 546, 4101},{ 655, 4326},{ 793, 4530}, + { 966, 4703},{ 1165, 4851},{ 1388, 4980},{ 1630, 5088}, + { 1869, 5189},{ 2122, 5268},{ 2403, 5328},{ 2667, 5417} + } + }, + { + /*Cr qi=42 INTRA*/ + { + { 15, 7},{ 120, 390},{ 202, 771},{ 298, 1150}, + { 421, 1473},{ 553, 1743},{ 681, 1982},{ 796, 2199}, + { 923, 2388},{ 1062, 2547},{ 1225, 2678},{ 1392, 2792}, + { 1531, 2907},{ 1682, 3007},{ 1856, 3074},{ 2009, 3134}, + { 2138, 3192},{ 2274, 3257},{ 2407, 3333},{ 2536, 3393}, + { 2711, 3455},{ 2875, 3531},{ 3000, 3598},{ 3186, 3599} + }, + /*Cr qi=42 INTER*/ + { + { 87, -4},{ 95, 358},{ 97, 683},{ 113, 1052}, + { 131, 1423},{ 148, 1774},{ 170, 2116},{ 198, 2448}, + { 234, 2762},{ 276, 3062},{ 331, 3343},{ 404, 3603}, + { 494, 3844},{ 598, 4067},{ 715, 4276},{ 842, 4471}, + { 977, 4661},{ 1128, 4840},{ 1311, 4991},{ 1516, 5127}, + { 1759, 5233},{ 2050, 5300},{ 2377, 5323},{ 2710, 5304} + } + } + }, + { + { + /*Y' qi=43 INTRA*/ + { + { 99, 79},{ 557, 1244},{ 1175, 2016},{ 1882, 2408}, + { 2570, 2677},{ 3288, 2926},{ 4030, 3141},{ 4760, 3307}, + { 5458, 3435},{ 6115, 3537},{ 6743, 3608},{ 7312, 3636}, + { 7841, 3652},{ 8357, 3687},{ 8870, 3742},{ 9376, 3788}, + { 9850, 3821},{10315, 3853},{10734, 3873},{11084, 3870}, + {11442, 3862},{11800, 3874},{12160, 3879},{12618, 3876} + }, + /*Y' qi=43 INTER*/ + { + { 69, -22},{ 134, 1331},{ 294, 2601},{ 551, 3703}, + { 1056, 4563},{ 2003, 5061},{ 3276, 5215},{ 4534, 5194}, + { 5599, 5133},{ 6488, 5083},{ 7257, 5044},{ 7938, 5014}, + { 8556, 4992},{ 9124, 4975},{ 9648, 4960},{10138, 4948}, + {10594, 4939},{11039, 4926},{11462, 4919},{11847, 4912}, + {12216, 4904},{12570, 4896},{12883, 4889},{13189, 4879} + } + }, + { + /*Cb qi=43 INTRA*/ + { + { 9, 3},{ 114, 371},{ 202, 740},{ 294, 1110}, + { 417, 1440},{ 558, 1716},{ 700, 1956},{ 833, 2172}, + { 966, 2365},{ 1116, 2524},{ 1269, 2661},{ 1431, 2781}, + { 1599, 2885},{ 1756, 2980},{ 1902, 3082},{ 2051, 3185}, + { 2209, 3261},{ 2337, 3342},{ 2464, 3420},{ 2633, 3475}, + { 2809, 3525},{ 2948, 3579},{ 3094, 3633},{ 3347, 3678} + }, + /*Cb qi=43 INTER*/ + { + { 111, 44},{ 106, 353},{ 102, 670},{ 112, 1040}, + { 128, 1416},{ 148, 1771},{ 176, 2104},{ 211, 2424}, + { 250, 2734},{ 293, 3030},{ 347, 3309},{ 411, 3575}, + { 490, 3828},{ 589, 4064},{ 716, 4278},{ 869, 4472}, + { 1050, 4640},{ 1264, 4781},{ 1512, 4895},{ 1775, 4991}, + { 2042, 5069},{ 2310, 5141},{ 2593, 5207},{ 2912, 5239} + } + }, + { + /*Cr qi=43 INTRA*/ + { + { 15, 7},{ 121, 390},{ 208, 767},{ 315, 1135}, + { 449, 1449},{ 586, 1715},{ 718, 1950},{ 843, 2158}, + { 977, 2342},{ 1120, 2501},{ 1290, 2632},{ 1466, 2739}, + { 1613, 2845},{ 1763, 2945},{ 1937, 3015},{ 2093, 3070}, + { 2225, 3126},{ 2366, 3194},{ 2501, 3267},{ 2634, 3324}, + { 2815, 3385},{ 2964, 3466},{ 3087, 3538},{ 3263, 3555} + }, + /*Cr qi=43 INTER*/ + { + { 84, -4},{ 93, 358},{ 95, 683},{ 113, 1052}, + { 131, 1421},{ 148, 1770},{ 171, 2110},{ 201, 2439}, + { 240, 2750},{ 287, 3046},{ 348, 3322},{ 429, 3576}, + { 527, 3811},{ 641, 4029},{ 767, 4230},{ 904, 4422}, + { 1053, 4603},{ 1225, 4765},{ 1433, 4903},{ 1661, 5030}, + { 1928, 5121},{ 2252, 5160},{ 2604, 5164},{ 2979, 5125} + } + } + }, + { + { + /*Y' qi=44 INTRA*/ + { + { 103, 80},{ 560, 1244},{ 1183, 2009},{ 1891, 2391}, + { 2586, 2649},{ 3324, 2884},{ 4093, 3089},{ 4850, 3243}, + { 5575, 3358},{ 6252, 3452},{ 6886, 3518},{ 7459, 3546}, + { 7993, 3562},{ 8515, 3594},{ 9030, 3645},{ 9534, 3691}, + {10004, 3723},{10469, 3750},{10887, 3765},{11236, 3766}, + {11596, 3762},{11960, 3775},{12317, 3784},{12766, 3789} + }, + /*Y' qi=44 INTER*/ + { + { 77, -24},{ 145, 1332},{ 332, 2580},{ 642, 3649}, + { 1270, 4438},{ 2360, 4860},{ 3685, 4982},{ 4910, 4966}, + { 5929, 4928},{ 6785, 4900},{ 7529, 4880},{ 8198, 4863}, + { 8804, 4850},{ 9361, 4842},{ 9882, 4836},{10371, 4830}, + {10827, 4822},{11262, 4816},{11672, 4811},{12052, 4807}, + {12431, 4806},{12780, 4798},{13095, 4792},{13401, 4791} + } + }, + { + /*Cb qi=44 INTRA*/ + { + { 9, 2},{ 122, 371},{ 214, 741},{ 307, 1109}, + { 433, 1432},{ 576, 1704},{ 718, 1939},{ 855, 2152}, + { 991, 2340},{ 1141, 2497},{ 1298, 2632},{ 1463, 2749}, + { 1636, 2851},{ 1796, 2944},{ 1947, 3041},{ 2101, 3140}, + { 2260, 3219},{ 2392, 3297},{ 2527, 3366},{ 2693, 3424}, + { 2872, 3477},{ 3025, 3525},{ 3175, 3584},{ 3451, 3626} + }, + /*Cb qi=44 INTER*/ + { + { 111, 14},{ 110, 339},{ 109, 671},{ 120, 1040}, + { 139, 1410},{ 162, 1758},{ 197, 2084},{ 243, 2397}, + { 291, 2702},{ 342, 2992},{ 405, 3265},{ 484, 3521}, + { 584, 3760},{ 705, 3983},{ 855, 4185},{ 1048, 4356}, + { 1274, 4500},{ 1531, 4617},{ 1816, 4707},{ 2111, 4783}, + { 2409, 4846},{ 2720, 4901},{ 3044, 4957},{ 3391, 4985} + } + }, + { + /*Cr qi=44 INTRA*/ + { + { 17, 7},{ 128, 392},{ 219, 770},{ 329, 1135}, + { 465, 1442},{ 601, 1703},{ 734, 1935},{ 862, 2142}, + { 998, 2325},{ 1147, 2482},{ 1321, 2606},{ 1496, 2710}, + { 1649, 2813},{ 1809, 2908},{ 1984, 2977},{ 2143, 3032}, + { 2279, 3087},{ 2423, 3152},{ 2559, 3225},{ 2684, 3288}, + { 2866, 3351},{ 3025, 3426},{ 3161, 3492},{ 3372, 3500} + }, + /*Cr qi=44 INTER*/ + { + { 89, 0},{ 101, 352},{ 104, 683},{ 121, 1051}, + { 141, 1414},{ 163, 1757},{ 192, 2092},{ 231, 2415}, + { 278, 2720},{ 336, 3007},{ 412, 3273},{ 510, 3516}, + { 633, 3733},{ 769, 3936},{ 914, 4130},{ 1076, 4307}, + { 1256, 4472},{ 1469, 4617},{ 1723, 4732},{ 2012, 4822}, + { 2347, 4871},{ 2716, 4875},{ 3082, 4866},{ 3422, 4826} + } + } + }, + { + { + /*Y' qi=45 INTRA*/ + { + { 119, 78},{ 610, 1226},{ 1271, 1965},{ 2026, 2319}, + { 2768, 2550},{ 3556, 2757},{ 4369, 2938},{ 5157, 3076}, + { 5901, 3182},{ 6598, 3268},{ 7253, 3326},{ 7844, 3343}, + { 8392, 3356},{ 8922, 3386},{ 9453, 3433},{ 9973, 3474}, + {10457, 3503},{10929, 3530},{11351, 3543},{11709, 3541}, + {12068, 3537},{12434, 3547},{12805, 3555},{13268, 3563} + }, + /*Y' qi=45 INTER*/ + { + { 77, -20},{ 146, 1330},{ 342, 2566},{ 699, 3604}, + { 1439, 4332},{ 2669, 4672},{ 4075, 4727},{ 5318, 4679}, + { 6345, 4630},{ 7209, 4595},{ 7963, 4570},{ 8644, 4551}, + { 9262, 4535},{ 9831, 4525},{10370, 4515},{10872, 4506}, + {11334, 4500},{11783, 4492},{12219, 4489},{12617, 4483}, + {12995, 4477},{13350, 4472},{13674, 4466},{13968, 4468} + } + }, + { + /*Cb qi=45 INTRA*/ + { + { 9, 2},{ 122, 370},{ 219, 735},{ 324, 1096}, + { 465, 1414},{ 619, 1679},{ 771, 1905},{ 920, 2103}, + { 1070, 2276},{ 1236, 2419},{ 1410, 2539},{ 1595, 2644}, + { 1784, 2736},{ 1949, 2831},{ 2104, 2931},{ 2275, 3021}, + { 2443, 3092},{ 2586, 3166},{ 2735, 3234},{ 2904, 3288}, + { 3093, 3338},{ 3262, 3382},{ 3419, 3427},{ 3708, 3456} + }, + /*Cb qi=45 INTER*/ + { + { 103, 0},{ 109, 339},{ 109, 670},{ 119, 1039}, + { 137, 1408},{ 162, 1754},{ 199, 2076},{ 248, 2386}, + { 301, 2684},{ 360, 2967},{ 433, 3234},{ 525, 3481}, + { 640, 3713},{ 780, 3924},{ 956, 4110},{ 1176, 4266}, + { 1438, 4390},{ 1736, 4481},{ 2057, 4553},{ 2385, 4613}, + { 2718, 4656},{ 3056, 4698},{ 3416, 4733},{ 3799, 4755} + } + }, + { + /*Cr qi=45 INTRA*/ + { + { 16, 7},{ 128, 391},{ 225, 763},{ 350, 1120}, + { 500, 1420},{ 649, 1673},{ 792, 1893},{ 929, 2089}, + { 1084, 2257},{ 1250, 2401},{ 1440, 2518},{ 1633, 2614}, + { 1799, 2708},{ 1968, 2798},{ 2151, 2863},{ 2314, 2914}, + { 2453, 2968},{ 2611, 3025},{ 2759, 3095},{ 2887, 3160}, + { 3082, 3210},{ 3259, 3278},{ 3403, 3342},{ 3593, 3354} + }, + /*Cr qi=45 INTER*/ + { + { 92, 0},{ 101, 352},{ 103, 682},{ 120, 1049}, + { 140, 1412},{ 163, 1752},{ 193, 2083},{ 234, 2402}, + { 287, 2702},{ 353, 2983},{ 442, 3240},{ 557, 3471}, + { 694, 3680},{ 846, 3873},{ 1014, 4056},{ 1200, 4224}, + { 1414, 4369},{ 1664, 4495},{ 1946, 4595},{ 2278, 4654}, + { 2654, 4673},{ 3047, 4658},{ 3438, 4627},{ 3825, 4585} + } + } + }, + { + { + /*Y' qi=46 INTRA*/ + { + { 119, 78},{ 610, 1227},{ 1277, 1960},{ 2043, 2309}, + { 2805, 2529},{ 3618, 2719},{ 4452, 2887},{ 5257, 3016}, + { 6017, 3115},{ 6727, 3195},{ 7392, 3248},{ 7984, 3267}, + { 8528, 3281},{ 9059, 3310},{ 9593, 3354},{10119, 3395}, + {10599, 3425},{11064, 3450},{11493, 3464},{11850, 3466}, + {12207, 3462},{12578, 3471},{12948, 3480},{13407, 3487} + }, + /*Y' qi=46 INTER*/ + { + { 74, -14},{ 149, 1326},{ 382, 2538},{ 807, 3541}, + { 1670, 4211},{ 3000, 4499},{ 4416, 4533},{ 5628, 4490}, + { 6628, 4453},{ 7479, 4425},{ 8228, 4406},{ 8902, 4393}, + { 9521, 4380},{10090, 4371},{10623, 4364},{11124, 4356}, + {11586, 4351},{12043, 4344},{12476, 4341},{12863, 4340}, + {13244, 4337},{13610, 4329},{13936, 4324},{14246, 4329} + } + }, + { + /*Cb qi=46 INTRA*/ + { + { 11, 2},{ 132, 371},{ 234, 737},{ 340, 1094}, + { 481, 1405},{ 637, 1667},{ 791, 1891},{ 944, 2084}, + { 1099, 2253},{ 1268, 2392},{ 1444, 2507},{ 1633, 2610}, + { 1825, 2700},{ 1990, 2794},{ 2147, 2895},{ 2321, 2984}, + { 2493, 3053},{ 2640, 3126},{ 2787, 3198},{ 2954, 3253}, + { 3146, 3297},{ 3313, 3344},{ 3473, 3393},{ 3757, 3434} + }, + /*Cb qi=46 INTER*/ + { + { 97, 0},{ 109, 339},{ 108, 669},{ 120, 1035}, + { 142, 1398},{ 173, 1737},{ 221, 2052},{ 281, 2353}, + { 345, 2646},{ 415, 2924},{ 504, 3183},{ 616, 3421}, + { 749, 3643},{ 914, 3842},{ 1123, 4012},{ 1379, 4150}, + { 1685, 4250},{ 2014, 4327},{ 2366, 4382},{ 2731, 4426}, + { 3083, 4470},{ 3445, 4490},{ 3805, 4511},{ 4146, 4539} + } + }, + { + /*Cr qi=46 INTRA*/ + { + { 19, 7},{ 137, 393},{ 237, 765},{ 364, 1116}, + { 516, 1411},{ 665, 1662},{ 809, 1880},{ 951, 2072}, + { 1109, 2236},{ 1278, 2378},{ 1474, 2491},{ 1669, 2584}, + { 1835, 2678},{ 2014, 2766},{ 2203, 2828},{ 2366, 2880}, + { 2506, 2933},{ 2661, 2988},{ 2810, 3053},{ 2941, 3116}, + { 3131, 3175},{ 3310, 3243},{ 3461, 3303},{ 3656, 3321} + }, + /*Cr qi=46 INTER*/ + { + { 91, 1},{ 103, 351},{ 104, 681},{ 121, 1046}, + { 144, 1401},{ 173, 1736},{ 213, 2060},{ 265, 2373}, + { 330, 2666},{ 410, 2938},{ 517, 3185},{ 655, 3404}, + { 815, 3601},{ 989, 3784},{ 1183, 3951},{ 1400, 4104}, + { 1649, 4241},{ 1933, 4352},{ 2261, 4427},{ 2646, 4458}, + { 3057, 4446},{ 3453, 4418},{ 3820, 4385},{ 4171, 4352} + } + } + }, + { + { + /*Y' qi=47 INTRA*/ + { + { 117, 83},{ 670, 1205},{ 1408, 1904},{ 2239, 2219}, + { 3049, 2414},{ 3905, 2584},{ 4775, 2734},{ 5610, 2852}, + { 6393, 2944},{ 7121, 3017},{ 7804, 3066},{ 8407, 3081}, + { 8957, 3093},{ 9498, 3119},{10043, 3160},{10582, 3199}, + {11083, 3226},{11561, 3250},{11993, 3263},{12352, 3264}, + {12711, 3259},{13092, 3266},{13463, 3271},{13918, 3275} + }, + /*Y' qi=47 INTER*/ + { + { 74, -11},{ 148, 1325},{ 404, 2518},{ 910, 3478}, + { 1916, 4080},{ 3369, 4298},{ 4823, 4292},{ 6035, 4238}, + { 7037, 4197},{ 7894, 4168},{ 8650, 4146},{ 9337, 4129}, + { 9968, 4116},{10549, 4105},{11096, 4096},{11605, 4089}, + {12081, 4083},{12547, 4076},{12990, 4070},{13399, 4070}, + {13776, 4065},{14133, 4059},{14486, 4057},{14842, 4053} + } + }, + { + /*Cb qi=47 INTRA*/ + { + { 11, 2},{ 133, 370},{ 242, 731},{ 367, 1077}, + { 524, 1378},{ 692, 1630},{ 860, 1844},{ 1028, 2024}, + { 1203, 2178},{ 1393, 2305},{ 1582, 2413},{ 1787, 2507}, + { 1992, 2590},{ 2175, 2676},{ 2351, 2767},{ 2534, 2851}, + { 2707, 2923},{ 2862, 2994},{ 3021, 3060},{ 3193, 3111}, + { 3396, 3147},{ 3573, 3184},{ 3752, 3220},{ 4038, 3255} + }, + /*Cb qi=47 INTER*/ + { + { 101, 0},{ 107, 339},{ 108, 667},{ 120, 1033}, + { 142, 1394},{ 175, 1729},{ 227, 2040},{ 295, 2335}, + { 369, 2619},{ 452, 2888},{ 556, 3138},{ 686, 3368}, + { 850, 3574},{ 1050, 3758},{ 1299, 3910},{ 1605, 4024}, + { 1950, 4104},{ 2317, 4163},{ 2689, 4210},{ 3077, 4239}, + { 3466, 4258},{ 3840, 4278},{ 4205, 4298},{ 4515, 4340} + } + }, + { + /*Cr qi=47 INTRA*/ + { + { 19, 7},{ 138, 392},{ 248, 758},{ 396, 1094}, + { 563, 1378},{ 723, 1621},{ 881, 1829},{ 1037, 2011}, + { 1214, 2165},{ 1410, 2290},{ 1623, 2393},{ 1834, 2480}, + { 2016, 2564},{ 2203, 2647},{ 2405, 2707},{ 2569, 2757}, + { 2709, 2810},{ 2871, 2860},{ 3027, 2924},{ 3178, 2980}, + { 3375, 3034},{ 3563, 3097},{ 3724, 3151},{ 3952, 3153} + }, + /*Cr qi=47 INTER*/ + { + { 91, 1},{ 100, 351},{ 102, 681},{ 120, 1043}, + { 144, 1397},{ 175, 1729},{ 219, 2049},{ 277, 2356}, + { 353, 2640},{ 451, 2902},{ 579, 3136},{ 739, 3342}, + { 926, 3525},{ 1125, 3698},{ 1343, 3859},{ 1595, 3998}, + { 1881, 4113},{ 2208, 4205},{ 2589, 4253},{ 3014, 4250}, + { 3444, 4220},{ 3838, 4183},{ 4196, 4147},{ 4521, 4116} + } + } + }, + { + { + /*Y' qi=48 INTRA*/ + { + { 107, 87},{ 681, 1200},{ 1456, 1883},{ 2306, 2193}, + { 3122, 2386},{ 3984, 2548},{ 4862, 2693},{ 5704, 2808}, + { 6495, 2899},{ 7232, 2970},{ 7915, 3018},{ 8524, 3034}, + { 9085, 3043},{ 9635, 3068},{10192, 3108},{10735, 3145}, + {11237, 3171},{11719, 3194},{12153, 3207},{12516, 3206}, + {12888, 3202},{13266, 3210},{13637, 3218},{14101, 3219} + }, + /*Y' qi=48 INTER*/ + { + { 83, -18},{ 147, 1328},{ 398, 2519},{ 923, 3468}, + { 1979, 4047},{ 3472, 4246},{ 4936, 4232},{ 6148, 4178}, + { 7150, 4139},{ 8007, 4111},{ 8765, 4091},{ 9458, 4076}, + {10090, 4063},{10676, 4054},{11226, 4045},{11742, 4038}, + {12223, 4033},{12686, 4029},{13127, 4022},{13527, 4015}, + {13915, 4012},{14277, 4007},{14619, 4004},{14966, 4001} + } + }, + { + /*Cb qi=48 INTRA*/ + { + { 11, 2},{ 134, 369},{ 245, 730},{ 373, 1075}, + { 531, 1374},{ 698, 1625},{ 865, 1839},{ 1033, 2019}, + { 1207, 2173},{ 1397, 2300},{ 1588, 2408},{ 1795, 2501}, + { 2003, 2581},{ 2187, 2666},{ 2362, 2757},{ 2548, 2841}, + { 2719, 2912},{ 2876, 2983},{ 3034, 3047},{ 3209, 3097}, + { 3409, 3137},{ 3589, 3178},{ 3762, 3216},{ 4004, 3252} + }, + /*Cb qi=48 INTER*/ + { + { 113, 26},{ 112, 344},{ 111, 668},{ 120, 1032}, + { 141, 1392},{ 173, 1727},{ 224, 2036},{ 290, 2330}, + { 363, 2612},{ 447, 2880},{ 551, 3130},{ 685, 3358}, + { 852, 3563},{ 1061, 3742},{ 1332, 3884},{ 1654, 3993}, + { 2011, 4068},{ 2394, 4120},{ 2782, 4160},{ 3172, 4186}, + { 3557, 4209},{ 3932, 4228},{ 4306, 4237},{ 4675, 4236} + } + }, + { + /*Cr qi=48 INTRA*/ + { + { 18, 7},{ 139, 389},{ 252, 755},{ 404, 1090}, + { 573, 1372},{ 732, 1615},{ 889, 1823},{ 1045, 2005}, + { 1222, 2159},{ 1417, 2285},{ 1631, 2387},{ 1843, 2474}, + { 2027, 2558},{ 2212, 2639},{ 2413, 2697},{ 2578, 2746}, + { 2720, 2798},{ 2887, 2852},{ 3040, 2913},{ 3181, 2970}, + { 3381, 3024},{ 3581, 3081},{ 3743, 3130},{ 3948, 3133} + }, + /*Cr qi=48 INTER*/ + { + { 89, 0},{ 106, 352},{ 105, 682},{ 120, 1044}, + { 144, 1395},{ 174, 1724},{ 215, 2044},{ 270, 2350}, + { 343, 2635},{ 441, 2895},{ 571, 3129},{ 735, 3334}, + { 926, 3518},{ 1139, 3684},{ 1371, 3836},{ 1628, 3977}, + { 1933, 4089},{ 2279, 4164},{ 2672, 4204},{ 3105, 4205}, + { 3533, 4176},{ 3931, 4135},{ 4290, 4089},{ 4624, 4057} + } + } + }, + { + { + /*Y' qi=49 INTRA*/ + { + { 120, 85},{ 706, 1194},{ 1485, 1875},{ 2348, 2187}, + { 3190, 2372},{ 4076, 2521},{ 4967, 2658},{ 5819, 2771}, + { 6611, 2861},{ 7345, 2936},{ 8026, 2990},{ 8626, 3013}, + { 9182, 3030},{ 9723, 3059},{10266, 3100},{10802, 3143}, + {11293, 3179},{11768, 3206},{12201, 3221},{12556, 3225}, + {12914, 3226},{13281, 3237},{13639, 3247},{14089, 3257} + }, + /*Y' qi=49 INTER*/ + { + { 72, -11},{ 155, 1320},{ 458, 2485},{ 1090, 3386}, + { 2284, 3907},{ 3835, 4075},{ 5272, 4064},{ 6449, 4026}, + { 7426, 4003},{ 8267, 3987},{ 9017, 3976},{ 9698, 3967}, + {10328, 3962},{10913, 3959},{11452, 3954},{11961, 3950}, + {12442, 3947},{12904, 3946},{13347, 3945},{13749, 3943}, + {14123, 3941},{14490, 3941},{14826, 3939},{15153, 3937} + } + }, + { + /*Cb qi=49 INTRA*/ + { + { 11, 2},{ 145, 369},{ 262, 729},{ 393, 1070}, + { 557, 1363},{ 731, 1607},{ 907, 1811},{ 1085, 1983}, + { 1268, 2130},{ 1465, 2251},{ 1658, 2359},{ 1868, 2454}, + { 2079, 2534},{ 2264, 2621},{ 2440, 2717},{ 2625, 2802}, + { 2792, 2878},{ 2945, 2954},{ 3106, 3021},{ 3277, 3075}, + { 3466, 3119},{ 3638, 3170},{ 3824, 3213},{ 4100, 3243} + }, + /*Cb qi=49 INTER*/ + { + { 98, -6},{ 113, 343},{ 110, 669},{ 122, 1029}, + { 149, 1380},{ 192, 1706},{ 258, 2007},{ 340, 2293}, + { 426, 2569},{ 525, 2831},{ 653, 3071},{ 814, 3287}, + { 1013, 3478},{ 1262, 3637},{ 1575, 3761},{ 1936, 3851}, + { 2328, 3910},{ 2741, 3949},{ 3163, 3970},{ 3559, 3994}, + { 3936, 4025},{ 4300, 4050},{ 4655, 4060},{ 4962, 4062} + } + }, + { + /*Cr qi=49 INTRA*/ + { + { 19, 7},{ 151, 389},{ 270, 753},{ 427, 1084}, + { 602, 1360},{ 767, 1595},{ 933, 1794},{ 1098, 1968}, + { 1285, 2115},{ 1489, 2237},{ 1699, 2342},{ 1912, 2435}, + { 2101, 2519},{ 2288, 2601},{ 2486, 2663},{ 2651, 2715}, + { 2799, 2769},{ 2958, 2825},{ 3106, 2890},{ 3257, 2948}, + { 3452, 3007},{ 3634, 3075},{ 3786, 3136},{ 3959, 3164} + }, + /*Cr qi=49 INTER*/ + { + { 85, 1},{ 103, 352},{ 104, 681},{ 121, 1039}, + { 152, 1382},{ 195, 1702},{ 248, 2015},{ 316, 2316}, + { 403, 2595},{ 520, 2847},{ 676, 3068},{ 870, 3258}, + { 1091, 3429},{ 1329, 3585},{ 1597, 3725},{ 1894, 3849}, + { 2242, 3940},{ 2656, 3984},{ 3098, 3992},{ 3531, 3981}, + { 3936, 3950},{ 4304, 3915},{ 4646, 3879},{ 4915, 3861} + } + } + }, + { + { + /*Y' qi=50 INTRA*/ + { + { 122, 89},{ 798, 1170},{ 1682, 1812},{ 2613, 2096}, + { 3501, 2260},{ 4430, 2388},{ 5352, 2510},{ 6228, 2613}, + { 7043, 2698},{ 7793, 2770},{ 8486, 2823},{ 9092, 2846}, + { 9652, 2865},{10210, 2895},{10773, 2936},{11315, 2979}, + {11817, 3014},{12297, 3041},{12734, 3057},{13097, 3064}, + {13443, 3067},{13813, 3078},{14190, 3088},{14646, 3103} + }, + /*Y' qi=50 INTER*/ + { + { 73, -11},{ 154, 1318},{ 501, 2457},{ 1281, 3291}, + { 2685, 3719},{ 4356, 3810},{ 5811, 3769},{ 6988, 3726}, + { 7976, 3700},{ 8835, 3682},{ 9606, 3669},{10307, 3659}, + {10953, 3652},{11556, 3645},{12115, 3643},{12641, 3640}, + {13138, 3636},{13613, 3634},{14068, 3629},{14488, 3627}, + {14876, 3625},{15237, 3621},{15585, 3623},{15922, 3629} + } + }, + { + /*Cb qi=50 INTRA*/ + { + { 11, 2},{ 148, 368},{ 278, 724},{ 431, 1052}, + { 613, 1334},{ 806, 1567},{ 1004, 1756},{ 1203, 1915}, + { 1405, 2051},{ 1621, 2163},{ 1833, 2262},{ 2059, 2347}, + { 2280, 2424},{ 2476, 2512},{ 2670, 2598},{ 2864, 2679}, + { 3037, 2754},{ 3201, 2826},{ 3376, 2887},{ 3562, 2936}, + { 3756, 2976},{ 3932, 3022},{ 4117, 3065},{ 4385, 3094} + }, + /*Cb qi=50 INTER*/ + { + { 92, -3},{ 112, 343},{ 109, 669},{ 121, 1027}, + { 149, 1375},{ 196, 1697},{ 270, 1992},{ 366, 2267}, + { 471, 2532},{ 594, 2782},{ 747, 3011},{ 942, 3212}, + { 1189, 3384},{ 1497, 3521},{ 1875, 3613},{ 2297, 3673}, + { 2739, 3710},{ 3195, 3725},{ 3644, 3737},{ 4057, 3751}, + { 4445, 3763},{ 4841, 3769},{ 5211, 3779},{ 5568, 3769} + } + }, + { + /*Cr qi=50 INTRA*/ + { + { 19, 7},{ 155, 388},{ 290, 744},{ 474, 1060}, + { 666, 1324},{ 847, 1549},{ 1033, 1737},{ 1219, 1898}, + { 1428, 2034},{ 1653, 2147},{ 1885, 2245},{ 2115, 2329}, + { 2316, 2410},{ 2517, 2486},{ 2730, 2539},{ 2901, 2586}, + { 3042, 2638},{ 3199, 2693},{ 3366, 2755},{ 3534, 2805}, + { 3738, 2858},{ 3934, 2916},{ 4079, 2975},{ 4257, 2992} + }, + /*Cr qi=50 INTER*/ + { + { 87, 1},{ 102, 353},{ 103, 680},{ 121, 1036}, + { 153, 1377},{ 199, 1694},{ 260, 1999},{ 339, 2291}, + { 446, 2559},{ 590, 2797},{ 780, 3003},{ 1010, 3176}, + { 1267, 3331},{ 1547, 3474},{ 1874, 3594},{ 2245, 3688}, + { 2666, 3742},{ 3130, 3758},{ 3594, 3748},{ 4028, 3711}, + { 4415, 3674},{ 4771, 3641},{ 5122, 3605},{ 5482, 3569} + } + } + }, + { + { + /*Y' qi=51 INTRA*/ + { + { 115, 93},{ 819, 1164},{ 1739, 1806},{ 2695, 2101}, + { 3612, 2257},{ 4552, 2374},{ 5479, 2490},{ 6352, 2593}, + { 7158, 2683},{ 7898, 2761},{ 8580, 2823},{ 9177, 2854}, + { 9728, 2880},{10268, 2917},{10816, 2966},{11350, 3016}, + {11834, 3058},{12311, 3089},{12741, 3109},{13092, 3119}, + {13434, 3126},{13791, 3142},{14156, 3155},{14590, 3171} + }, + /*Y' qi=51 INTER*/ + { + { 58, 0},{ 171, 1307},{ 610, 2407},{ 1563, 3175}, + { 3116, 3545},{ 4789, 3624},{ 6185, 3602},{ 7320, 3583}, + { 8282, 3574},{ 9124, 3569},{ 9878, 3567},{10569, 3565}, + {11207, 3563},{11801, 3564},{12359, 3566},{12884, 3567}, + {13373, 3568},{13841, 3567},{14289, 3566},{14699, 3568}, + {15086, 3568},{15446, 3566},{15788, 3564},{16103, 3568} + } + }, + { + /*Cb qi=51 INTRA*/ + { + { 14, 3},{ 161, 369},{ 297, 722},{ 454, 1047}, + { 639, 1325},{ 833, 1554},{ 1033, 1742},{ 1236, 1897}, + { 1440, 2032},{ 1653, 2148},{ 1860, 2253},{ 2077, 2347}, + { 2288, 2432},{ 2476, 2525},{ 2661, 2621},{ 2841, 2714}, + { 3010, 2797},{ 3170, 2876},{ 3333, 2945},{ 3510, 3000}, + { 3696, 3054},{ 3865, 3114},{ 4046, 3164},{ 4317, 3200} + }, + /*Cb qi=51 INTER*/ + { + { 88, -11},{ 109, 341},{ 109, 668},{ 126, 1019}, + { 168, 1358},{ 233, 1670},{ 329, 1955},{ 451, 2219}, + { 584, 2472},{ 736, 2711},{ 931, 2923},{ 1179, 3104}, + { 1480, 3254},{ 1846, 3368},{ 2265, 3448},{ 2714, 3501}, + { 3180, 3524},{ 3638, 3529},{ 4074, 3543},{ 4485, 3560}, + { 4868, 3571},{ 5238, 3581},{ 5597, 3594},{ 5953, 3591} + } + }, + { + /*Cr qi=51 INTRA*/ + { + { 24, 7},{ 168, 388},{ 309, 742},{ 496, 1054}, + { 688, 1316},{ 873, 1538},{ 1063, 1723},{ 1252, 1882}, + { 1460, 2018},{ 1682, 2134},{ 1907, 2238},{ 2125, 2332}, + { 2317, 2422},{ 2507, 2510},{ 2705, 2575},{ 2869, 2630}, + { 3015, 2684},{ 3178, 2744},{ 3329, 2815},{ 3477, 2878}, + { 3667, 2945},{ 3848, 3016},{ 3997, 3082},{ 4174, 3121} + }, + /*Cr qi=51 INTER*/ + { + { 83, -2},{ 102, 351},{ 102, 680},{ 126, 1029}, + { 172, 1359},{ 238, 1665},{ 321, 1962},{ 422, 2246}, + { 552, 2505},{ 733, 2728},{ 970, 2912},{ 1247, 3069}, + { 1552, 3209},{ 1876, 3338},{ 2251, 3440},{ 2692, 3502}, + { 3161, 3529},{ 3637, 3525},{ 4084, 3509},{ 4487, 3479}, + { 4850, 3444},{ 5181, 3419},{ 5507, 3406},{ 5786, 3398} + } + } + }, + { + { + /*Y' qi=52 INTRA*/ + { + { 117, 93},{ 814, 1168},{ 1729, 1822},{ 2706, 2119}, + { 3655, 2262},{ 4604, 2374},{ 5528, 2490},{ 6394, 2596}, + { 7189, 2691},{ 7921, 2777},{ 8596, 2846},{ 9184, 2885}, + { 9728, 2918},{10260, 2961},{10796, 3014},{11316, 3069}, + {11793, 3115},{12267, 3150},{12692, 3172},{13037, 3185}, + {13367, 3196},{13717, 3214},{14087, 3227},{14521, 3249} + }, + /*Y' qi=52 INTER*/ + { + { 52, 0},{ 169, 1308},{ 668, 2382},{ 1735, 3112}, + { 3384, 3451},{ 5077, 3519},{ 6461, 3506},{ 7587, 3496}, + { 8545, 3494},{ 9384, 3494},{10142, 3498},{10838, 3501}, + {11475, 3503},{12078, 3508},{12640, 3511},{13162, 3513}, + {13654, 3517},{14130, 3521},{14576, 3522},{14980, 3523}, + {15369, 3523},{15737, 3522},{16071, 3521},{16382, 3516} + } + }, + { + /*Cb qi=52 INTRA*/ + { + { 14, 3},{ 163, 369},{ 299, 722},{ 457, 1044}, + { 645, 1319},{ 843, 1545},{ 1050, 1728},{ 1261, 1879}, + { 1468, 2013},{ 1678, 2132},{ 1883, 2240},{ 2093, 2338}, + { 2301, 2428},{ 2488, 2523},{ 2667, 2619},{ 2843, 2718}, + { 3010, 2805},{ 3163, 2887},{ 3323, 2963},{ 3490, 3028}, + { 3665, 3087},{ 3841, 3145},{ 4011, 3197},{ 4289, 3230} + }, + /*Cb qi=52 INTER*/ + { + { 98, -7},{ 109, 342},{ 109, 668},{ 126, 1018}, + { 170, 1355},{ 242, 1663},{ 352, 1941},{ 490, 2195}, + { 642, 2439},{ 823, 2666},{ 1052, 2868},{ 1333, 3039}, + { 1670, 3178},{ 2074, 3280},{ 2524, 3348},{ 2996, 3390}, + { 3469, 3410},{ 3923, 3420},{ 4355, 3434},{ 4771, 3451}, + { 5166, 3468},{ 5532, 3483},{ 5885, 3499},{ 6263, 3501} + } + }, + { + /*Cr qi=52 INTRA*/ + { + { 25, 7},{ 170, 388},{ 312, 741},{ 500, 1051}, + { 694, 1310},{ 883, 1529},{ 1082, 1709},{ 1280, 1864}, + { 1491, 1998},{ 1710, 2117},{ 1932, 2225},{ 2143, 2324}, + { 2328, 2418},{ 2516, 2506},{ 2708, 2578},{ 2870, 2637}, + { 3017, 2693},{ 3170, 2758},{ 3312, 2835},{ 3455, 2901}, + { 3644, 2972},{ 3827, 3049},{ 3968, 3121},{ 4115, 3166} + }, + /*Cr qi=52 INTER*/ + { + { 86, -2},{ 101, 352},{ 100, 680},{ 126, 1028}, + { 175, 1356},{ 247, 1657},{ 341, 1948},{ 458, 2224}, + { 615, 2471},{ 828, 2681},{ 1091, 2857},{ 1395, 3008}, + { 1732, 3140},{ 2095, 3257},{ 2502, 3348},{ 2968, 3402}, + { 3457, 3420},{ 3926, 3413},{ 4360, 3388},{ 4759, 3357}, + { 5128, 3329},{ 5449, 3306},{ 5741, 3295},{ 6071, 3296} + } + } + }, + { + { + /*Y' qi=53 INTRA*/ + { + { 138, 93},{ 850, 1161},{ 1773, 1810},{ 2763, 2103}, + { 3722, 2245},{ 4675, 2360},{ 5600, 2483},{ 6464, 2597}, + { 7255, 2700},{ 7982, 2792},{ 8652, 2867},{ 9237, 2913}, + { 9775, 2950},{10302, 2998},{10834, 3058},{11347, 3121}, + {11826, 3169},{12299, 3207},{12713, 3235},{13054, 3250}, + {13387, 3265},{13744, 3286},{14110, 3302},{14515, 3323} + }, + /*Y' qi=53 INTER*/ + { + { 52, 2},{ 169, 1308},{ 680, 2377},{ 1763, 3103}, + { 3410, 3450},{ 5094, 3531},{ 6469, 3526},{ 7590, 3525}, + { 8547, 3530},{ 9385, 3534},{10139, 3540},{10835, 3548}, + {11479, 3553},{12075, 3559},{12634, 3565},{13159, 3570}, + {13650, 3573},{14124, 3576},{14575, 3580},{14993, 3583}, + {15375, 3584},{15744, 3584},{16091, 3583},{16421, 3586} + } + }, + { + /*Cb qi=53 INTRA*/ + { + { 14, 3},{ 167, 367},{ 317, 717},{ 492, 1033}, + { 687, 1306},{ 887, 1531},{ 1095, 1715},{ 1309, 1866}, + { 1517, 2000},{ 1729, 2119},{ 1932, 2227},{ 2146, 2325}, + { 2358, 2414},{ 2544, 2511},{ 2724, 2611},{ 2902, 2711}, + { 3070, 2800},{ 3227, 2878},{ 3381, 2954},{ 3548, 3021}, + { 3724, 3077},{ 3888, 3140},{ 4065, 3196},{ 4359, 3225} + }, + /*Cb qi=53 INTER*/ + { + { 93, -8},{ 110, 342},{ 108, 668},{ 125, 1018}, + { 170, 1355},{ 242, 1663},{ 353, 1939},{ 494, 2192}, + { 651, 2433},{ 838, 2658},{ 1076, 2856},{ 1368, 3022}, + { 1716, 3158},{ 2123, 3260},{ 2575, 3330},{ 3042, 3373}, + { 3507, 3396},{ 3962, 3413},{ 4394, 3430},{ 4797, 3452}, + { 5169, 3476},{ 5547, 3496},{ 5914, 3510},{ 6235, 3525} + } + }, + { + /*Cr qi=53 INTRA*/ + { + { 25, 7},{ 175, 386},{ 335, 734},{ 541, 1037}, + { 737, 1296},{ 926, 1516},{ 1125, 1696},{ 1324, 1851}, + { 1540, 1984},{ 1763, 2102},{ 1989, 2210},{ 2202, 2310}, + { 2386, 2404},{ 2572, 2495},{ 2768, 2569},{ 2929, 2627}, + { 3071, 2684},{ 3231, 2749},{ 3374, 2825},{ 3514, 2894}, + { 3703, 2963},{ 3882, 3040},{ 4024, 3111},{ 4190, 3150} + }, + /*Cr qi=53 INTER*/ + { + { 87, -1},{ 99, 352},{ 100, 680},{ 125, 1027}, + { 175, 1355},{ 249, 1657},{ 343, 1946},{ 462, 2220}, + { 624, 2465},{ 844, 2671},{ 1122, 2841},{ 1435, 2989}, + { 1768, 3125},{ 2134, 3243},{ 2545, 3334},{ 3002, 3393}, + { 3490, 3412},{ 3965, 3405},{ 4401, 3384},{ 4797, 3359}, + { 5156, 3328},{ 5482, 3297},{ 5800, 3292},{ 6135, 3293} + } + } + }, + { + { + /*Y' qi=54 INTRA*/ + { + { 184, 94},{ 902, 1151},{ 1876, 1776},{ 2881, 2057}, + { 3832, 2200},{ 4785, 2315},{ 5709, 2442},{ 6570, 2562}, + { 7362, 2672},{ 8092, 2771},{ 8760, 2852},{ 9337, 2901}, + { 9874, 2943},{10402, 2995},{10928, 3059},{11443, 3126}, + {11926, 3178},{12396, 3220},{12805, 3251},{13139, 3266}, + {13466, 3280},{13822, 3304},{14184, 3322},{14585, 3342} + }, + /*Y' qi=54 INTER*/ + { + { 60, 5},{ 169, 1308},{ 683, 2375},{ 1791, 3090}, + { 3478, 3412},{ 5184, 3470},{ 6568, 3455},{ 7697, 3446}, + { 8659, 3446},{ 9503, 3447},{10266, 3450},{10971, 3454}, + {11619, 3458},{12223, 3462},{12789, 3467},{13315, 3471}, + {13811, 3475},{14291, 3479},{14743, 3479},{15148, 3481}, + {15535, 3483},{15913, 3481},{16252, 3479},{16569, 3472} + } + }, + { + /*Cb qi=54 INTRA*/ + { + { 13, 2},{ 165, 367},{ 318, 715},{ 498, 1030}, + { 698, 1301},{ 906, 1523},{ 1121, 1703},{ 1336, 1853}, + { 1549, 1984},{ 1765, 2100},{ 1974, 2207},{ 2192, 2306}, + { 2402, 2396},{ 2587, 2493},{ 2773, 2591},{ 2953, 2691}, + { 3119, 2778},{ 3277, 2858},{ 3430, 2940},{ 3603, 3004}, + { 3788, 3059},{ 3950, 3121},{ 4128, 3173},{ 4398, 3215} + }, + /*Cb qi=54 INTER*/ + { + { 100, -3},{ 109, 343},{ 107, 668},{ 125, 1018}, + { 169, 1354},{ 241, 1662},{ 353, 1938},{ 496, 2190}, + { 655, 2431},{ 843, 2655},{ 1082, 2851},{ 1381, 3015}, + { 1739, 3146},{ 2154, 3243},{ 2610, 3310},{ 3094, 3344}, + { 3581, 3358},{ 4034, 3371},{ 4457, 3384},{ 4867, 3399}, + { 5255, 3413},{ 5630, 3425},{ 6003, 3440},{ 6346, 3440} + } + }, + { + /*Cr qi=54 INTRA*/ + { + { 23, 7},{ 174, 386},{ 338, 732},{ 549, 1034}, + { 751, 1289},{ 947, 1506},{ 1150, 1685},{ 1353, 1837}, + { 1572, 1969},{ 1800, 2087},{ 2031, 2192},{ 2248, 2291}, + { 2434, 2387},{ 2622, 2477},{ 2815, 2549},{ 2976, 2607}, + { 3126, 2663},{ 3286, 2727},{ 3427, 2807},{ 3569, 2877}, + { 3761, 2941},{ 3942, 3016},{ 4084, 3093},{ 4226, 3131} + }, + /*Cr qi=54 INTER*/ + { + { 88, -2},{ 99, 351},{ 100, 680},{ 125, 1027}, + { 175, 1354},{ 248, 1656},{ 343, 1945},{ 463, 2219}, + { 626, 2463},{ 850, 2668},{ 1128, 2837},{ 1445, 2983}, + { 1791, 3111},{ 2168, 3224},{ 2597, 3309},{ 3075, 3351}, + { 3560, 3364},{ 4029, 3356},{ 4464, 3335},{ 4858, 3307}, + { 5218, 3275},{ 5547, 3256},{ 5850, 3247},{ 6171, 3214} + } + } + }, + { + { + /*Y' qi=55 INTRA*/ + { + { 178, 95},{ 968, 1137},{ 2000, 1747},{ 3013, 2027}, + { 3966, 2173},{ 4920, 2294},{ 5842, 2427},{ 6702, 2553}, + { 7489, 2668},{ 8213, 2773},{ 8875, 2858},{ 9452, 2913}, + { 9986, 2959},{10504, 3016},{11023, 3085},{11530, 3157}, + {12011, 3213},{12480, 3257},{12882, 3291},{13214, 3310}, + {13542, 3325},{13890, 3350},{14248, 3371},{14671, 3398} + }, + /*Y' qi=55 INTER*/ + { + { 59, 5},{ 170, 1307},{ 725, 2358},{ 1886, 3058}, + { 3589, 3385},{ 5284, 3459},{ 6654, 3458},{ 7771, 3461}, + { 8727, 3470},{ 9564, 3478},{10322, 3488},{11019, 3497}, + {11658, 3505},{12258, 3513},{12819, 3520},{13344, 3527}, + {13840, 3533},{14314, 3537},{14755, 3541},{15161, 3544}, + {15552, 3548},{15916, 3548},{16257, 3548},{16576, 3540} + } + }, + { + /*Cb qi=55 INTRA*/ + { + { 13, 2},{ 167, 366},{ 322, 714},{ 508, 1026}, + { 716, 1292},{ 930, 1511},{ 1148, 1690},{ 1366, 1839}, + { 1578, 1972},{ 1793, 2090},{ 2001, 2199},{ 2217, 2300}, + { 2427, 2393},{ 2609, 2495},{ 2784, 2600},{ 2961, 2704}, + { 3121, 2797},{ 3268, 2884},{ 3423, 2965},{ 3590, 3032}, + { 3764, 3096},{ 3926, 3165},{ 4101, 3223},{ 4405, 3258} + }, + /*Cb qi=55 INTER*/ + { + { 90, -4},{ 109, 344},{ 107, 668},{ 126, 1017}, + { 172, 1351},{ 249, 1657},{ 370, 1928},{ 527, 2174}, + { 702, 2407},{ 909, 2624},{ 1170, 2814},{ 1493, 2970}, + { 1869, 3097},{ 2292, 3192},{ 2752, 3258},{ 3232, 3295}, + { 3709, 3314},{ 4156, 3335},{ 4592, 3355},{ 5004, 3373}, + { 5377, 3389},{ 5737, 3411},{ 6092, 3432},{ 6473, 3423} + } + }, + { + /*Cr qi=55 INTRA*/ + { + { 23, 7},{ 175, 385},{ 342, 730},{ 561, 1028}, + { 771, 1279},{ 973, 1493},{ 1181, 1669},{ 1384, 1822}, + { 1602, 1956},{ 1830, 2076},{ 2057, 2184},{ 2270, 2288}, + { 2452, 2389},{ 2637, 2484},{ 2823, 2559},{ 2983, 2621}, + { 3129, 2682},{ 3280, 2753},{ 3417, 2833},{ 3554, 2904}, + { 3743, 2977},{ 3921, 3060},{ 4055, 3137},{ 4185, 3186} + }, + /*Cr qi=55 INTER*/ + { + { 85, 0},{ 99, 352},{ 100, 679},{ 126, 1025}, + { 178, 1351},{ 256, 1650},{ 359, 1935},{ 493, 2202}, + { 675, 2439},{ 921, 2636},{ 1220, 2799},{ 1552, 2941}, + { 1910, 3068},{ 2303, 3177},{ 2735, 3262},{ 3206, 3311}, + { 3689, 3333},{ 4152, 3327},{ 4588, 3299},{ 4978, 3272}, + { 5325, 3243},{ 5651, 3221},{ 5969, 3210},{ 6218, 3185} + } + } + }, + { + { + /*Y' qi=56 INTRA*/ + { + { 137, 104},{ 1048, 1128},{ 2147, 1760},{ 3261, 2029}, + { 4319, 2131},{ 5310, 2234},{ 6245, 2351},{ 7101, 2464}, + { 7886, 2572},{ 8610, 2675},{ 9270, 2762},{ 9840, 2818}, + {10365, 2869},{10875, 2928},{11393, 2997},{11900, 3071}, + {12371, 3128},{12834, 3172},{13233, 3208},{13562, 3228}, + {13878, 3245},{14221, 3271},{14584, 3292},{15008, 3320} + }, + /*Y' qi=56 INTER*/ + { + { 19, 21},{ 207, 1292},{ 1031, 2252},{ 2553, 2846}, + { 4463, 3085},{ 6137, 3131},{ 7441, 3151},{ 8526, 3172}, + { 9468, 3193},{10301, 3209},{11059, 3224},{11760, 3237}, + {12405, 3249},{13008, 3261},{13570, 3270},{14100, 3278}, + {14597, 3284},{15074, 3289},{15524, 3297},{15929, 3302}, + {16314, 3306},{16675, 3307},{17004, 3305},{17288, 3301} + } + }, + { + /*Cb qi=56 INTRA*/ + { + { 16, 3},{ 188, 367},{ 353, 712},{ 546, 1017}, + { 765, 1275},{ 989, 1484},{ 1221, 1653},{ 1459, 1791}, + { 1681, 1920},{ 1893, 2046},{ 2102, 2160},{ 2323, 2257}, + { 2534, 2347},{ 2720, 2447},{ 2902, 2549},{ 3075, 2654}, + { 3239, 2749},{ 3392, 2835},{ 3544, 2920},{ 3712, 2988}, + { 3882, 3052},{ 4052, 3123},{ 4227, 3181},{ 4483, 3213} + }, + /*Cb qi=56 INTER*/ + { + { 92, -1},{ 111, 343},{ 114, 665},{ 148, 1003}, + { 224, 1321},{ 345, 1609},{ 526, 1858},{ 754, 2077}, + { 1009, 2281},{ 1319, 2464},{ 1702, 2614},{ 2145, 2732}, + { 2625, 2824},{ 3123, 2890},{ 3634, 2933},{ 4137, 2954}, + { 4614, 2965},{ 5052, 2988},{ 5468, 3015},{ 5852, 3035}, + { 6213, 3060},{ 6557, 3081},{ 6906, 3094},{ 7243, 3112} + } + }, + { + /*Cr qi=56 INTRA*/ + { + { 28, 8},{ 195, 385},{ 373, 727},{ 598, 1019}, + { 816, 1263},{ 1033, 1465},{ 1260, 1630},{ 1482, 1773}, + { 1717, 1900},{ 1949, 2018},{ 2178, 2128},{ 2393, 2233}, + { 2570, 2338},{ 2749, 2435},{ 2937, 2514},{ 3097, 2577}, + { 3240, 2638},{ 3398, 2709},{ 3540, 2791},{ 3673, 2865}, + { 3869, 2938},{ 4049, 3019},{ 4179, 3095},{ 4330, 3137} + }, + /*Cr qi=56 INTER*/ + { + { 83, 0},{ 99, 353},{ 103, 676},{ 146, 1010}, + { 232, 1320},{ 355, 1601},{ 512, 1866},{ 713, 2109}, + { 988, 2312},{ 1344, 2471},{ 1750, 2602},{ 2180, 2719}, + { 2642, 2819},{ 3141, 2892},{ 3653, 2939},{ 4159, 2961}, + { 4636, 2961},{ 5072, 2945},{ 5464, 2917},{ 5813, 2895}, + { 6134, 2890},{ 6458, 2883},{ 6735, 2881},{ 6953, 2902} + } + } + }, + { + { + /*Y' qi=57 INTRA*/ + { + { 170, 106},{ 1106, 1120},{ 2246, 1740},{ 3399, 1993}, + { 4482, 2077},{ 5492, 2167},{ 6446, 2273},{ 7324, 2379}, + { 8130, 2482},{ 8866, 2578},{ 9537, 2661},{10119, 2715}, + {10646, 2762},{11161, 2820},{11694, 2886},{12214, 2957}, + {12693, 3013},{13166, 3053},{13569, 3087},{13897, 3106}, + {14224, 3122},{14568, 3148},{14931, 3167},{15390, 3192} + }, + /*Y' qi=57 INTER*/ + { + { 19, 20},{ 205, 1292},{ 1096, 2229},{ 2775, 2766}, + { 4811, 2943},{ 6512, 2964},{ 7832, 2976},{ 8940, 2990}, + { 9903, 3004},{10755, 3017},{11532, 3029},{12243, 3039}, + {12891, 3047},{13502, 3058},{14073, 3065},{14603, 3071}, + {15097, 3078},{15581, 3083},{16036, 3086},{16452, 3090}, + {16855, 3093},{17222, 3094},{17552, 3092},{17851, 3098} + } + }, + { + /*Cb qi=57 INTRA*/ + { + { 16, 3},{ 197, 365},{ 384, 704},{ 603, 1001}, + { 837, 1252},{ 1077, 1455},{ 1326, 1618},{ 1581, 1748}, + { 1819, 1871},{ 2042, 1993},{ 2264, 2104},{ 2500, 2196}, + { 2722, 2280},{ 2916, 2375},{ 3103, 2473},{ 3290, 2575}, + { 3456, 2667},{ 3612, 2748},{ 3775, 2829},{ 3958, 2896}, + { 4145, 2947},{ 4307, 3012},{ 4476, 3070},{ 4733, 3110} + }, + /*Cb qi=57 INTER*/ + { + { 94, -1},{ 111, 344},{ 112, 665},{ 147, 1002}, + { 227, 1319},{ 353, 1604},{ 543, 1849},{ 785, 2062}, + { 1066, 2257},{ 1408, 2430},{ 1827, 2568},{ 2320, 2670}, + { 2848, 2743},{ 3386, 2791},{ 3934, 2812},{ 4453, 2820}, + { 4929, 2830},{ 5368, 2842},{ 5787, 2856},{ 6190, 2875}, + { 6554, 2896},{ 6895, 2913},{ 7229, 2927},{ 7572, 2932} + } + }, + { + /*Cr qi=57 INTRA*/ + { + { 28, 8},{ 207, 383},{ 413, 716},{ 661, 999}, + { 889, 1237},{ 1123, 1433},{ 1365, 1592},{ 1603, 1731}, + { 1853, 1852},{ 2103, 1965},{ 2345, 2072},{ 2571, 2173}, + { 2763, 2271},{ 2949, 2364},{ 3146, 2438},{ 3315, 2497}, + { 3459, 2552},{ 3618, 2616},{ 3767, 2697},{ 3906, 2773}, + { 4099, 2841},{ 4281, 2916},{ 4429, 2987},{ 4569, 3030} + }, + /*Cr qi=57 INTER*/ + { + { 85, 0},{ 99, 352},{ 102, 675},{ 147, 1008}, + { 235, 1317},{ 363, 1597},{ 529, 1858},{ 748, 2094}, + { 1050, 2287},{ 1439, 2436},{ 1877, 2557},{ 2352, 2660}, + { 2869, 2740},{ 3413, 2791},{ 3962, 2815},{ 4485, 2819}, + { 4955, 2816},{ 5382, 2800},{ 5769, 2772},{ 6107, 2748}, + { 6443, 2740},{ 6754, 2739},{ 7029, 2737},{ 7284, 2745} + } + } + }, + { + { + /*Y' qi=58 INTRA*/ + { + { 164, 109},{ 1198, 1111},{ 2396, 1737},{ 3606, 1978}, + { 4727, 2048},{ 5749, 2138},{ 6708, 2243},{ 7584, 2347}, + { 8388, 2449},{ 9122, 2549},{ 9784, 2635},{10354, 2691}, + {10876, 2740},{11385, 2800},{11912, 2869},{12429, 2941}, + {12902, 2997},{13375, 3040},{13779, 3075},{14103, 3096}, + {14435, 3112},{14783, 3140},{15141, 3160},{15599, 3186} + }, + /*Y' qi=58 INTER*/ + { + { 14, 23},{ 210, 1290},{ 1277, 2178},{ 3118, 2677}, + { 5207, 2834},{ 6902, 2857},{ 8218, 2878},{ 9323, 2900}, + {10285, 2919},{11132, 2934},{11899, 2949},{12599, 2961}, + {13235, 2971},{13835, 2982},{14394, 2991},{14917, 2997}, + {15412, 3005},{15882, 3009},{16325, 3013},{16735, 3016}, + {17131, 3018},{17501, 3021},{17824, 3021},{18125, 3016} + } + }, + { + /*Cb qi=58 INTRA*/ + { + { 17, 3},{ 200, 365},{ 389, 703},{ 613, 996}, + { 853, 1243},{ 1095, 1445},{ 1349, 1604},{ 1613, 1731}, + { 1853, 1853},{ 2074, 1978},{ 2292, 2091},{ 2526, 2184}, + { 2750, 2266},{ 2945, 2360},{ 3134, 2458},{ 3320, 2561}, + { 3482, 2654},{ 3641, 2737},{ 3804, 2818},{ 3985, 2881}, + { 4168, 2935},{ 4331, 3003},{ 4499, 3060},{ 4751, 3100} + }, + /*Cb qi=58 INTER*/ + { + { 94, -1},{ 112, 345},{ 112, 665},{ 152, 998}, + { 247, 1307},{ 406, 1580},{ 644, 1810},{ 938, 2007}, + { 1271, 2189},{ 1668, 2348},{ 2151, 2470},{ 2691, 2558}, + { 3249, 2619},{ 3798, 2659},{ 4334, 2682},{ 4849, 2692}, + { 5314, 2700},{ 5747, 2721},{ 6167, 2742},{ 6547, 2765}, + { 6902, 2790},{ 7251, 2804},{ 7583, 2819},{ 7924, 2833} + } + }, + { + /*Cr qi=58 INTRA*/ + { + { 29, 8},{ 210, 382},{ 419, 714},{ 671, 993}, + { 903, 1229},{ 1141, 1422},{ 1390, 1578},{ 1635, 1713}, + { 1889, 1833},{ 2140, 1946},{ 2379, 2055},{ 2604, 2157}, + { 2794, 2256},{ 2977, 2349},{ 3174, 2422},{ 3339, 2482}, + { 3483, 2537},{ 3643, 2604},{ 3790, 2684},{ 3927, 2757}, + { 4112, 2826},{ 4294, 2900},{ 4451, 2975},{ 4600, 3011} + }, + /*Cr qi=58 INTER*/ + { + { 86, 0},{ 99, 352},{ 103, 675},{ 151, 1004}, + { 256, 1306},{ 417, 1573},{ 628, 1819},{ 901, 2040}, + { 1262, 2217},{ 1705, 2353},{ 2191, 2466},{ 2713, 2556}, + { 3268, 2622},{ 3831, 2664},{ 4374, 2682},{ 4881, 2686}, + { 5339, 2685},{ 5747, 2668},{ 6123, 2646},{ 6465, 2630}, + { 6783, 2618},{ 7082, 2623},{ 7366, 2632},{ 7673, 2654} + } + } + }, + { + { + /*Y' qi=59 INTRA*/ + { + { 142, 112},{ 1259, 1100},{ 2552, 1711},{ 3815, 1933}, + { 4955, 1987},{ 5983, 2068},{ 6949, 2165},{ 7832, 2263}, + { 8645, 2359},{ 9392, 2454},{10066, 2536},{10643, 2589}, + {11174, 2636},{11696, 2693},{12230, 2758},{12752, 2826}, + {13239, 2883},{13721, 2926},{14139, 2959},{14479, 2978}, + {14811, 2993},{15166, 3020},{15532, 3039},{16000, 3062} + }, + /*Y' qi=59 INTER*/ + { + { 8, 25},{ 211, 1289},{ 1394, 2144},{ 3421, 2580}, + { 5611, 2689},{ 7316, 2701},{ 8643, 2717},{ 9762, 2734}, + {10735, 2750},{11587, 2763},{12353, 2775},{13056, 2785}, + {13693, 2793},{14288, 2805},{14843, 2814},{15361, 2821}, + {15857, 2827},{16328, 2831},{16763, 2834},{17171, 2838}, + {17568, 2840},{17941, 2842},{18285, 2843},{18586, 2839} + } + }, + { + /*Cb qi=59 INTRA*/ + { + { 17, 3},{ 224, 363},{ 441, 696},{ 689, 982}, + { 945, 1222},{ 1204, 1416},{ 1474, 1571},{ 1751, 1695}, + { 2001, 1816},{ 2228, 1941},{ 2453, 2055},{ 2693, 2147}, + { 2924, 2227},{ 3125, 2321},{ 3321, 2416},{ 3510, 2520}, + { 3676, 2616},{ 3839, 2699},{ 4008, 2778},{ 4193, 2842}, + { 4371, 2898},{ 4535, 2965},{ 4710, 3023},{ 4921, 3068} + }, + /*Cb qi=59 INTER*/ + { + { 95, -5},{ 111, 343},{ 112, 664},{ 157, 995}, + { 258, 1302},{ 429, 1569},{ 691, 1790},{ 1017, 1977}, + { 1387, 2148},{ 1832, 2294},{ 2368, 2401},{ 2961, 2472}, + { 3553, 2518},{ 4133, 2545},{ 4688, 2557},{ 5198, 2563}, + { 5663, 2574},{ 6100, 2590},{ 6511, 2608},{ 6898, 2621}, + { 7274, 2634},{ 7631, 2655},{ 7984, 2669},{ 8361, 2669} + } + }, + { + /*Cr qi=59 INTRA*/ + { + { 31, 8},{ 240, 379},{ 480, 706},{ 748, 978}, + { 993, 1208},{ 1250, 1394},{ 1519, 1543},{ 1779, 1674}, + { 2047, 1792},{ 2307, 1904},{ 2552, 2013},{ 2780, 2116}, + { 2973, 2216},{ 3165, 2309},{ 3362, 2383},{ 3528, 2444}, + { 3677, 2499},{ 3841, 2566},{ 3995, 2646},{ 4139, 2720}, + { 4324, 2793},{ 4504, 2867},{ 4658, 2939},{ 4806, 2975} + }, + /*Cr qi=59 INTER*/ + { + { 89, -3},{ 98, 352},{ 103, 674},{ 156, 1002}, + { 268, 1300},{ 441, 1562},{ 673, 1801},{ 980, 2010}, + { 1385, 2175},{ 1868, 2301},{ 2401, 2402},{ 2984, 2474}, + { 3591, 2520},{ 4179, 2545},{ 4729, 2555},{ 5232, 2553}, + { 5679, 2545},{ 6081, 2530},{ 6447, 2510},{ 6791, 2496}, + { 7101, 2487},{ 7393, 2489},{ 7684, 2499},{ 7950, 2501} + } + } + }, + { + { + /*Y' qi=60 INTRA*/ + { + { 92, 116},{ 1361, 1085},{ 2746, 1686},{ 4050, 1895}, + { 5209, 1939},{ 6244, 2012},{ 7213, 2103},{ 8105, 2197}, + { 8928, 2290},{ 9685, 2381},{10371, 2460},{10952, 2511}, + {11487, 2556},{12026, 2611},{12574, 2674},{13102, 2739}, + {13597, 2793},{14092, 2831},{14523, 2862},{14862, 2881}, + {15198, 2897},{15568, 2923},{15949, 2941},{16416, 2964} + }, + /*Y' qi=60 INTER*/ + { + { 4, 30},{ 215, 1287},{ 1547, 2104},{ 3729, 2491}, + { 5973, 2568},{ 7672, 2577},{ 9001, 2591},{10123, 2606}, + {11094, 2620},{11943, 2632},{12709, 2643},{13409, 2652}, + {14044, 2660},{14641, 2669},{15193, 2677},{15709, 2684}, + {16201, 2689},{16675, 2693},{17118, 2696},{17522, 2701}, + {17920, 2704},{18293, 2706},{18620, 2702},{18923, 2700} + } + }, + { + /*Cb qi=60 INTRA*/ + { + { 18, 3},{ 227, 362},{ 447, 694},{ 708, 974}, + { 981, 1207},{ 1252, 1397},{ 1532, 1547},{ 1822, 1663}, + { 2082, 1780},{ 2316, 1903},{ 2548, 2013},{ 2794, 2101}, + { 3029, 2178},{ 3242, 2266},{ 3445, 2360},{ 3638, 2459}, + { 3816, 2547},{ 3980, 2628},{ 4146, 2708},{ 4344, 2766}, + { 4546, 2812},{ 4725, 2872},{ 4880, 2930},{ 5054, 2966} + }, + /*Cb qi=60 INTER*/ + { + { 97, -4},{ 112, 343},{ 114, 664},{ 162, 993}, + { 273, 1294},{ 472, 1553},{ 774, 1762},{ 1138, 1939}, + { 1543, 2102},{ 2034, 2236},{ 2620, 2329},{ 3244, 2389}, + { 3860, 2423},{ 4443, 2440},{ 4997, 2449},{ 5502, 2455}, + { 5962, 2458},{ 6413, 2466},{ 6836, 2485},{ 7217, 2506}, + { 7592, 2518},{ 7957, 2533},{ 8291, 2543},{ 8574, 2545} + } + }, + { + /*Cr qi=60 INTRA*/ + { + { 32, 8},{ 243, 379},{ 488, 702},{ 771, 968}, + { 1030, 1192},{ 1300, 1373},{ 1581, 1517},{ 1854, 1643}, + { 2127, 1757},{ 2393, 1864},{ 2645, 1968},{ 2879, 2068}, + { 3078, 2166},{ 3277, 2256},{ 3484, 2325},{ 3660, 2381}, + { 3808, 2433},{ 3970, 2496},{ 4138, 2571},{ 4288, 2643}, + { 4475, 2710},{ 4655, 2778},{ 4810, 2843},{ 4959, 2879} + }, + /*Cr qi=60 INTER*/ + { + { 86, -2},{ 99, 352},{ 103, 673},{ 160, 998}, + { 284, 1292},{ 484, 1546},{ 753, 1774},{ 1100, 1973}, + { 1546, 2129},{ 2072, 2246},{ 2652, 2334},{ 3279, 2392}, + { 3911, 2425},{ 4504, 2440},{ 5044, 2443},{ 5536, 2440}, + { 5979, 2430},{ 6381, 2413},{ 6735, 2397},{ 7062, 2382}, + { 7383, 2376},{ 7680, 2375},{ 7962, 2373},{ 8203, 2379} + } + } + }, + { + { + /*Y' qi=61 INTRA*/ + { + { 54, 121},{ 1477, 1069},{ 3061, 1638},{ 4465, 1808}, + { 5649, 1827},{ 6710, 1884},{ 7716, 1958},{ 8648, 2037}, + { 9514, 2116},{10311, 2192},{11033, 2261},{11641, 2305}, + {12202, 2342},{12771, 2387},{13356, 2440},{13924, 2493}, + {14444, 2541},{14951, 2576},{15409, 2600},{15779, 2615}, + {16131, 2626},{16521, 2648},{16921, 2663},{17409, 2694} + }, + /*Y' qi=61 INTER*/ + { + { -1, 32},{ 216, 1286},{ 1806, 2036},{ 4279, 2327}, + { 6629, 2352},{ 8347, 2352},{ 9707, 2357},{10860, 2364}, + {11857, 2372},{12726, 2377},{13508, 2382},{14225, 2387}, + {14877, 2392},{15484, 2398},{16048, 2401},{16581, 2405}, + {17092, 2409},{17573, 2409},{18016, 2410},{18427, 2413}, + {18829, 2415},{19221, 2415},{19578, 2415},{19980, 2413} + } + }, + { + /*Cb qi=61 INTRA*/ + { + { 19, 3},{ 231, 362},{ 456, 693},{ 733, 965}, + { 1032, 1188},{ 1330, 1369},{ 1637, 1508},{ 1956, 1612}, + { 2241, 1718},{ 2496, 1832},{ 2750, 1932},{ 3019, 2007}, + { 3274, 2074},{ 3505, 2154},{ 3725, 2236},{ 3943, 2323}, + { 4138, 2403},{ 4323, 2476},{ 4505, 2543},{ 4706, 2592}, + { 4909, 2630},{ 5109, 2675},{ 5292, 2724},{ 5495, 2768} + }, + /*Cb qi=61 INTER*/ + { + { 91, -2},{ 111, 344},{ 114, 663},{ 166, 989}, + { 291, 1285},{ 522, 1534},{ 875, 1729},{ 1302, 1889}, + { 1786, 2031},{ 2368, 2141},{ 3042, 2207},{ 3734, 2243}, + { 4388, 2259},{ 4982, 2264},{ 5533, 2265},{ 6043, 2262}, + { 6524, 2264},{ 6982, 2274},{ 7422, 2283},{ 7831, 2295}, + { 8198, 2308},{ 8593, 2319},{ 8965, 2329},{ 9258, 2340} + } + }, + { + /*Cr qi=61 INTRA*/ + { + { 33, 9},{ 245, 378},{ 497, 699},{ 801, 958}, + { 1087, 1171},{ 1384, 1342},{ 1692, 1474},{ 1992, 1589}, + { 2290, 1692},{ 2576, 1789},{ 2852, 1884},{ 3109, 1973}, + { 3324, 2061},{ 3544, 2142},{ 3763, 2199},{ 3945, 2244}, + { 4103, 2292},{ 4283, 2349},{ 4469, 2413},{ 4635, 2476}, + { 4836, 2534},{ 5038, 2592},{ 5210, 2649},{ 5358, 2682} + }, + /*Cr qi=61 INTER*/ + { + { 82, 0},{ 97, 353},{ 104, 672},{ 165, 995}, + { 303, 1284},{ 532, 1529},{ 852, 1742},{ 1273, 1921}, + { 1798, 2057},{ 2409, 2154},{ 3090, 2212},{ 3794, 2240}, + { 4460, 2251},{ 5057, 2249},{ 5596, 2249},{ 6085, 2245}, + { 6519, 2234},{ 6908, 2220},{ 7269, 2203},{ 7618, 2196}, + { 7949, 2198},{ 8269, 2195},{ 8554, 2196},{ 8928, 2217} + } + } + }, + { + { + /*Y' qi=62 INTRA*/ + { + { 29, 124},{ 1527, 1067},{ 3221, 1618},{ 4703, 1751}, + { 5909, 1744},{ 7001, 1779},{ 8057, 1829},{ 9049, 1885}, + { 9968, 1943},{10813, 1999},{11572, 2050},{12206, 2082}, + {12801, 2107},{13402, 2140},{14020, 2180},{14625, 2223}, + {15179, 2260},{15718, 2288},{16196, 2305},{16581, 2313}, + {16963, 2324},{17382, 2341},{17800, 2351},{18318, 2376} + }, + /*Y' qi=62 INTER*/ + { + { -8, 36},{ 218, 1284},{ 2073, 1965},{ 4814, 2159}, + { 7237, 2138},{ 8979, 2124},{10378, 2115},{11570, 2109}, + {12601, 2106},{13503, 2103},{14320, 2103},{15064, 2103}, + {15746, 2103},{16384, 2104},{16975, 2105},{17534, 2105}, + {18062, 2106},{18564, 2107},{19035, 2106},{19471, 2107}, + {19890, 2107},{20288, 2107},{20651, 2107},{21012, 2108} + } + }, + { + /*Cb qi=62 INTRA*/ + { + { 21, 3},{ 283, 360},{ 565, 683},{ 907, 938}, + { 1269, 1143},{ 1611, 1311},{ 1949, 1441},{ 2290, 1535}, + { 2596, 1632},{ 2877, 1738},{ 3162, 1828},{ 3458, 1893}, + { 3745, 1948},{ 4011, 2016},{ 4253, 2089},{ 4506, 2164}, + { 4734, 2233},{ 4943, 2294},{ 5162, 2353},{ 5381, 2393}, + { 5593, 2420},{ 5807, 2454},{ 6003, 2496},{ 6210, 2543} + }, + /*Cb qi=62 INTER*/ + { + { 91, -1},{ 110, 344},{ 113, 663},{ 169, 987}, + { 306, 1279},{ 562, 1519},{ 961, 1701},{ 1450, 1845}, + { 2013, 1967},{ 2686, 2053},{ 3437, 2095},{ 4171, 2109}, + { 4841, 2109},{ 5441, 2105},{ 6002, 2097},{ 6542, 2089}, + { 7028, 2087},{ 7491, 2088},{ 7949, 2090},{ 8377, 2089}, + { 8789, 2095},{ 9195, 2103},{ 9569, 2104},{ 9937, 2102} + } + }, + { + /*Cr qi=62 INTRA*/ + { + { 38, 8},{ 308, 374},{ 619, 685},{ 984, 925}, + { 1326, 1126},{ 1662, 1285},{ 1999, 1407},{ 2328, 1512}, + { 2659, 1604},{ 2976, 1691},{ 3285, 1774},{ 3570, 1853}, + { 3815, 1931},{ 4068, 1998},{ 4304, 2044},{ 4491, 2082}, + { 4666, 2124},{ 4870, 2174},{ 5078, 2231},{ 5262, 2285}, + { 5480, 2335},{ 5703, 2378},{ 5905, 2423},{ 6075, 2454} + }, + /*Cr qi=62 INTER*/ + { + { 79, 1},{ 95, 353},{ 102, 671},{ 169, 992}, + { 318, 1277},{ 569, 1515},{ 936, 1716},{ 1428, 1876}, + { 2034, 1993},{ 2738, 2067},{ 3511, 2095},{ 4268, 2094}, + { 4943, 2087},{ 5543, 2079},{ 6074, 2074},{ 6552, 2069}, + { 6985, 2057},{ 7366, 2043},{ 7728, 2030},{ 8086, 2021}, + { 8423, 2017},{ 8752, 2016},{ 9057, 2014},{ 9376, 2008} + } + } + }, + { + { + /*Y' qi=63 INTRA*/ + { + { -59, 134},{ 1734, 1036},{ 3743, 1521},{ 5309, 1618}, + { 6520, 1597},{ 7664, 1609},{ 8809, 1630},{ 9894, 1657}, + {10907, 1687},{11838, 1717},{12673, 1744},{13379, 1758}, + {14038, 1767},{14698, 1784},{15379, 1806},{16062, 1831}, + {16694, 1852},{17300, 1867},{17827, 1878},{18250, 1881}, + {18702, 1884},{19199, 1892},{19665, 1896},{20273, 1908} + }, + /*Y' qi=63 INTER*/ + { + { -7, 33},{ 209, 1285},{ 2309, 1904},{ 5274, 2025}, + { 7801, 1966},{ 9637, 1924},{11126, 1892},{12403, 1868}, + {13515, 1849},{14491, 1834},{15380, 1822},{16197, 1814}, + {16944, 1806},{17645, 1799},{18303, 1794},{18916, 1789}, + {19494, 1785},{20056, 1782},{20568, 1779},{21047, 1776}, + {21508, 1775},{21925, 1772},{22327, 1770},{22678, 1771} + } + }, + { + /*Cb qi=63 INTRA*/ + { + { 20, 3},{ 294, 357},{ 608, 673},{ 1047, 908}, + { 1501, 1090},{ 1898, 1240},{ 2275, 1353},{ 2654, 1427}, + { 3014, 1502},{ 3366, 1579},{ 3726, 1637},{ 4084, 1674}, + { 4425, 1703},{ 4752, 1743},{ 5058, 1791},{ 5377, 1838}, + { 5676, 1877},{ 5946, 1912},{ 6213, 1945},{ 6458, 1969}, + { 6704, 1982},{ 6969, 1997},{ 7210, 2017},{ 7439, 2037} + }, + /*Cb qi=63 INTER*/ + { + { 86, 1},{ 108, 345},{ 111, 663},{ 168, 985}, + { 307, 1276},{ 577, 1513},{ 1007, 1688},{ 1550, 1819}, + { 2189, 1921},{ 2938, 1981},{ 3744, 2002},{ 4512, 2002}, + { 5199, 1996},{ 5824, 1986},{ 6419, 1971},{ 6978, 1954}, + { 7507, 1940},{ 8015, 1932},{ 8502, 1928},{ 8978, 1920}, + { 9410, 1915},{ 9842, 1910},{10262, 1901},{10634, 1896} + } + }, + { + /*Cr qi=63 INTRA*/ + { + { 38, 7},{ 324, 367},{ 677, 670},{ 1136, 892}, + { 1562, 1070},{ 1951, 1209},{ 2326, 1313},{ 2694, 1399}, + { 3074, 1471},{ 3460, 1531},{ 3850, 1575},{ 4214, 1622}, + { 4522, 1679},{ 4819, 1723},{ 5089, 1749},{ 5315, 1769}, + { 5530, 1792},{ 5756, 1825},{ 6006, 1860},{ 6244, 1889}, + { 6514, 1924},{ 6792, 1946},{ 7026, 1962},{ 7191, 1971} + }, + /*Cr qi=63 INTER*/ + { + { 80, 2},{ 95, 354},{ 101, 671},{ 167, 990}, + { 321, 1274},{ 585, 1509},{ 984, 1702},{ 1534, 1849}, + { 2217, 1947},{ 3005, 1995},{ 3839, 1999},{ 4619, 1986}, + { 5310, 1973},{ 5933, 1961},{ 6486, 1952},{ 6988, 1942}, + { 7435, 1927},{ 7817, 1911},{ 8198, 1900},{ 8552, 1895}, + { 8881, 1890},{ 9253, 1883},{ 9598, 1876},{ 9923, 1859} + } + } + } +}; + +#endif diff --git a/Engine/lib/libtheora/lib/ocintrin.h b/Engine/lib/libtheora/lib/ocintrin.h new file mode 100644 index 000000000..d49ebb215 --- /dev/null +++ b/Engine/lib/libtheora/lib/ocintrin.h @@ -0,0 +1,128 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: ocintrin.h 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ + +/*Some common macros for potential platform-specific optimization.*/ +#include +#if !defined(_ocintrin_H) +# define _ocintrin_H (1) + +/*Some specific platforms may have optimized intrinsic or inline assembly + versions of these functions which can substantially improve performance. + We define macros for them to allow easy incorporation of these non-ANSI + features.*/ + +/*Note that we do not provide a macro for abs(), because it is provided as a + library function, which we assume is translated into an intrinsic to avoid + the function call overhead and then implemented in the smartest way for the + target platform. + With modern gcc (4.x), this is true: it uses cmov instructions if the + architecture supports it and branchless bit-twiddling if it does not (the + speed difference between the two approaches is not measurable). + Interestingly, the bit-twiddling method was patented in 2000 (US 6,073,150) + by Sun Microsystems, despite prior art dating back to at least 1996: + http://web.archive.org/web/19961201174141/www.x86.org/ftp/articles/pentopt/PENTOPT.TXT + On gcc 3.x, however, our assumption is not true, as abs() is translated to a + conditional jump, which is horrible on deeply piplined architectures (e.g., + all consumer architectures for the past decade or more). + Also be warned that -C*abs(x) where C is a constant is mis-optimized as + abs(C*x) on every gcc release before 4.2.3. + See bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34130 */ + +/*Modern gcc (4.x) can compile the naive versions of min and max with cmov if + given an appropriate architecture, but the branchless bit-twiddling versions + are just as fast, and do not require any special target architecture. + Earlier gcc versions (3.x) compiled both code to the same assembly + instructions, because of the way they represented ((_b)>(_a)) internally.*/ +#define OC_MAXI(_a,_b) ((_a)-((_a)-(_b)&-((_b)>(_a)))) +#define OC_MINI(_a,_b) ((_a)+((_b)-(_a)&-((_b)<(_a)))) +/*Clamps an integer into the given range. + If _a>_c, then the lower bound _a is respected over the upper bound _c (this + behavior is required to meet our documented API behavior). + _a: The lower bound. + _b: The value to clamp. + _c: The upper boud.*/ +#define OC_CLAMPI(_a,_b,_c) (OC_MAXI(_a,OC_MINI(_b,_c))) +#define OC_CLAMP255(_x) ((unsigned char)((((_x)<0)-1)&((_x)|-((_x)>255)))) +/*This has a chance of compiling branchless, and is just as fast as the + bit-twiddling method, which is slightly less portable, since it relies on a + sign-extended rightshift, which is not guaranteed by ANSI (but present on + every relevant platform).*/ +#define OC_SIGNI(_a) (((_a)>0)-((_a)<0)) +/*Slightly more portable than relying on a sign-extended right-shift (which is + not guaranteed by ANSI), and just as fast, since gcc (3.x and 4.x both) + compile it into the right-shift anyway.*/ +#define OC_SIGNMASK(_a) (-((_a)<0)) +/*Divides an integer by a power of two, truncating towards 0. + _dividend: The integer to divide. + _shift: The non-negative power of two to divide by. + _rmask: (1<<_shift)-1*/ +#define OC_DIV_POW2(_dividend,_shift,_rmask)\ + ((_dividend)+(OC_SIGNMASK(_dividend)&(_rmask))>>(_shift)) +/*Divides _x by 65536, truncating towards 0.*/ +#define OC_DIV2_16(_x) OC_DIV_POW2(_x,16,0xFFFF) +/*Divides _x by 2, truncating towards 0.*/ +#define OC_DIV2(_x) OC_DIV_POW2(_x,1,0x1) +/*Divides _x by 8, truncating towards 0.*/ +#define OC_DIV8(_x) OC_DIV_POW2(_x,3,0x7) +/*Divides _x by 16, truncating towards 0.*/ +#define OC_DIV16(_x) OC_DIV_POW2(_x,4,0xF) +/*Right shifts _dividend by _shift, adding _rval, and subtracting one for + negative dividends first. + When _rval is (1<<_shift-1), this is equivalent to division with rounding + ties away from zero.*/ +#define OC_DIV_ROUND_POW2(_dividend,_shift,_rval)\ + ((_dividend)+OC_SIGNMASK(_dividend)+(_rval)>>(_shift)) +/*Divides a _x by 2, rounding towards even numbers.*/ +#define OC_DIV2_RE(_x) ((_x)+((_x)>>1&1)>>1) +/*Divides a _x by (1<<(_shift)), rounding towards even numbers.*/ +#define OC_DIV_POW2_RE(_x,_shift) \ + ((_x)+((_x)>>(_shift)&1)+((1<<(_shift))-1>>1)>>(_shift)) +/*Swaps two integers _a and _b if _a>_b.*/ +#define OC_SORT2I(_a,_b) \ + do{ \ + int t__; \ + t__=((_a)^(_b))&-((_b)<(_a)); \ + (_a)^=t__; \ + (_b)^=t__; \ + } \ + while(0) + +/*Accesses one of four (signed) bytes given an index. + This can be used to avoid small lookup tables.*/ +#define OC_BYTE_TABLE32(_a,_b,_c,_d,_i) \ + ((signed char) \ + (((_a)&0xFF|((_b)&0xFF)<<8|((_c)&0xFF)<<16|((_d)&0xFF)<<24)>>(_i)*8)) +/*Accesses one of eight (unsigned) nibbles given an index. + This can be used to avoid small lookup tables.*/ +#define OC_UNIBBLE_TABLE32(_a,_b,_c,_d,_e,_f,_g,_h,_i) \ + ((((_a)&0xF|((_b)&0xF)<<4|((_c)&0xF)<<8|((_d)&0xF)<<12| \ + ((_e)&0xF)<<16|((_f)&0xF)<<20|((_g)&0xF)<<24|((_h)&0xF)<<28)>>(_i)*4)&0xF) + + + +/*All of these macros should expect floats as arguments.*/ +#define OC_MAXF(_a,_b) ((_a)<(_b)?(_b):(_a)) +#define OC_MINF(_a,_b) ((_a)>(_b)?(_b):(_a)) +#define OC_CLAMPF(_a,_b,_c) (OC_MINF(_a,OC_MAXF(_b,_c))) +#define OC_FABSF(_f) ((float)fabs(_f)) +#define OC_SQRTF(_f) ((float)sqrt(_f)) +#define OC_POWF(_b,_e) ((float)pow(_b,_e)) +#define OC_LOGF(_f) ((float)log(_f)) +#define OC_IFLOORF(_f) ((int)floor(_f)) +#define OC_ICEILF(_f) ((int)ceil(_f)) + +#endif diff --git a/Engine/lib/libtheora/lib/quant.c b/Engine/lib/libtheora/lib/quant.c new file mode 100644 index 000000000..8359f5abe --- /dev/null +++ b/Engine/lib/libtheora/lib/quant.c @@ -0,0 +1,119 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: quant.c 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ + +#include +#include +#include +#include "quant.h" +#include "decint.h" + +static const unsigned OC_DC_QUANT_MIN[2]={4<<2,8<<2}; +static const unsigned OC_AC_QUANT_MIN[2]={2<<2,4<<2}; + +/*Initializes the dequantization tables from a set of quantizer info. + Currently the dequantizer (and elsewhere enquantizer) tables are expected to + be initialized as pointing to the storage reserved for them in the + oc_theora_state (resp. oc_enc_ctx) structure. + If some tables are duplicates of others, the pointers will be adjusted to + point to a single copy of the tables, but the storage for them will not be + freed. + If you're concerned about the memory footprint, the obvious thing to do is + to move the storage out of its fixed place in the structures and allocate + it on demand. + However, a much, much better option is to only store the quantization + matrices being used for the current frame, and to recalculate these as the + qi values change between frames (this is what VP3 did).*/ +void oc_dequant_tables_init(ogg_uint16_t *_dequant[64][3][2], + int _pp_dc_scale[64],const th_quant_info *_qinfo){ + /*Coding mode: intra or inter.*/ + int qti; + /*Y', C_b, C_r*/ + int pli; + for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){ + /*Quality index.*/ + int qi; + /*Range iterator.*/ + int qri; + for(qi=0,qri=0;qri<=_qinfo->qi_ranges[qti][pli].nranges;qri++){ + th_quant_base base; + ogg_uint32_t q; + int qi_start; + int qi_end; + memcpy(base,_qinfo->qi_ranges[qti][pli].base_matrices[qri], + sizeof(base)); + qi_start=qi; + if(qri==_qinfo->qi_ranges[qti][pli].nranges)qi_end=qi+1; + else qi_end=qi+_qinfo->qi_ranges[qti][pli].sizes[qri]; + /*Iterate over quality indicies in this range.*/ + for(;;){ + ogg_uint32_t qfac; + int zzi; + int ci; + /*In the original VP3.2 code, the rounding offset and the size of the + dead zone around 0 were controlled by a "sharpness" parameter. + The size of our dead zone is now controlled by the per-coefficient + quality thresholds returned by our HVS module. + We round down from a more accurate value when the quality of the + reconstruction does not fall below our threshold and it saves bits. + Hence, all of that VP3.2 code is gone from here, and the remaining + floating point code has been implemented as equivalent integer code + with exact precision.*/ + qfac=(ogg_uint32_t)_qinfo->dc_scale[qi]*base[0]; + /*For postprocessing, not dequantization.*/ + if(_pp_dc_scale!=NULL)_pp_dc_scale[qi]=(int)(qfac/160); + /*Scale DC the coefficient from the proper table.*/ + q=(qfac/100)<<2; + q=OC_CLAMPI(OC_DC_QUANT_MIN[qti],q,OC_QUANT_MAX); + _dequant[qi][pli][qti][0]=(ogg_uint16_t)q; + /*Now scale AC coefficients from the proper table.*/ + for(zzi=1;zzi<64;zzi++){ + q=((ogg_uint32_t)_qinfo->ac_scale[qi]*base[OC_FZIG_ZAG[zzi]]/100)<<2; + q=OC_CLAMPI(OC_AC_QUANT_MIN[qti],q,OC_QUANT_MAX); + _dequant[qi][pli][qti][zzi]=(ogg_uint16_t)q; + } + /*If this is a duplicate of a previous matrix, use that instead. + This simple check helps us improve cache coherency later.*/ + { + int dupe; + int qtj; + int plj; + dupe=0; + for(qtj=0;qtj<=qti;qtj++){ + for(plj=0;plj<(qtj=qi_end)break; + /*Interpolate the next base matrix.*/ + for(ci=0;ci<64;ci++){ + base[ci]=(unsigned char)( + (2*((qi_end-qi)*_qinfo->qi_ranges[qti][pli].base_matrices[qri][ci]+ + (qi-qi_start)*_qinfo->qi_ranges[qti][pli].base_matrices[qri+1][ci]) + +_qinfo->qi_ranges[qti][pli].sizes[qri])/ + (2*_qinfo->qi_ranges[qti][pli].sizes[qri])); + } + } + } + } +} diff --git a/Engine/lib/libtheora/lib/dec/quant.h b/Engine/lib/libtheora/lib/quant.h similarity index 82% rename from Engine/lib/libtheora/lib/dec/quant.h rename to Engine/lib/libtheora/lib/quant.h index c3cefd1d8..49ce13a65 100644 --- a/Engine/lib/libtheora/lib/dec/quant.h +++ b/Engine/lib/libtheora/lib/quant.h @@ -5,13 +5,13 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: quant.h 15400 2008-10-15 12:10:58Z tterribe $ + last mod: $Id: quant.h 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ @@ -21,14 +21,13 @@ # include "ocintrin.h" typedef ogg_uint16_t oc_quant_table[64]; -typedef oc_quant_table oc_quant_tables[64]; /*Maximum scaled quantizer value.*/ #define OC_QUANT_MAX (1024<<2) -void oc_dequant_tables_init(oc_quant_table *_dequant[2][3], +void oc_dequant_tables_init(ogg_uint16_t *_dequant[64][3][2], int _pp_dc_scale[64],const th_quant_info *_qinfo); #endif diff --git a/Engine/lib/libtheora/lib/rate.c b/Engine/lib/libtheora/lib/rate.c new file mode 100644 index 000000000..4f43bb2e5 --- /dev/null +++ b/Engine/lib/libtheora/lib/rate.c @@ -0,0 +1,1137 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: rate.c 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ +#include +#include +#include "encint.h" + +/*A rough lookup table for tan(x), 0<=x>24; + if(i>=17)i=16; + t0=OC_ROUGH_TAN_LOOKUP[i]; + t1=OC_ROUGH_TAN_LOOKUP[i+1]; + d=_alpha*36-(i<<24); + return (int)(((ogg_int64_t)t0<<32)+(t1-t0<<8)*(ogg_int64_t)d>>32); +} + +/*Re-initialize the Bessel filter coefficients with the specified delay. + This does not alter the x/y state, but changes the reaction time of the + filter. + Altering the time constant of a reactive filter without alterning internal + state is something that has to be done carefuly, but our design operates at + high enough delays and with small enough time constant changes to make it + safe.*/ +static void oc_iir_filter_reinit(oc_iir_filter *_f,int _delay){ + int alpha; + ogg_int64_t one48; + ogg_int64_t warp; + ogg_int64_t k1; + ogg_int64_t k2; + ogg_int64_t d; + ogg_int64_t a; + ogg_int64_t ik2; + ogg_int64_t b1; + ogg_int64_t b2; + /*This borrows some code from an unreleased version of Postfish. + See the recipe at http://unicorn.us.com/alex/2polefilters.html for details + on deriving the filter coefficients.*/ + /*alpha is Q24*/ + alpha=(1<<24)/_delay; + one48=(ogg_int64_t)1<<48; + /*warp is 7.12*/ + warp=OC_MAXI(oc_warp_alpha(alpha),1); + /*k1 is 9.12*/ + k1=3*warp; + /*k2 is 16.24.*/ + k2=k1*warp; + /*d is 16.15.*/ + d=((1<<12)+k1<<12)+k2+256>>9; + /*a is 0.32, since d is larger than both 1.0 and k2.*/ + a=(k2<<23)/d; + /*ik2 is 25.24.*/ + ik2=one48/k2; + /*b1 is Q56; in practice, the integer ranges between -2 and 2.*/ + b1=2*a*(ik2-(1<<24)); + /*b2 is Q56; in practice, the integer ranges between -2 and 2.*/ + b2=(one48<<8)-(4*a<<24)-b1; + /*All of the filter parameters are Q24.*/ + _f->c[0]=(ogg_int32_t)(b1+((ogg_int64_t)1<<31)>>32); + _f->c[1]=(ogg_int32_t)(b2+((ogg_int64_t)1<<31)>>32); + _f->g=(ogg_int32_t)(a+128>>8); +} + +/*Initialize a 2nd order low-pass Bessel filter with the corresponding delay + and initial value. + _value is Q24.*/ +static void oc_iir_filter_init(oc_iir_filter *_f,int _delay,ogg_int32_t _value){ + oc_iir_filter_reinit(_f,_delay); + _f->y[1]=_f->y[0]=_f->x[1]=_f->x[0]=_value; +} + +static ogg_int64_t oc_iir_filter_update(oc_iir_filter *_f,ogg_int32_t _x){ + ogg_int64_t c0; + ogg_int64_t c1; + ogg_int64_t g; + ogg_int64_t x0; + ogg_int64_t x1; + ogg_int64_t y0; + ogg_int64_t y1; + ogg_int64_t ya; + c0=_f->c[0]; + c1=_f->c[1]; + g=_f->g; + x0=_f->x[0]; + x1=_f->x[1]; + y0=_f->y[0]; + y1=_f->y[1]; + ya=(_x+x0*2+x1)*g+y0*c0+y1*c1+(1<<23)>>24; + _f->x[1]=(ogg_int32_t)x0; + _f->x[0]=_x; + _f->y[1]=(ogg_int32_t)y0; + _f->y[0]=(ogg_int32_t)ya; + return ya; +} + + + +/*Search for the quantizer that matches the target most closely. + We don't assume a linear ordering, but when there are ties we pick the + quantizer closest to the old one.*/ +static int oc_enc_find_qi_for_target(oc_enc_ctx *_enc,int _qti,int _qi_old, + int _qi_min,ogg_int64_t _log_qtarget){ + ogg_int64_t best_qdiff; + int best_qi; + int qi; + best_qi=_qi_min; + best_qdiff=_enc->log_qavg[_qti][best_qi]-_log_qtarget; + best_qdiff=best_qdiff+OC_SIGNMASK(best_qdiff)^OC_SIGNMASK(best_qdiff); + for(qi=_qi_min+1;qi<64;qi++){ + ogg_int64_t qdiff; + qdiff=_enc->log_qavg[_qti][qi]-_log_qtarget; + qdiff=qdiff+OC_SIGNMASK(qdiff)^OC_SIGNMASK(qdiff); + if(qdiffstate.qis[0]; + /*If rate control is active, use the lambda for the _target_ quantizer. + This allows us to scale to rates slightly lower than we'd normally be able + to reach, and give the rate control a semblance of "fractional qi" + precision. + TODO: Add API for changing QI, and allow extra precision.*/ + if(_enc->state.info.target_bitrate>0)lq=_enc->rc.log_qtarget; + else lq=_enc->log_qavg[_qti][qi]; + /*The resulting lambda value is less than 0x500000.*/ + _enc->lambda=(int)oc_bexp64(2*lq-0x4780BD468D6B62BLL); + /*Select additional quantizers. + The R-D optimal block AC quantizer statistics suggest that the distribution + is roughly Gaussian-like with a slight positive skew. + K-means clustering on log_qavg to select 3 quantizers produces cluster + centers of {log_qavg-0.6,log_qavg,log_qavg+0.7}. + Experiments confirm these are relatively good choices. + + Although we do greedy R-D optimization of the qii flags to avoid switching + too frequently, this becomes ineffective at low rates, either because we + do a poor job of predicting the actual R-D cost, or the greedy + optimization is not sufficient. + Therefore adaptive quantization is disabled above an (experimentally + suggested) threshold of log_qavg=7.00 (e.g., below INTRA qi=12 or + INTER qi=20 with current matrices). + This may need to be revised if the R-D cost estimation or qii flag + optimization strategies change.*/ + nqis=1; + if(lq<(OC_Q57(56)>>3)&&!_enc->vp3_compatible){ + qi1=oc_enc_find_qi_for_target(_enc,_qti,OC_MAXI(qi-1,0),0, + lq+(OC_Q57(7)+5)/10); + if(qi1!=qi)_enc->state.qis[nqis++]=qi1; + qi1=oc_enc_find_qi_for_target(_enc,_qti,OC_MINI(qi+1,63),0, + lq-(OC_Q57(6)+5)/10); + if(qi1!=qi&&qi1!=_enc->state.qis[nqis-1])_enc->state.qis[nqis++]=qi1; + } + _enc->state.nqis=nqis; +} + +/*Binary exponential of _log_scale with 24-bit fractional precision and + saturation. + _log_scale: A binary logarithm in Q24 format. + Return: The binary exponential in Q24 format, saturated to 2**47-1 if + _log_scale was too large.*/ +static ogg_int64_t oc_bexp_q24(ogg_int32_t _log_scale){ + if(_log_scale<(ogg_int32_t)23<<24){ + ogg_int64_t ret; + ret=oc_bexp64(((ogg_int64_t)_log_scale<<33)+OC_Q57(24)); + return ret<0x7FFFFFFFFFFFLL?ret:0x7FFFFFFFFFFFLL; + } + return 0x7FFFFFFFFFFFLL; +} + +/*Convenience function converts Q57 value to a clamped 32-bit Q24 value + _in: input in Q57 format. + Return: same number in Q24 */ +static ogg_int32_t oc_q57_to_q24(ogg_int64_t _in){ + ogg_int64_t ret; + ret=_in+((ogg_int64_t)1<<32)>>33; + /*0x80000000 is automatically converted to unsigned on 32-bit systems. + -0x7FFFFFFF-1 is needed to avoid "promoting" the whole expression to + unsigned.*/ + return (ogg_int32_t)OC_CLAMPI(-0x7FFFFFFF-1,ret,0x7FFFFFFF); +} + +/*Binary exponential of _log_scale with 24-bit fractional precision and + saturation. + _log_scale: A binary logarithm in Q57 format. + Return: The binary exponential in Q24 format, saturated to 2**31-1 if + _log_scale was too large.*/ +static ogg_int32_t oc_bexp64_q24(ogg_int64_t _log_scale){ + if(_log_scalerc.bits_per_frame=(_enc->state.info.target_bitrate* + (ogg_int64_t)_enc->state.info.fps_denominator)/ + _enc->state.info.fps_numerator; + /*Insane framerates or frame sizes mean insane bitrates. + Let's not get carried away.*/ + if(_enc->rc.bits_per_frame>0x400000000000LL){ + _enc->rc.bits_per_frame=(ogg_int64_t)0x400000000000LL; + } + else if(_enc->rc.bits_per_frame<32)_enc->rc.bits_per_frame=32; + _enc->rc.buf_delay=OC_MAXI(_enc->rc.buf_delay,12); + _enc->rc.max=_enc->rc.bits_per_frame*_enc->rc.buf_delay; + /*Start with a buffer fullness of 50% plus 25% of the amount we plan to spend + on a single keyframe interval. + We can require fully half the bits in an interval for a keyframe, so this + initial level gives us maximum flexibility for over/under-shooting in + subsequent frames.*/ + _enc->rc.target=(_enc->rc.max+1>>1)+(_enc->rc.bits_per_frame+2>>2)* + OC_MINI(_enc->keyframe_frequency_force,_enc->rc.buf_delay); + _enc->rc.fullness=_enc->rc.target; + /*Pick exponents and initial scales for quantizer selection.*/ + npixels=_enc->state.info.frame_width* + (ogg_int64_t)_enc->state.info.frame_height; + _enc->rc.log_npixels=oc_blog64(npixels); + ibpp=npixels/_enc->rc.bits_per_frame; + if(ibpp<1){ + _enc->rc.exp[0]=59; + _enc->rc.log_scale[0]=oc_blog64(1997)-OC_Q57(8); + } + else if(ibpp<2){ + _enc->rc.exp[0]=55; + _enc->rc.log_scale[0]=oc_blog64(1604)-OC_Q57(8); + } + else{ + _enc->rc.exp[0]=48; + _enc->rc.log_scale[0]=oc_blog64(834)-OC_Q57(8); + } + if(ibpp<4){ + _enc->rc.exp[1]=100; + _enc->rc.log_scale[1]=oc_blog64(2249)-OC_Q57(8); + } + else if(ibpp<8){ + _enc->rc.exp[1]=95; + _enc->rc.log_scale[1]=oc_blog64(1751)-OC_Q57(8); + } + else{ + _enc->rc.exp[1]=73; + _enc->rc.log_scale[1]=oc_blog64(1260)-OC_Q57(8); + } + _enc->rc.prev_drop_count=0; + _enc->rc.log_drop_scale=OC_Q57(0); + /*Set up second order followers, initialized according to corresponding + time constants.*/ + oc_iir_filter_init(&_enc->rc.scalefilter[0],4, + oc_q57_to_q24(_enc->rc.log_scale[0])); + inter_delay=(_enc->rc.twopass? + OC_MAXI(_enc->keyframe_frequency_force,12):_enc->rc.buf_delay)>>1; + _enc->rc.inter_count=0; + /*We clamp the actual inter_delay to a minimum of 10 to work within the range + of values where later incrementing the delay works as designed. + 10 is not an exact choice, but rather a good working trade-off.*/ + _enc->rc.inter_delay=10; + _enc->rc.inter_delay_target=inter_delay; + oc_iir_filter_init(&_enc->rc.scalefilter[1],_enc->rc.inter_delay, + oc_q57_to_q24(_enc->rc.log_scale[1])); + oc_iir_filter_init(&_enc->rc.vfrfilter,4, + oc_bexp64_q24(_enc->rc.log_drop_scale)); +} + +void oc_rc_state_init(oc_rc_state *_rc,oc_enc_ctx *_enc){ + _rc->twopass=0; + _rc->twopass_buffer_bytes=0; + _rc->twopass_force_kf=0; + _rc->frame_metrics=NULL; + _rc->rate_bias=0; + if(_enc->state.info.target_bitrate>0){ + /*The buffer size is set equal to the keyframe interval, clamped to the + range [12,256] frames. + The 12 frame minimum gives us some chance to distribute bit estimation + errors. + The 256 frame maximum means we'll require 8-10 seconds of pre-buffering + at 24-30 fps, which is not unreasonable.*/ + _rc->buf_delay=_enc->keyframe_frequency_force>256? + 256:_enc->keyframe_frequency_force; + /*By default, enforce all buffer constraints.*/ + _rc->drop_frames=1; + _rc->cap_overflow=1; + _rc->cap_underflow=0; + oc_enc_rc_reset(_enc); + } +} + +void oc_rc_state_clear(oc_rc_state *_rc){ + _ogg_free(_rc->frame_metrics); +} + +void oc_enc_rc_resize(oc_enc_ctx *_enc){ + /*If encoding has not yet begun, reset the buffer state.*/ + if(_enc->state.curframe_num<0)oc_enc_rc_reset(_enc); + else{ + int idt; + /*Otherwise, update the bounds on the buffer, but not the current + fullness.*/ + _enc->rc.bits_per_frame=(_enc->state.info.target_bitrate* + (ogg_int64_t)_enc->state.info.fps_denominator)/ + _enc->state.info.fps_numerator; + /*Insane framerates or frame sizes mean insane bitrates. + Let's not get carried away.*/ + if(_enc->rc.bits_per_frame>0x400000000000LL){ + _enc->rc.bits_per_frame=(ogg_int64_t)0x400000000000LL; + } + else if(_enc->rc.bits_per_frame<32)_enc->rc.bits_per_frame=32; + _enc->rc.buf_delay=OC_MAXI(_enc->rc.buf_delay,12); + _enc->rc.max=_enc->rc.bits_per_frame*_enc->rc.buf_delay; + _enc->rc.target=(_enc->rc.max+1>>1)+(_enc->rc.bits_per_frame+2>>2)* + OC_MINI(_enc->keyframe_frequency_force,_enc->rc.buf_delay); + /*Update the INTER-frame scale filter delay. + We jump to it immediately if we've already seen enough frames; otherwise + it is simply set as the new target.*/ + _enc->rc.inter_delay_target=idt=OC_MAXI(_enc->rc.buf_delay>>1,10); + if(idtrc.inter_delay,_enc->rc.inter_count)){ + oc_iir_filter_init(&_enc->rc.scalefilter[1],idt, + _enc->rc.scalefilter[1].y[0]); + _enc->rc.inter_delay=idt; + } + } + /*If we're in pass-2 mode, make sure the frame metrics array is big enough + to hold frame statistics for the full buffer.*/ + if(_enc->rc.twopass==2){ + int cfm; + int buf_delay; + int reset_window; + buf_delay=_enc->rc.buf_delay; + reset_window=_enc->rc.frame_metrics==NULL&&(_enc->rc.frames_total[0]==0|| + buf_delay<_enc->rc.frames_total[0]+_enc->rc.frames_total[1] + +_enc->rc.frames_total[2]); + cfm=_enc->rc.cframe_metrics; + /*Only try to resize the frame metrics buffer if a) it's too small and + b) we were using a finite buffer, or are about to start.*/ + if(cfmrc.frame_metrics!=NULL||reset_window)){ + oc_frame_metrics *fm; + int nfm; + int fmh; + fm=(oc_frame_metrics *)_ogg_realloc(_enc->rc.frame_metrics, + buf_delay*sizeof(*_enc->rc.frame_metrics)); + if(fm==NULL){ + /*We failed to allocate a finite buffer.*/ + /*If we don't have a valid 2-pass header yet, just return; we'll reset + the buffer size when we read the header.*/ + if(_enc->rc.frames_total[0]==0)return; + /*Otherwise revert to the largest finite buffer previously set, or to + whole-file buffering if we were still using that.*/ + _enc->rc.buf_delay=_enc->rc.frame_metrics!=NULL? + cfm:_enc->rc.frames_total[0]+_enc->rc.frames_total[1] + +_enc->rc.frames_total[2]; + oc_enc_rc_resize(_enc); + return; + } + _enc->rc.frame_metrics=fm; + _enc->rc.cframe_metrics=buf_delay; + /*Re-organize the circular buffer.*/ + fmh=_enc->rc.frame_metrics_head; + nfm=_enc->rc.nframe_metrics; + if(fmh+nfm>cfm){ + int shift; + shift=OC_MINI(fmh+nfm-cfm,buf_delay-cfm); + memcpy(fm+cfm,fm,OC_MINI(fmh+nfm-cfm,buf_delay-cfm)*sizeof(*fm)); + if(fmh+nfm>buf_delay)memmove(fm,fm+shift,fmh+nfm-buf_delay); + } + } + /*We were using whole-file buffering; now we're not.*/ + if(reset_window){ + _enc->rc.nframes[0]=_enc->rc.nframes[1]=_enc->rc.nframes[2]=0; + _enc->rc.scale_sum[0]=_enc->rc.scale_sum[1]=0; + _enc->rc.scale_window_end=_enc->rc.scale_window0= + _enc->state.curframe_num+_enc->prev_dup_count+1; + if(_enc->rc.twopass_buffer_bytes){ + int qti; + /*We already read the metrics for the first frame in the window.*/ + *(_enc->rc.frame_metrics)=*&_enc->rc.cur_metrics; + _enc->rc.nframe_metrics++; + qti=_enc->rc.cur_metrics.frame_type; + _enc->rc.nframes[qti]++; + _enc->rc.nframes[2]+=_enc->rc.cur_metrics.dup_count; + _enc->rc.scale_sum[qti]+=oc_bexp_q24(_enc->rc.cur_metrics.log_scale); + _enc->rc.scale_window_end+=_enc->rc.cur_metrics.dup_count+1; + if(_enc->rc.scale_window_end-_enc->rc.scale_window0rc.twopass_buffer_bytes=0; + } + } + } + /*Otherwise, we could shrink the size of the current window, if necessary, + but leaving it like it is lets us adapt to the new buffer size more + gracefully.*/ + } +} + +/*Scale the number of frames by the number of expected drops/duplicates.*/ +static int oc_rc_scale_drop(oc_rc_state *_rc,int _nframes){ + if(_rc->prev_drop_count>0||_rc->log_drop_scale>OC_Q57(0)){ + ogg_int64_t dup_scale; + dup_scale=oc_bexp64((_rc->log_drop_scale + +oc_blog64(_rc->prev_drop_count+1)>>1)+OC_Q57(8)); + if(dup_scale<_nframes<<8){ + int dup_scalei; + dup_scalei=(int)dup_scale; + if(dup_scalei>0)_nframes=((_nframes<<8)+dup_scalei-1)/dup_scalei; + } + else _nframes=!!_nframes; + } + return _nframes; +} + +int oc_enc_select_qi(oc_enc_ctx *_enc,int _qti,int _clamp){ + ogg_int64_t rate_total; + ogg_int64_t rate_bias; + int nframes[2]; + int buf_delay; + int buf_pad; + ogg_int64_t log_qtarget; + ogg_int64_t log_scale0; + ogg_int64_t log_cur_scale; + ogg_int64_t log_qexp; + int exp0; + int old_qi; + int qi; + /*Figure out how to re-distribute bits so that we hit our fullness target + before the last keyframe in our current buffer window (after the current + frame), or the end of the buffer window, whichever comes first.*/ + log_cur_scale=(ogg_int64_t)_enc->rc.scalefilter[_qti].y[0]<<33; + buf_pad=0; + switch(_enc->rc.twopass){ + default:{ + ogg_uint32_t next_key_frame; + /*Single pass mode: assume only forced keyframes and attempt to estimate + the drop count for VFR content.*/ + next_key_frame=_qti?_enc->keyframe_frequency_force + -(_enc->state.curframe_num-_enc->state.keyframe_num):0; + nframes[0]=(_enc->rc.buf_delay-OC_MINI(next_key_frame,_enc->rc.buf_delay) + +_enc->keyframe_frequency_force-1)/_enc->keyframe_frequency_force; + if(nframes[0]+_qti>1){ + nframes[0]--; + buf_delay=next_key_frame+nframes[0]*_enc->keyframe_frequency_force; + } + else buf_delay=_enc->rc.buf_delay; + nframes[1]=buf_delay-nframes[0]; + /*Downgrade the delta frame rate to correspond to the recent drop count + history.*/ + nframes[1]=oc_rc_scale_drop(&_enc->rc,nframes[1]); + }break; + case 1:{ + /*Pass 1 mode: use a fixed qi value.*/ + qi=_enc->state.qis[0]; + _enc->rc.log_qtarget=_enc->log_qavg[_qti][qi]; + return qi; + }break; + case 2:{ + ogg_int64_t scale_sum[2]; + int qti; + /*Pass 2 mode: we know exactly how much of each frame type there is in + the current buffer window, and have estimates for the scales.*/ + nframes[0]=_enc->rc.nframes[0]; + nframes[1]=_enc->rc.nframes[1]; + scale_sum[0]=_enc->rc.scale_sum[0]; + scale_sum[1]=_enc->rc.scale_sum[1]; + /*The window size can be slightly larger than the buffer window for VFR + content; clamp it down, if appropriate (the excess will all be dup + frames).*/ + buf_delay=OC_MINI(_enc->rc.scale_window_end-_enc->rc.scale_window0, + _enc->rc.buf_delay); + /*If we're approaching the end of the file, add some slack to keep us + from slamming into a rail. + Our rate accuracy goes down, but it keeps the result sensible. + We position the target where the first forced keyframe beyond the end + of the file would be (for consistency with 1-pass mode).*/ + buf_pad=OC_MINI(_enc->rc.buf_delay,_enc->state.keyframe_num + +_enc->keyframe_frequency_force-_enc->rc.scale_window0); + if(buf_delayrc.frame_metrics!=NULL){ + int fmi; + int fm_tail; + fm_tail=_enc->rc.frame_metrics_head+_enc->rc.nframe_metrics; + if(fm_tail>=_enc->rc.cframe_metrics)fm_tail-=_enc->rc.cframe_metrics; + for(fmi=fm_tail;;){ + oc_frame_metrics *m; + fmi--; + if(fmi<0)fmi+=_enc->rc.cframe_metrics; + /*Stop before we remove the first frame.*/ + if(fmi==_enc->rc.frame_metrics_head)break; + m=_enc->rc.frame_metrics+fmi; + /*If we find a keyframe, remove it and everything past it.*/ + if(m->frame_type==OC_INTRA_FRAME){ + do{ + qti=m->frame_type; + nframes[qti]--; + scale_sum[qti]-=oc_bexp_q24(m->log_scale); + buf_delay-=m->dup_count+1; + fmi++; + if(fmi>=_enc->rc.cframe_metrics)fmi=0; + m=_enc->rc.frame_metrics+fmi; + } + while(fmi!=fm_tail); + /*And stop scanning backwards.*/ + break; + } + } + } + } + /*If we're not using the same frame type as in pass 1 (because someone + changed the keyframe interval), remove that scale estimate. + We'll add in a replacement for the correct frame type below.*/ + qti=_enc->rc.cur_metrics.frame_type; + if(qti!=_qti){ + nframes[qti]--; + scale_sum[qti]-=oc_bexp_q24(_enc->rc.cur_metrics.log_scale); + } + /*Compute log_scale estimates for each frame type from the pass-1 scales + we measured in the current window.*/ + for(qti=0;qti<2;qti++){ + _enc->rc.log_scale[qti]=nframes[qti]>0? + oc_blog64(scale_sum[qti])-oc_blog64(nframes[qti])-OC_Q57(24): + -_enc->rc.log_npixels; + } + /*If we're not using the same frame type as in pass 1, add a scale + estimate for the corresponding frame using the current low-pass + filter value. + This is mostly to ensure we have a valid estimate even when pass 1 had + no frames of this type in the buffer window. + TODO: We could also plan ahead and figure out how many keyframes we'll + be forced to add in the current buffer window.*/ + qti=_enc->rc.cur_metrics.frame_type; + if(qti!=_qti){ + ogg_int64_t scale; + scale=_enc->rc.log_scale[_qti]rc.log_scale[_qti]+OC_Q57(24)):0x7FFFFFFFFFFFLL; + scale*=nframes[_qti]; + nframes[_qti]++; + scale+=oc_bexp_q24(log_cur_scale>>33); + _enc->rc.log_scale[_qti]=oc_blog64(scale) + -oc_blog64(nframes[qti])-OC_Q57(24); + } + else log_cur_scale=(ogg_int64_t)_enc->rc.cur_metrics.log_scale<<33; + /*Add the padding from above. + This basically reverts to 1-pass estimations in the last keyframe + interval.*/ + if(buf_pad>0){ + ogg_int64_t scale; + int nextra_frames; + /*Extend the buffer.*/ + buf_delay+=buf_pad; + /*Add virtual delta frames according to the estimated drop count.*/ + nextra_frames=oc_rc_scale_drop(&_enc->rc,buf_pad); + /*And blend in the low-pass filtered scale according to how many frames + we added.*/ + scale= + oc_bexp64(_enc->rc.log_scale[1]+OC_Q57(24))*(ogg_int64_t)nframes[1] + +oc_bexp_q24(_enc->rc.scalefilter[1].y[0])*(ogg_int64_t)nextra_frames; + nframes[1]+=nextra_frames; + _enc->rc.log_scale[1]=oc_blog64(scale)-oc_blog64(nframes[1])-OC_Q57(24); + } + }break; + } + /*If we've been missing our target, add a penalty term.*/ + rate_bias=(_enc->rc.rate_bias/(_enc->state.curframe_num+1000))* + (buf_delay-buf_pad); + /*rate_total is the total bits available over the next buf_delay frames.*/ + rate_total=_enc->rc.fullness-_enc->rc.target+rate_bias + +buf_delay*_enc->rc.bits_per_frame; + log_scale0=_enc->rc.log_scale[_qti]+_enc->rc.log_npixels; + /*If there aren't enough bits to achieve our desired fullness level, use the + minimum quality permitted.*/ + if(rate_total<=buf_delay)log_qtarget=OC_QUANT_MAX_LOG; + else{ + static const ogg_int64_t LOG_KEY_RATIO=0x0137222BB70747BALL; + ogg_int64_t log_scale1; + ogg_int64_t rlo; + ogg_int64_t rhi; + log_scale1=_enc->rc.log_scale[1-_qti]+_enc->rc.log_npixels; + rlo=0; + rhi=(rate_total+nframes[_qti]-1)/nframes[_qti]; + while(rlo>1; + log_rpow=oc_blog64(curr)-log_scale0; + log_rpow=(log_rpow+(_enc->rc.exp[_qti]>>1))/_enc->rc.exp[_qti]; + if(_qti)log_rpow+=LOG_KEY_RATIO>>6; + else log_rpow-=LOG_KEY_RATIO>>6; + log_rpow*=_enc->rc.exp[1-_qti]; + rscale=nframes[1-_qti]*oc_bexp64(log_scale1+log_rpow); + rdiff=nframes[_qti]*curr+rscale-rate_total; + if(rdiff<0)rlo=curr+1; + else if(rdiff>0)rhi=curr-1; + else break; + } + log_qtarget=OC_Q57(2)-((oc_blog64(rlo)-log_scale0+(_enc->rc.exp[_qti]>>1))/ + _enc->rc.exp[_qti]<<6); + log_qtarget=OC_MINI(log_qtarget,OC_QUANT_MAX_LOG); + } + /*The above allocation looks only at the total rate we'll accumulate in the + next buf_delay frames. + However, we could overflow the buffer on the very next frame, so check for + that here, if we're not using a soft target.*/ + exp0=_enc->rc.exp[_qti]; + if(_enc->rc.cap_overflow){ + ogg_int64_t margin; + ogg_int64_t soft_limit; + ogg_int64_t log_soft_limit; + /*Allow 3% of the buffer for prediction error. + This should be plenty, and we don't mind if we go a bit over; we only + want to keep these bits from being completely wasted.*/ + margin=_enc->rc.max+31>>5; + /*We want to use at least this many bits next frame.*/ + soft_limit=_enc->rc.fullness+_enc->rc.bits_per_frame-(_enc->rc.max-margin); + log_soft_limit=oc_blog64(soft_limit); + /*If we're predicting we won't use that many...*/ + log_qexp=(log_qtarget-OC_Q57(2)>>6)*exp0; + if(log_scale0-log_qexp>32)* + ((OC_MINI(margin,soft_limit)<<32)/margin); + log_qtarget=((log_qexp+(exp0>>1))/exp0<<6)+OC_Q57(2); + } + } + /*If this was not one of the initial frames, limit the change in quality.*/ + old_qi=_enc->state.qis[0]; + if(_clamp){ + ogg_int64_t log_qmin; + ogg_int64_t log_qmax; + /*Clamp the target quantizer to within [0.8*Q,1.2*Q], where Q is the + current quantizer. + TODO: With user-specified quant matrices, we need to enlarge these limits + if they don't actually let us change qi values.*/ + log_qmin=_enc->log_qavg[_qti][old_qi]-0x00A4D3C25E68DC58LL; + log_qmax=_enc->log_qavg[_qti][old_qi]+0x00A4D3C25E68DC58LL; + log_qtarget=OC_CLAMPI(log_qmin,log_qtarget,log_qmax); + } + /*The above allocation looks only at the total rate we'll accumulate in the + next buf_delay frames. + However, we could bust the budget on the very next frame, so check for that + here, if we're not using a soft target.*/ + /* Disabled when our minimum qi > 0; if we saturate log_qtarget to + to the maximum possible size when we have a minimum qi, the + resulting lambda will interact very strangely with SKIP. The + resulting artifacts look like waterfalls. */ + if(_enc->state.info.quality==0){ + ogg_int64_t log_hard_limit; + /*Compute the maximum number of bits we can use in the next frame. + Allow 50% of the rate for a single frame for prediction error. + This may not be enough for keyframes or sudden changes in complexity.*/ + log_hard_limit=oc_blog64(_enc->rc.fullness+(_enc->rc.bits_per_frame>>1)); + /*If we're predicting we'll use more than this...*/ + log_qexp=(log_qtarget-OC_Q57(2)>>6)*exp0; + if(log_scale0-log_qexp>log_hard_limit){ + /*Force the target to hit our limit exactly.*/ + log_qexp=log_scale0-log_hard_limit; + log_qtarget=((log_qexp+(exp0>>1))/exp0<<6)+OC_Q57(2); + /*If that target is unreasonable, oh well; we'll have to drop.*/ + log_qtarget=OC_MINI(log_qtarget,OC_QUANT_MAX_LOG); + } + } + /*Compute a final estimate of the number of bits we plan to use.*/ + log_qexp=(log_qtarget-OC_Q57(2)>>6)*_enc->rc.exp[_qti]; + _enc->rc.rate_bias+=oc_bexp64(log_cur_scale+_enc->rc.log_npixels-log_qexp); + qi=oc_enc_find_qi_for_target(_enc,_qti,old_qi, + _enc->state.info.quality,log_qtarget); + /*Save the quantizer target for lambda calculations.*/ + _enc->rc.log_qtarget=log_qtarget; + return qi; +} + +int oc_enc_update_rc_state(oc_enc_ctx *_enc, + long _bits,int _qti,int _qi,int _trial,int _droppable){ + ogg_int64_t buf_delta; + ogg_int64_t log_scale; + int dropped; + dropped=0; + /* Drop frames also disabled for now in the case of infinite-buffer + two-pass mode */ + if(!_enc->rc.drop_frames||_enc->rc.twopass&&_enc->rc.frame_metrics==NULL){ + _droppable=0; + } + buf_delta=_enc->rc.bits_per_frame*(1+_enc->dup_count); + if(_bits<=0){ + /*We didn't code any blocks in this frame.*/ + log_scale=OC_Q57(-64); + _bits=0; + } + else{ + ogg_int64_t log_bits; + ogg_int64_t log_qexp; + /*Compute the estimated scale factor for this frame type.*/ + log_bits=oc_blog64(_bits); + log_qexp=_enc->rc.log_qtarget-OC_Q57(2); + log_qexp=(log_qexp>>6)*(_enc->rc.exp[_qti]); + log_scale=OC_MINI(log_bits-_enc->rc.log_npixels+log_qexp,OC_Q57(16)); + } + /*Special two-pass processing.*/ + switch(_enc->rc.twopass){ + case 1:{ + /*Pass 1 mode: save the metrics for this frame.*/ + _enc->rc.cur_metrics.log_scale=oc_q57_to_q24(log_scale); + _enc->rc.cur_metrics.dup_count=_enc->dup_count; + _enc->rc.cur_metrics.frame_type=_enc->state.frame_type; + _enc->rc.twopass_buffer_bytes=0; + }break; + case 2:{ + /*Pass 2 mode:*/ + if(!_trial){ + ogg_int64_t next_frame_num; + int qti; + /*Move the current metrics back one frame.*/ + *&_enc->rc.prev_metrics=*&_enc->rc.cur_metrics; + next_frame_num=_enc->state.curframe_num+_enc->dup_count+1; + /*Back out the last frame's statistics from the sliding window.*/ + qti=_enc->rc.prev_metrics.frame_type; + _enc->rc.frames_left[qti]--; + _enc->rc.frames_left[2]-=_enc->rc.prev_metrics.dup_count; + _enc->rc.nframes[qti]--; + _enc->rc.nframes[2]-=_enc->rc.prev_metrics.dup_count; + _enc->rc.scale_sum[qti]-=oc_bexp_q24(_enc->rc.prev_metrics.log_scale); + _enc->rc.scale_window0=(int)next_frame_num; + /*Free the corresponding entry in the circular buffer.*/ + if(_enc->rc.frame_metrics!=NULL){ + _enc->rc.nframe_metrics--; + _enc->rc.frame_metrics_head++; + if(_enc->rc.frame_metrics_head>=_enc->rc.cframe_metrics){ + _enc->rc.frame_metrics_head=0; + } + } + /*Mark us ready for the next 2-pass packet.*/ + _enc->rc.twopass_buffer_bytes=0; + /*Update state, so the user doesn't have to keep calling 2pass_in after + they've fed in all the data when we're using a finite buffer.*/ + _enc->prev_dup_count=_enc->dup_count; + oc_enc_rc_2pass_in(_enc,NULL,0); + } + }break; + } + /*Common to all passes:*/ + if(_bits>0){ + if(_trial){ + oc_iir_filter *f; + /*Use the estimated scale factor directly if this was a trial.*/ + f=_enc->rc.scalefilter+_qti; + f->y[1]=f->y[0]=f->x[1]=f->x[0]=oc_q57_to_q24(log_scale); + _enc->rc.log_scale[_qti]=log_scale; + } + else{ + /*Lengthen the time constant for the INTER filter as we collect more + frame statistics, until we reach our target.*/ + if(_enc->rc.inter_delay<_enc->rc.inter_delay_target&& + _enc->rc.inter_count>=_enc->rc.inter_delay&&_qti==OC_INTER_FRAME){ + oc_iir_filter_reinit(&_enc->rc.scalefilter[1],++_enc->rc.inter_delay); + } + /*Otherwise update the low-pass scale filter for this frame type, + regardless of whether or not we dropped this frame.*/ + _enc->rc.log_scale[_qti]=oc_iir_filter_update( + _enc->rc.scalefilter+_qti,oc_q57_to_q24(log_scale))<<33; + /*If this frame busts our budget, it must be dropped.*/ + if(_droppable&&_enc->rc.fullness+buf_delta<_bits){ + _enc->rc.prev_drop_count+=1+_enc->dup_count; + _bits=0; + dropped=1; + } + else{ + ogg_uint32_t drop_count; + /*Update a low-pass filter to estimate the "real" frame rate taking + drops and duplicates into account. + This is only done if the frame is coded, as it needs the final + count of dropped frames.*/ + drop_count=_enc->rc.prev_drop_count+1; + if(drop_count>0x7F)drop_count=0x7FFFFFFF; + else drop_count<<=24; + _enc->rc.log_drop_scale=oc_blog64(oc_iir_filter_update( + &_enc->rc.vfrfilter,drop_count))-OC_Q57(24); + /*Initialize the drop count for this frame to the user-requested dup + count. + It will be increased if we drop more frames.*/ + _enc->rc.prev_drop_count=_enc->dup_count; + } + } + /*Increment the INTER frame count, for filter adaptation purposes.*/ + if(_enc->rc.inter_countrc.inter_count+=_qti; + } + /*Increase the drop count.*/ + else _enc->rc.prev_drop_count+=1+_enc->dup_count; + /*And update the buffer fullness level.*/ + if(!_trial){ + _enc->rc.fullness+=buf_delta-_bits; + /*If we're too quick filling the buffer and overflow is capped, + that rate is lost forever.*/ + if(_enc->rc.cap_overflow&&_enc->rc.fullness>_enc->rc.max){ + _enc->rc.fullness=_enc->rc.max; + } + /*If we're too quick draining the buffer and underflow is capped, + don't try to make up that rate later.*/ + if(_enc->rc.cap_underflow&&_enc->rc.fullness<0){ + _enc->rc.fullness=0; + } + /*Adjust the bias for the real bits we've used.*/ + _enc->rc.rate_bias-=_bits; + } + return dropped; +} + +#define OC_RC_2PASS_VERSION (1) +#define OC_RC_2PASS_HDR_SZ (38) +#define OC_RC_2PASS_PACKET_SZ (8) + +static void oc_rc_buffer_val(oc_rc_state *_rc,ogg_int64_t _val,int _bytes){ + while(_bytes-->0){ + _rc->twopass_buffer[_rc->twopass_buffer_bytes++]=(unsigned char)(_val&0xFF); + _val>>=8; + } +} + +int oc_enc_rc_2pass_out(oc_enc_ctx *_enc,unsigned char **_buf){ + if(_enc->rc.twopass_buffer_bytes==0){ + if(_enc->rc.twopass==0){ + int qi; + /*Pick first-pass qi for scale calculations.*/ + qi=oc_enc_select_qi(_enc,0,0); + _enc->state.nqis=1; + _enc->state.qis[0]=qi; + _enc->rc.twopass=1; + _enc->rc.frames_total[0]=_enc->rc.frames_total[1]= + _enc->rc.frames_total[2]=0; + _enc->rc.scale_sum[0]=_enc->rc.scale_sum[1]=0; + /*Fill in dummy summary values.*/ + oc_rc_buffer_val(&_enc->rc,0x5032544F,4); + oc_rc_buffer_val(&_enc->rc,OC_RC_2PASS_VERSION,4); + oc_rc_buffer_val(&_enc->rc,0,OC_RC_2PASS_HDR_SZ-8); + } + else{ + int qti; + qti=_enc->rc.cur_metrics.frame_type; + _enc->rc.scale_sum[qti]+=oc_bexp_q24(_enc->rc.cur_metrics.log_scale); + _enc->rc.frames_total[qti]++; + _enc->rc.frames_total[2]+=_enc->rc.cur_metrics.dup_count; + oc_rc_buffer_val(&_enc->rc, + _enc->rc.cur_metrics.dup_count|_enc->rc.cur_metrics.frame_type<<31,4); + oc_rc_buffer_val(&_enc->rc,_enc->rc.cur_metrics.log_scale,4); + } + } + else if(_enc->packet_state==OC_PACKET_DONE&& + _enc->rc.twopass_buffer_bytes!=OC_RC_2PASS_HDR_SZ){ + _enc->rc.twopass_buffer_bytes=0; + oc_rc_buffer_val(&_enc->rc,0x5032544F,4); + oc_rc_buffer_val(&_enc->rc,OC_RC_2PASS_VERSION,4); + oc_rc_buffer_val(&_enc->rc,_enc->rc.frames_total[0],4); + oc_rc_buffer_val(&_enc->rc,_enc->rc.frames_total[1],4); + oc_rc_buffer_val(&_enc->rc,_enc->rc.frames_total[2],4); + oc_rc_buffer_val(&_enc->rc,_enc->rc.exp[0],1); + oc_rc_buffer_val(&_enc->rc,_enc->rc.exp[1],1); + oc_rc_buffer_val(&_enc->rc,_enc->rc.scale_sum[0],8); + oc_rc_buffer_val(&_enc->rc,_enc->rc.scale_sum[1],8); + } + else{ + /*The data for this frame has already been retrieved.*/ + *_buf=NULL; + return 0; + } + *_buf=_enc->rc.twopass_buffer; + return _enc->rc.twopass_buffer_bytes; +} + +static size_t oc_rc_buffer_fill(oc_rc_state *_rc, + unsigned char *_buf,size_t _bytes,size_t _consumed,size_t _goal){ + while(_rc->twopass_buffer_fill<_goal&&_consumed<_bytes){ + _rc->twopass_buffer[_rc->twopass_buffer_fill++]=_buf[_consumed++]; + } + return _consumed; +} + +static ogg_int64_t oc_rc_unbuffer_val(oc_rc_state *_rc,int _bytes){ + ogg_int64_t ret; + int shift; + ret=0; + shift=0; + while(_bytes-->0){ + ret|=((ogg_int64_t)_rc->twopass_buffer[_rc->twopass_buffer_bytes++])<rc.twopass==0){ + _enc->rc.twopass=2; + _enc->rc.twopass_buffer_fill=0; + _enc->rc.frames_total[0]=0; + _enc->rc.nframe_metrics=0; + _enc->rc.cframe_metrics=0; + _enc->rc.frame_metrics_head=0; + _enc->rc.scale_window0=0; + _enc->rc.scale_window_end=0; + } + /*If we haven't got a valid summary header yet, try to parse one.*/ + if(_enc->rc.frames_total[0]==0){ + if(!_buf){ + int frames_needed; + /*If we're using a whole-file buffer, we just need the first frame. + Otherwise, we may need as many as one per buffer slot.*/ + frames_needed=_enc->rc.frame_metrics==NULL?1:_enc->rc.buf_delay; + return OC_RC_2PASS_HDR_SZ+frames_needed*OC_RC_2PASS_PACKET_SZ + -_enc->rc.twopass_buffer_fill; + } + consumed=oc_rc_buffer_fill(&_enc->rc, + _buf,_bytes,consumed,OC_RC_2PASS_HDR_SZ); + if(_enc->rc.twopass_buffer_fill>=OC_RC_2PASS_HDR_SZ){ + ogg_int64_t scale_sum[2]; + int exp[2]; + int buf_delay; + /*Read the summary header data.*/ + /*Check the magic value and version number.*/ + if(oc_rc_unbuffer_val(&_enc->rc,4)!=0x5032544F|| + oc_rc_unbuffer_val(&_enc->rc,4)!=OC_RC_2PASS_VERSION){ + _enc->rc.twopass_buffer_bytes=0; + return TH_ENOTFORMAT; + } + _enc->rc.frames_total[0]=(ogg_uint32_t)oc_rc_unbuffer_val(&_enc->rc,4); + _enc->rc.frames_total[1]=(ogg_uint32_t)oc_rc_unbuffer_val(&_enc->rc,4); + _enc->rc.frames_total[2]=(ogg_uint32_t)oc_rc_unbuffer_val(&_enc->rc,4); + exp[0]=(int)oc_rc_unbuffer_val(&_enc->rc,1); + exp[1]=(int)oc_rc_unbuffer_val(&_enc->rc,1); + scale_sum[0]=oc_rc_unbuffer_val(&_enc->rc,8); + scale_sum[1]=oc_rc_unbuffer_val(&_enc->rc,8); + /*Make sure the file claims to have at least one frame. + Otherwise we probably got the placeholder data from an aborted pass 1. + Also make sure the total frame count doesn't overflow an integer.*/ + buf_delay=_enc->rc.frames_total[0]+_enc->rc.frames_total[1] + +_enc->rc.frames_total[2]; + if(_enc->rc.frames_total[0]==0||buf_delay<0|| + (ogg_uint32_t)buf_delay<_enc->rc.frames_total[0]|| + (ogg_uint32_t)buf_delay<_enc->rc.frames_total[1]){ + _enc->rc.frames_total[0]=0; + _enc->rc.twopass_buffer_bytes=0; + return TH_EBADHEADER; + } + /*Got a valid header; set up pass 2.*/ + _enc->rc.frames_left[0]=_enc->rc.frames_total[0]; + _enc->rc.frames_left[1]=_enc->rc.frames_total[1]; + _enc->rc.frames_left[2]=_enc->rc.frames_total[2]; + /*If the user hasn't specified a buffer size, use the whole file.*/ + if(_enc->rc.frame_metrics==NULL){ + _enc->rc.buf_delay=buf_delay; + _enc->rc.nframes[0]=_enc->rc.frames_total[0]; + _enc->rc.nframes[1]=_enc->rc.frames_total[1]; + _enc->rc.nframes[2]=_enc->rc.frames_total[2]; + _enc->rc.scale_sum[0]=scale_sum[0]; + _enc->rc.scale_sum[1]=scale_sum[1]; + _enc->rc.scale_window_end=buf_delay; + oc_enc_rc_reset(_enc); + } + _enc->rc.exp[0]=exp[0]; + _enc->rc.exp[1]=exp[1]; + /*Clear the header data from the buffer to make room for packet data.*/ + _enc->rc.twopass_buffer_fill=0; + _enc->rc.twopass_buffer_bytes=0; + } + } + if(_enc->rc.frames_total[0]!=0){ + ogg_int64_t curframe_num; + int nframes_total; + curframe_num=_enc->state.curframe_num; + if(curframe_num>=0){ + /*We just encoded a frame; make sure things matched.*/ + if(_enc->rc.prev_metrics.dup_count!=_enc->prev_dup_count){ + _enc->rc.twopass_buffer_bytes=0; + return TH_EINVAL; + } + } + curframe_num+=_enc->prev_dup_count+1; + nframes_total=_enc->rc.frames_total[0]+_enc->rc.frames_total[1] + +_enc->rc.frames_total[2]; + if(curframe_num>=nframes_total){ + /*We don't want any more data after the last frame, and we don't want to + allow any more frames to be encoded.*/ + _enc->rc.twopass_buffer_bytes=0; + } + else if(_enc->rc.twopass_buffer_bytes==0){ + if(_enc->rc.frame_metrics==NULL){ + /*We're using a whole-file buffer:*/ + if(!_buf)return OC_RC_2PASS_PACKET_SZ-_enc->rc.twopass_buffer_fill; + consumed=oc_rc_buffer_fill(&_enc->rc, + _buf,_bytes,consumed,OC_RC_2PASS_PACKET_SZ); + if(_enc->rc.twopass_buffer_fill>=OC_RC_2PASS_PACKET_SZ){ + ogg_uint32_t dup_count; + ogg_int32_t log_scale; + int qti; + int arg; + /*Read the metrics for the next frame.*/ + dup_count=oc_rc_unbuffer_val(&_enc->rc,4); + log_scale=oc_rc_unbuffer_val(&_enc->rc,4); + _enc->rc.cur_metrics.log_scale=log_scale; + qti=(dup_count&0x80000000)>>31; + _enc->rc.cur_metrics.dup_count=dup_count&0x7FFFFFFF; + _enc->rc.cur_metrics.frame_type=qti; + _enc->rc.twopass_force_kf=qti==OC_INTRA_FRAME; + /*"Helpfully" set the dup count back to what it was in pass 1.*/ + arg=_enc->rc.cur_metrics.dup_count; + th_encode_ctl(_enc,TH_ENCCTL_SET_DUP_COUNT,&arg,sizeof(arg)); + /*Clear the buffer for the next frame.*/ + _enc->rc.twopass_buffer_fill=0; + } + } + else{ + int frames_needed; + /*We're using a finite buffer:*/ + frames_needed=OC_CLAMPI(0,_enc->rc.buf_delay + -(_enc->rc.scale_window_end-_enc->rc.scale_window0), + _enc->rc.frames_left[0]+_enc->rc.frames_left[1] + -_enc->rc.nframes[0]-_enc->rc.nframes[1]); + while(frames_needed>0){ + if(!_buf){ + return OC_RC_2PASS_PACKET_SZ*frames_needed + -_enc->rc.twopass_buffer_fill; + } + consumed=oc_rc_buffer_fill(&_enc->rc, + _buf,_bytes,consumed,OC_RC_2PASS_PACKET_SZ); + if(_enc->rc.twopass_buffer_fill>=OC_RC_2PASS_PACKET_SZ){ + oc_frame_metrics *m; + int fmi; + ogg_uint32_t dup_count; + ogg_int32_t log_scale; + int qti; + /*Read the metrics for the next frame.*/ + dup_count=oc_rc_unbuffer_val(&_enc->rc,4); + log_scale=oc_rc_unbuffer_val(&_enc->rc,4); + /*Add the to the circular buffer.*/ + fmi=_enc->rc.frame_metrics_head+_enc->rc.nframe_metrics++; + if(fmi>=_enc->rc.cframe_metrics)fmi-=_enc->rc.cframe_metrics; + m=_enc->rc.frame_metrics+fmi; + m->log_scale=log_scale; + qti=(dup_count&0x80000000)>>31; + m->dup_count=dup_count&0x7FFFFFFF; + m->frame_type=qti; + /*And accumulate the statistics over the window.*/ + _enc->rc.nframes[qti]++; + _enc->rc.nframes[2]+=m->dup_count; + _enc->rc.scale_sum[qti]+=oc_bexp_q24(m->log_scale); + _enc->rc.scale_window_end+=m->dup_count+1; + /*Compute an upper bound on the number of remaining packets needed + for the current window.*/ + frames_needed=OC_CLAMPI(0,_enc->rc.buf_delay + -(_enc->rc.scale_window_end-_enc->rc.scale_window0), + _enc->rc.frames_left[0]+_enc->rc.frames_left[1] + -_enc->rc.nframes[0]-_enc->rc.nframes[1]); + /*Clear the buffer for the next frame.*/ + _enc->rc.twopass_buffer_fill=0; + _enc->rc.twopass_buffer_bytes=0; + } + /*Go back for more data.*/ + else break; + } + /*If we've got all the frames we need, fill in the current metrics. + We're ready to go.*/ + if(frames_needed<=0){ + int arg; + *&_enc->rc.cur_metrics= + *(_enc->rc.frame_metrics+_enc->rc.frame_metrics_head); + _enc->rc.twopass_force_kf= + _enc->rc.cur_metrics.frame_type==OC_INTRA_FRAME; + /*"Helpfully" set the dup count back to what it was in pass 1.*/ + arg=_enc->rc.cur_metrics.dup_count; + th_encode_ctl(_enc,TH_ENCCTL_SET_DUP_COUNT,&arg,sizeof(arg)); + /*Mark us ready for the next frame.*/ + _enc->rc.twopass_buffer_bytes=1; + } + } + } + } + return (int)consumed; +} diff --git a/Engine/lib/libtheora/lib/dec/state.c b/Engine/lib/libtheora/lib/state.c similarity index 55% rename from Engine/lib/libtheora/lib/dec/state.c rename to Engine/lib/libtheora/lib/state.c index 387f2d0b1..42ed33a9a 100644 --- a/Engine/lib/libtheora/lib/dec/state.c +++ b/Engine/lib/libtheora/lib/state.c @@ -5,21 +5,20 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: state.c 15469 2008-10-30 12:49:42Z tterribe $ + last mod: $Id: state.c 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ #include #include -#include "../internal.h" -#include "idct.h" -#if defined(USE_ASM) +#include "internal.h" +#if defined(OC_X86_ASM) #if defined(_MSC_VER) # include "x86_vc/x86int.h" #else @@ -31,35 +30,30 @@ # include "png.h" #endif -void oc_restore_fpu(const oc_theora_state *_state){ - _state->opt_vtable.restore_fpu(); -} - -void oc_restore_fpu_c(void){} - /*Returns the fragment index of the top-left block in a macro block. - This can be used to test whether or not the whole macro block is coded. - _sb: The super block. - _quadi: The quadrant number. + This can be used to test whether or not the whole macro block is valid. + _sb_map: The super block map. + _quadi: The quadrant number. Return: The index of the fragment of the upper left block in the macro block, or -1 if the block lies outside the coded frame.*/ -static int oc_sb_quad_top_left_frag(const oc_sb *_sb,int _quadi){ +static ptrdiff_t oc_sb_quad_top_left_frag(oc_sb_map_quad _sb_map[4],int _quadi){ /*It so happens that under the Hilbert curve ordering described below, the upper-left block in each macro block is at index 0, except in macro block 3, where it is at index 2.*/ - return _sb->map[_quadi][_quadi&_quadi<<1]; + return _sb_map[_quadi][_quadi&_quadi<<1]; } /*Fills in the mapping from block positions to fragment numbers for a single color plane. - This function also fills in the "valid" flag of each quadrant in a super - block. - _sbs: The array of super blocks for the color plane. - _frag0: The index of the first fragment in the plane. - _hfrags: The number of horizontal fragments in a coded frame. - _vfrags: The number of vertical fragments in a coded frame.*/ -static void oc_sb_create_plane_mapping(oc_sb _sbs[],int _frag0,int _hfrags, - int _vfrags){ + This function also fills in the "valid" flag of each quadrant in the super + block flags. + _sb_maps: The array of super block maps for the color plane. + _sb_flags: The array of super block flags for the color plane. + _frag0: The index of the first fragment in the plane. + _hfrags: The number of horizontal fragments in a coded frame. + _vfrags: The number of vertical fragments in a coded frame.*/ +static void oc_sb_create_plane_mapping(oc_sb_map _sb_maps[], + oc_sb_flags _sb_flags[],ptrdiff_t _frag0,int _hfrags,int _vfrags){ /*Contains the (macro_block,block) indices for a 4x4 grid of fragments. The pattern is a 4x4 Hilbert space-filling curve. @@ -74,10 +68,10 @@ static void oc_sb_create_plane_mapping(oc_sb _sbs[],int _frag0,int _hfrags, {{1,0},{1,3},{2,0},{2,3}}, {{1,1},{1,2},{2,1},{2,2}} }; - oc_sb *sb; - int yfrag; - int y; - sb=_sbs; + ptrdiff_t yfrag; + unsigned sbi; + int y; + sbi=0; yfrag=_frag0; for(y=0;;y+=4){ int imax; @@ -87,30 +81,31 @@ static void oc_sb_create_plane_mapping(oc_sb _sbs[],int _frag0,int _hfrags, imax=_vfrags-y; if(imax>4)imax=4; else if(imax<=0)break; - for(x=0;;x+=4,sb++){ - int xfrag; - int jmax; - int quadi; - int i; + for(x=0;;x+=4,sbi++){ + ptrdiff_t xfrag; + int jmax; + int quadi; + int i; /*Figure out how many rows of blocks in this super block lie within the image.*/ jmax=_hfrags-x; if(jmax>4)jmax=4; else if(jmax<=0)break; /*By default, set all fragment indices to -1.*/ - memset(sb->map[0],0xFF,sizeof(sb->map)); + memset(_sb_maps[sbi][0],0xFF,sizeof(_sb_maps[sbi])); /*Fill in the fragment map for this super block.*/ xfrag=yfrag+x; for(i=0;imap[SB_MAP[i][j][0]][SB_MAP[i][j][1]]=xfrag+j; + _sb_maps[sbi][SB_MAP[i][j][0]][SB_MAP[i][j][1]]=xfrag+j; } xfrag+=_hfrags; } /*Mark which quadrants of this super block lie within the image.*/ for(quadi=0;quadi<4;quadi++){ - sb->quad_valid|=(oc_sb_quad_top_left_frag(sb,quadi)>=0)<=0)<=_fplane->nvfrags)break; - for(j=0;j<2;j++){ - if(_x+j>=_fplane->nhfrags)break; - _mb->map[0][i<<1|j]=(_y+i)*_fplane->nhfrags+_x+j; - } + int j; + for(i=0;i<2;i++)for(j=0;j<2;j++){ + _mb_map[0][i<<1|j]=(_yfrag0+i)*(ptrdiff_t)_fplane->nhfrags+_xfrag0+j; } } /*Fills in the chroma plane fragment maps for a macro block. - This version is for use with chroma decimated in the X and Y directions. - _mb: The macro block to fill. + This version is for use with chroma decimated in the X and Y directions + (4:2:0). + _mb_map: The macro block map to fill. _fplanes: The descriptions of the fragment planes. - _x: The X location of the upper-left hand fragment in the Y plane. - _y: The Y location of the upper-left hand fragment in the Y plane.*/ -static void oc_mb_fill_cmapping00(oc_mb *_mb, - const oc_fragment_plane _fplanes[3],int _x,int _y){ - int fragi; - _x>>=1; - _y>>=1; - fragi=_y*_fplanes[1].nhfrags+_x; - _mb->map[1][0]=fragi+_fplanes[1].froffset; - _mb->map[2][0]=fragi+_fplanes[2].froffset; + _xfrag0: The X location of the upper-left hand fragment in the luma plane. + _yfrag0: The Y location of the upper-left hand fragment in the luma plane.*/ +static void oc_mb_fill_cmapping00(oc_mb_map_plane _mb_map[3], + const oc_fragment_plane _fplanes[3],int _xfrag0,int _yfrag0){ + ptrdiff_t fragi; + _xfrag0>>=1; + _yfrag0>>=1; + fragi=_yfrag0*(ptrdiff_t)_fplanes[1].nhfrags+_xfrag0; + _mb_map[1][0]=fragi+_fplanes[1].froffset; + _mb_map[2][0]=fragi+_fplanes[2].froffset; } /*Fills in the chroma plane fragment maps for a macro block. This version is for use with chroma decimated in the Y direction. - _mb: The macro block to fill. + _mb_map: The macro block map to fill. _fplanes: The descriptions of the fragment planes. - _x: The X location of the upper-left hand fragment in the Y plane. - _y: The Y location of the upper-left hand fragment in the Y plane.*/ -static void oc_mb_fill_cmapping01(oc_mb *_mb, - const oc_fragment_plane _fplanes[3],int _x,int _y){ - int fragi; - int j; - _y>>=1; - fragi=_y*_fplanes[1].nhfrags+_x; + _xfrag0: The X location of the upper-left hand fragment in the luma plane. + _yfrag0: The Y location of the upper-left hand fragment in the luma plane.*/ +static void oc_mb_fill_cmapping01(oc_mb_map_plane _mb_map[3], + const oc_fragment_plane _fplanes[3],int _xfrag0,int _yfrag0){ + ptrdiff_t fragi; + int j; + _yfrag0>>=1; + fragi=_yfrag0*(ptrdiff_t)_fplanes[1].nhfrags+_xfrag0; for(j=0;j<2;j++){ - if(_x+j>=_fplanes[1].nhfrags)break; - _mb->map[1][j]=fragi+_fplanes[1].froffset; - _mb->map[2][j]=fragi+_fplanes[2].froffset; + _mb_map[1][j]=fragi+_fplanes[1].froffset; + _mb_map[2][j]=fragi+_fplanes[2].froffset; fragi++; } } /*Fills in the chroma plane fragment maps for a macro block. - This version is for use with chroma decimated in the X direction. - _mb: The macro block to fill. + This version is for use with chroma decimated in the X direction (4:2:2). + _mb_map: The macro block map to fill. _fplanes: The descriptions of the fragment planes. - _x: The X location of the upper-left hand fragment in the Y plane. - _y: The Y location of the upper-left hand fragment in the Y plane.*/ -static void oc_mb_fill_cmapping10(oc_mb *_mb, - const oc_fragment_plane _fplanes[3],int _x,int _y){ - int fragi; - int i; - _x>>=1; - fragi=_y*_fplanes[1].nhfrags+_x; + _xfrag0: The X location of the upper-left hand fragment in the luma plane. + _yfrag0: The Y location of the upper-left hand fragment in the luma plane.*/ +static void oc_mb_fill_cmapping10(oc_mb_map_plane _mb_map[3], + const oc_fragment_plane _fplanes[3],int _xfrag0,int _yfrag0){ + ptrdiff_t fragi; + int i; + _xfrag0>>=1; + fragi=_yfrag0*(ptrdiff_t)_fplanes[1].nhfrags+_xfrag0; for(i=0;i<2;i++){ - if(_y+i>=_fplanes[1].nvfrags)break; - _mb->map[1][i<<1]=fragi+_fplanes[1].froffset; - _mb->map[2][i<<1]=fragi+_fplanes[2].froffset; + _mb_map[1][i<<1]=fragi+_fplanes[1].froffset; + _mb_map[2][i<<1]=fragi+_fplanes[2].froffset; fragi+=_fplanes[1].nhfrags; } } /*Fills in the chroma plane fragment maps for a macro block. - This version is for use with no chroma decimation. - This uses the already filled-in Y plane values. - _mb: The macro block to fill. + This version is for use with no chroma decimation (4:4:4). + This uses the already filled-in luma plane values. + _mb_map: The macro block map to fill. _fplanes: The descriptions of the fragment planes.*/ -static void oc_mb_fill_cmapping11(oc_mb *_mb, +static void oc_mb_fill_cmapping11(oc_mb_map_plane _mb_map[3], const oc_fragment_plane _fplanes[3]){ int k; for(k=0;k<4;k++){ - if(_mb->map[0][k]>=0){ - _mb->map[1][k]=_mb->map[0][k]+_fplanes[1].froffset; - _mb->map[2][k]=_mb->map[0][k]+_fplanes[2].froffset; - } + _mb_map[1][k]=_mb_map[0][k]+_fplanes[1].froffset; + _mb_map[2][k]=_mb_map[0][k]+_fplanes[2].froffset; } } /*The function type used to fill in the chroma plane fragment maps for a macro block. - _mb: The macro block to fill. + _mb_map: The macro block map to fill. _fplanes: The descriptions of the fragment planes. - _x: The X location of the upper-left hand fragment in the Y plane. - _y: The Y location of the upper-left hand fragment in the Y plane.*/ -typedef void (*oc_mb_fill_cmapping_func)(oc_mb *_mb, + _xfrag0: The X location of the upper-left hand fragment in the luma plane. + _yfrag0: The Y location of the upper-left hand fragment in the luma plane.*/ +typedef void (*oc_mb_fill_cmapping_func)(oc_mb_map_plane _mb_map[3], const oc_fragment_plane _fplanes[3],int _xfrag0,int _yfrag0); /*A table of functions used to fill in the chroma plane fragment maps for a @@ -228,44 +216,43 @@ static const oc_mb_fill_cmapping_func OC_MB_FILL_CMAPPING_TABLE[4]={ /*Fills in the mapping from macro blocks to their corresponding fragment numbers in each plane. - _mbs: The array of macro blocks. - _fplanes: The descriptions of the fragment planes. - _ctype: The chroma decimation type.*/ -static void oc_mb_create_mapping(oc_mb _mbs[], - const oc_fragment_plane _fplanes[3],int _ctype){ + _mb_maps: The list of macro block maps. + _mb_modes: The list of macro block modes; macro blocks completely outside + the coded region are marked invalid. + _fplanes: The descriptions of the fragment planes. + _pixel_fmt: The chroma decimation type.*/ +static void oc_mb_create_mapping(oc_mb_map _mb_maps[], + signed char _mb_modes[],const oc_fragment_plane _fplanes[3],int _pixel_fmt){ oc_mb_fill_cmapping_func mb_fill_cmapping; - oc_mb *mb0; + unsigned sbi; int y; - mb0=_mbs; - mb_fill_cmapping=OC_MB_FILL_CMAPPING_TABLE[_ctype]; - /*Loop through the Y plane super blocks.*/ - for(y=0;y<_fplanes[0].nvfrags;y+=4){ + mb_fill_cmapping=OC_MB_FILL_CMAPPING_TABLE[_pixel_fmt]; + /*Loop through the luma plane super blocks.*/ + for(sbi=y=0;y<_fplanes[0].nvfrags;y+=4){ int x; - for(x=0;x<_fplanes[0].nhfrags;x+=4,mb0+=4){ + for(x=0;x<_fplanes[0].nhfrags;x+=4,sbi++){ int ymb; /*Loop through the macro blocks in each super block in display order.*/ for(ymb=0;ymb<2;ymb++){ int xmb; for(xmb=0;xmb<2;xmb++){ - oc_mb *mb; - int mbx; - int mby; - mb=mb0+OC_MB_MAP[ymb][xmb]; + unsigned mbi; + int mbx; + int mby; + mbi=sbi<<2|OC_MB_MAP[ymb][xmb]; mbx=x|xmb<<1; mby=y|ymb<<1; - mb->x=mbx<<3; - mb->y=mby<<3; - /*Initialize fragment indexes to -1.*/ - memset(mb->map,0xFF,sizeof(mb->map)); + /*Initialize fragment indices to -1.*/ + memset(_mb_maps[mbi],0xFF,sizeof(_mb_maps[mbi])); /*Make sure this macro block is within the encoded region.*/ if(mbx>=_fplanes[0].nhfrags||mby>=_fplanes[0].nvfrags){ - mb->mode=OC_MODE_INVALID; + _mb_modes[mbi]=OC_MODE_INVALID; continue; } - /*Fill in the fragment indices for the Y plane.*/ - oc_mb_fill_ymapping(mb,_fplanes,mbx,mby); + /*Fill in the fragment indices for the luma plane.*/ + oc_mb_fill_ymapping(_mb_maps[mbi],_fplanes,mbx,mby); /*Fill in the fragment indices for the chroma planes.*/ - (*mb_fill_cmapping)(mb,_fplanes,mbx,mby); + (*mb_fill_cmapping)(_mb_maps[mbi],_fplanes,mbx,mby); } } } @@ -276,18 +263,14 @@ static void oc_mb_create_mapping(oc_mb _mbs[], region of the frame. _state: The Theora state containing the fragments to be marked.*/ static void oc_state_border_init(oc_theora_state *_state){ - typedef struct{ - int x0; - int y0; - int xf; - int yf; - }oc_crop_rect; oc_fragment *frag; oc_fragment *yfrag_end; oc_fragment *xfrag_end; oc_fragment_plane *fplane; - oc_crop_rect *crop; - oc_crop_rect crop_rects[3]; + int crop_x0; + int crop_y0; + int crop_xf; + int crop_yf; int pli; int y; int x; @@ -301,20 +284,19 @@ static void oc_state_border_init(oc_theora_state *_state){ yfrag_end=frag=_state->frags; for(pli=0;pli<3;pli++){ fplane=_state->fplanes+pli; - crop=crop_rects+pli; /*Set up the cropping rectangle for this plane.*/ - crop->x0=_state->info.pic_x; - crop->xf=_state->info.pic_x+_state->info.pic_width; - crop->y0=_state->info.pic_y; - crop->yf=_state->info.pic_y+_state->info.pic_height; + crop_x0=_state->info.pic_x; + crop_xf=_state->info.pic_x+_state->info.pic_width; + crop_y0=_state->info.pic_y; + crop_yf=_state->info.pic_y+_state->info.pic_height; if(pli>0){ if(!(_state->info.pixel_fmt&1)){ - crop->x0=crop->x0>>1; - crop->xf=crop->xf+1>>1; + crop_x0=crop_x0>>1; + crop_xf=crop_xf+1>>1; } if(!(_state->info.pixel_fmt&2)){ - crop->y0=crop->y0>>1; - crop->yf=crop->yf+1>>1; + crop_y0=crop_y0>>1; + crop_yf=crop_yf+1>>1; } } y=0; @@ -327,13 +309,13 @@ static void oc_state_border_init(oc_theora_state *_state){ This guarantees that if we count a fragment as straddling the border below, at least one pixel in the fragment will be inside the displayable region.*/ - if(x+8<=crop->x0||crop->xf<=x||y+8<=crop->y0||crop->yf<=y|| - crop->x0>=crop->xf||crop->y0>=crop->yf){ + if(x+8<=crop_x0||crop_xf<=x||y+8<=crop_y0||crop_yf<=y|| + crop_x0>=crop_xf||crop_y0>=crop_yf){ frag->invalid=1; } /*Otherwise, check to see if it straddles the border.*/ - else if(xx0&&crop->x0xf&&crop->xfy0&&crop->y0yf&&crop->yf=crop->x0&&x+jxf&&y+i>=crop->y0&&y+iyf){ + if(x+j>=crop_x0&&x+j=crop_y0&&y+i=_state->nborders){ _state->nborders++; @@ -357,34 +339,35 @@ static void oc_state_border_init(oc_theora_state *_state){ _state->borders[i].npixels=npixels; } else if(_state->borders[i].mask!=mask)continue; - frag->border=_state->borders+i; + frag->borderi=i; break; } } + else frag->borderi=-1; } } } } -static void oc_state_frarray_init(oc_theora_state *_state){ - int yhfrags; - int yvfrags; - int chfrags; - int cvfrags; - int yfrags; - int cfrags; - int nfrags; - int yhsbs; - int yvsbs; - int chsbs; - int cvsbs; - int ysbs; - int csbs; - int nsbs; - int nmbs; - int hdec; - int vdec; - int pli; +static int oc_state_frarray_init(oc_theora_state *_state){ + int yhfrags; + int yvfrags; + int chfrags; + int cvfrags; + ptrdiff_t yfrags; + ptrdiff_t cfrags; + ptrdiff_t nfrags; + unsigned yhsbs; + unsigned yvsbs; + unsigned chsbs; + unsigned cvsbs; + unsigned ysbs; + unsigned csbs; + unsigned nsbs; + size_t nmbs; + int hdec; + int vdec; + int pli; /*Figure out the number of fragments in each plane.*/ /*These parameters have already been validated to be multiples of 16.*/ yhfrags=_state->info.frame_width>>3; @@ -393,8 +376,8 @@ static void oc_state_frarray_init(oc_theora_state *_state){ vdec=!(_state->info.pixel_fmt&2); chfrags=yhfrags+hdec>>hdec; cvfrags=yvfrags+vdec>>vdec; - yfrags=yhfrags*yvfrags; - cfrags=chfrags*cvfrags; + yfrags=yhfrags*(ptrdiff_t)yvfrags; + cfrags=chfrags*(ptrdiff_t)cvfrags; nfrags=yfrags+2*cfrags; /*Figure out the number of super blocks in each plane.*/ yhsbs=yhfrags+3>>2; @@ -404,7 +387,20 @@ static void oc_state_frarray_init(oc_theora_state *_state){ ysbs=yhsbs*yvsbs; csbs=chsbs*cvsbs; nsbs=ysbs+2*csbs; - nmbs=ysbs<<2; + nmbs=(size_t)ysbs<<2; + /*Check for overflow. + We support the ridiculous upper limits of the specification (1048560 by + 1048560, or 3 TB frames) if the target architecture has 64-bit pointers, + but for those with 32-bit pointers (or smaller!) we have to check. + If the caller wants to prevent denial-of-service by imposing a more + reasonable upper limit on the size of attempted allocations, they must do + so themselves; we have no platform independent way to determine how much + system memory there is nor an application-independent way to decide what a + "reasonable" allocation is.*/ + if(yfrags/yhfrags!=yvfrags||2*cfrags>2!=ysbs){ + return TH_EIMPL; + } /*Initialize the fragment array.*/ _state->fplanes[0].nhfrags=yhfrags; _state->fplanes[0].nvfrags=yvfrags; @@ -425,34 +421,45 @@ static void oc_state_frarray_init(oc_theora_state *_state){ _state->fplanes[2].sboffset=ysbs+csbs; _state->fplanes[1].nsbs=_state->fplanes[2].nsbs=csbs; _state->nfrags=nfrags; - _state->frags=_ogg_calloc(nfrags,sizeof(oc_fragment)); + _state->frags=_ogg_calloc(nfrags,sizeof(*_state->frags)); + _state->frag_mvs=_ogg_malloc(nfrags*sizeof(*_state->frag_mvs)); _state->nsbs=nsbs; - _state->sbs=_ogg_calloc(nsbs,sizeof(oc_sb)); + _state->sb_maps=_ogg_malloc(nsbs*sizeof(*_state->sb_maps)); + _state->sb_flags=_ogg_calloc(nsbs,sizeof(*_state->sb_flags)); _state->nhmbs=yhsbs<<1; _state->nvmbs=yvsbs<<1; _state->nmbs=nmbs; - _state->mbs=_ogg_calloc(nmbs,sizeof(oc_mb)); - _state->coded_fragis=_ogg_malloc(nfrags*sizeof(_state->coded_fragis[0])); - _state->uncoded_fragis=_state->coded_fragis+nfrags; - _state->coded_mbis=_ogg_malloc(nmbs*sizeof(_state->coded_mbis[0])); + _state->mb_maps=_ogg_calloc(nmbs,sizeof(*_state->mb_maps)); + _state->mb_modes=_ogg_calloc(nmbs,sizeof(*_state->mb_modes)); + _state->coded_fragis=_ogg_malloc(nfrags*sizeof(*_state->coded_fragis)); + if(_state->frags==NULL||_state->frag_mvs==NULL||_state->sb_maps==NULL|| + _state->sb_flags==NULL||_state->mb_maps==NULL||_state->mb_modes==NULL|| + _state->coded_fragis==NULL){ + return TH_EFAULT; + } /*Create the mapping from super blocks to fragments.*/ for(pli=0;pli<3;pli++){ oc_fragment_plane *fplane; fplane=_state->fplanes+pli; - oc_sb_create_plane_mapping(_state->sbs+fplane->sboffset, - fplane->froffset,fplane->nhfrags,fplane->nvfrags); + oc_sb_create_plane_mapping(_state->sb_maps+fplane->sboffset, + _state->sb_flags+fplane->sboffset,fplane->froffset, + fplane->nhfrags,fplane->nvfrags); } /*Create the mapping from macro blocks to fragments.*/ - oc_mb_create_mapping(_state->mbs,_state->fplanes,_state->info.pixel_fmt); - /*Initialize the invalid and border fields of each fragment.*/ + oc_mb_create_mapping(_state->mb_maps,_state->mb_modes, + _state->fplanes,_state->info.pixel_fmt); + /*Initialize the invalid and borderi fields of each fragment.*/ oc_state_border_init(_state); + return 0; } static void oc_state_frarray_clear(oc_theora_state *_state){ - _ogg_free(_state->coded_mbis); _ogg_free(_state->coded_fragis); - _ogg_free(_state->mbs); - _ogg_free(_state->sbs); + _ogg_free(_state->mb_modes); + _ogg_free(_state->mb_maps); + _ogg_free(_state->sb_flags); + _ogg_free(_state->sb_maps); + _ogg_free(_state->frag_mvs); _ogg_free(_state->frags); } @@ -462,84 +469,144 @@ static void oc_state_frarray_clear(oc_theora_state *_state){ unrestricted motion vectors without special casing the boundary. If chroma is decimated in either direction, the padding is reduced by a factor of 2 on the appropriate sides. - _enc: The encoding context to store the buffers in.*/ -static void oc_state_ref_bufs_init(oc_theora_state *_state){ - th_info *info; + _nrefs: The number of reference buffers to init; must be 3 or 4.*/ +static int oc_state_ref_bufs_init(oc_theora_state *_state,int _nrefs){ + th_info *info; unsigned char *ref_frame_data; + size_t ref_frame_data_sz; + size_t ref_frame_sz; size_t yplane_sz; size_t cplane_sz; int yhstride; - int yvstride; + int yheight; int chstride; - int cvstride; - int yoffset; - int coffset; + int cheight; + ptrdiff_t yoffset; + ptrdiff_t coffset; + ptrdiff_t *frag_buf_offs; + ptrdiff_t fragi; + int hdec; + int vdec; int rfi; + int pli; + if(_nrefs<3||_nrefs>4)return TH_EINVAL; info=&_state->info; /*Compute the image buffer parameters for each plane.*/ + hdec=!(info->pixel_fmt&1); + vdec=!(info->pixel_fmt&2); yhstride=info->frame_width+2*OC_UMV_PADDING; - yvstride=info->frame_height+2*OC_UMV_PADDING; - chstride=yhstride>>!(info->pixel_fmt&1); - cvstride=yvstride>>!(info->pixel_fmt&2); - yplane_sz=(size_t)yhstride*yvstride; - cplane_sz=(size_t)chstride*cvstride; - yoffset=OC_UMV_PADDING+OC_UMV_PADDING*yhstride; - coffset=(OC_UMV_PADDING>>!(info->pixel_fmt&1))+ - (OC_UMV_PADDING>>!(info->pixel_fmt&2))*chstride; - _state->ref_frame_data=ref_frame_data=_ogg_malloc(3*(yplane_sz+2*cplane_sz)); + yheight=info->frame_height+2*OC_UMV_PADDING; + chstride=yhstride>>hdec; + cheight=yheight>>vdec; + yplane_sz=yhstride*(size_t)yheight; + cplane_sz=chstride*(size_t)cheight; + yoffset=OC_UMV_PADDING+OC_UMV_PADDING*(ptrdiff_t)yhstride; + coffset=(OC_UMV_PADDING>>hdec)+(OC_UMV_PADDING>>vdec)*(ptrdiff_t)chstride; + ref_frame_sz=yplane_sz+2*cplane_sz; + ref_frame_data_sz=_nrefs*ref_frame_sz; + /*Check for overflow. + The same caveats apply as for oc_state_frarray_init().*/ + if(yplane_sz/yhstride!=yheight||2*cplane_szfrag_buf_offs= + _ogg_malloc(_state->nfrags*sizeof(*frag_buf_offs)); + if(ref_frame_data==NULL||frag_buf_offs==NULL){ + _ogg_free(frag_buf_offs); + _ogg_free(ref_frame_data); + return TH_EFAULT; + } /*Set up the width, height and stride for the image buffers.*/ _state->ref_frame_bufs[0][0].width=info->frame_width; _state->ref_frame_bufs[0][0].height=info->frame_height; _state->ref_frame_bufs[0][0].stride=yhstride; _state->ref_frame_bufs[0][1].width=_state->ref_frame_bufs[0][2].width= - info->frame_width>>!(info->pixel_fmt&1); + info->frame_width>>hdec; _state->ref_frame_bufs[0][1].height=_state->ref_frame_bufs[0][2].height= - info->frame_height>>!(info->pixel_fmt&2); + info->frame_height>>vdec; _state->ref_frame_bufs[0][1].stride=_state->ref_frame_bufs[0][2].stride= chstride; - memcpy(_state->ref_frame_bufs[1],_state->ref_frame_bufs[0], - sizeof(_state->ref_frame_bufs[0])); - memcpy(_state->ref_frame_bufs[2],_state->ref_frame_bufs[0], - sizeof(_state->ref_frame_bufs[0])); + for(rfi=1;rfi<_nrefs;rfi++){ + memcpy(_state->ref_frame_bufs[rfi],_state->ref_frame_bufs[0], + sizeof(_state->ref_frame_bufs[0])); + } /*Set up the data pointers for the image buffers.*/ - for(rfi=0;rfi<3;rfi++){ + for(rfi=0;rfi<_nrefs;rfi++){ + _state->ref_frame_data[rfi]=ref_frame_data; _state->ref_frame_bufs[rfi][0].data=ref_frame_data+yoffset; ref_frame_data+=yplane_sz; _state->ref_frame_bufs[rfi][1].data=ref_frame_data+coffset; ref_frame_data+=cplane_sz; _state->ref_frame_bufs[rfi][2].data=ref_frame_data+coffset; ref_frame_data+=cplane_sz; - /*Flip the buffer upside down.*/ + /*Flip the buffer upside down. + This allows us to decode Theora's bottom-up frames in their natural + order, yet return a top-down buffer with a positive stride to the user.*/ oc_ycbcr_buffer_flip(_state->ref_frame_bufs[rfi], _state->ref_frame_bufs[rfi]); - /*Initialize the fragment pointers into this buffer.*/ - oc_state_fill_buffer_ptrs(_state,rfi,_state->ref_frame_bufs[rfi]); } - /*Initialize the reference frame indexes.*/ + _state->ref_ystride[0]=-yhstride; + _state->ref_ystride[1]=_state->ref_ystride[2]=-chstride; + /*Initialize the fragment buffer offsets.*/ + ref_frame_data=_state->ref_frame_data[0]; + fragi=0; + for(pli=0;pli<3;pli++){ + th_img_plane *iplane; + oc_fragment_plane *fplane; + unsigned char *vpix; + ptrdiff_t stride; + ptrdiff_t vfragi_end; + int nhfrags; + iplane=_state->ref_frame_bufs[0]+pli; + fplane=_state->fplanes+pli; + vpix=iplane->data; + vfragi_end=fplane->froffset+fplane->nfrags; + nhfrags=fplane->nhfrags; + stride=iplane->stride; + while(fragiref_frame_idx[OC_FRAME_GOLD]= _state->ref_frame_idx[OC_FRAME_PREV]= _state->ref_frame_idx[OC_FRAME_SELF]=-1; + _state->ref_frame_idx[OC_FRAME_IO]=_nrefs>3?3:-1; + return 0; } static void oc_state_ref_bufs_clear(oc_theora_state *_state){ - _ogg_free(_state->ref_frame_data); + _ogg_free(_state->frag_buf_offs); + _ogg_free(_state->ref_frame_data[0]); } void oc_state_vtable_init_c(oc_theora_state *_state){ + _state->opt_vtable.frag_copy=oc_frag_copy_c; _state->opt_vtable.frag_recon_intra=oc_frag_recon_intra_c; _state->opt_vtable.frag_recon_inter=oc_frag_recon_inter_c; _state->opt_vtable.frag_recon_inter2=oc_frag_recon_inter2_c; - _state->opt_vtable.state_frag_copy=oc_state_frag_copy_c; + _state->opt_vtable.idct8x8=oc_idct8x8_c; _state->opt_vtable.state_frag_recon=oc_state_frag_recon_c; + _state->opt_vtable.state_frag_copy_list=oc_state_frag_copy_list_c; _state->opt_vtable.state_loop_filter_frag_rows= oc_state_loop_filter_frag_rows_c; _state->opt_vtable.restore_fpu=oc_restore_fpu_c; + _state->opt_data.dct_fzig_zag=OC_FZIG_ZAG; } /*Initialize the accelerated function pointers.*/ void oc_state_vtable_init(oc_theora_state *_state){ -#if defined(USE_ASM) +#if defined(OC_X86_ASM) oc_state_vtable_init_x86(_state); #else oc_state_vtable_init_c(_state); @@ -547,8 +614,8 @@ void oc_state_vtable_init(oc_theora_state *_state){ } -int oc_state_init(oc_theora_state *_state,const th_info *_info){ - int old_granpos; +int oc_state_init(oc_theora_state *_state,const th_info *_info,int _nrefs){ + int ret; /*First validate the parameters.*/ if(_info==NULL)return TH_EFAULT; /*The width and height of the encoded frame must be multiples of 16. @@ -561,11 +628,16 @@ int oc_state_init(oc_theora_state *_state,const th_info *_info){ The displayable frame must fit inside the encoded frame. The color space must be one known by the encoder.*/ if((_info->frame_width&0xF)||(_info->frame_height&0xF)|| - _info->frame_width>=0x100000||_info->frame_height>=0x100000|| + _info->frame_width<=0||_info->frame_width>=0x100000|| + _info->frame_height<=0||_info->frame_height>=0x100000|| _info->pic_x+_info->pic_width>_info->frame_width|| _info->pic_y+_info->pic_height>_info->frame_height|| - _info->pic_x>255|| - _info->frame_height-_info->pic_height-_info->pic_y>255|| + _info->pic_x>255||_info->frame_height-_info->pic_height-_info->pic_y>255|| + /*Note: the following <0 comparisons may generate spurious warnings on + platforms where enums are unsigned. + We could cast them to unsigned and just use the following >= comparison, + but there are a number of compilers which will mis-optimize this. + It's better to live with the spurious warnings.*/ _info->colorspace<0||_info->colorspace>=TH_CS_NSPACES|| _info->pixel_fmt<0||_info->pixel_fmt>=TH_PF_NFORMATS){ return TH_EINVAL; @@ -577,22 +649,24 @@ int oc_state_init(oc_theora_state *_state,const th_info *_info){ _state->info.pic_y=_info->frame_height-_info->pic_height-_info->pic_y; _state->frame_type=OC_UNKWN_FRAME; oc_state_vtable_init(_state); - oc_state_frarray_init(_state); - oc_state_ref_bufs_init(_state); + ret=oc_state_frarray_init(_state); + if(ret>=0)ret=oc_state_ref_bufs_init(_state,_nrefs); + if(ret<0){ + oc_state_frarray_clear(_state); + return ret; + } /*If the keyframe_granule_shift is out of range, use the maximum allowable value.*/ if(_info->keyframe_granule_shift<0||_info->keyframe_granule_shift>31){ _state->info.keyframe_granule_shift=31; } - _state->keyframe_num=1; - _state->curframe_num=0; + _state->keyframe_num=0; + _state->curframe_num=-1; /*3.2.0 streams mark the frame index instead of the frame count. This was changed with stream version 3.2.1 to conform to other Ogg codecs. - We subtract an extra one from the frame number for old streams.*/ - old_granpos=!TH_VERSION_CHECK(_info,3,2,1); - _state->curframe_num-=old_granpos; - _state->keyframe_num-=old_granpos; + We add an extra bias when computing granule positions for new streams.*/ + _state->granpos_bias=TH_VERSION_CHECK(_info,3,2,1); return 0; } @@ -612,22 +686,24 @@ void oc_state_clear(oc_theora_state *_state){ _yend: The Y coordinate of the row to stop padding at.*/ void oc_state_borders_fill_rows(oc_theora_state *_state,int _refi,int _pli, int _y0,int _yend){ - th_img_plane *iplane; - unsigned char *apix; - unsigned char *bpix; - unsigned char *epix; - int hpadding; + th_img_plane *iplane; + unsigned char *apix; + unsigned char *bpix; + unsigned char *epix; + int stride; + int hpadding; hpadding=OC_UMV_PADDING>>(_pli!=0&&!(_state->info.pixel_fmt&1)); iplane=_state->ref_frame_bufs[_refi]+_pli; - apix=iplane->data+_y0*iplane->stride; + stride=iplane->stride; + apix=iplane->data+_y0*(ptrdiff_t)stride; bpix=apix+iplane->width-1; - epix=iplane->data+_yend*iplane->stride; - /*Note the use of != instead of <, which allows ystride to be negative.*/ + epix=iplane->data+_yend*(ptrdiff_t)stride; + /*Note the use of != instead of <, which allows the stride to be negative.*/ while(apix!=epix){ memset(apix-hpadding,apix[0],hpadding); memset(bpix+1,bpix[0],hpadding); - apix+=iplane->stride; - bpix+=iplane->stride; + apix+=stride; + bpix+=stride; } } @@ -638,25 +714,27 @@ void oc_state_borders_fill_rows(oc_theora_state *_state,int _refi,int _pli, _refi: The index of the reference buffer to pad. _pli: The color plane.*/ void oc_state_borders_fill_caps(oc_theora_state *_state,int _refi,int _pli){ - th_img_plane *iplane; - unsigned char *apix; - unsigned char *bpix; - unsigned char *epix; - int hpadding; - int vpadding; - int fullw; + th_img_plane *iplane; + unsigned char *apix; + unsigned char *bpix; + unsigned char *epix; + int stride; + int hpadding; + int vpadding; + int fullw; hpadding=OC_UMV_PADDING>>(_pli!=0&&!(_state->info.pixel_fmt&1)); vpadding=OC_UMV_PADDING>>(_pli!=0&&!(_state->info.pixel_fmt&2)); iplane=_state->ref_frame_bufs[_refi]+_pli; + stride=iplane->stride; fullw=iplane->width+(hpadding<<1); apix=iplane->data-hpadding; - bpix=iplane->data+(iplane->height-1)*iplane->stride-hpadding; - epix=apix-iplane->stride*vpadding; + bpix=iplane->data+(iplane->height-1)*(ptrdiff_t)stride-hpadding; + epix=apix-stride*(ptrdiff_t)vpadding; while(apix!=epix){ - memcpy(apix-iplane->stride,apix,fullw); - memcpy(bpix+iplane->stride,bpix,fullw); - apix-=iplane->stride; - bpix+=iplane->stride; + memcpy(apix-stride,apix,fullw); + memcpy(bpix+stride,bpix,fullw); + apix-=stride; + bpix+=stride; } } @@ -673,73 +751,18 @@ void oc_state_borders_fill(oc_theora_state *_state,int _refi){ } } -/*Sets the buffer pointer in each fragment to point to the portion of the - image buffer which it corresponds to. - _state: The Theora state to fill. - _buf_idx: The index of the buffer pointer to fill. - The first three correspond to our reconstructed frame buffers, - while the last corresponds to the input image. - _img: The image buffer to fill the fragments with.*/ -void oc_state_fill_buffer_ptrs(oc_theora_state *_state,int _buf_idx, - th_ycbcr_buffer _img){ - int pli; - /*Special handling for the input image to give us the opportunity to skip - some updates. - The other buffers do not change throughout the encoding process.*/ - if(_buf_idx==OC_FRAME_IO){ - if(memcmp(_state->input,_img,sizeof(th_ycbcr_buffer))==0)return; - memcpy(_state->input,_img,sizeof(th_ycbcr_buffer)); - } - for(pli=0;pli<3;pli++){ - th_img_plane *iplane; - oc_fragment_plane *fplane; - oc_fragment *frag; - oc_fragment *vfrag_end; - unsigned char *vpix; - iplane=&_img[pli]; - fplane=&_state->fplanes[pli]; - vpix=iplane->data; - frag=_state->frags+fplane->froffset; - vfrag_end=frag+fplane->nfrags; - while(fragnhfrags;fragbuffer[_buf_idx]=hpix; - hpix+=8; - } - vpix+=iplane->stride<<3; - } - } -} - -/*Returns the macro block index of the macro block in the given position. - _state: The Theora state the macro block is contained in. - _mbx: The X coordinate of the macro block (in macro blocks, not pixels). - _mby: The Y coordinate of the macro block (in macro blocks, not pixels). - Return: The index of the macro block in the given position.*/ -int oc_state_mbi_for_pos(oc_theora_state *_state,int _mbx,int _mby){ - return ((_mbx&~1)<<1)+(_mby&~1)*_state->nhmbs+OC_MB_MAP[_mby&1][_mbx&1]; -} - /*Determines the offsets in an image buffer to use for motion compensation. _state: The Theora state the offsets are to be computed with. _offsets: Returns the offset for the buffer(s). _offsets[0] is always set. _offsets[1] is set if the motion vector has non-zero fractional components. + _pli: The color plane index. _dx: The X component of the motion vector. _dy: The Y component of the motion vector. - _ystride: The Y stride in the buffer the motion vector points into. - _pli: The color plane index. Return: The number of offsets returned: 1 or 2.*/ -int oc_state_get_mv_offsets(oc_theora_state *_state,int _offsets[2], - int _dx,int _dy,int _ystride,int _pli){ - int xprec; - int yprec; - int xfrac; - int yfrac; +int oc_state_get_mv_offsets(const oc_theora_state *_state,int _offsets[2], + int _pli,int _dx,int _dy){ /*Here is a brief description of how Theora handles motion vectors: Motion vector components are specified to half-pixel accuracy in undecimated directions of each plane, and quarter-pixel accuracy in @@ -754,131 +777,142 @@ int oc_state_get_mv_offsets(oc_theora_state *_state,int _offsets[2], non-zero fractional parts. The second offset is computed by dividing (not shifting) by the appropriate amount, always truncating _away_ from zero.*/ +#if 0 + /*This version of the code doesn't use any tables, but is slower.*/ + int ystride; + int xprec; + int yprec; + int xfrac; + int yfrac; + int offs; + ystride=_state->ref_ystride[_pli]; /*These two variables decide whether we are in half- or quarter-pixel precision in each component.*/ - xprec=1+(!(_state->info.pixel_fmt&1)&&_pli); - yprec=1+(!(_state->info.pixel_fmt&2)&&_pli); - /*These two variables are either 0 if all the fractional bits are 0 or 1 if - any of them are non-zero.*/ - xfrac=!!(_dx&(1<>xprec)+(_dy>>yprec)*_ystride; + xprec=1+(_pli!=0&&!(_state->info.pixel_fmt&1)); + yprec=1+(_pli!=0&&!(_state->info.pixel_fmt&2)); + /*These two variables are either 0 if all the fractional bits are zero or -1 + if any of them are non-zero.*/ + xfrac=OC_SIGNMASK(-(_dx&(xprec|1))); + yfrac=OC_SIGNMASK(-(_dy&(yprec|1))); + offs=(_dx>>xprec)+(_dy>>yprec)*ystride; if(xfrac||yfrac){ - /*This branchless code is equivalent to: - if(_dx<0)_offests[0]=-(-_dx>>xprec); - else _offsets[0]=(_dx>>xprec); - if(_dy<0)_offsets[0]-=(-_dy>>yprec)*_ystride; - else _offsets[0]+=(_dy>>yprec)*_ystride; - _offsets[1]=_offsets[0]; - if(xfrac){ - if(_dx<0)_offsets[1]++; - else _offsets[1]--; - } - if(yfrac){ - if(_dy<0)_offsets[1]+=_ystride; - else _offsets[1]-=_ystride; - }*/ - _offsets[1]=_offsets[0]; - _offsets[_dx>=0]+=xfrac; - _offsets[_dy>=0]+=_ystride&-yfrac; + int xmask; + int ymask; + xmask=OC_SIGNMASK(_dx); + ymask=OC_SIGNMASK(_dy); + yfrac&=ystride; + _offsets[0]=offs-(xfrac&xmask)+(yfrac&ymask); + _offsets[1]=offs-(xfrac&~xmask)+(yfrac&~ymask); return 2; } - else return 1; + else{ + _offsets[0]=offs; + return 1; + } +#else + /*Using tables simplifies the code, and there's enough arithmetic to hide the + latencies of the memory references.*/ + static const signed char OC_MVMAP[2][64]={ + { + -15,-15,-14,-14,-13,-13,-12,-12,-11,-11,-10,-10, -9, -9, -8, + -8, -7, -7, -6, -6, -5, -5, -4, -4, -3, -3, -2, -2, -1, -1, 0, + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, + 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15 + }, + { + -7, -7, -7, -7, -6, -6, -6, -6, -5, -5, -5, -5, -4, -4, -4, + -4, -3, -3, -3, -3, -2, -2, -2, -2, -1, -1, -1, -1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7 + } + }; + static const signed char OC_MVMAP2[2][64]={ + { + -1, 0,-1, 0,-1, 0,-1, 0,-1, 0,-1, 0,-1, 0,-1, + 0,-1, 0,-1, 0,-1, 0,-1, 0,-1, 0,-1, 0,-1, 0,-1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + }, + { + -1,-1,-1, 0,-1,-1,-1, 0,-1,-1,-1, 0,-1,-1,-1, + 0,-1,-1,-1, 0,-1,-1,-1, 0,-1,-1,-1, 0,-1,-1,-1, + 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 + } + }; + int ystride; + int qpx; + int qpy; + int mx; + int my; + int mx2; + int my2; + int offs; + ystride=_state->ref_ystride[_pli]; + qpy=_pli!=0&&!(_state->info.pixel_fmt&2); + my=OC_MVMAP[qpy][_dy+31]; + my2=OC_MVMAP2[qpy][_dy+31]; + qpx=_pli!=0&&!(_state->info.pixel_fmt&1); + mx=OC_MVMAP[qpx][_dx+31]; + mx2=OC_MVMAP2[qpx][_dx+31]; + offs=my*ystride+mx; + if(mx2||my2){ + _offsets[1]=offs+my2*ystride+mx2; + _offsets[0]=offs; + return 2; + } + _offsets[0]=offs; + return 1; +#endif } -void oc_state_frag_recon(oc_theora_state *_state,oc_fragment *_frag, - int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,int _ncoefs, - ogg_uint16_t _dc_iquant,const ogg_uint16_t _ac_iquant[64]){ - _state->opt_vtable.state_frag_recon(_state,_frag,_pli,_dct_coeffs, - _last_zzi,_ncoefs,_dc_iquant,_ac_iquant); +void oc_state_frag_recon(const oc_theora_state *_state,ptrdiff_t _fragi, + int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant){ + _state->opt_vtable.state_frag_recon(_state,_fragi,_pli,_dct_coeffs, + _last_zzi,_dc_quant); } -void oc_state_frag_recon_c(oc_theora_state *_state,oc_fragment *_frag, - int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,int _ncoefs, - ogg_uint16_t _dc_iquant, const ogg_uint16_t _ac_iquant[64]){ - ogg_int16_t dct_buf[64]; - ogg_int16_t res_buf[64]; - int dst_framei; - int dst_ystride; - int zzi; - int ci; - /*_last_zzi is subtly different from an actual count of the number of - coefficients we decoded for this block. - It contains the value of zzi BEFORE the final token in the block was - decoded. - In most cases this is an EOB token (the continuation of an EOB run from a - previous block counts), and so this is the same as the coefficient count. - However, in the case that the last token was NOT an EOB token, but filled - the block up with exactly 64 coefficients, _last_zzi will be less than 64. - Provided the last token was not a pure zero run, the minimum value it can - be is 46, and so that doesn't affect any of the cases in this routine. - However, if the last token WAS a pure zero run of length 63, then _last_zzi - will be 1 while the number of coefficients decoded is 64. - Thus, we will trigger the following special case, where the real - coefficient count would not. - Note also that a zero run of length 64 will give _last_zzi a value of 0, - but we still process the DC coefficient, which might have a non-zero value - due to DC prediction. - Although convoluted, this is arguably the correct behavior: it allows us to - dequantize fewer coefficients and use a smaller transform when the block - ends with a long zero run instead of a normal EOB token. - It could be smarter... multiple separate zero runs at the end of a block - will fool it, but an encoder that generates these really deserves what it - gets. - Needless to say we inherited this approach from VP3.*/ +void oc_state_frag_recon_c(const oc_theora_state *_state,ptrdiff_t _fragi, + int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant){ + unsigned char *dst; + ptrdiff_t frag_buf_off; + int ystride; + int mb_mode; + /*Apply the inverse transform.*/ /*Special case only having a DC component.*/ if(_last_zzi<2){ ogg_int16_t p; - /*Why is the iquant product rounded in this case and no others? - Who knows.*/ - p=(ogg_int16_t)((ogg_int32_t)_frag->dc*_dc_iquant+15>>5); + int ci; + /*We round this dequant product (and not any of the others) because there's + no iDCT rounding.*/ + p=(ogg_int16_t)(_dct_coeffs[0]*(ogg_int32_t)_dc_quant+15>>5); /*LOOP VECTORIZES.*/ - for(ci=0;ci<64;ci++)res_buf[ci]=p; + for(ci=0;ci<64;ci++)_dct_coeffs[ci]=p; } else{ - /*First, dequantize the coefficients.*/ - dct_buf[0]=(ogg_int16_t)((ogg_int32_t)_frag->dc*_dc_iquant); - for(zzi=1;zzi<_ncoefs;zzi++){ - int ci; - ci=OC_FZIG_ZAG[zzi]; - dct_buf[ci]=(ogg_int16_t)((ogg_int32_t)_dct_coeffs[zzi]*_ac_iquant[ci]); - } - /*Then, fill in the remainder of the coefficients with 0's, and perform - the iDCT.*/ - if(_last_zzi<10){ - for(;zzi<10;zzi++)dct_buf[OC_FZIG_ZAG[zzi]]=0; - oc_idct8x8_10_c(res_buf,dct_buf); - } - else{ - for(;zzi<64;zzi++)dct_buf[OC_FZIG_ZAG[zzi]]=0; - oc_idct8x8_c(res_buf,dct_buf); - } + /*First, dequantize the DC coefficient.*/ + _dct_coeffs[0]=(ogg_int16_t)(_dct_coeffs[0]*(int)_dc_quant); + oc_idct8x8(_state,_dct_coeffs,_last_zzi); } /*Fill in the target buffer.*/ - dst_framei=_state->ref_frame_idx[OC_FRAME_SELF]; - dst_ystride=_state->ref_frame_bufs[dst_framei][_pli].stride; - /*For now ystride values in all ref frames assumed to be equal.*/ - if(_frag->mbmode==OC_MODE_INTRA){ - oc_frag_recon_intra(_state,_frag->buffer[dst_framei],dst_ystride,res_buf); - } + frag_buf_off=_state->frag_buf_offs[_fragi]; + mb_mode=_state->frags[_fragi].mb_mode; + ystride=_state->ref_ystride[_pli]; + dst=_state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_SELF]]+frag_buf_off; + if(mb_mode==OC_MODE_INTRA)oc_frag_recon_intra(_state,dst,ystride,_dct_coeffs); else{ - int ref_framei; - int ref_ystride; - int mvoffsets[2]; - ref_framei=_state->ref_frame_idx[OC_FRAME_FOR_MODE[_frag->mbmode]]; - ref_ystride=_state->ref_frame_bufs[ref_framei][_pli].stride; - if(oc_state_get_mv_offsets(_state,mvoffsets,_frag->mv[0],_frag->mv[1], - ref_ystride,_pli)>1){ - oc_frag_recon_inter2(_state,_frag->buffer[dst_framei],dst_ystride, - _frag->buffer[ref_framei]+mvoffsets[0],ref_ystride, - _frag->buffer[ref_framei]+mvoffsets[1],ref_ystride,res_buf); - } - else{ - oc_frag_recon_inter(_state,_frag->buffer[dst_framei],dst_ystride, - _frag->buffer[ref_framei]+mvoffsets[0],ref_ystride,res_buf); + const unsigned char *ref; + int mvoffsets[2]; + ref= + _state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_FOR_MODE(mb_mode)]] + +frag_buf_off; + if(oc_state_get_mv_offsets(_state,mvoffsets,_pli, + _state->frag_mvs[_fragi][0],_state->frag_mvs[_fragi][1])>1){ + oc_frag_recon_inter2(_state, + dst,ref+mvoffsets[0],ref+mvoffsets[1],ystride,_dct_coeffs); } + else oc_frag_recon_inter(_state,dst,ref+mvoffsets[0],ystride,_dct_coeffs); } - oc_restore_fpu(_state); } /*Copies the fragments specified by the lists of fragment indices from one @@ -888,38 +922,30 @@ void oc_state_frag_recon_c(oc_theora_state *_state,oc_fragment *_frag, _dst_frame: The reference frame to copy to. _src_frame: The reference frame to copy from. _pli: The color plane the fragments lie in.*/ -void oc_state_frag_copy(const oc_theora_state *_state,const int *_fragis, - int _nfragis,int _dst_frame,int _src_frame,int _pli){ - _state->opt_vtable.state_frag_copy(_state,_fragis,_nfragis,_dst_frame, +void oc_state_frag_copy_list(const oc_theora_state *_state, + const ptrdiff_t *_fragis,ptrdiff_t _nfragis, + int _dst_frame,int _src_frame,int _pli){ + _state->opt_vtable.state_frag_copy_list(_state,_fragis,_nfragis,_dst_frame, _src_frame,_pli); } -void oc_state_frag_copy_c(const oc_theora_state *_state,const int *_fragis, - int _nfragis,int _dst_frame,int _src_frame,int _pli){ - const int *fragi; - const int *fragi_end; - int dst_framei; - int dst_ystride; - int src_framei; - int src_ystride; - dst_framei=_state->ref_frame_idx[_dst_frame]; - src_framei=_state->ref_frame_idx[_src_frame]; - dst_ystride=_state->ref_frame_bufs[dst_framei][_pli].stride; - src_ystride=_state->ref_frame_bufs[src_framei][_pli].stride; - fragi_end=_fragis+_nfragis; - for(fragi=_fragis;fragifrags+*fragi; - dst=frag->buffer[dst_framei]; - src=frag->buffer[src_framei]; - for(j=0;j<8;j++){ - memcpy(dst,src,sizeof(dst[0])*8); - dst+=dst_ystride; - src+=src_ystride; - } +void oc_state_frag_copy_list_c(const oc_theora_state *_state, + const ptrdiff_t *_fragis,ptrdiff_t _nfragis, + int _dst_frame,int _src_frame,int _pli){ + const ptrdiff_t *frag_buf_offs; + const unsigned char *src_frame_data; + unsigned char *dst_frame_data; + ptrdiff_t fragii; + int ystride; + dst_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_dst_frame]]; + src_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_src_frame]]; + ystride=_state->ref_ystride[_pli]; + frag_buf_offs=_state->frag_buf_offs; + for(fragii=0;fragii<_nfragis;fragii++){ + ptrdiff_t frag_buf_off; + frag_buf_off=frag_buf_offs[_fragis[fragii]]; + oc_frag_copy(_state,dst_frame_data+frag_buf_off, + src_frame_data+frag_buf_off,ystride); } } @@ -940,25 +966,24 @@ static void loop_filter_h(unsigned char *_pix,int _ystride,int *_bv){ } static void loop_filter_v(unsigned char *_pix,int _ystride,int *_bv){ - int y; + int x; _pix-=_ystride*2; - for(y=0;y<8;y++){ + for(x=0;x<8;x++){ int f; - f=_pix[0]-_pix[_ystride*3]+3*(_pix[_ystride*2]-_pix[_ystride]); + f=_pix[x]-_pix[_ystride*3+x]+3*(_pix[_ystride*2+x]-_pix[_ystride+x]); /*The _bv array is used to compute the function f=OC_CLAMPI(OC_MINI(-_2flimit-f,0),f,OC_MAXI(_2flimit-f,0)); where _2flimit=_state->loop_filter_limits[_state->qis[0]]<<1;*/ f=*(_bv+(f+4>>3)); - _pix[_ystride]=OC_CLAMP255(_pix[_ystride]+f); - _pix[_ystride*2]=OC_CLAMP255(_pix[_ystride*2]-f); - _pix++; + _pix[_ystride+x]=OC_CLAMP255(_pix[_ystride+x]+f); + _pix[_ystride*2+x]=OC_CLAMP255(_pix[_ystride*2+x]-f); } } /*Initialize the bounding values array used by the loop filter. _bv: Storage for the array. Return: 0 on success, or a non-zero value if no filtering need be applied.*/ -int oc_state_loop_filter_init(oc_theora_state *_state,int *_bv){ +int oc_state_loop_filter_init(oc_theora_state *_state,int _bv[256]){ int flimit; int i; flimit=_state->loop_filter_limits[_state->qis[0]]; @@ -981,56 +1006,61 @@ int oc_state_loop_filter_init(oc_theora_state *_state,int *_bv){ _pli: The color plane to filter. _fragy0: The Y coordinate of the first fragment row to filter. _fragy_end: The Y coordinate of the fragment row to stop filtering at.*/ -void oc_state_loop_filter_frag_rows(oc_theora_state *_state,int *_bv, +void oc_state_loop_filter_frag_rows(const oc_theora_state *_state,int _bv[256], int _refi,int _pli,int _fragy0,int _fragy_end){ _state->opt_vtable.state_loop_filter_frag_rows(_state,_bv,_refi,_pli, _fragy0,_fragy_end); } -void oc_state_loop_filter_frag_rows_c(oc_theora_state *_state,int *_bv, +void oc_state_loop_filter_frag_rows_c(const oc_theora_state *_state,int *_bv, int _refi,int _pli,int _fragy0,int _fragy_end){ - th_img_plane *iplane; - oc_fragment_plane *fplane; - oc_fragment *frag_top; - oc_fragment *frag0; - oc_fragment *frag; - oc_fragment *frag_end; - oc_fragment *frag0_end; - oc_fragment *frag_bot; + const oc_fragment_plane *fplane; + const oc_fragment *frags; + const ptrdiff_t *frag_buf_offs; + unsigned char *ref_frame_data; + ptrdiff_t fragi_top; + ptrdiff_t fragi_bot; + ptrdiff_t fragi0; + ptrdiff_t fragi0_end; + int ystride; + int nhfrags; _bv+=127; - iplane=_state->ref_frame_bufs[_refi]+_pli; fplane=_state->fplanes+_pli; + nhfrags=fplane->nhfrags; + fragi_top=fplane->froffset; + fragi_bot=fragi_top+fplane->nfrags; + fragi0=fragi_top+_fragy0*(ptrdiff_t)nhfrags; + fragi0_end=fragi0+(_fragy_end-_fragy0)*(ptrdiff_t)nhfrags; + ystride=_state->ref_ystride[_pli]; + frags=_state->frags; + frag_buf_offs=_state->frag_buf_offs; + ref_frame_data=_state->ref_frame_data[_refi]; /*The following loops are constructed somewhat non-intuitively on purpose. The main idea is: if a block boundary has at least one coded fragment on it, the filter is applied to it. However, the order that the filters are applied in matters, and VP3 chose the somewhat strange ordering used below.*/ - frag_top=_state->frags+fplane->froffset; - frag0=frag_top+_fragy0*fplane->nhfrags; - frag0_end=frag0+(_fragy_end-_fragy0)*fplane->nhfrags; - frag_bot=_state->frags+fplane->froffset+fplane->nfrags; - while(frag0nhfrags; - while(fragcoded){ - if(frag>frag0){ - loop_filter_h(frag->buffer[_refi],iplane->stride,_bv); + while(fragi0fragi0)loop_filter_h(ref,ystride,_bv); + if(fragi0>fragi_top)loop_filter_v(ref,ystride,_bv); + if(fragi+1frag_top){ - loop_filter_v(frag->buffer[_refi],iplane->stride,_bv); - } - if(frag+1coded){ - loop_filter_h(frag->buffer[_refi]+8,iplane->stride,_bv); - } - if(frag+fplane->nhfragsnhfrags)->coded){ - loop_filter_v((frag+fplane->nhfrags)->buffer[_refi], - iplane->stride,_bv); + if(fragi+nhfragsnhfrags; + fragi0+=nhfrags; } } @@ -1066,7 +1096,11 @@ int oc_state_dump_frame(const oc_theora_state *_state,int _frame, sprintf(fname,"%08i%s.png",(int)(iframe+pframe),_suf); fp=fopen(fname,"wb"); if(fp==NULL)return TH_EFAULT; - image=(png_bytep *)oc_malloc_2d(height,6*width,sizeof(image[0][0])); + image=(png_bytep *)oc_malloc_2d(height,6*width,sizeof(**image)); + if(image==NULL){ + fclose(fp); + return TH_EFAULT; + } png=png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); if(png==NULL){ oc_free_2d(image); @@ -1149,6 +1183,7 @@ int oc_state_dump_frame(const oc_theora_state *_state,int _frame, png_set_cHRM_fixed(png,info,31271,32902, 64000,33000,29000,60000,15000,6000); }break; + default:break; } png_set_pHYs(png,info,_state->info.aspect_numerator, _state->info.aspect_denominator,0); diff --git a/Engine/lib/libtheora/lib/tokenize.c b/Engine/lib/libtheora/lib/tokenize.c new file mode 100644 index 000000000..60574c359 --- /dev/null +++ b/Engine/lib/libtheora/lib/tokenize.c @@ -0,0 +1,1072 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: tokenize.c 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ +#include +#include +#include "encint.h" + + + +static int oc_make_eob_token(int _run_count){ + if(_run_count<4)return OC_DCT_EOB1_TOKEN+_run_count-1; + else{ + int cat; + cat=OC_ILOGNZ_32(_run_count)-3; + cat=OC_MINI(cat,3); + return OC_DCT_REPEAT_RUN0_TOKEN+cat; + } +} + +static int oc_make_eob_token_full(int _run_count,int *_eb){ + if(_run_count<4){ + *_eb=0; + return OC_DCT_EOB1_TOKEN+_run_count-1; + } + else{ + int cat; + cat=OC_ILOGNZ_32(_run_count)-3; + cat=OC_MINI(cat,3); + *_eb=_run_count-OC_BYTE_TABLE32(4,8,16,0,cat); + return OC_DCT_REPEAT_RUN0_TOKEN+cat; + } +} + +/*Returns the number of blocks ended by an EOB token.*/ +static int oc_decode_eob_token(int _token,int _eb){ + return (0x20820C41U>>_token*5&0x1F)+_eb; +} + +/*TODO: This is now only used during DCT tokenization, and never for runs; it + should be simplified.*/ +static int oc_make_dct_token_full(int _zzi,int _zzj,int _val,int *_eb){ + int neg; + int zero_run; + int token; + int eb; + neg=_val<0; + _val=abs(_val); + zero_run=_zzj-_zzi; + if(zero_run>0){ + int adj; + /*Implement a minor restriction on stack 1 so that we know during DC fixups + that extending a dctrun token from stack 1 will never overflow.*/ + adj=_zzi!=1; + if(_val<2&&zero_run<17+adj){ + if(zero_run<6){ + token=OC_DCT_RUN_CAT1A+zero_run-1; + eb=neg; + } + else if(zero_run<10){ + token=OC_DCT_RUN_CAT1B; + eb=zero_run-6+(neg<<2); + } + else{ + token=OC_DCT_RUN_CAT1C; + eb=zero_run-10+(neg<<3); + } + } + else if(_val<4&&zero_run<3+adj){ + if(zero_run<2){ + token=OC_DCT_RUN_CAT2A; + eb=_val-2+(neg<<1); + } + else{ + token=OC_DCT_RUN_CAT2B; + eb=zero_run-2+(_val-2<<1)+(neg<<2); + } + } + else{ + if(zero_run<9)token=OC_DCT_SHORT_ZRL_TOKEN; + else token=OC_DCT_ZRL_TOKEN; + eb=zero_run-1; + } + } + else if(_val<3){ + token=OC_ONE_TOKEN+(_val-1<<1)+neg; + eb=0; + } + else if(_val<7){ + token=OC_DCT_VAL_CAT2+_val-3; + eb=neg; + } + else if(_val<9){ + token=OC_DCT_VAL_CAT3; + eb=_val-7+(neg<<1); + } + else if(_val<13){ + token=OC_DCT_VAL_CAT4; + eb=_val-9+(neg<<2); + } + else if(_val<21){ + token=OC_DCT_VAL_CAT5; + eb=_val-13+(neg<<3); + } + else if(_val<37){ + token=OC_DCT_VAL_CAT6; + eb=_val-21+(neg<<4); + } + else if(_val<69){ + token=OC_DCT_VAL_CAT7; + eb=_val-37+(neg<<5); + } + else{ + token=OC_DCT_VAL_CAT8; + eb=_val-69+(neg<<9); + } + *_eb=eb; + return token; +} + +/*Token logging to allow a few fragments of efficient rollback. + Late SKIP analysis is tied up in the tokenization process, so we need to be + able to undo a fragment's tokens on a whim.*/ + +static const unsigned char OC_ZZI_HUFF_OFFSET[64]={ + 0,16,16,16,16,16,32,32, + 32,32,32,32,32,32,32,48, + 48,48,48,48,48,48,48,48, + 48,48,48,48,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64 +}; + +static int oc_token_bits(oc_enc_ctx *_enc,int _huffi,int _zzi,int _token){ + return _enc->huff_codes[_huffi+OC_ZZI_HUFF_OFFSET[_zzi]][_token].nbits + +OC_DCT_TOKEN_EXTRA_BITS[_token]; +} + +static void oc_enc_tokenlog_checkpoint(oc_enc_ctx *_enc, + oc_token_checkpoint *_cp,int _pli,int _zzi){ + _cp->pli=_pli; + _cp->zzi=_zzi; + _cp->eob_run=_enc->eob_run[_pli][_zzi]; + _cp->ndct_tokens=_enc->ndct_tokens[_pli][_zzi]; +} + +void oc_enc_tokenlog_rollback(oc_enc_ctx *_enc, + const oc_token_checkpoint *_stack,int _n){ + int i; + for(i=_n;i-->0;){ + int pli; + int zzi; + pli=_stack[i].pli; + zzi=_stack[i].zzi; + _enc->eob_run[pli][zzi]=_stack[i].eob_run; + _enc->ndct_tokens[pli][zzi]=_stack[i].ndct_tokens; + } +} + +static void oc_enc_token_log(oc_enc_ctx *_enc, + int _pli,int _zzi,int _token,int _eb){ + ptrdiff_t ti; + ti=_enc->ndct_tokens[_pli][_zzi]++; + _enc->dct_tokens[_pli][_zzi][ti]=(unsigned char)_token; + _enc->extra_bits[_pli][_zzi][ti]=(ogg_uint16_t)_eb; +} + +static void oc_enc_eob_log(oc_enc_ctx *_enc, + int _pli,int _zzi,int _run_count){ + int token; + int eb; + token=oc_make_eob_token_full(_run_count,&eb); + oc_enc_token_log(_enc,_pli,_zzi,token,eb); +} + + +void oc_enc_tokenize_start(oc_enc_ctx *_enc){ + memset(_enc->ndct_tokens,0,sizeof(_enc->ndct_tokens)); + memset(_enc->eob_run,0,sizeof(_enc->eob_run)); + memset(_enc->dct_token_offs,0,sizeof(_enc->dct_token_offs)); + memset(_enc->dc_pred_last,0,sizeof(_enc->dc_pred_last)); +} + +typedef struct oc_quant_token oc_quant_token; + +/*A single node in the Viterbi trellis. + We maintain up to 2 of these per coefficient: + - A token to code if the value is zero (EOB, zero run, or combo token). + - A token to code if the value is not zero (DCT value token).*/ +struct oc_quant_token{ + unsigned char next; + signed char token; + ogg_int16_t eb; + ogg_uint32_t cost; + int bits; + int qc; +}; + +/*Tokenizes the AC coefficients, possibly adjusting the quantization, and then + dequantizes and de-zig-zags the result. + The DC coefficient is not preserved; it should be restored by the caller.*/ +int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi, + ogg_int16_t *_qdct,const ogg_uint16_t *_dequant,const ogg_int16_t *_dct, + int _zzi,oc_token_checkpoint **_stack,int _acmin){ + oc_token_checkpoint *stack; + ogg_int64_t zflags; + ogg_int64_t nzflags; + ogg_int64_t best_flags; + ogg_uint32_t d2_accum[64]; + oc_quant_token tokens[64][2]; + ogg_uint16_t *eob_run; + const unsigned char *dct_fzig_zag; + ogg_uint32_t cost; + int bits; + int eob; + int token; + int eb; + int next; + int huffi; + int zzi; + int ti; + int zzj; + int qc; + huffi=_enc->huff_idxs[_enc->state.frame_type][1][_pli+1>>1]; + eob_run=_enc->eob_run[_pli]; + memset(tokens[0],0,sizeof(tokens[0])); + best_flags=nzflags=0; + zflags=1; + d2_accum[0]=0; + zzj=64; + for(zzi=OC_MINI(_zzi,63);zzi>0;zzi--){ + ogg_int32_t lambda; + ogg_uint32_t best_cost; + int best_bits=best_bits; + int best_next=best_next; + int best_token=best_token; + int best_eb=best_eb; + int best_qc=best_qc; + int flush_bits; + ogg_uint32_t d2; + int dq; + int e; + int c; + int s; + int tj; + lambda=_enc->lambda; + qc=_qdct[zzi]; + s=-(qc<0); + qc=qc+s^s; + c=_dct[OC_FZIG_ZAG[zzi]]; + if(qc<=1){ + ogg_uint32_t sum_d2; + int nzeros; + int dc_reserve; + /*The hard case: try a zero run.*/ + if(!qc){ + /*Skip runs that are already quantized to zeros. + If we considered each zero coefficient in turn, we might + theoretically find a better way to partition long zero runs (e.g., + a run of > 17 zeros followed by a 1 might be better coded as a short + zero run followed by a combo token, rather than the longer zero + token followed by a 1 value token), but zeros are so common that + this becomes very computationally expensive (quadratic instead of + linear in the number of coefficients), for a marginal gain.*/ + while(zzi>1&&!_qdct[zzi-1])zzi--; + /*The distortion of coefficients originally quantized to zero is + treated as zero (since we'll never quantize them to anything else).*/ + d2=0; + } + else{ + c=c+s^s; + d2=c*(ogg_int32_t)c; + } + eob=eob_run[zzi]; + nzeros=zzj-zzi; + zzj&=63; + sum_d2=d2+d2_accum[zzj]; + d2_accum[zzi]=sum_d2; + flush_bits=eob>0?oc_token_bits(_enc,huffi,zzi,oc_make_eob_token(eob)):0; + /*We reserve 1 spot for combo run tokens that start in the 1st AC stack + to ensure they can be extended to include the DC coefficient if + necessary; this greatly simplifies stack-rewriting later on.*/ + dc_reserve=zzi+62>>6; + best_cost=0xFFFFFFFF; + for(;;){ + if(nzflags>>zzj&1){ + int cat; + int val; + int val_s; + int zzk; + int tk; + next=tokens[zzj][1].next; + tk=next&1; + zzk=next>>1; + /*Try a pure zero run to this point.*/ + cat=nzeros+55>>6; + token=OC_DCT_SHORT_ZRL_TOKEN+cat; + bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token); + d2=sum_d2-d2_accum[zzj]; + cost=d2+lambda*bits+tokens[zzj][1].cost; + if(cost<=best_cost){ + best_next=(zzj<<1)+1; + best_token=token; + best_eb=nzeros-1; + best_cost=cost; + best_bits=bits+tokens[zzj][1].bits; + best_qc=0; + } + if(nzeros<16+dc_reserve){ + val=_qdct[zzj]; + val_s=-(val<0); + val=val+val_s^val_s; + if(val<=2){ + /*Try a +/- 1 combo token.*/ + if(nzeros<6){ + token=OC_DCT_RUN_CAT1A+nzeros-1; + eb=-val_s; + } + else{ + cat=nzeros+54>>6; + token=OC_DCT_RUN_CAT1B+cat; + eb=(-val_s<>1; + token=OC_DCT_RUN_CAT2A+cat; + bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token); + val=2+((val+val_s^val_s)>2); + e=(_dct[OC_FZIG_ZAG[zzj]]+val_s^val_s)-_dequant[zzj]*val; + d2=e*(ogg_int32_t)e+sum_d2-d2_accum[zzj]; + cost=d2+lambda*bits+tokens[zzk][tk].cost; + if(cost<=best_cost){ + best_cost=cost; + best_bits=bits+tokens[zzk][tk].bits; + best_next=next; + best_token=token; + best_eb=(-val_s<<1+cat)+(val-2<>1); + best_qc=val+val_s^val_s; + } + } + } + /*zzj can't be coded as a zero, so stop trying to extend the run.*/ + if(!(zflags>>zzj&1))break; + } + /*We could try to consider _all_ potentially non-zero coefficients, but + if we already found a bunch of them not worth coding, it's fairly + unlikely they would now be worth coding from this position; skipping + them saves a lot of work.*/ + zzj=(tokens[zzj][0].next>>1)-(tokens[zzj][0].qc!=0)&63; + if(zzj==0){ + /*We made it all the way to the end of the block; try an EOB token.*/ + if(eob<4095){ + bits=oc_token_bits(_enc,huffi,zzi,oc_make_eob_token(eob+1)) + -flush_bits; + } + else bits=oc_token_bits(_enc,huffi,zzi,OC_DCT_EOB1_TOKEN); + cost=sum_d2+bits*lambda; + /*If the best route so far is still a pure zero run to the end of the + block, force coding it as an EOB. + Even if it's not optimal for this block, it has a good chance of + getting combined with an EOB token from subsequent blocks, saving + bits overall.*/ + if(cost<=best_cost||best_token<=OC_DCT_ZRL_TOKEN&&zzi+best_eb==63){ + best_next=0; + /*This token is just a marker; in reality we may not emit any + tokens, but update eob_run[] instead.*/ + best_token=OC_DCT_EOB1_TOKEN; + best_eb=0; + best_cost=cost; + best_bits=bits; + best_qc=0; + } + break; + } + nzeros=zzj-zzi; + } + tokens[zzi][0].next=(unsigned char)best_next; + tokens[zzi][0].token=(signed char)best_token; + tokens[zzi][0].eb=(ogg_int16_t)best_eb; + tokens[zzi][0].cost=best_cost; + tokens[zzi][0].bits=best_bits; + tokens[zzi][0].qc=best_qc; + zflags|=(ogg_int64_t)1<>zzj&1; + next=(zzj<<1)+tj; + tokens[zzi][1].next=(unsigned char)next; + tokens[zzi][1].token=(signed char)token; + tokens[zzi][1].eb=0; + tokens[zzi][1].cost=d2+lambda*bits+tokens[zzj][tj].cost; + tokens[zzi][1].bits=bits+tokens[zzj][tj].bits; + tokens[zzi][1].qc=1+s^s; + nzflags|=(ogg_int64_t)1<0?oc_token_bits(_enc,huffi,zzi,oc_make_eob_token(eob)):0; + if(qc<=2){ + e=2*dq-c; + d2=e*(ogg_int32_t)e; + best_token=OC_TWO_TOKEN-s; + best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token); + best_cost=d2+lambda*best_bits; + e-=dq; + d2=e*(ogg_int32_t)e; + token=OC_ONE_TOKEN-s; + bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token); + cost=d2+lambda*bits; + if(cost<=best_cost){ + best_token=token; + best_bits=bits; + best_cost=cost; + qc--; + } + best_eb=0; + } + else if(qc<=3){ + e=3*dq-c; + d2=e*(ogg_int32_t)e; + best_token=OC_DCT_VAL_CAT2; + best_eb=-s; + best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token); + best_cost=d2+lambda*best_bits; + e-=dq; + d2=e*(ogg_int32_t)e; + token=OC_TWO_TOKEN-s; + bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token); + cost=d2+lambda*bits; + if(cost<=best_cost){ + best_token=token; + best_eb=0; + best_bits=bits; + best_cost=cost; + qc--; + } + } + else if(qc<=6){ + e=qc*dq-c; + d2=e*(ogg_int32_t)e; + best_token=OC_DCT_VAL_CAT2+qc-3; + best_eb=-s; + best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token); + best_cost=d2+lambda*best_bits; + e-=dq; + d2=e*(ogg_int32_t)e; + token=best_token-1; + bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token); + cost=d2+lambda*bits; + if(cost<=best_cost){ + best_token=token; + best_bits=bits; + best_cost=cost; + qc--; + } + } + else if(qc<=8){ + e=qc*dq-c; + d2=e*(ogg_int32_t)e; + best_token=OC_DCT_VAL_CAT3; + best_eb=(-s<<1)+qc-7; + best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token); + best_cost=d2+lambda*best_bits; + e=6*dq-c; + d2=e*(ogg_int32_t)e; + token=OC_DCT_VAL_CAT2+3; + bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token); + cost=d2+lambda*bits; + if(cost<=best_cost){ + best_token=token; + best_eb=-s; + best_bits=bits; + best_cost=cost; + qc=6; + } + } + else if(qc<=12){ + e=qc*dq-c; + d2=e*(ogg_int32_t)e; + best_token=OC_DCT_VAL_CAT4; + best_eb=(-s<<2)+qc-9; + best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token); + best_cost=d2+lambda*best_bits; + e=8*dq-c; + d2=e*(ogg_int32_t)e; + token=best_token-1; + bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token); + cost=d2+lambda*bits; + if(cost<=best_cost){ + best_token=token; + best_eb=(-s<<1)+1; + best_bits=bits; + best_cost=cost; + qc=8; + } + } + else if(qc<=20){ + e=qc*dq-c; + d2=e*(ogg_int32_t)e; + best_token=OC_DCT_VAL_CAT5; + best_eb=(-s<<3)+qc-13; + best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token); + best_cost=d2+lambda*best_bits; + e=12*dq-c; + d2=e*(ogg_int32_t)e; + token=best_token-1; + bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token); + cost=d2+lambda*bits; + if(cost<=best_cost){ + best_token=token; + best_eb=(-s<<2)+3; + best_bits=bits; + best_cost=cost; + qc=12; + } + } + else if(qc<=36){ + e=qc*dq-c; + d2=e*(ogg_int32_t)e; + best_token=OC_DCT_VAL_CAT6; + best_eb=(-s<<4)+qc-21; + best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token); + best_cost=d2+lambda*best_bits; + e=20*dq-c; + d2=e*(ogg_int32_t)e; + token=best_token-1; + bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token); + cost=d2+lambda*bits; + if(cost<=best_cost){ + best_token=token; + best_eb=(-s<<3)+7; + best_bits=bits; + best_cost=cost; + qc=20; + } + } + else if(qc<=68){ + e=qc*dq-c; + d2=e*(ogg_int32_t)e; + best_token=OC_DCT_VAL_CAT7; + best_eb=(-s<<5)+qc-37; + best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token); + best_cost=d2+lambda*best_bits; + e=36*dq-c; + d2=e*(ogg_int32_t)e; + token=best_token-1; + bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token); + cost=d2+lambda*bits; + if(cost>zzj&1; + next=(zzj<<1)+tj; + tokens[zzi][1].next=(unsigned char)next; + tokens[zzi][1].token=(signed char)best_token; + tokens[zzi][1].eb=best_eb; + tokens[zzi][1].cost=best_cost+tokens[zzj][tj].cost; + tokens[zzi][1].bits=best_bits+tokens[zzj][tj].bits; + tokens[zzi][1].qc=qc+s^s; + nzflags|=(ogg_int64_t)1<state.opt_data.dct_fzig_zag; + zzi=1; + ti=best_flags>>1&1; + bits=tokens[zzi][ti].bits; + do{ + oc_enc_tokenlog_checkpoint(_enc,stack++,_pli,zzi); + eob=eob_run[zzi]; + if(tokens[zzi][ti].token=4095){ + oc_enc_eob_log(_enc,_pli,zzi,eob); + eob=0; + } + eob_run[zzi]=eob; + /*We don't include the actual EOB cost for this block in the return value. + It will be paid for by the fragment that terminates the EOB run.*/ + bits-=tokens[zzi][ti].bits; + zzi=_zzi; + break; + } + /*Emit pending EOB run if any.*/ + if(eob>0){ + oc_enc_eob_log(_enc,_pli,zzi,eob); + eob_run[zzi]=0; + } + oc_enc_token_log(_enc,_pli,zzi,tokens[zzi][ti].token,tokens[zzi][ti].eb); + next=tokens[zzi][ti].next; + qc=tokens[zzi][ti].qc; + zzj=(next>>1)-1&63; + /*TODO: It may be worth saving the dequantized coefficient in the trellis + above; we had to compute it to measure the error anyway.*/ + _qdct[dct_fzig_zag[zzj]]=(ogg_int16_t)(qc*(int)_dequant[zzj]); + zzi=next>>1; + ti=next&1; + } + while(zzi); + *_stack=stack; + return bits; +} + +void oc_enc_pred_dc_frag_rows(oc_enc_ctx *_enc, + int _pli,int _fragy0,int _frag_yend){ + const oc_fragment_plane *fplane; + const oc_fragment *frags; + ogg_int16_t *frag_dc; + ptrdiff_t fragi; + int *pred_last; + int nhfrags; + int fragx; + int fragy; + fplane=_enc->state.fplanes+_pli; + frags=_enc->state.frags; + frag_dc=_enc->frag_dc; + pred_last=_enc->dc_pred_last[_pli]; + nhfrags=fplane->nhfrags; + fragi=fplane->froffset+_fragy0*nhfrags; + for(fragy=_fragy0;fragy<_frag_yend;fragy++){ + if(fragy==0){ + /*For the first row, all of the cases reduce to just using the previous + predictor for the same reference frame.*/ + for(fragx=0;fragx=nhfrags)ur_ref=-1; + else{ + ur_ref=u_frags[fragi+1].coded? + OC_FRAME_FOR_MODE(u_frags[fragi+1].mb_mode):-1; + } + if(frags[fragi].coded){ + int pred; + int ref; + ref=OC_FRAME_FOR_MODE(frags[fragi].mb_mode); + /*We break out a separate case based on which of our neighbors use + the same reference frames. + This is somewhat faster than trying to make a generic case which + handles all of them, since it reduces lots of poorly predicted + jumps to one switch statement, and also lets a number of the + multiplications be optimized out by strength reduction.*/ + switch((l_ref==ref)|(ul_ref==ref)<<1| + (u_ref==ref)<<2|(ur_ref==ref)<<3){ + default:pred=pred_last[ref];break; + case 1: + case 3:pred=frags[fragi-1].dc;break; + case 2:pred=u_frags[fragi-1].dc;break; + case 4: + case 6: + case 12:pred=u_frags[fragi].dc;break; + case 5:pred=(frags[fragi-1].dc+u_frags[fragi].dc)/2;break; + case 8:pred=u_frags[fragi+1].dc;break; + case 9: + case 11: + case 13:{ + pred=(75*frags[fragi-1].dc+53*u_frags[fragi+1].dc)/128; + }break; + case 10:pred=(u_frags[fragi-1].dc+u_frags[fragi+1].dc)/2;break; + case 14:{ + pred=(3*(u_frags[fragi-1].dc+u_frags[fragi+1].dc) + +10*u_frags[fragi].dc)/16; + }break; + case 7: + case 15:{ + int p0; + int p1; + int p2; + p0=frags[fragi-1].dc; + p1=u_frags[fragi-1].dc; + p2=u_frags[fragi].dc; + pred=(29*(p0+p2)-26*p1)/32; + if(abs(pred-p2)>128)pred=p2; + else if(abs(pred-p0)>128)pred=p0; + else if(abs(pred-p1)>128)pred=p1; + }break; + } + frag_dc[fragi]=(ogg_int16_t)(frags[fragi].dc-pred); + pred_last[ref]=frags[fragi].dc; + l_ref=ref; + } + else l_ref=-1; + ul_ref=u_ref; + u_ref=ur_ref; + } + } + } +} + +void oc_enc_tokenize_dc_frag_list(oc_enc_ctx *_enc,int _pli, + const ptrdiff_t *_coded_fragis,ptrdiff_t _ncoded_fragis, + int _prev_ndct_tokens1,int _prev_eob_run1){ + const ogg_int16_t *frag_dc; + ptrdiff_t fragii; + unsigned char *dct_tokens0; + unsigned char *dct_tokens1; + ogg_uint16_t *extra_bits0; + ogg_uint16_t *extra_bits1; + ptrdiff_t ti0; + ptrdiff_t ti1r; + ptrdiff_t ti1w; + int eob_run0; + int eob_run1; + int neobs1; + int token; + int eb; + int token1=token1; + int eb1=eb1; + /*Return immediately if there are no coded fragments; otherwise we'd flush + any trailing EOB run into the AC 1 list and never read it back out.*/ + if(_ncoded_fragis<=0)return; + frag_dc=_enc->frag_dc; + dct_tokens0=_enc->dct_tokens[_pli][0]; + dct_tokens1=_enc->dct_tokens[_pli][1]; + extra_bits0=_enc->extra_bits[_pli][0]; + extra_bits1=_enc->extra_bits[_pli][1]; + ti0=_enc->ndct_tokens[_pli][0]; + ti1w=ti1r=_prev_ndct_tokens1; + eob_run0=_enc->eob_run[_pli][0]; + /*Flush any trailing EOB run for the 1st AC coefficient. + This is needed to allow us to track tokens to the end of the list.*/ + eob_run1=_enc->eob_run[_pli][1]; + if(eob_run1>0)oc_enc_eob_log(_enc,_pli,1,eob_run1); + /*If there was an active EOB run at the start of the 1st AC stack, read it + in and decode it.*/ + if(_prev_eob_run1>0){ + token1=dct_tokens1[ti1r]; + eb1=extra_bits1[ti1r]; + ti1r++; + eob_run1=oc_decode_eob_token(token1,eb1); + /*Consume the portion of the run that came before these fragments.*/ + neobs1=eob_run1-_prev_eob_run1; + } + else eob_run1=neobs1=0; + for(fragii=0;fragii<_ncoded_fragis;fragii++){ + int val; + /*All tokens in the 1st AC coefficient stack are regenerated as the DC + coefficients are produced. + This can be done in-place; stack 1 cannot get larger.*/ + if(!neobs1){ + /*There's no active EOB run in stack 1; read the next token.*/ + token1=dct_tokens1[ti1r]; + eb1=extra_bits1[ti1r]; + ti1r++; + if(token10){ + token=oc_make_eob_token_full(eob_run0,&eb); + dct_tokens0[ti0]=(unsigned char)token; + extra_bits0[ti0]=(ogg_uint16_t)eb; + ti0++; + eob_run0=0; + } + token=oc_make_dct_token_full(0,0,val,&eb); + dct_tokens0[ti0]=(unsigned char)token; + extra_bits0[ti0]=(ogg_uint16_t)eb; + ti0++; + } + else{ + /*Zero DC value; that means the entry in stack 1 might need to be coded + from stack 0. + This requires a stack 1 fixup.*/ + if(neobs1>0){ + /*We're in the middle of an active EOB run in stack 1. + Move it to stack 0.*/ + if(++eob_run0>=4095){ + token=oc_make_eob_token_full(eob_run0,&eb); + dct_tokens0[ti0]=(unsigned char)token; + extra_bits0[ti0]=(ogg_uint16_t)eb; + ti0++; + eob_run0=0; + } + eob_run1--; + } + else{ + /*No active EOB run in stack 1, so we can't extend one in stack 0. + Flush it if we've got it.*/ + if(eob_run0>0){ + token=oc_make_eob_token_full(eob_run0,&eb); + dct_tokens0[ti0]=(unsigned char)token; + extra_bits0[ti0]=(ogg_uint16_t)eb; + ti0++; + eob_run0=0; + } + /*Stack 1 token is one of: a pure zero run token, a single + coefficient token, or a zero run/coefficient combo token. + A zero run token is expanded and moved to token stack 0, and the + stack 1 entry dropped. + A single coefficient value may be transformed into combo token that + is moved to stack 0, or if it cannot be combined, it is left alone + and a single length-1 zero run is emitted in stack 0. + A combo token is extended and moved to stack 0. + During AC coding, we restrict the run lengths on combo tokens for + stack 1 to guarantee we can extend them.*/ + switch(token1){ + case OC_DCT_SHORT_ZRL_TOKEN:{ + if(eb1<7){ + dct_tokens0[ti0]=OC_DCT_SHORT_ZRL_TOKEN; + extra_bits0[ti0]=(ogg_uint16_t)(eb1+1); + ti0++; + /*Don't write the AC coefficient back out.*/ + continue; + } + /*Fall through.*/ + } + case OC_DCT_ZRL_TOKEN:{ + dct_tokens0[ti0]=OC_DCT_ZRL_TOKEN; + extra_bits0[ti0]=(ogg_uint16_t)(eb1+1); + ti0++; + /*Don't write the AC coefficient back out.*/ + }continue; + case OC_ONE_TOKEN: + case OC_MINUS_ONE_TOKEN:{ + dct_tokens0[ti0]=OC_DCT_RUN_CAT1A; + extra_bits0[ti0]=(ogg_uint16_t)(token1-OC_ONE_TOKEN); + ti0++; + /*Don't write the AC coefficient back out.*/ + }continue; + case OC_TWO_TOKEN: + case OC_MINUS_TWO_TOKEN:{ + dct_tokens0[ti0]=OC_DCT_RUN_CAT2A; + extra_bits0[ti0]=(ogg_uint16_t)(token1-OC_TWO_TOKEN<<1); + ti0++; + /*Don't write the AC coefficient back out.*/ + }continue; + case OC_DCT_VAL_CAT2:{ + dct_tokens0[ti0]=OC_DCT_RUN_CAT2A; + extra_bits0[ti0]=(ogg_uint16_t)((eb1<<1)+1); + ti0++; + /*Don't write the AC coefficient back out.*/ + }continue; + case OC_DCT_RUN_CAT1A: + case OC_DCT_RUN_CAT1A+1: + case OC_DCT_RUN_CAT1A+2: + case OC_DCT_RUN_CAT1A+3:{ + dct_tokens0[ti0]=(unsigned char)(token1+1); + extra_bits0[ti0]=(ogg_uint16_t)eb1; + ti0++; + /*Don't write the AC coefficient back out.*/ + }continue; + case OC_DCT_RUN_CAT1A+4:{ + dct_tokens0[ti0]=OC_DCT_RUN_CAT1B; + extra_bits0[ti0]=(ogg_uint16_t)(eb1<<2); + ti0++; + /*Don't write the AC coefficient back out.*/ + }continue; + case OC_DCT_RUN_CAT1B:{ + if((eb1&3)<3){ + dct_tokens0[ti0]=OC_DCT_RUN_CAT1B; + extra_bits0[ti0]=(ogg_uint16_t)(eb1+1); + ti0++; + /*Don't write the AC coefficient back out.*/ + continue; + } + eb1=((eb1&4)<<1)-1; + /*Fall through.*/ + } + case OC_DCT_RUN_CAT1C:{ + dct_tokens0[ti0]=OC_DCT_RUN_CAT1C; + extra_bits0[ti0]=(ogg_uint16_t)(eb1+1); + ti0++; + /*Don't write the AC coefficient back out.*/ + }continue; + case OC_DCT_RUN_CAT2A:{ + eb1=(eb1<<1)-1; + /*Fall through.*/ + } + case OC_DCT_RUN_CAT2B:{ + dct_tokens0[ti0]=OC_DCT_RUN_CAT2B; + extra_bits0[ti0]=(ogg_uint16_t)(eb1+1); + ti0++; + /*Don't write the AC coefficient back out.*/ + }continue; + } + /*We can't merge tokens, write a short zero run and keep going.*/ + dct_tokens0[ti0]=OC_DCT_SHORT_ZRL_TOKEN; + extra_bits0[ti0]=0; + ti0++; + } + } + if(!neobs1){ + /*Flush any (inactive) EOB run.*/ + if(eob_run1>0){ + token=oc_make_eob_token_full(eob_run1,&eb); + dct_tokens1[ti1w]=(unsigned char)token; + extra_bits1[ti1w]=(ogg_uint16_t)eb; + ti1w++; + eob_run1=0; + } + /*There's no active EOB run, so log the current token.*/ + dct_tokens1[ti1w]=(unsigned char)token1; + extra_bits1[ti1w]=(ogg_uint16_t)eb1; + ti1w++; + } + else{ + /*Otherwise consume one EOB from the current run.*/ + neobs1--; + /*If we have more than 4095 EOBs outstanding in stack1, flush the run.*/ + if(eob_run1-neobs1>=4095){ + token=oc_make_eob_token_full(4095,&eb); + dct_tokens1[ti1w]=(unsigned char)token; + extra_bits1[ti1w]=(ogg_uint16_t)eb; + ti1w++; + eob_run1-=4095; + } + } + } + /*Save the current state.*/ + _enc->ndct_tokens[_pli][0]=ti0; + _enc->ndct_tokens[_pli][1]=ti1w; + _enc->eob_run[_pli][0]=eob_run0; + _enc->eob_run[_pli][1]=eob_run1; +} + +/*Final EOB run welding.*/ +void oc_enc_tokenize_finish(oc_enc_ctx *_enc){ + int pli; + int zzi; + /*Emit final EOB runs.*/ + for(pli=0;pli<3;pli++)for(zzi=0;zzi<64;zzi++){ + int eob_run; + eob_run=_enc->eob_run[pli][zzi]; + if(eob_run>0)oc_enc_eob_log(_enc,pli,zzi,eob_run); + } + /*Merge the final EOB run of one token list with the start of the next, if + possible.*/ + for(zzi=0;zzi<64;zzi++)for(pli=0;pli<3;pli++){ + int old_tok1; + int old_tok2; + int old_eb1; + int old_eb2; + int new_tok; + int new_eb; + int zzj; + int plj; + ptrdiff_t ti=ti; + int run_count; + /*Make sure this coefficient has tokens at all.*/ + if(_enc->ndct_tokens[pli][zzi]<=0)continue; + /*Ensure the first token is an EOB run.*/ + old_tok2=_enc->dct_tokens[pli][zzi][0]; + if(old_tok2>=OC_NDCT_EOB_TOKEN_MAX)continue; + /*Search for a previous coefficient that has any tokens at all.*/ + old_tok1=OC_NDCT_EOB_TOKEN_MAX; + for(zzj=zzi,plj=pli;zzj>=0;zzj--){ + while(plj-->0){ + ti=_enc->ndct_tokens[plj][zzj]-1; + if(ti>=_enc->dct_token_offs[plj][zzj]){ + old_tok1=_enc->dct_tokens[plj][zzj][ti]; + break; + } + } + if(plj>=0)break; + plj=3; + } + /*Ensure its last token was an EOB run.*/ + if(old_tok1>=OC_NDCT_EOB_TOKEN_MAX)continue; + /*Pull off the associated extra bits, if any, and decode the runs.*/ + old_eb1=_enc->extra_bits[plj][zzj][ti]; + old_eb2=_enc->extra_bits[pli][zzi][0]; + run_count=oc_decode_eob_token(old_tok1,old_eb1) + +oc_decode_eob_token(old_tok2,old_eb2); + /*We can't possibly combine these into one run. + It might be possible to split them more optimally, but we'll just leave + them as-is.*/ + if(run_count>=4096)continue; + /*We CAN combine them into one run.*/ + new_tok=oc_make_eob_token_full(run_count,&new_eb); + _enc->dct_tokens[plj][zzj][ti]=(unsigned char)new_tok; + _enc->extra_bits[plj][zzj][ti]=(ogg_uint16_t)new_eb; + _enc->dct_token_offs[pli][zzi]++; + } +} diff --git a/Engine/lib/libtheora/lib/x86/mmxencfrag.c b/Engine/lib/libtheora/lib/x86/mmxencfrag.c new file mode 100644 index 000000000..c79ff01fc --- /dev/null +++ b/Engine/lib/libtheora/lib/x86/mmxencfrag.c @@ -0,0 +1,900 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: dsp_mmx.c 14579 2008-03-12 06:42:40Z xiphmont $ + + ********************************************************************/ +#include +#include "x86enc.h" + +#if defined(OC_X86_ASM) + +unsigned oc_enc_frag_sad_mmxext(const unsigned char *_src, + const unsigned char *_ref,int _ystride){ + ptrdiff_t ystride3; + ptrdiff_t ret; + __asm__ __volatile__( + /*Load the first 4 rows of each block.*/ + "movq (%[src]),%%mm0\n\t" + "movq (%[ref]),%%mm1\n\t" + "movq (%[src],%[ystride]),%%mm2\n\t" + "movq (%[ref],%[ystride]),%%mm3\n\t" + "lea (%[ystride],%[ystride],2),%[ystride3]\n\t" + "movq (%[src],%[ystride],2),%%mm4\n\t" + "movq (%[ref],%[ystride],2),%%mm5\n\t" + "movq (%[src],%[ystride3]),%%mm6\n\t" + "movq (%[ref],%[ystride3]),%%mm7\n\t" + /*Compute their SADs and add them in %%mm0*/ + "psadbw %%mm1,%%mm0\n\t" + "psadbw %%mm3,%%mm2\n\t" + "lea (%[src],%[ystride],4),%[src]\n\t" + "paddw %%mm2,%%mm0\n\t" + "lea (%[ref],%[ystride],4),%[ref]\n\t" + /*Load the next 3 rows as registers become available.*/ + "movq (%[src]),%%mm2\n\t" + "movq (%[ref]),%%mm3\n\t" + "psadbw %%mm5,%%mm4\n\t" + "psadbw %%mm7,%%mm6\n\t" + "paddw %%mm4,%%mm0\n\t" + "movq (%[ref],%[ystride]),%%mm5\n\t" + "movq (%[src],%[ystride]),%%mm4\n\t" + "paddw %%mm6,%%mm0\n\t" + "movq (%[ref],%[ystride],2),%%mm7\n\t" + "movq (%[src],%[ystride],2),%%mm6\n\t" + /*Start adding their SADs to %%mm0*/ + "psadbw %%mm3,%%mm2\n\t" + "psadbw %%mm5,%%mm4\n\t" + "paddw %%mm2,%%mm0\n\t" + "psadbw %%mm7,%%mm6\n\t" + /*Load last row as registers become available.*/ + "movq (%[src],%[ystride3]),%%mm2\n\t" + "movq (%[ref],%[ystride3]),%%mm3\n\t" + /*And finish adding up their SADs.*/ + "paddw %%mm4,%%mm0\n\t" + "psadbw %%mm3,%%mm2\n\t" + "paddw %%mm6,%%mm0\n\t" + "paddw %%mm2,%%mm0\n\t" + "movd %%mm0,%[ret]\n\t" + :[ret]"=a"(ret),[src]"+%r"(_src),[ref]"+r"(_ref),[ystride3]"=&r"(ystride3) + :[ystride]"r"((ptrdiff_t)_ystride) + ); + return (unsigned)ret; +} + +unsigned oc_enc_frag_sad_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _thresh){ + /*Early termination is for suckers.*/ + return oc_enc_frag_sad_mmxext(_src,_ref,_ystride); +} + +/*Assumes the first two rows of %[ref1] and %[ref2] are in %%mm0...%%mm3, the + first two rows of %[src] are in %%mm4,%%mm5, and {1}x8 is in %%mm7. + We pre-load the next two rows of data as registers become available.*/ +#define OC_SAD2_LOOP \ + "#OC_SAD2_LOOP\n\t" \ + /*We want to compute (%%mm0+%%mm1>>1) on unsigned bytes without overflow, but \ + pavgb computes (%%mm0+%%mm1+1>>1). \ + The latter is exactly 1 too large when the low bit of two corresponding \ + bytes is only set in one of them. \ + Therefore we pxor the operands, pand to mask out the low bits, and psubb to \ + correct the output of pavgb.*/ \ + "movq %%mm0,%%mm6\n\t" \ + "lea (%[ref1],%[ystride],2),%[ref1]\n\t" \ + "pxor %%mm1,%%mm0\n\t" \ + "pavgb %%mm1,%%mm6\n\t" \ + "lea (%[ref2],%[ystride],2),%[ref2]\n\t" \ + "movq %%mm2,%%mm1\n\t" \ + "pand %%mm7,%%mm0\n\t" \ + "pavgb %%mm3,%%mm2\n\t" \ + "pxor %%mm3,%%mm1\n\t" \ + "movq (%[ref2],%[ystride]),%%mm3\n\t" \ + "psubb %%mm0,%%mm6\n\t" \ + "movq (%[ref1]),%%mm0\n\t" \ + "pand %%mm7,%%mm1\n\t" \ + "psadbw %%mm6,%%mm4\n\t" \ + "movd %[ret],%%mm6\n\t" \ + "psubb %%mm1,%%mm2\n\t" \ + "movq (%[ref2]),%%mm1\n\t" \ + "lea (%[src],%[ystride],2),%[src]\n\t" \ + "psadbw %%mm2,%%mm5\n\t" \ + "movq (%[ref1],%[ystride]),%%mm2\n\t" \ + "paddw %%mm4,%%mm5\n\t" \ + "movq (%[src]),%%mm4\n\t" \ + "paddw %%mm5,%%mm6\n\t" \ + "movq (%[src],%[ystride]),%%mm5\n\t" \ + "movd %%mm6,%[ret]\n\t" \ + +/*Same as above, but does not pre-load the next two rows.*/ +#define OC_SAD2_TAIL \ + "#OC_SAD2_TAIL\n\t" \ + "movq %%mm0,%%mm6\n\t" \ + "pavgb %%mm1,%%mm0\n\t" \ + "pxor %%mm1,%%mm6\n\t" \ + "movq %%mm2,%%mm1\n\t" \ + "pand %%mm7,%%mm6\n\t" \ + "pavgb %%mm3,%%mm2\n\t" \ + "pxor %%mm3,%%mm1\n\t" \ + "psubb %%mm6,%%mm0\n\t" \ + "pand %%mm7,%%mm1\n\t" \ + "psadbw %%mm0,%%mm4\n\t" \ + "psubb %%mm1,%%mm2\n\t" \ + "movd %[ret],%%mm6\n\t" \ + "psadbw %%mm2,%%mm5\n\t" \ + "paddw %%mm4,%%mm5\n\t" \ + "paddw %%mm5,%%mm6\n\t" \ + "movd %%mm6,%[ret]\n\t" \ + +unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref1,const unsigned char *_ref2,int _ystride, + unsigned _thresh){ + ptrdiff_t ret; + __asm__ __volatile__( + "movq (%[ref1]),%%mm0\n\t" + "movq (%[ref2]),%%mm1\n\t" + "movq (%[ref1],%[ystride]),%%mm2\n\t" + "movq (%[ref2],%[ystride]),%%mm3\n\t" + "xor %[ret],%[ret]\n\t" + "movq (%[src]),%%mm4\n\t" + "pxor %%mm7,%%mm7\n\t" + "pcmpeqb %%mm6,%%mm6\n\t" + "movq (%[src],%[ystride]),%%mm5\n\t" + "psubb %%mm6,%%mm7\n\t" + OC_SAD2_LOOP + OC_SAD2_LOOP + OC_SAD2_LOOP + OC_SAD2_TAIL + :[ret]"=&a"(ret),[src]"+r"(_src),[ref1]"+%r"(_ref1),[ref2]"+r"(_ref2) + :[ystride]"r"((ptrdiff_t)_ystride) + ); + return (unsigned)ret; +} + +/*Load an 8x4 array of pixel values from %[src] and %[ref] and compute their + 16-bit difference in %%mm0...%%mm7.*/ +#define OC_LOAD_SUB_8x4(_off) \ + "#OC_LOAD_SUB_8x4\n\t" \ + "movd "_off"(%[src]),%%mm0\n\t" \ + "movd "_off"(%[ref]),%%mm4\n\t" \ + "movd "_off"(%[src],%[src_ystride]),%%mm1\n\t" \ + "lea (%[src],%[src_ystride],2),%[src]\n\t" \ + "movd "_off"(%[ref],%[ref_ystride]),%%mm5\n\t" \ + "lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \ + "movd "_off"(%[src]),%%mm2\n\t" \ + "movd "_off"(%[ref]),%%mm7\n\t" \ + "movd "_off"(%[src],%[src_ystride]),%%mm3\n\t" \ + "movd "_off"(%[ref],%[ref_ystride]),%%mm6\n\t" \ + "punpcklbw %%mm4,%%mm0\n\t" \ + "lea (%[src],%[src_ystride],2),%[src]\n\t" \ + "punpcklbw %%mm4,%%mm4\n\t" \ + "lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \ + "psubw %%mm4,%%mm0\n\t" \ + "movd "_off"(%[src]),%%mm4\n\t" \ + "movq %%mm0,"_off"*2(%[buf])\n\t" \ + "movd "_off"(%[ref]),%%mm0\n\t" \ + "punpcklbw %%mm5,%%mm1\n\t" \ + "punpcklbw %%mm5,%%mm5\n\t" \ + "psubw %%mm5,%%mm1\n\t" \ + "movd "_off"(%[src],%[src_ystride]),%%mm5\n\t" \ + "punpcklbw %%mm7,%%mm2\n\t" \ + "punpcklbw %%mm7,%%mm7\n\t" \ + "psubw %%mm7,%%mm2\n\t" \ + "movd "_off"(%[ref],%[ref_ystride]),%%mm7\n\t" \ + "punpcklbw %%mm6,%%mm3\n\t" \ + "lea (%[src],%[src_ystride],2),%[src]\n\t" \ + "punpcklbw %%mm6,%%mm6\n\t" \ + "psubw %%mm6,%%mm3\n\t" \ + "movd "_off"(%[src]),%%mm6\n\t" \ + "punpcklbw %%mm0,%%mm4\n\t" \ + "lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \ + "punpcklbw %%mm0,%%mm0\n\t" \ + "lea (%[src],%[src_ystride],2),%[src]\n\t" \ + "psubw %%mm0,%%mm4\n\t" \ + "movd "_off"(%[ref]),%%mm0\n\t" \ + "punpcklbw %%mm7,%%mm5\n\t" \ + "neg %[src_ystride]\n\t" \ + "punpcklbw %%mm7,%%mm7\n\t" \ + "psubw %%mm7,%%mm5\n\t" \ + "movd "_off"(%[src],%[src_ystride]),%%mm7\n\t" \ + "punpcklbw %%mm0,%%mm6\n\t" \ + "lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \ + "punpcklbw %%mm0,%%mm0\n\t" \ + "neg %[ref_ystride]\n\t" \ + "psubw %%mm0,%%mm6\n\t" \ + "movd "_off"(%[ref],%[ref_ystride]),%%mm0\n\t" \ + "lea (%[src],%[src_ystride],8),%[src]\n\t" \ + "punpcklbw %%mm0,%%mm7\n\t" \ + "neg %[src_ystride]\n\t" \ + "punpcklbw %%mm0,%%mm0\n\t" \ + "lea (%[ref],%[ref_ystride],8),%[ref]\n\t" \ + "psubw %%mm0,%%mm7\n\t" \ + "neg %[ref_ystride]\n\t" \ + "movq "_off"*2(%[buf]),%%mm0\n\t" \ + +/*Load an 8x4 array of pixel values from %[src] into %%mm0...%%mm7.*/ +#define OC_LOAD_8x4(_off) \ + "#OC_LOAD_8x4\n\t" \ + "movd "_off"(%[src]),%%mm0\n\t" \ + "movd "_off"(%[src],%[ystride]),%%mm1\n\t" \ + "movd "_off"(%[src],%[ystride],2),%%mm2\n\t" \ + "pxor %%mm7,%%mm7\n\t" \ + "movd "_off"(%[src],%[ystride3]),%%mm3\n\t" \ + "punpcklbw %%mm7,%%mm0\n\t" \ + "movd "_off"(%[src4]),%%mm4\n\t" \ + "punpcklbw %%mm7,%%mm1\n\t" \ + "movd "_off"(%[src4],%[ystride]),%%mm5\n\t" \ + "punpcklbw %%mm7,%%mm2\n\t" \ + "movd "_off"(%[src4],%[ystride],2),%%mm6\n\t" \ + "punpcklbw %%mm7,%%mm3\n\t" \ + "movd "_off"(%[src4],%[ystride3]),%%mm7\n\t" \ + "punpcklbw %%mm4,%%mm4\n\t" \ + "punpcklbw %%mm5,%%mm5\n\t" \ + "psrlw $8,%%mm4\n\t" \ + "psrlw $8,%%mm5\n\t" \ + "punpcklbw %%mm6,%%mm6\n\t" \ + "punpcklbw %%mm7,%%mm7\n\t" \ + "psrlw $8,%%mm6\n\t" \ + "psrlw $8,%%mm7\n\t" \ + +/*Performs the first two stages of an 8-point 1-D Hadamard transform. + The transform is performed in place, except that outputs 0-3 are swapped with + outputs 4-7. + Outputs 2, 3, 6 and 7 from the second stage are negated (which allows us to + perform this stage in place with no temporary registers).*/ +#define OC_HADAMARD_AB_8x4 \ + "#OC_HADAMARD_AB_8x4\n\t" \ + /*Stage A: \ + Outputs 0-3 are swapped with 4-7 here.*/ \ + "paddw %%mm1,%%mm5\n\t" \ + "paddw %%mm2,%%mm6\n\t" \ + "paddw %%mm1,%%mm1\n\t" \ + "paddw %%mm2,%%mm2\n\t" \ + "psubw %%mm5,%%mm1\n\t" \ + "psubw %%mm6,%%mm2\n\t" \ + "paddw %%mm3,%%mm7\n\t" \ + "paddw %%mm0,%%mm4\n\t" \ + "paddw %%mm3,%%mm3\n\t" \ + "paddw %%mm0,%%mm0\n\t" \ + "psubw %%mm7,%%mm3\n\t" \ + "psubw %%mm4,%%mm0\n\t" \ + /*Stage B:*/ \ + "paddw %%mm2,%%mm0\n\t" \ + "paddw %%mm3,%%mm1\n\t" \ + "paddw %%mm6,%%mm4\n\t" \ + "paddw %%mm7,%%mm5\n\t" \ + "paddw %%mm2,%%mm2\n\t" \ + "paddw %%mm3,%%mm3\n\t" \ + "paddw %%mm6,%%mm6\n\t" \ + "paddw %%mm7,%%mm7\n\t" \ + "psubw %%mm0,%%mm2\n\t" \ + "psubw %%mm1,%%mm3\n\t" \ + "psubw %%mm4,%%mm6\n\t" \ + "psubw %%mm5,%%mm7\n\t" \ + +/*Performs the last stage of an 8-point 1-D Hadamard transform in place. + Ouputs 1, 3, 5, and 7 are negated (which allows us to perform this stage in + place with no temporary registers).*/ +#define OC_HADAMARD_C_8x4 \ + "#OC_HADAMARD_C_8x4\n\t" \ + /*Stage C:*/ \ + "paddw %%mm1,%%mm0\n\t" \ + "paddw %%mm3,%%mm2\n\t" \ + "paddw %%mm5,%%mm4\n\t" \ + "paddw %%mm7,%%mm6\n\t" \ + "paddw %%mm1,%%mm1\n\t" \ + "paddw %%mm3,%%mm3\n\t" \ + "paddw %%mm5,%%mm5\n\t" \ + "paddw %%mm7,%%mm7\n\t" \ + "psubw %%mm0,%%mm1\n\t" \ + "psubw %%mm2,%%mm3\n\t" \ + "psubw %%mm4,%%mm5\n\t" \ + "psubw %%mm6,%%mm7\n\t" \ + +/*Performs an 8-point 1-D Hadamard transform. + The transform is performed in place, except that outputs 0-3 are swapped with + outputs 4-7. + Outputs 1, 2, 5 and 6 are negated (which allows us to perform the transform + in place with no temporary registers).*/ +#define OC_HADAMARD_8x4 \ + OC_HADAMARD_AB_8x4 \ + OC_HADAMARD_C_8x4 \ + +/*Performs the first part of the final stage of the Hadamard transform and + summing of absolute values. + At the end of this part, %%mm1 will contain the DC coefficient of the + transform.*/ +#define OC_HADAMARD_C_ABS_ACCUM_A_8x4(_r6,_r7) \ + /*We use the fact that \ + (abs(a+b)+abs(a-b))/2=max(abs(a),abs(b)) \ + to merge the final butterfly with the abs and the first stage of \ + accumulation. \ + Thus we can avoid using pabsw, which is not available until SSSE3. \ + Emulating pabsw takes 3 instructions, so the straightforward MMXEXT \ + implementation would be (3+3)*8+7=55 instructions (+4 for spilling \ + registers). \ + Even with pabsw, it would be (3+1)*8+7=39 instructions (with no spills). \ + This implementation is only 26 (+4 for spilling registers).*/ \ + "#OC_HADAMARD_C_ABS_ACCUM_A_8x4\n\t" \ + "movq %%mm7,"_r7"(%[buf])\n\t" \ + "movq %%mm6,"_r6"(%[buf])\n\t" \ + /*mm7={0x7FFF}x4 \ + mm0=max(abs(mm0),abs(mm1))-0x7FFF*/ \ + "pcmpeqb %%mm7,%%mm7\n\t" \ + "movq %%mm0,%%mm6\n\t" \ + "psrlw $1,%%mm7\n\t" \ + "paddw %%mm1,%%mm6\n\t" \ + "pmaxsw %%mm1,%%mm0\n\t" \ + "paddsw %%mm7,%%mm6\n\t" \ + "psubw %%mm6,%%mm0\n\t" \ + /*mm2=max(abs(mm2),abs(mm3))-0x7FFF \ + mm4=max(abs(mm4),abs(mm5))-0x7FFF*/ \ + "movq %%mm2,%%mm6\n\t" \ + "movq %%mm4,%%mm1\n\t" \ + "pmaxsw %%mm3,%%mm2\n\t" \ + "pmaxsw %%mm5,%%mm4\n\t" \ + "paddw %%mm3,%%mm6\n\t" \ + "paddw %%mm5,%%mm1\n\t" \ + "movq "_r7"(%[buf]),%%mm3\n\t" \ + +/*Performs the second part of the final stage of the Hadamard transform and + summing of absolute values.*/ +#define OC_HADAMARD_C_ABS_ACCUM_B_8x4(_r6,_r7) \ + "#OC_HADAMARD_C_ABS_ACCUM_B_8x4\n\t" \ + "paddsw %%mm7,%%mm6\n\t" \ + "movq "_r6"(%[buf]),%%mm5\n\t" \ + "paddsw %%mm7,%%mm1\n\t" \ + "psubw %%mm6,%%mm2\n\t" \ + "psubw %%mm1,%%mm4\n\t" \ + /*mm7={1}x4 (needed for the horizontal add that follows) \ + mm0+=mm2+mm4+max(abs(mm3),abs(mm5))-0x7FFF*/ \ + "movq %%mm3,%%mm6\n\t" \ + "pmaxsw %%mm5,%%mm3\n\t" \ + "paddw %%mm2,%%mm0\n\t" \ + "paddw %%mm5,%%mm6\n\t" \ + "paddw %%mm4,%%mm0\n\t" \ + "paddsw %%mm7,%%mm6\n\t" \ + "paddw %%mm3,%%mm0\n\t" \ + "psrlw $14,%%mm7\n\t" \ + "psubw %%mm6,%%mm0\n\t" \ + +/*Performs the last stage of an 8-point 1-D Hadamard transform, takes the + absolute value of each component, and accumulates everything into mm0. + This is the only portion of SATD which requires MMXEXT (we could use plain + MMX, but it takes 4 instructions and an extra register to work around the + lack of a pmaxsw, which is a pretty serious penalty).*/ +#define OC_HADAMARD_C_ABS_ACCUM_8x4(_r6,_r7) \ + OC_HADAMARD_C_ABS_ACCUM_A_8x4(_r6,_r7) \ + OC_HADAMARD_C_ABS_ACCUM_B_8x4(_r6,_r7) \ + +/*Performs an 8-point 1-D Hadamard transform, takes the absolute value of each + component, and accumulates everything into mm0. + Note that mm0 will have an extra 4 added to each column, and that after + removing this value, the remainder will be half the conventional value.*/ +#define OC_HADAMARD_ABS_ACCUM_8x4(_r6,_r7) \ + OC_HADAMARD_AB_8x4 \ + OC_HADAMARD_C_ABS_ACCUM_8x4(_r6,_r7) + +/*Performs two 4x4 transposes (mostly) in place. + On input, {mm0,mm1,mm2,mm3} contains rows {e,f,g,h}, and {mm4,mm5,mm6,mm7} + contains rows {a,b,c,d}. + On output, {0x40,0x50,0x60,0x70}+_off(%[buf]) contains {e,f,g,h}^T, and + {mm4,mm5,mm6,mm7} contains the transposed rows {a,b,c,d}^T.*/ +#define OC_TRANSPOSE_4x4x2(_off) \ + "#OC_TRANSPOSE_4x4x2\n\t" \ + /*First 4x4 transpose:*/ \ + "movq %%mm5,0x10+"_off"(%[buf])\n\t" \ + /*mm0 = e3 e2 e1 e0 \ + mm1 = f3 f2 f1 f0 \ + mm2 = g3 g2 g1 g0 \ + mm3 = h3 h2 h1 h0*/ \ + "movq %%mm2,%%mm5\n\t" \ + "punpcklwd %%mm3,%%mm2\n\t" \ + "punpckhwd %%mm3,%%mm5\n\t" \ + "movq %%mm0,%%mm3\n\t" \ + "punpcklwd %%mm1,%%mm0\n\t" \ + "punpckhwd %%mm1,%%mm3\n\t" \ + /*mm0 = f1 e1 f0 e0 \ + mm3 = f3 e3 f2 e2 \ + mm2 = h1 g1 h0 g0 \ + mm5 = h3 g3 h2 g2*/ \ + "movq %%mm0,%%mm1\n\t" \ + "punpckldq %%mm2,%%mm0\n\t" \ + "punpckhdq %%mm2,%%mm1\n\t" \ + "movq %%mm3,%%mm2\n\t" \ + "punpckhdq %%mm5,%%mm3\n\t" \ + "movq %%mm0,0x40+"_off"(%[buf])\n\t" \ + "punpckldq %%mm5,%%mm2\n\t" \ + /*mm0 = h0 g0 f0 e0 \ + mm1 = h1 g1 f1 e1 \ + mm2 = h2 g2 f2 e2 \ + mm3 = h3 g3 f3 e3*/ \ + "movq 0x10+"_off"(%[buf]),%%mm5\n\t" \ + /*Second 4x4 transpose:*/ \ + /*mm4 = a3 a2 a1 a0 \ + mm5 = b3 b2 b1 b0 \ + mm6 = c3 c2 c1 c0 \ + mm7 = d3 d2 d1 d0*/ \ + "movq %%mm6,%%mm0\n\t" \ + "punpcklwd %%mm7,%%mm6\n\t" \ + "movq %%mm1,0x50+"_off"(%[buf])\n\t" \ + "punpckhwd %%mm7,%%mm0\n\t" \ + "movq %%mm4,%%mm7\n\t" \ + "punpcklwd %%mm5,%%mm4\n\t" \ + "movq %%mm2,0x60+"_off"(%[buf])\n\t" \ + "punpckhwd %%mm5,%%mm7\n\t" \ + /*mm4 = b1 a1 b0 a0 \ + mm7 = b3 a3 b2 a2 \ + mm6 = d1 c1 d0 c0 \ + mm0 = d3 c3 d2 c2*/ \ + "movq %%mm4,%%mm5\n\t" \ + "punpckldq %%mm6,%%mm4\n\t" \ + "movq %%mm3,0x70+"_off"(%[buf])\n\t" \ + "punpckhdq %%mm6,%%mm5\n\t" \ + "movq %%mm7,%%mm6\n\t" \ + "punpckhdq %%mm0,%%mm7\n\t" \ + "punpckldq %%mm0,%%mm6\n\t" \ + /*mm4 = d0 c0 b0 a0 \ + mm5 = d1 c1 b1 a1 \ + mm6 = d2 c2 b2 a2 \ + mm7 = d3 c3 b3 a3*/ \ + +static unsigned oc_int_frag_satd_thresh_mmxext(const unsigned char *_src, + int _src_ystride,const unsigned char *_ref,int _ref_ystride,unsigned _thresh){ + OC_ALIGN8(ogg_int16_t buf[64]); + ogg_int16_t *bufp; + unsigned ret; + unsigned ret2; + bufp=buf; + __asm__ __volatile__( + OC_LOAD_SUB_8x4("0x00") + OC_HADAMARD_8x4 + OC_TRANSPOSE_4x4x2("0x00") + /*Finish swapping out this 8x4 block to make room for the next one. + mm0...mm3 have been swapped out already.*/ + "movq %%mm4,0x00(%[buf])\n\t" + "movq %%mm5,0x10(%[buf])\n\t" + "movq %%mm6,0x20(%[buf])\n\t" + "movq %%mm7,0x30(%[buf])\n\t" + OC_LOAD_SUB_8x4("0x04") + OC_HADAMARD_8x4 + OC_TRANSPOSE_4x4x2("0x08") + /*Here the first 4x4 block of output from the last transpose is the second + 4x4 block of input for the next transform. + We have cleverly arranged that it already be in the appropriate place, so + we only have to do half the loads.*/ + "movq 0x10(%[buf]),%%mm1\n\t" + "movq 0x20(%[buf]),%%mm2\n\t" + "movq 0x30(%[buf]),%%mm3\n\t" + "movq 0x00(%[buf]),%%mm0\n\t" + OC_HADAMARD_ABS_ACCUM_8x4("0x28","0x38") + /*Up to this point, everything fit in 16 bits (8 input + 1 for the + difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1 + for the factor of two we dropped + 3 for the vertical accumulation). + Now we finally have to promote things to dwords. + We break this part out of OC_HADAMARD_ABS_ACCUM_8x4 to hide the long + latency of pmaddwd by starting the next series of loads now.*/ + "mov %[thresh],%[ret2]\n\t" + "pmaddwd %%mm7,%%mm0\n\t" + "movq 0x50(%[buf]),%%mm1\n\t" + "movq 0x58(%[buf]),%%mm5\n\t" + "movq %%mm0,%%mm4\n\t" + "movq 0x60(%[buf]),%%mm2\n\t" + "punpckhdq %%mm0,%%mm0\n\t" + "movq 0x68(%[buf]),%%mm6\n\t" + "paddd %%mm0,%%mm4\n\t" + "movq 0x70(%[buf]),%%mm3\n\t" + "movd %%mm4,%[ret]\n\t" + "movq 0x78(%[buf]),%%mm7\n\t" + /*The sums produced by OC_HADAMARD_ABS_ACCUM_8x4 each have an extra 4 + added to them, and a factor of two removed; correct the final sum here.*/ + "lea -32(%[ret],%[ret]),%[ret]\n\t" + "movq 0x40(%[buf]),%%mm0\n\t" + "cmp %[ret2],%[ret]\n\t" + "movq 0x48(%[buf]),%%mm4\n\t" + "jae 1f\n\t" + OC_HADAMARD_ABS_ACCUM_8x4("0x68","0x78") + "pmaddwd %%mm7,%%mm0\n\t" + /*There isn't much to stick in here to hide the latency this time, but the + alternative to pmaddwd is movq->punpcklwd->punpckhwd->paddd, whose + latency is even worse.*/ + "sub $32,%[ret]\n\t" + "movq %%mm0,%%mm4\n\t" + "punpckhdq %%mm0,%%mm0\n\t" + "paddd %%mm0,%%mm4\n\t" + "movd %%mm4,%[ret2]\n\t" + "lea (%[ret],%[ret2],2),%[ret]\n\t" + ".p2align 4,,15\n\t" + "1:\n\t" + /*Although it looks like we're using 7 registers here, gcc can alias %[ret] + and %[ret2] with some of the inputs, since for once we don't write to + them until after we're done using everything but %[buf] (which is also + listed as an output to ensure gcc _doesn't_ alias them against it).*/ + /*Note that _src_ystride and _ref_ystride must be given non-overlapping + constraints, otherewise if gcc can prove they're equal it will allocate + them to the same register (which is bad); _src and _ref face a similar + problem, though those are never actually the same.*/ + :[ret]"=a"(ret),[ret2]"=r"(ret2),[buf]"+r"(bufp) + :[src]"r"(_src),[src_ystride]"c"((ptrdiff_t)_src_ystride), + [ref]"r"(_ref),[ref_ystride]"d"((ptrdiff_t)_ref_ystride), + [thresh]"m"(_thresh) + /*We have to use neg, so we actually clobber the condition codes for once + (not to mention cmp, sub, and add).*/ + :"cc" + ); + return ret; +} + +unsigned oc_enc_frag_satd_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _thresh){ + return oc_int_frag_satd_thresh_mmxext(_src,_ystride,_ref,_ystride,_thresh); +} + +/*Our internal implementation of frag_copy2 takes an extra stride parameter so + we can share code with oc_enc_frag_satd2_thresh_mmxext().*/ +static void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride, + const unsigned char *_src1,const unsigned char *_src2,int _src_ystride){ + __asm__ __volatile__( + /*Load the first 3 rows.*/ + "movq (%[src1]),%%mm0\n\t" + "movq (%[src2]),%%mm1\n\t" + "movq (%[src1],%[src_ystride]),%%mm2\n\t" + "lea (%[src1],%[src_ystride],2),%[src1]\n\t" + "movq (%[src2],%[src_ystride]),%%mm3\n\t" + "lea (%[src2],%[src_ystride],2),%[src2]\n\t" + "pxor %%mm7,%%mm7\n\t" + "movq (%[src1]),%%mm4\n\t" + "pcmpeqb %%mm6,%%mm6\n\t" + "movq (%[src2]),%%mm5\n\t" + /*mm7={1}x8.*/ + "psubb %%mm6,%%mm7\n\t" + /*Start averaging %%mm0 and %%mm1 into %%mm6.*/ + "movq %%mm0,%%mm6\n\t" + "pxor %%mm1,%%mm0\n\t" + "pavgb %%mm1,%%mm6\n\t" + /*%%mm1 is free, start averaging %%mm3 into %%mm2 using %%mm1.*/ + "movq %%mm2,%%mm1\n\t" + "pand %%mm7,%%mm0\n\t" + "pavgb %%mm3,%%mm2\n\t" + "pxor %%mm3,%%mm1\n\t" + /*%%mm3 is free.*/ + "psubb %%mm0,%%mm6\n\t" + /*%%mm0 is free, start loading the next row.*/ + "movq (%[src1],%[src_ystride]),%%mm0\n\t" + /*Start averaging %%mm5 and %%mm4 using %%mm3.*/ + "movq %%mm4,%%mm3\n\t" + /*%%mm6 (row 0) is done; write it out.*/ + "movq %%mm6,(%[dst])\n\t" + "pand %%mm7,%%mm1\n\t" + "pavgb %%mm5,%%mm4\n\t" + "psubb %%mm1,%%mm2\n\t" + /*%%mm1 is free, continue loading the next row.*/ + "movq (%[src2],%[src_ystride]),%%mm1\n\t" + "pxor %%mm5,%%mm3\n\t" + "lea (%[src1],%[src_ystride],2),%[src1]\n\t" + /*%%mm2 (row 1) is done; write it out.*/ + "movq %%mm2,(%[dst],%[dst_ystride])\n\t" + "pand %%mm7,%%mm3\n\t" + /*Start loading the next row.*/ + "movq (%[src1]),%%mm2\n\t" + "lea (%[dst],%[dst_ystride],2),%[dst]\n\t" + "psubb %%mm3,%%mm4\n\t" + "lea (%[src2],%[src_ystride],2),%[src2]\n\t" + /*%%mm4 (row 2) is done; write it out.*/ + "movq %%mm4,(%[dst])\n\t" + /*Continue loading the next row.*/ + "movq (%[src2]),%%mm3\n\t" + /*Start averaging %%mm0 and %%mm1 into %%mm6.*/ + "movq %%mm0,%%mm6\n\t" + "pxor %%mm1,%%mm0\n\t" + /*Start loading the next row.*/ + "movq (%[src1],%[src_ystride]),%%mm4\n\t" + "pavgb %%mm1,%%mm6\n\t" + /*%%mm1 is free; start averaging %%mm3 into %%mm2 using %%mm1.*/ + "movq %%mm2,%%mm1\n\t" + "pand %%mm7,%%mm0\n\t" + /*Continue loading the next row.*/ + "movq (%[src2],%[src_ystride]),%%mm5\n\t" + "pavgb %%mm3,%%mm2\n\t" + "lea (%[src1],%[src_ystride],2),%[src1]\n\t" + "pxor %%mm3,%%mm1\n\t" + /*%%mm3 is free.*/ + "psubb %%mm0,%%mm6\n\t" + /*%%mm0 is free, start loading the next row.*/ + "movq (%[src1]),%%mm0\n\t" + /*Start averaging %%mm5 into %%mm4 using %%mm3.*/ + "movq %%mm4,%%mm3\n\t" + /*%%mm6 (row 3) is done; write it out.*/ + "movq %%mm6,(%[dst],%[dst_ystride])\n\t" + "pand %%mm7,%%mm1\n\t" + "lea (%[src2],%[src_ystride],2),%[src2]\n\t" + "pavgb %%mm5,%%mm4\n\t" + "lea (%[dst],%[dst_ystride],2),%[dst]\n\t" + "psubb %%mm1,%%mm2\n\t" + /*%%mm1 is free; continue loading the next row.*/ + "movq (%[src2]),%%mm1\n\t" + "pxor %%mm5,%%mm3\n\t" + /*%%mm2 (row 4) is done; write it out.*/ + "movq %%mm2,(%[dst])\n\t" + "pand %%mm7,%%mm3\n\t" + /*Start loading the next row.*/ + "movq (%[src1],%[src_ystride]),%%mm2\n\t" + "psubb %%mm3,%%mm4\n\t" + /*Start averaging %%mm0 and %%mm1 into %%mm6.*/ + "movq %%mm0,%%mm6\n\t" + /*Continue loading the next row.*/ + "movq (%[src2],%[src_ystride]),%%mm3\n\t" + /*%%mm4 (row 5) is done; write it out.*/ + "movq %%mm4,(%[dst],%[dst_ystride])\n\t" + "pxor %%mm1,%%mm0\n\t" + "pavgb %%mm1,%%mm6\n\t" + /*%%mm4 is free; start averaging %%mm3 into %%mm2 using %%mm4.*/ + "movq %%mm2,%%mm4\n\t" + "pand %%mm7,%%mm0\n\t" + "pavgb %%mm3,%%mm2\n\t" + "pxor %%mm3,%%mm4\n\t" + "lea (%[dst],%[dst_ystride],2),%[dst]\n\t" + "psubb %%mm0,%%mm6\n\t" + "pand %%mm7,%%mm4\n\t" + /*%%mm6 (row 6) is done, write it out.*/ + "movq %%mm6,(%[dst])\n\t" + "psubb %%mm4,%%mm2\n\t" + /*%%mm2 (row 7) is done, write it out.*/ + "movq %%mm2,(%[dst],%[dst_ystride])\n\t" + :[dst]"+r"(_dst),[src1]"+%r"(_src1),[src2]"+r"(_src2) + :[dst_ystride]"r"((ptrdiff_t)_dst_ystride), + [src_ystride]"r"((ptrdiff_t)_src_ystride) + :"memory" + ); +} + +unsigned oc_enc_frag_satd2_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref1,const unsigned char *_ref2,int _ystride, + unsigned _thresh){ + OC_ALIGN8(unsigned char ref[64]); + oc_int_frag_copy2_mmxext(ref,8,_ref1,_ref2,_ystride); + return oc_int_frag_satd_thresh_mmxext(_src,_ystride,ref,8,_thresh); +} + +unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src, + int _ystride){ + OC_ALIGN8(ogg_int16_t buf[64]); + ogg_int16_t *bufp; + unsigned ret; + unsigned ret2; + bufp=buf; + __asm__ __volatile__( + OC_LOAD_8x4("0x00") + OC_HADAMARD_8x4 + OC_TRANSPOSE_4x4x2("0x00") + /*Finish swapping out this 8x4 block to make room for the next one. + mm0...mm3 have been swapped out already.*/ + "movq %%mm4,0x00(%[buf])\n\t" + "movq %%mm5,0x10(%[buf])\n\t" + "movq %%mm6,0x20(%[buf])\n\t" + "movq %%mm7,0x30(%[buf])\n\t" + OC_LOAD_8x4("0x04") + OC_HADAMARD_8x4 + OC_TRANSPOSE_4x4x2("0x08") + /*Here the first 4x4 block of output from the last transpose is the second + 4x4 block of input for the next transform. + We have cleverly arranged that it already be in the appropriate place, so + we only have to do half the loads.*/ + "movq 0x10(%[buf]),%%mm1\n\t" + "movq 0x20(%[buf]),%%mm2\n\t" + "movq 0x30(%[buf]),%%mm3\n\t" + "movq 0x00(%[buf]),%%mm0\n\t" + /*We split out the stages here so we can save the DC coefficient in the + middle.*/ + OC_HADAMARD_AB_8x4 + OC_HADAMARD_C_ABS_ACCUM_A_8x4("0x28","0x38") + "movd %%mm1,%[ret]\n\t" + OC_HADAMARD_C_ABS_ACCUM_B_8x4("0x28","0x38") + /*Up to this point, everything fit in 16 bits (8 input + 1 for the + difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1 + for the factor of two we dropped + 3 for the vertical accumulation). + Now we finally have to promote things to dwords. + We break this part out of OC_HADAMARD_ABS_ACCUM_8x4 to hide the long + latency of pmaddwd by starting the next series of loads now.*/ + "pmaddwd %%mm7,%%mm0\n\t" + "movq 0x50(%[buf]),%%mm1\n\t" + "movq 0x58(%[buf]),%%mm5\n\t" + "movq 0x60(%[buf]),%%mm2\n\t" + "movq %%mm0,%%mm4\n\t" + "movq 0x68(%[buf]),%%mm6\n\t" + "punpckhdq %%mm0,%%mm0\n\t" + "movq 0x70(%[buf]),%%mm3\n\t" + "paddd %%mm0,%%mm4\n\t" + "movq 0x78(%[buf]),%%mm7\n\t" + "movd %%mm4,%[ret2]\n\t" + "movq 0x40(%[buf]),%%mm0\n\t" + "movq 0x48(%[buf]),%%mm4\n\t" + OC_HADAMARD_ABS_ACCUM_8x4("0x68","0x78") + "pmaddwd %%mm7,%%mm0\n\t" + /*We assume that the DC coefficient is always positive (which is true, + because the input to the INTRA transform was not a difference).*/ + "movzx %w[ret],%[ret]\n\t" + "add %[ret2],%[ret2]\n\t" + "sub %[ret],%[ret2]\n\t" + "movq %%mm0,%%mm4\n\t" + "punpckhdq %%mm0,%%mm0\n\t" + "paddd %%mm0,%%mm4\n\t" + "movd %%mm4,%[ret]\n\t" + "lea -64(%[ret2],%[ret],2),%[ret]\n\t" + /*Although it looks like we're using 7 registers here, gcc can alias %[ret] + and %[ret2] with some of the inputs, since for once we don't write to + them until after we're done using everything but %[buf] (which is also + listed as an output to ensure gcc _doesn't_ alias them against it).*/ + :[ret]"=a"(ret),[ret2]"=r"(ret2),[buf]"+r"(bufp) + :[src]"r"(_src),[src4]"r"(_src+4*_ystride), + [ystride]"r"((ptrdiff_t)_ystride),[ystride3]"r"((ptrdiff_t)3*_ystride) + /*We have to use sub, so we actually clobber the condition codes for once + (not to mention add).*/ + :"cc" + ); + return ret; +} + +void oc_enc_frag_sub_mmx(ogg_int16_t _residue[64], + const unsigned char *_src,const unsigned char *_ref,int _ystride){ + int i; + __asm__ __volatile__("pxor %%mm7,%%mm7\n\t"::); + for(i=4;i-->0;){ + __asm__ __volatile__( + /*mm0=[src]*/ + "movq (%[src]),%%mm0\n\t" + /*mm1=[ref]*/ + "movq (%[ref]),%%mm1\n\t" + /*mm4=[src+ystride]*/ + "movq (%[src],%[ystride]),%%mm4\n\t" + /*mm5=[ref+ystride]*/ + "movq (%[ref],%[ystride]),%%mm5\n\t" + /*Compute [src]-[ref].*/ + "movq %%mm0,%%mm2\n\t" + "punpcklbw %%mm7,%%mm0\n\t" + "movq %%mm1,%%mm3\n\t" + "punpckhbw %%mm7,%%mm2\n\t" + "punpcklbw %%mm7,%%mm1\n\t" + "punpckhbw %%mm7,%%mm3\n\t" + "psubw %%mm1,%%mm0\n\t" + "psubw %%mm3,%%mm2\n\t" + /*Compute [src+ystride]-[ref+ystride].*/ + "movq %%mm4,%%mm1\n\t" + "punpcklbw %%mm7,%%mm4\n\t" + "movq %%mm5,%%mm3\n\t" + "punpckhbw %%mm7,%%mm1\n\t" + "lea (%[src],%[ystride],2),%[src]\n\t" + "punpcklbw %%mm7,%%mm5\n\t" + "lea (%[ref],%[ystride],2),%[ref]\n\t" + "punpckhbw %%mm7,%%mm3\n\t" + "psubw %%mm5,%%mm4\n\t" + "psubw %%mm3,%%mm1\n\t" + /*Write the answer out.*/ + "movq %%mm0,0x00(%[residue])\n\t" + "movq %%mm2,0x08(%[residue])\n\t" + "movq %%mm4,0x10(%[residue])\n\t" + "movq %%mm1,0x18(%[residue])\n\t" + "lea 0x20(%[residue]),%[residue]\n\t" + :[residue]"+r"(_residue),[src]"+r"(_src),[ref]"+r"(_ref) + :[ystride]"r"((ptrdiff_t)_ystride) + :"memory" + ); + } +} + +void oc_enc_frag_sub_128_mmx(ogg_int16_t _residue[64], + const unsigned char *_src,int _ystride){ + ptrdiff_t ystride3; + __asm__ __volatile__( + /*mm0=[src]*/ + "movq (%[src]),%%mm0\n\t" + /*mm1=[src+ystride]*/ + "movq (%[src],%[ystride]),%%mm1\n\t" + /*mm6={-1}x4*/ + "pcmpeqw %%mm6,%%mm6\n\t" + /*mm2=[src+2*ystride]*/ + "movq (%[src],%[ystride],2),%%mm2\n\t" + /*[ystride3]=3*[ystride]*/ + "lea (%[ystride],%[ystride],2),%[ystride3]\n\t" + /*mm6={1}x4*/ + "psllw $15,%%mm6\n\t" + /*mm3=[src+3*ystride]*/ + "movq (%[src],%[ystride3]),%%mm3\n\t" + /*mm6={128}x4*/ + "psrlw $8,%%mm6\n\t" + /*mm7=0*/ + "pxor %%mm7,%%mm7\n\t" + /*[src]=[src]+4*[ystride]*/ + "lea (%[src],%[ystride],4),%[src]\n\t" + /*Compute [src]-128 and [src+ystride]-128*/ + "movq %%mm0,%%mm4\n\t" + "punpcklbw %%mm7,%%mm0\n\t" + "movq %%mm1,%%mm5\n\t" + "punpckhbw %%mm7,%%mm4\n\t" + "psubw %%mm6,%%mm0\n\t" + "punpcklbw %%mm7,%%mm1\n\t" + "psubw %%mm6,%%mm4\n\t" + "punpckhbw %%mm7,%%mm5\n\t" + "psubw %%mm6,%%mm1\n\t" + "psubw %%mm6,%%mm5\n\t" + /*Write the answer out.*/ + "movq %%mm0,0x00(%[residue])\n\t" + "movq %%mm4,0x08(%[residue])\n\t" + "movq %%mm1,0x10(%[residue])\n\t" + "movq %%mm5,0x18(%[residue])\n\t" + /*mm0=[src+4*ystride]*/ + "movq (%[src]),%%mm0\n\t" + /*mm1=[src+5*ystride]*/ + "movq (%[src],%[ystride]),%%mm1\n\t" + /*Compute [src+2*ystride]-128 and [src+3*ystride]-128*/ + "movq %%mm2,%%mm4\n\t" + "punpcklbw %%mm7,%%mm2\n\t" + "movq %%mm3,%%mm5\n\t" + "punpckhbw %%mm7,%%mm4\n\t" + "psubw %%mm6,%%mm2\n\t" + "punpcklbw %%mm7,%%mm3\n\t" + "psubw %%mm6,%%mm4\n\t" + "punpckhbw %%mm7,%%mm5\n\t" + "psubw %%mm6,%%mm3\n\t" + "psubw %%mm6,%%mm5\n\t" + /*Write the answer out.*/ + "movq %%mm2,0x20(%[residue])\n\t" + "movq %%mm4,0x28(%[residue])\n\t" + "movq %%mm3,0x30(%[residue])\n\t" + "movq %%mm5,0x38(%[residue])\n\t" + /*mm2=[src+6*ystride]*/ + "movq (%[src],%[ystride],2),%%mm2\n\t" + /*mm3=[src+7*ystride]*/ + "movq (%[src],%[ystride3]),%%mm3\n\t" + /*Compute [src+4*ystride]-128 and [src+5*ystride]-128*/ + "movq %%mm0,%%mm4\n\t" + "punpcklbw %%mm7,%%mm0\n\t" + "movq %%mm1,%%mm5\n\t" + "punpckhbw %%mm7,%%mm4\n\t" + "psubw %%mm6,%%mm0\n\t" + "punpcklbw %%mm7,%%mm1\n\t" + "psubw %%mm6,%%mm4\n\t" + "punpckhbw %%mm7,%%mm5\n\t" + "psubw %%mm6,%%mm1\n\t" + "psubw %%mm6,%%mm5\n\t" + /*Write the answer out.*/ + "movq %%mm0,0x40(%[residue])\n\t" + "movq %%mm4,0x48(%[residue])\n\t" + "movq %%mm1,0x50(%[residue])\n\t" + "movq %%mm5,0x58(%[residue])\n\t" + /*Compute [src+6*ystride]-128 and [src+7*ystride]-128*/ + "movq %%mm2,%%mm4\n\t" + "punpcklbw %%mm7,%%mm2\n\t" + "movq %%mm3,%%mm5\n\t" + "punpckhbw %%mm7,%%mm4\n\t" + "psubw %%mm6,%%mm2\n\t" + "punpcklbw %%mm7,%%mm3\n\t" + "psubw %%mm6,%%mm4\n\t" + "punpckhbw %%mm7,%%mm5\n\t" + "psubw %%mm6,%%mm3\n\t" + "psubw %%mm6,%%mm5\n\t" + /*Write the answer out.*/ + "movq %%mm2,0x60(%[residue])\n\t" + "movq %%mm4,0x68(%[residue])\n\t" + "movq %%mm3,0x70(%[residue])\n\t" + "movq %%mm5,0x78(%[residue])\n\t" + :[src]"+r"(_src),[ystride3]"=&r"(ystride3) + :[residue]"r"(_residue),[ystride]"r"((ptrdiff_t)_ystride) + :"memory" + ); +} + +void oc_enc_frag_copy2_mmxext(unsigned char *_dst, + const unsigned char *_src1,const unsigned char *_src2,int _ystride){ + oc_int_frag_copy2_mmxext(_dst,_ystride,_src1,_src2,_ystride); +} + +#endif diff --git a/Engine/lib/libtheora/lib/x86/mmxfdct.c b/Engine/lib/libtheora/lib/x86/mmxfdct.c new file mode 100644 index 000000000..211875255 --- /dev/null +++ b/Engine/lib/libtheora/lib/x86/mmxfdct.c @@ -0,0 +1,665 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 1999-2006 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ********************************************************************/ +/*MMX fDCT implementation for x86_32*/ +/*$Id: fdct_ses2.c 14579 2008-03-12 06:42:40Z xiphmont $*/ +#include "x86enc.h" + +#if defined(OC_X86_ASM) + +# define OC_FDCT_STAGE1_8x4 \ + "#OC_FDCT_STAGE1_8x4\n\t" \ + /*Stage 1:*/ \ + /*mm0=t7'=t0-t7*/ \ + "psubw %%mm7,%%mm0\n\t" \ + "paddw %%mm7,%%mm7\n\t" \ + /*mm1=t6'=t1-t6*/ \ + "psubw %%mm6,%%mm1\n\t" \ + "paddw %%mm6,%%mm6\n\t" \ + /*mm2=t5'=t2-t5*/ \ + "psubw %%mm5,%%mm2\n\t" \ + "paddw %%mm5,%%mm5\n\t" \ + /*mm3=t4'=t3-t4*/ \ + "psubw %%mm4,%%mm3\n\t" \ + "paddw %%mm4,%%mm4\n\t" \ + /*mm7=t0'=t0+t7*/ \ + "paddw %%mm0,%%mm7\n\t" \ + /*mm6=t1'=t1+t6*/ \ + "paddw %%mm1,%%mm6\n\t" \ + /*mm5=t2'=t2+t5*/ \ + "paddw %%mm2,%%mm5\n\t" \ + /*mm4=t3'=t3+t4*/ \ + "paddw %%mm3,%%mm4\n\t" \ + +# define OC_FDCT8x4(_r0,_r1,_r2,_r3,_r4,_r5,_r6,_r7) \ + "#OC_FDCT8x4\n\t" \ + /*Stage 2:*/ \ + /*mm7=t3''=t0'-t3'*/ \ + "psubw %%mm4,%%mm7\n\t" \ + "paddw %%mm4,%%mm4\n\t" \ + /*mm6=t2''=t1'-t2'*/ \ + "psubw %%mm5,%%mm6\n\t" \ + "movq %%mm7,"_r6"(%[y])\n\t" \ + "paddw %%mm5,%%mm5\n\t" \ + /*mm1=t5''=t6'-t5'*/ \ + "psubw %%mm2,%%mm1\n\t" \ + "movq %%mm6,"_r2"(%[y])\n\t" \ + /*mm4=t0''=t0'+t3'*/ \ + "paddw %%mm7,%%mm4\n\t" \ + "paddw %%mm2,%%mm2\n\t" \ + /*mm5=t1''=t1'+t2'*/ \ + "movq %%mm4,"_r0"(%[y])\n\t" \ + "paddw %%mm6,%%mm5\n\t" \ + /*mm2=t6''=t6'+t5'*/ \ + "paddw %%mm1,%%mm2\n\t" \ + "movq %%mm5,"_r4"(%[y])\n\t" \ + /*mm0=t7', mm1=t5'', mm2=t6'', mm3=t4'.*/ \ + /*mm4, mm5, mm6, mm7 are free.*/ \ + /*Stage 3:*/ \ + /*mm6={2}x4, mm7={27146,0xB500>>1}x2*/ \ + "mov $0x5A806A0A,%[a]\n\t" \ + "pcmpeqb %%mm6,%%mm6\n\t" \ + "movd %[a],%%mm7\n\t" \ + "psrlw $15,%%mm6\n\t" \ + "punpckldq %%mm7,%%mm7\n\t" \ + "paddw %%mm6,%%mm6\n\t" \ + /*mm0=0, m2={-1}x4 \ + mm5:mm4=t5''*27146+0xB500*/ \ + "movq %%mm1,%%mm4\n\t" \ + "movq %%mm1,%%mm5\n\t" \ + "punpcklwd %%mm6,%%mm4\n\t" \ + "movq %%mm2,"_r3"(%[y])\n\t" \ + "pmaddwd %%mm7,%%mm4\n\t" \ + "movq %%mm0,"_r7"(%[y])\n\t" \ + "punpckhwd %%mm6,%%mm5\n\t" \ + "pxor %%mm0,%%mm0\n\t" \ + "pmaddwd %%mm7,%%mm5\n\t" \ + "pcmpeqb %%mm2,%%mm2\n\t" \ + /*mm2=t6'', mm1=t5''+(t5''!=0) \ + mm4=(t5''*27146+0xB500>>16)*/ \ + "pcmpeqw %%mm1,%%mm0\n\t" \ + "psrad $16,%%mm4\n\t" \ + "psubw %%mm2,%%mm0\n\t" \ + "movq "_r3"(%[y]),%%mm2\n\t" \ + "psrad $16,%%mm5\n\t" \ + "paddw %%mm0,%%mm1\n\t" \ + "packssdw %%mm5,%%mm4\n\t" \ + /*mm4=s=(t5''*27146+0xB500>>16)+t5''+(t5''!=0)>>1*/ \ + "paddw %%mm1,%%mm4\n\t" \ + "movq "_r7"(%[y]),%%mm0\n\t" \ + "psraw $1,%%mm4\n\t" \ + "movq %%mm3,%%mm1\n\t" \ + /*mm3=t4''=t4'+s*/ \ + "paddw %%mm4,%%mm3\n\t" \ + /*mm1=t5'''=t4'-s*/ \ + "psubw %%mm4,%%mm1\n\t" \ + /*mm1=0, mm3={-1}x4 \ + mm5:mm4=t6''*27146+0xB500*/ \ + "movq %%mm2,%%mm4\n\t" \ + "movq %%mm2,%%mm5\n\t" \ + "punpcklwd %%mm6,%%mm4\n\t" \ + "movq %%mm1,"_r5"(%[y])\n\t" \ + "pmaddwd %%mm7,%%mm4\n\t" \ + "movq %%mm3,"_r1"(%[y])\n\t" \ + "punpckhwd %%mm6,%%mm5\n\t" \ + "pxor %%mm1,%%mm1\n\t" \ + "pmaddwd %%mm7,%%mm5\n\t" \ + "pcmpeqb %%mm3,%%mm3\n\t" \ + /*mm2=t6''+(t6''!=0), mm4=(t6''*27146+0xB500>>16)*/ \ + "psrad $16,%%mm4\n\t" \ + "pcmpeqw %%mm2,%%mm1\n\t" \ + "psrad $16,%%mm5\n\t" \ + "psubw %%mm3,%%mm1\n\t" \ + "packssdw %%mm5,%%mm4\n\t" \ + "paddw %%mm1,%%mm2\n\t" \ + /*mm1=t1'' \ + mm4=s=(t6''*27146+0xB500>>16)+t6''+(t6''!=0)>>1*/ \ + "paddw %%mm2,%%mm4\n\t" \ + "movq "_r4"(%[y]),%%mm1\n\t" \ + "psraw $1,%%mm4\n\t" \ + "movq %%mm0,%%mm2\n\t" \ + /*mm7={54491-0x7FFF,0x7FFF}x2 \ + mm0=t7''=t7'+s*/ \ + "paddw %%mm4,%%mm0\n\t" \ + /*mm2=t6'''=t7'-s*/ \ + "psubw %%mm4,%%mm2\n\t" \ + /*Stage 4:*/ \ + /*mm0=0, mm2=t0'' \ + mm5:mm4=t1''*27146+0xB500*/ \ + "movq %%mm1,%%mm4\n\t" \ + "movq %%mm1,%%mm5\n\t" \ + "punpcklwd %%mm6,%%mm4\n\t" \ + "movq %%mm2,"_r3"(%[y])\n\t" \ + "pmaddwd %%mm7,%%mm4\n\t" \ + "movq "_r0"(%[y]),%%mm2\n\t" \ + "punpckhwd %%mm6,%%mm5\n\t" \ + "movq %%mm0,"_r7"(%[y])\n\t" \ + "pmaddwd %%mm7,%%mm5\n\t" \ + "pxor %%mm0,%%mm0\n\t" \ + /*mm7={27146,0x4000>>1}x2 \ + mm0=s=(t1''*27146+0xB500>>16)+t1''+(t1''!=0)*/ \ + "psrad $16,%%mm4\n\t" \ + "mov $0x20006A0A,%[a]\n\t" \ + "pcmpeqw %%mm1,%%mm0\n\t" \ + "movd %[a],%%mm7\n\t" \ + "psrad $16,%%mm5\n\t" \ + "psubw %%mm3,%%mm0\n\t" \ + "packssdw %%mm5,%%mm4\n\t" \ + "paddw %%mm1,%%mm0\n\t" \ + "punpckldq %%mm7,%%mm7\n\t" \ + "paddw %%mm4,%%mm0\n\t" \ + /*mm6={0x00000E3D}x2 \ + mm1=-(t0''==0), mm5:mm4=t0''*27146+0x4000*/ \ + "movq %%mm2,%%mm4\n\t" \ + "movq %%mm2,%%mm5\n\t" \ + "punpcklwd %%mm6,%%mm4\n\t" \ + "mov $0x0E3D,%[a]\n\t" \ + "pmaddwd %%mm7,%%mm4\n\t" \ + "punpckhwd %%mm6,%%mm5\n\t" \ + "movd %[a],%%mm6\n\t" \ + "pmaddwd %%mm7,%%mm5\n\t" \ + "pxor %%mm1,%%mm1\n\t" \ + "punpckldq %%mm6,%%mm6\n\t" \ + "pcmpeqw %%mm2,%%mm1\n\t" \ + /*mm4=r=(t0''*27146+0x4000>>16)+t0''+(t0''!=0)*/ \ + "psrad $16,%%mm4\n\t" \ + "psubw %%mm3,%%mm1\n\t" \ + "psrad $16,%%mm5\n\t" \ + "paddw %%mm1,%%mm2\n\t" \ + "packssdw %%mm5,%%mm4\n\t" \ + "movq "_r5"(%[y]),%%mm1\n\t" \ + "paddw %%mm2,%%mm4\n\t" \ + /*mm2=t6'', mm0=_y[0]=u=r+s>>1 \ + The naive implementation could cause overflow, so we use \ + u=(r&s)+((r^s)>>1).*/ \ + "movq "_r3"(%[y]),%%mm2\n\t" \ + "movq %%mm0,%%mm7\n\t" \ + "pxor %%mm4,%%mm0\n\t" \ + "pand %%mm4,%%mm7\n\t" \ + "psraw $1,%%mm0\n\t" \ + "mov $0x7FFF54DC,%[a]\n\t" \ + "paddw %%mm7,%%mm0\n\t" \ + "movd %[a],%%mm7\n\t" \ + /*mm7={54491-0x7FFF,0x7FFF}x2 \ + mm4=_y[4]=v=r-u*/ \ + "psubw %%mm0,%%mm4\n\t" \ + "punpckldq %%mm7,%%mm7\n\t" \ + "movq %%mm4,"_r4"(%[y])\n\t" \ + /*mm0=0, mm7={36410}x4 \ + mm1=(t5'''!=0), mm5:mm4=54491*t5'''+0x0E3D*/ \ + "movq %%mm1,%%mm4\n\t" \ + "movq %%mm1,%%mm5\n\t" \ + "punpcklwd %%mm1,%%mm4\n\t" \ + "mov $0x8E3A8E3A,%[a]\n\t" \ + "pmaddwd %%mm7,%%mm4\n\t" \ + "movq %%mm0,"_r0"(%[y])\n\t" \ + "punpckhwd %%mm1,%%mm5\n\t" \ + "pxor %%mm0,%%mm0\n\t" \ + "pmaddwd %%mm7,%%mm5\n\t" \ + "pcmpeqw %%mm0,%%mm1\n\t" \ + "movd %[a],%%mm7\n\t" \ + "psubw %%mm3,%%mm1\n\t" \ + "punpckldq %%mm7,%%mm7\n\t" \ + "paddd %%mm6,%%mm4\n\t" \ + "paddd %%mm6,%%mm5\n\t" \ + /*mm0=0 \ + mm3:mm1=36410*t6'''+((t5'''!=0)<<16)*/ \ + "movq %%mm2,%%mm6\n\t" \ + "movq %%mm2,%%mm3\n\t" \ + "pmulhw %%mm7,%%mm6\n\t" \ + "paddw %%mm2,%%mm1\n\t" \ + "pmullw %%mm7,%%mm3\n\t" \ + "pxor %%mm0,%%mm0\n\t" \ + "paddw %%mm1,%%mm6\n\t" \ + "movq %%mm3,%%mm1\n\t" \ + "punpckhwd %%mm6,%%mm3\n\t" \ + "punpcklwd %%mm6,%%mm1\n\t" \ + /*mm3={-1}x4, mm6={1}x4 \ + mm4=_y[5]=u=(54491*t5'''+36410*t6'''+0x0E3D>>16)+(t5'''!=0)*/ \ + "paddd %%mm3,%%mm5\n\t" \ + "paddd %%mm1,%%mm4\n\t" \ + "psrad $16,%%mm5\n\t" \ + "pxor %%mm6,%%mm6\n\t" \ + "psrad $16,%%mm4\n\t" \ + "pcmpeqb %%mm3,%%mm3\n\t" \ + "packssdw %%mm5,%%mm4\n\t" \ + "psubw %%mm3,%%mm6\n\t" \ + /*mm1=t7'', mm7={26568,0x3400}x2 \ + mm2=s=t6'''-(36410*u>>16)*/ \ + "movq %%mm4,%%mm1\n\t" \ + "mov $0x340067C8,%[a]\n\t" \ + "pmulhw %%mm7,%%mm4\n\t" \ + "movd %[a],%%mm7\n\t" \ + "movq %%mm1,"_r5"(%[y])\n\t" \ + "punpckldq %%mm7,%%mm7\n\t" \ + "paddw %%mm1,%%mm4\n\t" \ + "movq "_r7"(%[y]),%%mm1\n\t" \ + "psubw %%mm4,%%mm2\n\t" \ + /*mm6={0x00007B1B}x2 \ + mm0=(s!=0), mm5:mm4=s*26568+0x3400*/ \ + "movq %%mm2,%%mm4\n\t" \ + "movq %%mm2,%%mm5\n\t" \ + "punpcklwd %%mm6,%%mm4\n\t" \ + "pcmpeqw %%mm2,%%mm0\n\t" \ + "pmaddwd %%mm7,%%mm4\n\t" \ + "mov $0x7B1B,%[a]\n\t" \ + "punpckhwd %%mm6,%%mm5\n\t" \ + "movd %[a],%%mm6\n\t" \ + "pmaddwd %%mm7,%%mm5\n\t" \ + "psubw %%mm3,%%mm0\n\t" \ + "punpckldq %%mm6,%%mm6\n\t" \ + /*mm7={64277-0x7FFF,0x7FFF}x2 \ + mm2=_y[3]=v=(s*26568+0x3400>>17)+s+(s!=0)*/ \ + "psrad $17,%%mm4\n\t" \ + "paddw %%mm0,%%mm2\n\t" \ + "psrad $17,%%mm5\n\t" \ + "mov $0x7FFF7B16,%[a]\n\t" \ + "packssdw %%mm5,%%mm4\n\t" \ + "movd %[a],%%mm7\n\t" \ + "paddw %%mm4,%%mm2\n\t" \ + "punpckldq %%mm7,%%mm7\n\t" \ + /*mm0=0, mm7={12785}x4 \ + mm1=(t7''!=0), mm2=t4'', mm5:mm4=64277*t7''+0x7B1B*/ \ + "movq %%mm1,%%mm4\n\t" \ + "movq %%mm1,%%mm5\n\t" \ + "movq %%mm2,"_r3"(%[y])\n\t" \ + "punpcklwd %%mm1,%%mm4\n\t" \ + "movq "_r1"(%[y]),%%mm2\n\t" \ + "pmaddwd %%mm7,%%mm4\n\t" \ + "mov $0x31F131F1,%[a]\n\t" \ + "punpckhwd %%mm1,%%mm5\n\t" \ + "pxor %%mm0,%%mm0\n\t" \ + "pmaddwd %%mm7,%%mm5\n\t" \ + "pcmpeqw %%mm0,%%mm1\n\t" \ + "movd %[a],%%mm7\n\t" \ + "psubw %%mm3,%%mm1\n\t" \ + "punpckldq %%mm7,%%mm7\n\t" \ + "paddd %%mm6,%%mm4\n\t" \ + "paddd %%mm6,%%mm5\n\t" \ + /*mm3:mm1=12785*t4'''+((t7''!=0)<<16)*/ \ + "movq %%mm2,%%mm6\n\t" \ + "movq %%mm2,%%mm3\n\t" \ + "pmulhw %%mm7,%%mm6\n\t" \ + "pmullw %%mm7,%%mm3\n\t" \ + "paddw %%mm1,%%mm6\n\t" \ + "movq %%mm3,%%mm1\n\t" \ + "punpckhwd %%mm6,%%mm3\n\t" \ + "punpcklwd %%mm6,%%mm1\n\t" \ + /*mm3={-1}x4, mm6={1}x4 \ + mm4=_y[1]=u=(12785*t4'''+64277*t7''+0x7B1B>>16)+(t7''!=0)*/ \ + "paddd %%mm3,%%mm5\n\t" \ + "paddd %%mm1,%%mm4\n\t" \ + "psrad $16,%%mm5\n\t" \ + "pxor %%mm6,%%mm6\n\t" \ + "psrad $16,%%mm4\n\t" \ + "pcmpeqb %%mm3,%%mm3\n\t" \ + "packssdw %%mm5,%%mm4\n\t" \ + "psubw %%mm3,%%mm6\n\t" \ + /*mm1=t3'', mm7={20539,0x3000}x2 \ + mm4=s=(12785*u>>16)-t4''*/ \ + "movq %%mm4,"_r1"(%[y])\n\t" \ + "pmulhw %%mm7,%%mm4\n\t" \ + "mov $0x3000503B,%[a]\n\t" \ + "movq "_r6"(%[y]),%%mm1\n\t" \ + "movd %[a],%%mm7\n\t" \ + "psubw %%mm2,%%mm4\n\t" \ + "punpckldq %%mm7,%%mm7\n\t" \ + /*mm6={0x00006CB7}x2 \ + mm0=(s!=0), mm5:mm4=s*20539+0x3000*/ \ + "movq %%mm4,%%mm5\n\t" \ + "movq %%mm4,%%mm2\n\t" \ + "punpcklwd %%mm6,%%mm4\n\t" \ + "pcmpeqw %%mm2,%%mm0\n\t" \ + "pmaddwd %%mm7,%%mm4\n\t" \ + "mov $0x6CB7,%[a]\n\t" \ + "punpckhwd %%mm6,%%mm5\n\t" \ + "movd %[a],%%mm6\n\t" \ + "pmaddwd %%mm7,%%mm5\n\t" \ + "psubw %%mm3,%%mm0\n\t" \ + "punpckldq %%mm6,%%mm6\n\t" \ + /*mm7={60547-0x7FFF,0x7FFF}x2 \ + mm2=_y[7]=v=(s*20539+0x3000>>20)+s+(s!=0)*/ \ + "psrad $20,%%mm4\n\t" \ + "paddw %%mm0,%%mm2\n\t" \ + "psrad $20,%%mm5\n\t" \ + "mov $0x7FFF6C84,%[a]\n\t" \ + "packssdw %%mm5,%%mm4\n\t" \ + "movd %[a],%%mm7\n\t" \ + "paddw %%mm4,%%mm2\n\t" \ + "punpckldq %%mm7,%%mm7\n\t" \ + /*mm0=0, mm7={25080}x4 \ + mm2=t2'', mm5:mm4=60547*t3''+0x6CB7*/ \ + "movq %%mm1,%%mm4\n\t" \ + "movq %%mm1,%%mm5\n\t" \ + "movq %%mm2,"_r7"(%[y])\n\t" \ + "punpcklwd %%mm1,%%mm4\n\t" \ + "movq "_r2"(%[y]),%%mm2\n\t" \ + "pmaddwd %%mm7,%%mm4\n\t" \ + "mov $0x61F861F8,%[a]\n\t" \ + "punpckhwd %%mm1,%%mm5\n\t" \ + "pxor %%mm0,%%mm0\n\t" \ + "pmaddwd %%mm7,%%mm5\n\t" \ + "movd %[a],%%mm7\n\t" \ + "pcmpeqw %%mm0,%%mm1\n\t" \ + "psubw %%mm3,%%mm1\n\t" \ + "punpckldq %%mm7,%%mm7\n\t" \ + "paddd %%mm6,%%mm4\n\t" \ + "paddd %%mm6,%%mm5\n\t" \ + /*mm3:mm1=25080*t2''+((t3''!=0)<<16)*/ \ + "movq %%mm2,%%mm6\n\t" \ + "movq %%mm2,%%mm3\n\t" \ + "pmulhw %%mm7,%%mm6\n\t" \ + "pmullw %%mm7,%%mm3\n\t" \ + "paddw %%mm1,%%mm6\n\t" \ + "movq %%mm3,%%mm1\n\t" \ + "punpckhwd %%mm6,%%mm3\n\t" \ + "punpcklwd %%mm6,%%mm1\n\t" \ + /*mm1={-1}x4 \ + mm4=u=(25080*t2''+60547*t3''+0x6CB7>>16)+(t3''!=0)*/ \ + "paddd %%mm3,%%mm5\n\t" \ + "paddd %%mm1,%%mm4\n\t" \ + "psrad $16,%%mm5\n\t" \ + "mov $0x28005460,%[a]\n\t" \ + "psrad $16,%%mm4\n\t" \ + "pcmpeqb %%mm1,%%mm1\n\t" \ + "packssdw %%mm5,%%mm4\n\t" \ + /*mm5={1}x4, mm6=_y[2]=u, mm7={21600,0x2800}x2 \ + mm4=s=(25080*u>>16)-t2''*/ \ + "movq %%mm4,%%mm6\n\t" \ + "pmulhw %%mm7,%%mm4\n\t" \ + "pxor %%mm5,%%mm5\n\t" \ + "movd %[a],%%mm7\n\t" \ + "psubw %%mm1,%%mm5\n\t" \ + "punpckldq %%mm7,%%mm7\n\t" \ + "psubw %%mm2,%%mm4\n\t" \ + /*mm2=s+(s!=0) \ + mm4:mm3=s*21600+0x2800*/ \ + "movq %%mm4,%%mm3\n\t" \ + "movq %%mm4,%%mm2\n\t" \ + "punpckhwd %%mm5,%%mm4\n\t" \ + "pcmpeqw %%mm2,%%mm0\n\t" \ + "pmaddwd %%mm7,%%mm4\n\t" \ + "psubw %%mm1,%%mm0\n\t" \ + "punpcklwd %%mm5,%%mm3\n\t" \ + "paddw %%mm0,%%mm2\n\t" \ + "pmaddwd %%mm7,%%mm3\n\t" \ + /*mm0=_y[4], mm1=_y[7], mm4=_y[0], mm5=_y[5] \ + mm3=_y[6]=v=(s*21600+0x2800>>18)+s+(s!=0)*/ \ + "movq "_r4"(%[y]),%%mm0\n\t" \ + "psrad $18,%%mm4\n\t" \ + "movq "_r5"(%[y]),%%mm5\n\t" \ + "psrad $18,%%mm3\n\t" \ + "movq "_r7"(%[y]),%%mm1\n\t" \ + "packssdw %%mm4,%%mm3\n\t" \ + "movq "_r0"(%[y]),%%mm4\n\t" \ + "paddw %%mm2,%%mm3\n\t" \ + +/*On input, mm4=_y[0], mm6=_y[2], mm0=_y[4], mm5=_y[5], mm3=_y[6], mm1=_y[7]. + On output, {_y[4],mm1,mm2,mm3} contains the transpose of _y[4...7] and + {mm4,mm5,mm6,mm7} contains the transpose of _y[0...3].*/ +# define OC_TRANSPOSE8x4(_r0,_r1,_r2,_r3,_r4,_r5,_r6,_r7) \ + "#OC_TRANSPOSE8x4\n\t" \ + /*First 4x4 transpose:*/ \ + /*mm0 = e3 e2 e1 e0 \ + mm5 = f3 f2 f1 f0 \ + mm3 = g3 g2 g1 g0 \ + mm1 = h3 h2 h1 h0*/ \ + "movq %%mm0,%%mm2\n\t" \ + "punpcklwd %%mm5,%%mm0\n\t" \ + "punpckhwd %%mm5,%%mm2\n\t" \ + "movq %%mm3,%%mm5\n\t" \ + "punpcklwd %%mm1,%%mm3\n\t" \ + "punpckhwd %%mm1,%%mm5\n\t" \ + /*mm0 = f1 e1 f0 e0 \ + mm2 = f3 e3 f2 e2 \ + mm3 = h1 g1 h0 g0 \ + mm5 = h3 g3 h2 g2*/ \ + "movq %%mm0,%%mm1\n\t" \ + "punpckldq %%mm3,%%mm0\n\t" \ + "movq %%mm0,"_r4"(%[y])\n\t" \ + "punpckhdq %%mm3,%%mm1\n\t" \ + "movq "_r1"(%[y]),%%mm0\n\t" \ + "movq %%mm2,%%mm3\n\t" \ + "punpckldq %%mm5,%%mm2\n\t" \ + "punpckhdq %%mm5,%%mm3\n\t" \ + "movq "_r3"(%[y]),%%mm5\n\t" \ + /*_y[4] = h0 g0 f0 e0 \ + mm1 = h1 g1 f1 e1 \ + mm2 = h2 g2 f2 e2 \ + mm3 = h3 g3 f3 e3*/ \ + /*Second 4x4 transpose:*/ \ + /*mm4 = a3 a2 a1 a0 \ + mm0 = b3 b2 b1 b0 \ + mm6 = c3 c2 c1 c0 \ + mm5 = d3 d2 d1 d0*/ \ + "movq %%mm4,%%mm7\n\t" \ + "punpcklwd %%mm0,%%mm4\n\t" \ + "punpckhwd %%mm0,%%mm7\n\t" \ + "movq %%mm6,%%mm0\n\t" \ + "punpcklwd %%mm5,%%mm6\n\t" \ + "punpckhwd %%mm5,%%mm0\n\t" \ + /*mm4 = b1 a1 b0 a0 \ + mm7 = b3 a3 b2 a2 \ + mm6 = d1 c1 d0 c0 \ + mm0 = d3 c3 d2 c2*/ \ + "movq %%mm4,%%mm5\n\t" \ + "punpckldq %%mm6,%%mm4\n\t" \ + "punpckhdq %%mm6,%%mm5\n\t" \ + "movq %%mm7,%%mm6\n\t" \ + "punpckhdq %%mm0,%%mm7\n\t" \ + "punpckldq %%mm0,%%mm6\n\t" \ + /*mm4 = d0 c0 b0 a0 \ + mm5 = d1 c1 b1 a1 \ + mm6 = d2 c2 b2 a2 \ + mm7 = d3 c3 b3 a3*/ \ + +/*MMX implementation of the fDCT.*/ +void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]){ + ptrdiff_t a; + __asm__ __volatile__( + /*Add two extra bits of working precision to improve accuracy; any more and + we could overflow.*/ + /*We also add biases to correct for some systematic error that remains in + the full fDCT->iDCT round trip.*/ + "movq 0x00(%[x]),%%mm0\n\t" + "movq 0x10(%[x]),%%mm1\n\t" + "movq 0x20(%[x]),%%mm2\n\t" + "movq 0x30(%[x]),%%mm3\n\t" + "pcmpeqb %%mm4,%%mm4\n\t" + "pxor %%mm7,%%mm7\n\t" + "movq %%mm0,%%mm5\n\t" + "psllw $2,%%mm0\n\t" + "pcmpeqw %%mm7,%%mm5\n\t" + "movq 0x70(%[x]),%%mm7\n\t" + "psllw $2,%%mm1\n\t" + "psubw %%mm4,%%mm5\n\t" + "psllw $2,%%mm2\n\t" + "mov $1,%[a]\n\t" + "pslld $16,%%mm5\n\t" + "movd %[a],%%mm6\n\t" + "psllq $16,%%mm5\n\t" + "mov $0x10001,%[a]\n\t" + "psllw $2,%%mm3\n\t" + "movd %[a],%%mm4\n\t" + "punpckhwd %%mm6,%%mm5\n\t" + "psubw %%mm6,%%mm1\n\t" + "movq 0x60(%[x]),%%mm6\n\t" + "paddw %%mm5,%%mm0\n\t" + "movq 0x50(%[x]),%%mm5\n\t" + "paddw %%mm4,%%mm0\n\t" + "movq 0x40(%[x]),%%mm4\n\t" + /*We inline stage1 of the transform here so we can get better instruction + scheduling with the shifts.*/ + /*mm0=t7'=t0-t7*/ + "psllw $2,%%mm7\n\t" + "psubw %%mm7,%%mm0\n\t" + "psllw $2,%%mm6\n\t" + "paddw %%mm7,%%mm7\n\t" + /*mm1=t6'=t1-t6*/ + "psllw $2,%%mm5\n\t" + "psubw %%mm6,%%mm1\n\t" + "psllw $2,%%mm4\n\t" + "paddw %%mm6,%%mm6\n\t" + /*mm2=t5'=t2-t5*/ + "psubw %%mm5,%%mm2\n\t" + "paddw %%mm5,%%mm5\n\t" + /*mm3=t4'=t3-t4*/ + "psubw %%mm4,%%mm3\n\t" + "paddw %%mm4,%%mm4\n\t" + /*mm7=t0'=t0+t7*/ + "paddw %%mm0,%%mm7\n\t" + /*mm6=t1'=t1+t6*/ + "paddw %%mm1,%%mm6\n\t" + /*mm5=t2'=t2+t5*/ + "paddw %%mm2,%%mm5\n\t" + /*mm4=t3'=t3+t4*/ + "paddw %%mm3,%%mm4\n\t" + OC_FDCT8x4("0x00","0x10","0x20","0x30","0x40","0x50","0x60","0x70") + OC_TRANSPOSE8x4("0x00","0x10","0x20","0x30","0x40","0x50","0x60","0x70") + /*Swap out this 8x4 block for the next one.*/ + "movq 0x08(%[x]),%%mm0\n\t" + "movq %%mm7,0x30(%[y])\n\t" + "movq 0x78(%[x]),%%mm7\n\t" + "movq %%mm1,0x50(%[y])\n\t" + "movq 0x18(%[x]),%%mm1\n\t" + "movq %%mm6,0x20(%[y])\n\t" + "movq 0x68(%[x]),%%mm6\n\t" + "movq %%mm2,0x60(%[y])\n\t" + "movq 0x28(%[x]),%%mm2\n\t" + "movq %%mm5,0x10(%[y])\n\t" + "movq 0x58(%[x]),%%mm5\n\t" + "movq %%mm3,0x70(%[y])\n\t" + "movq 0x38(%[x]),%%mm3\n\t" + /*And increase its working precision, too.*/ + "psllw $2,%%mm0\n\t" + "movq %%mm4,0x00(%[y])\n\t" + "psllw $2,%%mm7\n\t" + "movq 0x48(%[x]),%%mm4\n\t" + /*We inline stage1 of the transform here so we can get better instruction + scheduling with the shifts.*/ + /*mm0=t7'=t0-t7*/ + "psubw %%mm7,%%mm0\n\t" + "psllw $2,%%mm1\n\t" + "paddw %%mm7,%%mm7\n\t" + "psllw $2,%%mm6\n\t" + /*mm1=t6'=t1-t6*/ + "psubw %%mm6,%%mm1\n\t" + "psllw $2,%%mm2\n\t" + "paddw %%mm6,%%mm6\n\t" + "psllw $2,%%mm5\n\t" + /*mm2=t5'=t2-t5*/ + "psubw %%mm5,%%mm2\n\t" + "psllw $2,%%mm3\n\t" + "paddw %%mm5,%%mm5\n\t" + "psllw $2,%%mm4\n\t" + /*mm3=t4'=t3-t4*/ + "psubw %%mm4,%%mm3\n\t" + "paddw %%mm4,%%mm4\n\t" + /*mm7=t0'=t0+t7*/ + "paddw %%mm0,%%mm7\n\t" + /*mm6=t1'=t1+t6*/ + "paddw %%mm1,%%mm6\n\t" + /*mm5=t2'=t2+t5*/ + "paddw %%mm2,%%mm5\n\t" + /*mm4=t3'=t3+t4*/ + "paddw %%mm3,%%mm4\n\t" + OC_FDCT8x4("0x08","0x18","0x28","0x38","0x48","0x58","0x68","0x78") + OC_TRANSPOSE8x4("0x08","0x18","0x28","0x38","0x48","0x58","0x68","0x78") + /*Here the first 4x4 block of output from the last transpose is the second + 4x4 block of input for the next transform. + We have cleverly arranged that it already be in the appropriate place, + so we only have to do half the stores and loads.*/ + "movq 0x00(%[y]),%%mm0\n\t" + "movq %%mm1,0x58(%[y])\n\t" + "movq 0x10(%[y]),%%mm1\n\t" + "movq %%mm2,0x68(%[y])\n\t" + "movq 0x20(%[y]),%%mm2\n\t" + "movq %%mm3,0x78(%[y])\n\t" + "movq 0x30(%[y]),%%mm3\n\t" + OC_FDCT_STAGE1_8x4 + OC_FDCT8x4("0x00","0x10","0x20","0x30","0x08","0x18","0x28","0x38") + OC_TRANSPOSE8x4("0x00","0x10","0x20","0x30","0x08","0x18","0x28","0x38") + /*mm0={-2}x4*/ + "pcmpeqw %%mm0,%%mm0\n\t" + "paddw %%mm0,%%mm0\n\t" + /*Round the results.*/ + "psubw %%mm0,%%mm1\n\t" + "psubw %%mm0,%%mm2\n\t" + "psraw $2,%%mm1\n\t" + "psubw %%mm0,%%mm3\n\t" + "movq %%mm1,0x18(%[y])\n\t" + "psraw $2,%%mm2\n\t" + "psubw %%mm0,%%mm4\n\t" + "movq 0x08(%[y]),%%mm1\n\t" + "psraw $2,%%mm3\n\t" + "psubw %%mm0,%%mm5\n\t" + "psraw $2,%%mm4\n\t" + "psubw %%mm0,%%mm6\n\t" + "psraw $2,%%mm5\n\t" + "psubw %%mm0,%%mm7\n\t" + "psraw $2,%%mm6\n\t" + "psubw %%mm0,%%mm1\n\t" + "psraw $2,%%mm7\n\t" + "movq 0x40(%[y]),%%mm0\n\t" + "psraw $2,%%mm1\n\t" + "movq %%mm7,0x30(%[y])\n\t" + "movq 0x78(%[y]),%%mm7\n\t" + "movq %%mm1,0x08(%[y])\n\t" + "movq 0x50(%[y]),%%mm1\n\t" + "movq %%mm6,0x20(%[y])\n\t" + "movq 0x68(%[y]),%%mm6\n\t" + "movq %%mm2,0x28(%[y])\n\t" + "movq 0x60(%[y]),%%mm2\n\t" + "movq %%mm5,0x10(%[y])\n\t" + "movq 0x58(%[y]),%%mm5\n\t" + "movq %%mm3,0x38(%[y])\n\t" + "movq 0x70(%[y]),%%mm3\n\t" + "movq %%mm4,0x00(%[y])\n\t" + "movq 0x48(%[y]),%%mm4\n\t" + OC_FDCT_STAGE1_8x4 + OC_FDCT8x4("0x40","0x50","0x60","0x70","0x48","0x58","0x68","0x78") + OC_TRANSPOSE8x4("0x40","0x50","0x60","0x70","0x48","0x58","0x68","0x78") + /*mm0={-2}x4*/ + "pcmpeqw %%mm0,%%mm0\n\t" + "paddw %%mm0,%%mm0\n\t" + /*Round the results.*/ + "psubw %%mm0,%%mm1\n\t" + "psubw %%mm0,%%mm2\n\t" + "psraw $2,%%mm1\n\t" + "psubw %%mm0,%%mm3\n\t" + "movq %%mm1,0x58(%[y])\n\t" + "psraw $2,%%mm2\n\t" + "psubw %%mm0,%%mm4\n\t" + "movq 0x48(%[y]),%%mm1\n\t" + "psraw $2,%%mm3\n\t" + "psubw %%mm0,%%mm5\n\t" + "movq %%mm2,0x68(%[y])\n\t" + "psraw $2,%%mm4\n\t" + "psubw %%mm0,%%mm6\n\t" + "movq %%mm3,0x78(%[y])\n\t" + "psraw $2,%%mm5\n\t" + "psubw %%mm0,%%mm7\n\t" + "movq %%mm4,0x40(%[y])\n\t" + "psraw $2,%%mm6\n\t" + "psubw %%mm0,%%mm1\n\t" + "movq %%mm5,0x50(%[y])\n\t" + "psraw $2,%%mm7\n\t" + "movq %%mm6,0x60(%[y])\n\t" + "psraw $2,%%mm1\n\t" + "movq %%mm7,0x70(%[y])\n\t" + "movq %%mm1,0x48(%[y])\n\t" + :[a]"=&r"(a) + :[y]"r"(_y),[x]"r"(_x) + :"memory" + ); +} + +#endif diff --git a/Engine/lib/libtheora/lib/dec/x86/mmxfrag.c b/Engine/lib/libtheora/lib/x86/mmxfrag.c similarity index 83% rename from Engine/lib/libtheora/lib/dec/x86/mmxfrag.c rename to Engine/lib/libtheora/lib/x86/mmxfrag.c index b4f8167a6..2c732939c 100644 --- a/Engine/lib/libtheora/lib/dec/x86/mmxfrag.c +++ b/Engine/lib/libtheora/lib/x86/mmxfrag.c @@ -5,13 +5,13 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: mmxfrag.c 15400 2008-10-15 12:10:58Z tterribe $ + last mod: $Id: mmxfrag.c 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ @@ -20,12 +20,20 @@ Additional optimization by Nils Pipenbrinck. Note: Loops are unrolled for best performance. The iteration each instruction belongs to is marked in the comments as #i.*/ -#include "x86int.h" #include +#include "x86int.h" +#include "mmxfrag.h" -#if defined(USE_ASM) +#if defined(OC_X86_ASM) -void oc_frag_recon_intra_mmx(unsigned char *_dst,int _dst_ystride, +/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes + between rows.*/ +void oc_frag_copy_mmx(unsigned char *_dst, + const unsigned char *_src,int _ystride){ + OC_FRAG_COPY_MMX(_dst,_src,_ystride); +} + +void oc_frag_recon_intra_mmx(unsigned char *_dst,int _ystride, const ogg_int16_t *_residue){ __asm__ __volatile__( /*Set mm0 to 0xFFFFFFFFFFFFFFFF.*/ @@ -67,9 +75,9 @@ void oc_frag_recon_intra_mmx(unsigned char *_dst,int _dst_ystride, /*#0 Write row.*/ "movq %%mm1,(%[dst])\n\t" /*#1 Write row.*/ - "movq %%mm3,(%[dst],%[dst_ystride])\n\t" + "movq %%mm3,(%[dst],%[ystride])\n\t" /*#2 Write row.*/ - "movq %%mm5,(%[dst],%[dst_ystride],2)\n\t" + "movq %%mm5,(%[dst],%[ystride],2)\n\t" /*#3 Load low residue.*/ "movq 6*8(%[residue]),%%mm1\n\t" /*#3 Load high residue.*/ @@ -101,11 +109,11 @@ void oc_frag_recon_intra_mmx(unsigned char *_dst,int _dst_ystride, /*#5 Pack to byte.*/ "packuswb %%mm6,%%mm5\n\t" /*#3 Write row.*/ - "movq %%mm1,(%[dst],%[dst_ystride3])\n\t" + "movq %%mm1,(%[dst],%[ystride3])\n\t" /*#4 Write row.*/ "movq %%mm3,(%[dst4])\n\t" /*#5 Write row.*/ - "movq %%mm5,(%[dst4],%[dst_ystride])\n\t" + "movq %%mm5,(%[dst4],%[ystride])\n\t" /*#6 Load low residue.*/ "movq 12*8(%[residue]),%%mm1\n\t" /*#6 Load high residue.*/ @@ -127,21 +135,21 @@ void oc_frag_recon_intra_mmx(unsigned char *_dst,int _dst_ystride, /*#7 Pack to byte.*/ "packuswb %%mm4,%%mm3\n\t" /*#6 Write row.*/ - "movq %%mm1,(%[dst4],%[dst_ystride],2)\n\t" + "movq %%mm1,(%[dst4],%[ystride],2)\n\t" /*#7 Write row.*/ - "movq %%mm3,(%[dst4],%[dst_ystride3])\n\t" + "movq %%mm3,(%[dst4],%[ystride3])\n\t" : :[residue]"r"(_residue), [dst]"r"(_dst), - [dst4]"r"(_dst+(_dst_ystride<<2)), - [dst_ystride]"r"((ptrdiff_t)_dst_ystride), - [dst_ystride3]"r"((ptrdiff_t)_dst_ystride*3) + [dst4]"r"(_dst+(_ystride<<2)), + [ystride]"r"((ptrdiff_t)_ystride), + [ystride3]"r"((ptrdiff_t)_ystride*3) :"memory" ); } -void oc_frag_recon_inter_mmx(unsigned char *_dst,int _dst_ystride, - const unsigned char *_src,int _src_ystride,const ogg_int16_t *_residue){ +void oc_frag_recon_inter_mmx(unsigned char *_dst,const unsigned char *_src, + int _ystride,const ogg_int16_t *_residue){ int i; /*Zero mm0.*/ __asm__ __volatile__("pxor %%mm0,%%mm0\n\t"::); @@ -150,7 +158,7 @@ void oc_frag_recon_inter_mmx(unsigned char *_dst,int _dst_ystride, /*#0 Load source.*/ "movq (%[src]),%%mm3\n\t" /*#1 Load source.*/ - "movq (%[src],%[src_ystride]),%%mm7\n\t" + "movq (%[src],%[ystride]),%%mm7\n\t" /*#0 Get copy of src.*/ "movq %%mm3,%%mm4\n\t" /*#0 Expand high source.*/ @@ -178,29 +186,23 @@ void oc_frag_recon_inter_mmx(unsigned char *_dst,int _dst_ystride, /*#1 Pack final row pixels.*/ "packuswb %%mm2,%%mm7\n\t" /*Advance src.*/ - "lea (%[src],%[src_ystride],2),%[src]\n\t" + "lea (%[src],%[ystride],2),%[src]\n\t" /*#0 Write row.*/ "movq %%mm3,(%[dst])\n\t" /*#1 Write row.*/ - "movq %%mm7,(%[dst],%[dst_ystride])\n\t" + "movq %%mm7,(%[dst],%[ystride])\n\t" /*Advance dst.*/ - "lea (%[dst],%[dst_ystride],2),%[dst]\n\t" + "lea (%[dst],%[ystride],2),%[dst]\n\t" :[residue]"+r"(_residue),[dst]"+r"(_dst),[src]"+r"(_src) - :[dst_ystride]"r"((ptrdiff_t)_dst_ystride), - [src_ystride]"r"((ptrdiff_t)_src_ystride) + :[ystride]"r"((ptrdiff_t)_ystride) :"memory" ); } } -void oc_frag_recon_inter2_mmx(unsigned char *_dst,int _dst_ystride, - const unsigned char *_src1,int _src1_ystride,const unsigned char *_src2, - int _src2_ystride,const ogg_int16_t *_residue){ +void oc_frag_recon_inter2_mmx(unsigned char *_dst,const unsigned char *_src1, + const unsigned char *_src2,int _ystride,const ogg_int16_t *_residue){ int i; - /*NOTE: This assumes that - _dst_ystride==_src1_ystride&&_dst_ystride==_src2_ystride. - This is currently always the case, but a slower fallback version will need - to be written if it ever is not.*/ /*Zero mm7.*/ __asm__ __volatile__("pxor %%mm7,%%mm7\n\t"::); for(i=4;i-->0;){ @@ -278,8 +280,8 @@ void oc_frag_recon_inter2_mmx(unsigned char *_dst,int _dst_ystride, /*Advance dest ptr.*/ "lea (%[dst],%[ystride],2),%[dst]\n\t" :[dst]"+r"(_dst),[residue]"+r"(_residue), - [src1]"+r"(_src1),[src2]"+r"(_src2) - :[ystride]"r"((ptrdiff_t)_dst_ystride) + [src1]"+%r"(_src1),[src2]"+r"(_src2) + :[ystride]"r"((ptrdiff_t)_ystride) :"memory" ); } diff --git a/Engine/lib/libtheora/lib/x86/mmxfrag.h b/Engine/lib/libtheora/lib/x86/mmxfrag.h new file mode 100644 index 000000000..a39842762 --- /dev/null +++ b/Engine/lib/libtheora/lib/x86/mmxfrag.h @@ -0,0 +1,64 @@ +#if !defined(_x86_mmxfrag_H) +# define _x86_mmxfrag_H (1) +# include +# include "x86int.h" + +#if defined(OC_X86_ASM) + +/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes + between rows.*/ +#define OC_FRAG_COPY_MMX(_dst,_src,_ystride) \ + do{ \ + const unsigned char *src; \ + unsigned char *dst; \ + ptrdiff_t ystride3; \ + src=(_src); \ + dst=(_dst); \ + __asm__ __volatile__( \ + /*src+0*ystride*/ \ + "movq (%[src]),%%mm0\n\t" \ + /*src+1*ystride*/ \ + "movq (%[src],%[ystride]),%%mm1\n\t" \ + /*ystride3=ystride*3*/ \ + "lea (%[ystride],%[ystride],2),%[ystride3]\n\t" \ + /*src+2*ystride*/ \ + "movq (%[src],%[ystride],2),%%mm2\n\t" \ + /*src+3*ystride*/ \ + "movq (%[src],%[ystride3]),%%mm3\n\t" \ + /*dst+0*ystride*/ \ + "movq %%mm0,(%[dst])\n\t" \ + /*dst+1*ystride*/ \ + "movq %%mm1,(%[dst],%[ystride])\n\t" \ + /*Pointer to next 4.*/ \ + "lea (%[src],%[ystride],4),%[src]\n\t" \ + /*dst+2*ystride*/ \ + "movq %%mm2,(%[dst],%[ystride],2)\n\t" \ + /*dst+3*ystride*/ \ + "movq %%mm3,(%[dst],%[ystride3])\n\t" \ + /*Pointer to next 4.*/ \ + "lea (%[dst],%[ystride],4),%[dst]\n\t" \ + /*src+0*ystride*/ \ + "movq (%[src]),%%mm0\n\t" \ + /*src+1*ystride*/ \ + "movq (%[src],%[ystride]),%%mm1\n\t" \ + /*src+2*ystride*/ \ + "movq (%[src],%[ystride],2),%%mm2\n\t" \ + /*src+3*ystride*/ \ + "movq (%[src],%[ystride3]),%%mm3\n\t" \ + /*dst+0*ystride*/ \ + "movq %%mm0,(%[dst])\n\t" \ + /*dst+1*ystride*/ \ + "movq %%mm1,(%[dst],%[ystride])\n\t" \ + /*dst+2*ystride*/ \ + "movq %%mm2,(%[dst],%[ystride],2)\n\t" \ + /*dst+3*ystride*/ \ + "movq %%mm3,(%[dst],%[ystride3])\n\t" \ + :[dst]"+r"(dst),[src]"+r"(src),[ystride3]"=&r"(ystride3) \ + :[ystride]"r"((ptrdiff_t)(_ystride)) \ + :"memory" \ + ); \ + } \ + while(0) + +# endif +#endif diff --git a/Engine/lib/libtheora/lib/dec/x86/mmxidct.c b/Engine/lib/libtheora/lib/x86/mmxidct.c similarity index 86% rename from Engine/lib/libtheora/lib/dec/x86/mmxidct.c rename to Engine/lib/libtheora/lib/x86/mmxidct.c index 5dbbe201a..76424e636 100644 --- a/Engine/lib/libtheora/lib/dec/x86/mmxidct.c +++ b/Engine/lib/libtheora/lib/x86/mmxidct.c @@ -5,25 +5,22 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: mmxidct.c 15400 2008-10-15 12:10:58Z tterribe $ + last mod: $Id: mmxidct.c 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ /*MMX acceleration of Theora's iDCT. Originally written by Rudolf Marek, based on code from On2's VP3.*/ -#include -#include "../dct.h" -#include "../idct.h" - #include "x86int.h" +#include "../dct.h" -#if defined(USE_ASM) +#if defined(OC_X86_ASM) /*These are offsets into the table of constants below.*/ /*7 rows of cosines, in order: pi/16 * (1 ... 7).*/ @@ -194,7 +191,7 @@ static const ogg_uint16_t __attribute__((aligned(8),used)) J(7) = h3 g3 f3 e3 I(0) I(1) I(2) I(3) is the transpose of r0 I(1) r2 r3. - J(4) J(5) J(6) J(7) is the transpose of r4 r5 r6 r7. + J(4) J(5) J(6) J(7) is the transpose of r4 r5 r6 r7. Since r1 is free at entry, we calculate the Js first.*/ /*19 cycles.*/ @@ -313,9 +310,9 @@ static const ogg_uint16_t __attribute__((aligned(8),used)) #define OC_C(_i) OC_MID(OC_COSINE_OFFSET,_i-1) #define OC_8 OC_MID(OC_EIGHT_OFFSET,0) -void oc_idct8x8_mmx(ogg_int16_t _y[64]){ - /*This routine accepts an 8x8 matrix, but in transposed form. - Every 4x4 submatrix is transposed.*/ +static void oc_idct8x8_slow(ogg_int16_t _y[64]){ + /*This routine accepts an 8x8 matrix, but in partially transposed form. + Every 4x4 block is transposed.*/ __asm__ __volatile__( #define OC_I(_k) OC_M2STR((_k*16))"(%[y])" #define OC_J(_k) OC_M2STR(((_k-4)*16)+8)"(%[y])" @@ -339,7 +336,6 @@ void oc_idct8x8_mmx(ogg_int16_t _y[64]){ OC_COLUMN_IDCT #undef OC_I #undef OC_J - "emms\n\t" : :[y]"r"(_y),[c]"r"(OC_IDCT_CONSTS) ); @@ -507,7 +503,7 @@ void oc_idct8x8_mmx(ogg_int16_t _y[64]){ "movq %%mm0,"OC_I(0)"\n\t" \ "#end OC_COLUMN_IDCT_10\n\t" \ -void oc_idct8x8_10_mmx(ogg_int16_t _y[64]){ +static void oc_idct8x8_10(ogg_int16_t _y[64]){ __asm__ __volatile__( #define OC_I(_k) OC_M2STR((_k*16))"(%[y])" #define OC_J(_k) OC_M2STR(((_k-4)*16)+8)"(%[y])" @@ -527,9 +523,42 @@ void oc_idct8x8_10_mmx(ogg_int16_t _y[64]){ OC_COLUMN_IDCT_10 #undef OC_I #undef OC_J - "emms\n\t" : :[y]"r"(_y),[c]"r"(OC_IDCT_CONSTS) ); } + +/*Performs an inverse 8x8 Type-II DCT transform. + The input is assumed to be scaled by a factor of 4 relative to orthonormal + version of the transform.*/ +void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi){ + /*_last_zzi is subtly different from an actual count of the number of + coefficients we decoded for this block. + It contains the value of zzi BEFORE the final token in the block was + decoded. + In most cases this is an EOB token (the continuation of an EOB run from a + previous block counts), and so this is the same as the coefficient count. + However, in the case that the last token was NOT an EOB token, but filled + the block up with exactly 64 coefficients, _last_zzi will be less than 64. + Provided the last token was not a pure zero run, the minimum value it can + be is 46, and so that doesn't affect any of the cases in this routine. + However, if the last token WAS a pure zero run of length 63, then _last_zzi + will be 1 while the number of coefficients decoded is 64. + Thus, we will trigger the following special case, where the real + coefficient count would not. + Note also that a zero run of length 64 will give _last_zzi a value of 0, + but we still process the DC coefficient, which might have a non-zero value + due to DC prediction. + Although convoluted, this is arguably the correct behavior: it allows us to + use a smaller transform when the block ends with a long zero run instead + of a normal EOB token. + It could be smarter... multiple separate zero runs at the end of a block + will fool it, but an encoder that generates these really deserves what it + gets. + Needless to say we inherited this approach from VP3.*/ + /*Then perform the iDCT.*/ + if(_last_zzi<10)oc_idct8x8_10(_y); + else oc_idct8x8_slow(_y); +} + #endif diff --git a/Engine/lib/libtheora/lib/x86/mmxloop.h b/Engine/lib/libtheora/lib/x86/mmxloop.h new file mode 100644 index 000000000..2e870c795 --- /dev/null +++ b/Engine/lib/libtheora/lib/x86/mmxloop.h @@ -0,0 +1,215 @@ +#if !defined(_x86_mmxloop_H) +# define _x86_mmxloop_H (1) +# include +# include "x86int.h" + +#if defined(OC_X86_ASM) + +/*On entry, mm0={a0,...,a7}, mm1={b0,...,b7}, mm2={c0,...,c7}, mm3={d0,...d7}. + On exit, mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)} and + mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}; mm0 and mm3 are clobbered.*/ +#define OC_LOOP_FILTER8_MMX \ + "#OC_LOOP_FILTER8_MMX\n\t" \ + /*mm7=0*/ \ + "pxor %%mm7,%%mm7\n\t" \ + /*mm6:mm0={a0,...,a7}*/ \ + "movq %%mm0,%%mm6\n\t" \ + "punpcklbw %%mm7,%%mm0\n\t" \ + "punpckhbw %%mm7,%%mm6\n\t" \ + /*mm3:mm5={d0,...,d7}*/ \ + "movq %%mm3,%%mm5\n\t" \ + "punpcklbw %%mm7,%%mm3\n\t" \ + "punpckhbw %%mm7,%%mm5\n\t" \ + /*mm6:mm0={a0-d0,...,a7-d7}*/ \ + "psubw %%mm3,%%mm0\n\t" \ + "psubw %%mm5,%%mm6\n\t" \ + /*mm3:mm1={b0,...,b7}*/ \ + "movq %%mm1,%%mm3\n\t" \ + "punpcklbw %%mm7,%%mm1\n\t" \ + "movq %%mm2,%%mm4\n\t" \ + "punpckhbw %%mm7,%%mm3\n\t" \ + /*mm5:mm4={c0,...,c7}*/ \ + "movq %%mm2,%%mm5\n\t" \ + "punpcklbw %%mm7,%%mm4\n\t" \ + "punpckhbw %%mm7,%%mm5\n\t" \ + /*mm7={3}x4 \ + mm5:mm4={c0-b0,...,c7-b7}*/ \ + "pcmpeqw %%mm7,%%mm7\n\t" \ + "psubw %%mm1,%%mm4\n\t" \ + "psrlw $14,%%mm7\n\t" \ + "psubw %%mm3,%%mm5\n\t" \ + /*Scale by 3.*/ \ + "pmullw %%mm7,%%mm4\n\t" \ + "pmullw %%mm7,%%mm5\n\t" \ + /*mm7={4}x4 \ + mm5:mm4=f={a0-d0+3*(c0-b0),...,a7-d7+3*(c7-b7)}*/ \ + "psrlw $1,%%mm7\n\t" \ + "paddw %%mm0,%%mm4\n\t" \ + "psllw $2,%%mm7\n\t" \ + "movq (%[ll]),%%mm0\n\t" \ + "paddw %%mm6,%%mm5\n\t" \ + /*R_i has the range [-127,128], so we compute -R_i instead. \ + mm4=-R_i=-(f+4>>3)=0xFF^(f-4>>3)*/ \ + "psubw %%mm7,%%mm4\n\t" \ + "psubw %%mm7,%%mm5\n\t" \ + "psraw $3,%%mm4\n\t" \ + "psraw $3,%%mm5\n\t" \ + "pcmpeqb %%mm7,%%mm7\n\t" \ + "packsswb %%mm5,%%mm4\n\t" \ + "pxor %%mm6,%%mm6\n\t" \ + "pxor %%mm7,%%mm4\n\t" \ + "packuswb %%mm3,%%mm1\n\t" \ + /*Now compute lflim of -mm4 cf. Section 7.10 of the sepc.*/ \ + /*There's no unsigned byte+signed byte with unsigned saturation op code, so \ + we have to split things by sign (the other option is to work in 16 bits, \ + but working in 8 bits gives much better parallelism). \ + We compute abs(R_i), but save a mask of which terms were negative in mm6. \ + Then we compute mm4=abs(lflim(R_i,L))=min(abs(R_i),max(2*L-abs(R_i),0)). \ + Finally, we split mm4 into positive and negative pieces using the mask in \ + mm6, and add and subtract them as appropriate.*/ \ + /*mm4=abs(-R_i)*/ \ + /*mm7=255-2*L*/ \ + "pcmpgtb %%mm4,%%mm6\n\t" \ + "psubb %%mm0,%%mm7\n\t" \ + "pxor %%mm6,%%mm4\n\t" \ + "psubb %%mm0,%%mm7\n\t" \ + "psubb %%mm6,%%mm4\n\t" \ + /*mm7=255-max(2*L-abs(R_i),0)*/ \ + "paddusb %%mm4,%%mm7\n\t" \ + /*mm4=min(abs(R_i),max(2*L-abs(R_i),0))*/ \ + "paddusb %%mm7,%%mm4\n\t" \ + "psubusb %%mm7,%%mm4\n\t" \ + /*Now split mm4 by the original sign of -R_i.*/ \ + "movq %%mm4,%%mm5\n\t" \ + "pand %%mm6,%%mm4\n\t" \ + "pandn %%mm5,%%mm6\n\t" \ + /*mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)}*/ \ + /*mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}*/ \ + "paddusb %%mm4,%%mm1\n\t" \ + "psubusb %%mm4,%%mm2\n\t" \ + "psubusb %%mm6,%%mm1\n\t" \ + "paddusb %%mm6,%%mm2\n\t" \ + +#define OC_LOOP_FILTER_V_MMX(_pix,_ystride,_ll) \ + do{ \ + ptrdiff_t ystride3__; \ + __asm__ __volatile__( \ + /*mm0={a0,...,a7}*/ \ + "movq (%[pix]),%%mm0\n\t" \ + /*ystride3=_ystride*3*/ \ + "lea (%[ystride],%[ystride],2),%[ystride3]\n\t" \ + /*mm3={d0,...,d7}*/ \ + "movq (%[pix],%[ystride3]),%%mm3\n\t" \ + /*mm1={b0,...,b7}*/ \ + "movq (%[pix],%[ystride]),%%mm1\n\t" \ + /*mm2={c0,...,c7}*/ \ + "movq (%[pix],%[ystride],2),%%mm2\n\t" \ + OC_LOOP_FILTER8_MMX \ + /*Write it back out.*/ \ + "movq %%mm1,(%[pix],%[ystride])\n\t" \ + "movq %%mm2,(%[pix],%[ystride],2)\n\t" \ + :[ystride3]"=&r"(ystride3__) \ + :[pix]"r"(_pix-_ystride*2),[ystride]"r"((ptrdiff_t)(_ystride)), \ + [ll]"r"(_ll) \ + :"memory" \ + ); \ + } \ + while(0) + +#define OC_LOOP_FILTER_H_MMX(_pix,_ystride,_ll) \ + do{ \ + unsigned char *pix__; \ + ptrdiff_t ystride3__; \ + ptrdiff_t d__; \ + pix__=(_pix)-2; \ + __asm__ __volatile__( \ + /*x x x x d0 c0 b0 a0*/ \ + "movd (%[pix]),%%mm0\n\t" \ + /*x x x x d1 c1 b1 a1*/ \ + "movd (%[pix],%[ystride]),%%mm1\n\t" \ + /*ystride3=_ystride*3*/ \ + "lea (%[ystride],%[ystride],2),%[ystride3]\n\t" \ + /*x x x x d2 c2 b2 a2*/ \ + "movd (%[pix],%[ystride],2),%%mm2\n\t" \ + /*x x x x d3 c3 b3 a3*/ \ + "lea (%[pix],%[ystride],4),%[d]\n\t" \ + "movd (%[pix],%[ystride3]),%%mm3\n\t" \ + /*x x x x d4 c4 b4 a4*/ \ + "movd (%[d]),%%mm4\n\t" \ + /*x x x x d5 c5 b5 a5*/ \ + "movd (%[d],%[ystride]),%%mm5\n\t" \ + /*x x x x d6 c6 b6 a6*/ \ + "movd (%[d],%[ystride],2),%%mm6\n\t" \ + /*x x x x d7 c7 b7 a7*/ \ + "movd (%[d],%[ystride3]),%%mm7\n\t" \ + /*mm0=d1 d0 c1 c0 b1 b0 a1 a0*/ \ + "punpcklbw %%mm1,%%mm0\n\t" \ + /*mm2=d3 d2 c3 c2 b3 b2 a3 a2*/ \ + "punpcklbw %%mm3,%%mm2\n\t" \ + /*mm3=d1 d0 c1 c0 b1 b0 a1 a0*/ \ + "movq %%mm0,%%mm3\n\t" \ + /*mm0=b3 b2 b1 b0 a3 a2 a1 a0*/ \ + "punpcklwd %%mm2,%%mm0\n\t" \ + /*mm3=d3 d2 d1 d0 c3 c2 c1 c0*/ \ + "punpckhwd %%mm2,%%mm3\n\t" \ + /*mm1=b3 b2 b1 b0 a3 a2 a1 a0*/ \ + "movq %%mm0,%%mm1\n\t" \ + /*mm4=d5 d4 c5 c4 b5 b4 a5 a4*/ \ + "punpcklbw %%mm5,%%mm4\n\t" \ + /*mm6=d7 d6 c7 c6 b7 b6 a7 a6*/ \ + "punpcklbw %%mm7,%%mm6\n\t" \ + /*mm5=d5 d4 c5 c4 b5 b4 a5 a4*/ \ + "movq %%mm4,%%mm5\n\t" \ + /*mm4=b7 b6 b5 b4 a7 a6 a5 a4*/ \ + "punpcklwd %%mm6,%%mm4\n\t" \ + /*mm5=d7 d6 d5 d4 c7 c6 c5 c4*/ \ + "punpckhwd %%mm6,%%mm5\n\t" \ + /*mm2=d3 d2 d1 d0 c3 c2 c1 c0*/ \ + "movq %%mm3,%%mm2\n\t" \ + /*mm0=a7 a6 a5 a4 a3 a2 a1 a0*/ \ + "punpckldq %%mm4,%%mm0\n\t" \ + /*mm1=b7 b6 b5 b4 b3 b2 b1 b0*/ \ + "punpckhdq %%mm4,%%mm1\n\t" \ + /*mm2=c7 c6 c5 c4 c3 c2 c1 c0*/ \ + "punpckldq %%mm5,%%mm2\n\t" \ + /*mm3=d7 d6 d5 d4 d3 d2 d1 d0*/ \ + "punpckhdq %%mm5,%%mm3\n\t" \ + OC_LOOP_FILTER8_MMX \ + /*mm2={b0+R_0'',...,b7+R_7''}*/ \ + "movq %%mm1,%%mm0\n\t" \ + /*mm1={b0+R_0'',c0-R_0'',...,b3+R_3'',c3-R_3''}*/ \ + "punpcklbw %%mm2,%%mm1\n\t" \ + /*mm2={b4+R_4'',c4-R_4'',...,b7+R_7'',c7-R_7''}*/ \ + "punpckhbw %%mm2,%%mm0\n\t" \ + /*[d]=c1 b1 c0 b0*/ \ + "movd %%mm1,%[d]\n\t" \ + "movw %w[d],1(%[pix])\n\t" \ + "psrlq $32,%%mm1\n\t" \ + "shr $16,%[d]\n\t" \ + "movw %w[d],1(%[pix],%[ystride])\n\t" \ + /*[d]=c3 b3 c2 b2*/ \ + "movd %%mm1,%[d]\n\t" \ + "movw %w[d],1(%[pix],%[ystride],2)\n\t" \ + "shr $16,%[d]\n\t" \ + "movw %w[d],1(%[pix],%[ystride3])\n\t" \ + "lea (%[pix],%[ystride],4),%[pix]\n\t" \ + /*[d]=c5 b5 c4 b4*/ \ + "movd %%mm0,%[d]\n\t" \ + "movw %w[d],1(%[pix])\n\t" \ + "psrlq $32,%%mm0\n\t" \ + "shr $16,%[d]\n\t" \ + "movw %w[d],1(%[pix],%[ystride])\n\t" \ + /*[d]=c7 b7 c6 b6*/ \ + "movd %%mm0,%[d]\n\t" \ + "movw %w[d],1(%[pix],%[ystride],2)\n\t" \ + "shr $16,%[d]\n\t" \ + "movw %w[d],1(%[pix],%[ystride3])\n\t" \ + :[pix]"+r"(pix__),[ystride3]"=&r"(ystride3__),[d]"=&r"(d__) \ + :[ystride]"r"((ptrdiff_t)(_ystride)),[ll]"r"(_ll) \ + :"memory" \ + ); \ + } \ + while(0) + +# endif +#endif diff --git a/Engine/lib/libtheora/lib/x86/mmxstate.c b/Engine/lib/libtheora/lib/x86/mmxstate.c new file mode 100644 index 000000000..808b0a789 --- /dev/null +++ b/Engine/lib/libtheora/lib/x86/mmxstate.c @@ -0,0 +1,188 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: mmxstate.c 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ + +/*MMX acceleration of complete fragment reconstruction algorithm. + Originally written by Rudolf Marek.*/ +#include +#include "x86int.h" +#include "mmxfrag.h" +#include "mmxloop.h" + +#if defined(OC_X86_ASM) + +void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi, + int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant){ + unsigned char *dst; + ptrdiff_t frag_buf_off; + int ystride; + int mb_mode; + /*Apply the inverse transform.*/ + /*Special case only having a DC component.*/ + if(_last_zzi<2){ + /*Note that this value must be unsigned, to keep the __asm__ block from + sign-extending it when it puts it in a register.*/ + ogg_uint16_t p; + /*We round this dequant product (and not any of the others) because there's + no iDCT rounding.*/ + p=(ogg_int16_t)(_dct_coeffs[0]*(ogg_int32_t)_dc_quant+15>>5); + /*Fill _dct_coeffs with p.*/ + __asm__ __volatile__( + /*mm0=0000 0000 0000 AAAA*/ + "movd %[p],%%mm0\n\t" + /*mm0=0000 0000 AAAA AAAA*/ + "punpcklwd %%mm0,%%mm0\n\t" + /*mm0=AAAA AAAA AAAA AAAA*/ + "punpckldq %%mm0,%%mm0\n\t" + "movq %%mm0,(%[y])\n\t" + "movq %%mm0,8(%[y])\n\t" + "movq %%mm0,16(%[y])\n\t" + "movq %%mm0,24(%[y])\n\t" + "movq %%mm0,32(%[y])\n\t" + "movq %%mm0,40(%[y])\n\t" + "movq %%mm0,48(%[y])\n\t" + "movq %%mm0,56(%[y])\n\t" + "movq %%mm0,64(%[y])\n\t" + "movq %%mm0,72(%[y])\n\t" + "movq %%mm0,80(%[y])\n\t" + "movq %%mm0,88(%[y])\n\t" + "movq %%mm0,96(%[y])\n\t" + "movq %%mm0,104(%[y])\n\t" + "movq %%mm0,112(%[y])\n\t" + "movq %%mm0,120(%[y])\n\t" + : + :[y]"r"(_dct_coeffs),[p]"r"((unsigned)p) + :"memory" + ); + } + else{ + /*Dequantize the DC coefficient.*/ + _dct_coeffs[0]=(ogg_int16_t)(_dct_coeffs[0]*(int)_dc_quant); + oc_idct8x8_mmx(_dct_coeffs,_last_zzi); + } + /*Fill in the target buffer.*/ + frag_buf_off=_state->frag_buf_offs[_fragi]; + mb_mode=_state->frags[_fragi].mb_mode; + ystride=_state->ref_ystride[_pli]; + dst=_state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_SELF]]+frag_buf_off; + if(mb_mode==OC_MODE_INTRA)oc_frag_recon_intra_mmx(dst,ystride,_dct_coeffs); + else{ + const unsigned char *ref; + int mvoffsets[2]; + ref= + _state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_FOR_MODE(mb_mode)]] + +frag_buf_off; + if(oc_state_get_mv_offsets(_state,mvoffsets,_pli, + _state->frag_mvs[_fragi][0],_state->frag_mvs[_fragi][1])>1){ + oc_frag_recon_inter2_mmx(dst,ref+mvoffsets[0],ref+mvoffsets[1],ystride, + _dct_coeffs); + } + else oc_frag_recon_inter_mmx(dst,ref+mvoffsets[0],ystride,_dct_coeffs); + } +} + +/*We copy these entire function to inline the actual MMX routines so that we + use only a single indirect call.*/ + +/*Copies the fragments specified by the lists of fragment indices from one + frame to another. + _fragis: A pointer to a list of fragment indices. + _nfragis: The number of fragment indices to copy. + _dst_frame: The reference frame to copy to. + _src_frame: The reference frame to copy from. + _pli: The color plane the fragments lie in.*/ +void oc_state_frag_copy_list_mmx(const oc_theora_state *_state, + const ptrdiff_t *_fragis,ptrdiff_t _nfragis, + int _dst_frame,int _src_frame,int _pli){ + const ptrdiff_t *frag_buf_offs; + const unsigned char *src_frame_data; + unsigned char *dst_frame_data; + ptrdiff_t fragii; + int ystride; + dst_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_dst_frame]]; + src_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_src_frame]]; + ystride=_state->ref_ystride[_pli]; + frag_buf_offs=_state->frag_buf_offs; + for(fragii=0;fragii<_nfragis;fragii++){ + ptrdiff_t frag_buf_off; + frag_buf_off=frag_buf_offs[_fragis[fragii]]; + OC_FRAG_COPY_MMX(dst_frame_data+frag_buf_off, + src_frame_data+frag_buf_off,ystride); + } +} + +/*Apply the loop filter to a given set of fragment rows in the given plane. + The filter may be run on the bottom edge, affecting pixels in the next row of + fragments, so this row also needs to be available. + _bv: The bounding values array. + _refi: The index of the frame buffer to filter. + _pli: The color plane to filter. + _fragy0: The Y coordinate of the first fragment row to filter. + _fragy_end: The Y coordinate of the fragment row to stop filtering at.*/ +void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state, + int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end){ + OC_ALIGN8(unsigned char ll[8]); + const oc_fragment_plane *fplane; + const oc_fragment *frags; + const ptrdiff_t *frag_buf_offs; + unsigned char *ref_frame_data; + ptrdiff_t fragi_top; + ptrdiff_t fragi_bot; + ptrdiff_t fragi0; + ptrdiff_t fragi0_end; + int ystride; + int nhfrags; + memset(ll,_state->loop_filter_limits[_state->qis[0]],sizeof(ll)); + fplane=_state->fplanes+_pli; + nhfrags=fplane->nhfrags; + fragi_top=fplane->froffset; + fragi_bot=fragi_top+fplane->nfrags; + fragi0=fragi_top+_fragy0*(ptrdiff_t)nhfrags; + fragi0_end=fragi0+(_fragy_end-_fragy0)*(ptrdiff_t)nhfrags; + ystride=_state->ref_ystride[_pli]; + frags=_state->frags; + frag_buf_offs=_state->frag_buf_offs; + ref_frame_data=_state->ref_frame_data[_refi]; + /*The following loops are constructed somewhat non-intuitively on purpose. + The main idea is: if a block boundary has at least one coded fragment on + it, the filter is applied to it. + However, the order that the filters are applied in matters, and VP3 chose + the somewhat strange ordering used below.*/ + while(fragi0fragi0)OC_LOOP_FILTER_H_MMX(ref,ystride,ll); + if(fragi0>fragi_top)OC_LOOP_FILTER_V_MMX(ref,ystride,ll); + if(fragi+1 +#include "x86enc.h" + +#if defined(OC_X86_64_ASM) + +# define OC_FDCT8x8 \ + /*Note: xmm15={0}x8 and xmm14={-1}x8.*/ \ + "#OC_FDCT8x8\n\t" \ + /*Stage 1:*/ \ + "movdqa %%xmm0,%%xmm11\n\t" \ + "movdqa %%xmm1,%%xmm10\n\t" \ + "movdqa %%xmm2,%%xmm9\n\t" \ + "movdqa %%xmm3,%%xmm8\n\t" \ + /*xmm11=t7'=t0-t7*/ \ + "psubw %%xmm7,%%xmm11\n\t" \ + /*xmm10=t6'=t1-t6*/ \ + "psubw %%xmm6,%%xmm10\n\t" \ + /*xmm9=t5'=t2-t5*/ \ + "psubw %%xmm5,%%xmm9\n\t" \ + /*xmm8=t4'=t3-t4*/ \ + "psubw %%xmm4,%%xmm8\n\t" \ + /*xmm0=t0'=t0+t7*/ \ + "paddw %%xmm7,%%xmm0\n\t" \ + /*xmm1=t1'=t1+t6*/ \ + "paddw %%xmm6,%%xmm1\n\t" \ + /*xmm5=t2'=t2+t5*/ \ + "paddw %%xmm2,%%xmm5\n\t" \ + /*xmm4=t3'=t3+t4*/ \ + "paddw %%xmm3,%%xmm4\n\t" \ + /*xmm2,3,6,7 are now free.*/ \ + /*Stage 2:*/ \ + "movdqa %%xmm0,%%xmm3\n\t" \ + "mov $0x5A806A0A,%[a]\n\t" \ + "movdqa %%xmm1,%%xmm2\n\t" \ + "movd %[a],%%xmm13\n\t" \ + "movdqa %%xmm10,%%xmm6\n\t" \ + "pshufd $00,%%xmm13,%%xmm13\n\t" \ + /*xmm2=t2''=t1'-t2'*/ \ + "psubw %%xmm5,%%xmm2\n\t" \ + "pxor %%xmm12,%%xmm12\n\t" \ + /*xmm3=t3''=t0'-t3'*/ \ + "psubw %%xmm4,%%xmm3\n\t" \ + "psubw %%xmm14,%%xmm12\n\t" \ + /*xmm10=t5''=t6'-t5'*/ \ + "psubw %%xmm9,%%xmm10\n\t" \ + "paddw %%xmm12,%%xmm12\n\t" \ + /*xmm4=t0''=t0'+t3'*/ \ + "paddw %%xmm0,%%xmm4\n\t" \ + /*xmm1=t1''=t1'+t2'*/ \ + "paddw %%xmm5,%%xmm1\n\t" \ + /*xmm6=t6''=t6'+t5'*/ \ + "paddw %%xmm9,%%xmm6\n\t" \ + /*xmm0,xmm5,xmm9 are now free.*/ \ + /*Stage 3:*/ \ + /*xmm10:xmm5=t5''*27146+0xB500 \ + xmm0=t5''*/ \ + "movdqa %%xmm10,%%xmm5\n\t" \ + "movdqa %%xmm10,%%xmm0\n\t" \ + "punpckhwd %%xmm12,%%xmm10\n\t" \ + "pmaddwd %%xmm13,%%xmm10\n\t" \ + "punpcklwd %%xmm12,%%xmm5\n\t" \ + "pmaddwd %%xmm13,%%xmm5\n\t" \ + /*xmm5=(t5''*27146+0xB500>>16)+t5''*/ \ + "psrad $16,%%xmm10\n\t" \ + "psrad $16,%%xmm5\n\t" \ + "packssdw %%xmm10,%%xmm5\n\t" \ + "paddw %%xmm0,%%xmm5\n\t" \ + /*xmm0=s=(t5''*27146+0xB500>>16)+t5''+(t5''!=0)>>1*/ \ + "pcmpeqw %%xmm15,%%xmm0\n\t" \ + "psubw %%xmm14,%%xmm0\n\t" \ + "paddw %%xmm5,%%xmm0\n\t" \ + "movdqa %%xmm8,%%xmm5\n\t" \ + "psraw $1,%%xmm0\n\t" \ + /*xmm5=t5'''=t4'-s*/ \ + "psubw %%xmm0,%%xmm5\n\t" \ + /*xmm8=t4''=t4'+s*/ \ + "paddw %%xmm0,%%xmm8\n\t" \ + /*xmm0,xmm7,xmm9,xmm10 are free.*/ \ + /*xmm7:xmm9=t6''*27146+0xB500*/ \ + "movdqa %%xmm6,%%xmm7\n\t" \ + "movdqa %%xmm6,%%xmm9\n\t" \ + "punpckhwd %%xmm12,%%xmm7\n\t" \ + "pmaddwd %%xmm13,%%xmm7\n\t" \ + "punpcklwd %%xmm12,%%xmm9\n\t" \ + "pmaddwd %%xmm13,%%xmm9\n\t" \ + /*xmm9=(t6''*27146+0xB500>>16)+t6''*/ \ + "psrad $16,%%xmm7\n\t" \ + "psrad $16,%%xmm9\n\t" \ + "packssdw %%xmm7,%%xmm9\n\t" \ + "paddw %%xmm6,%%xmm9\n\t" \ + /*xmm9=s=(t6''*27146+0xB500>>16)+t6''+(t6''!=0)>>1*/ \ + "pcmpeqw %%xmm15,%%xmm6\n\t" \ + "psubw %%xmm14,%%xmm6\n\t" \ + "paddw %%xmm6,%%xmm9\n\t" \ + "movdqa %%xmm11,%%xmm7\n\t" \ + "psraw $1,%%xmm9\n\t" \ + /*xmm7=t6'''=t7'-s*/ \ + "psubw %%xmm9,%%xmm7\n\t" \ + /*xmm9=t7''=t7'+s*/ \ + "paddw %%xmm11,%%xmm9\n\t" \ + /*xmm0,xmm6,xmm10,xmm11 are free.*/ \ + /*Stage 4:*/ \ + /*xmm10:xmm0=t1''*27146+0xB500*/ \ + "movdqa %%xmm1,%%xmm0\n\t" \ + "movdqa %%xmm1,%%xmm10\n\t" \ + "punpcklwd %%xmm12,%%xmm0\n\t" \ + "pmaddwd %%xmm13,%%xmm0\n\t" \ + "punpckhwd %%xmm12,%%xmm10\n\t" \ + "pmaddwd %%xmm13,%%xmm10\n\t" \ + /*xmm0=(t1''*27146+0xB500>>16)+t1''*/ \ + "psrad $16,%%xmm0\n\t" \ + "psrad $16,%%xmm10\n\t" \ + "mov $0x20006A0A,%[a]\n\t" \ + "packssdw %%xmm10,%%xmm0\n\t" \ + "movd %[a],%%xmm13\n\t" \ + "paddw %%xmm1,%%xmm0\n\t" \ + /*xmm0=s=(t1''*27146+0xB500>>16)+t1''+(t1''!=0)*/ \ + "pcmpeqw %%xmm15,%%xmm1\n\t" \ + "pshufd $00,%%xmm13,%%xmm13\n\t" \ + "psubw %%xmm14,%%xmm1\n\t" \ + "paddw %%xmm1,%%xmm0\n\t" \ + /*xmm10:xmm4=t0''*27146+0x4000*/ \ + "movdqa %%xmm4,%%xmm1\n\t" \ + "movdqa %%xmm4,%%xmm10\n\t" \ + "punpcklwd %%xmm12,%%xmm4\n\t" \ + "pmaddwd %%xmm13,%%xmm4\n\t" \ + "punpckhwd %%xmm12,%%xmm10\n\t" \ + "pmaddwd %%xmm13,%%xmm10\n\t" \ + /*xmm4=(t0''*27146+0x4000>>16)+t0''*/ \ + "psrad $16,%%xmm4\n\t" \ + "psrad $16,%%xmm10\n\t" \ + "mov $0x6CB7,%[a]\n\t" \ + "packssdw %%xmm10,%%xmm4\n\t" \ + "movd %[a],%%xmm12\n\t" \ + "paddw %%xmm1,%%xmm4\n\t" \ + /*xmm4=r=(t0''*27146+0x4000>>16)+t0''+(t0''!=0)*/ \ + "pcmpeqw %%xmm15,%%xmm1\n\t" \ + "pshufd $00,%%xmm12,%%xmm12\n\t" \ + "psubw %%xmm14,%%xmm1\n\t" \ + "mov $0x7FFF6C84,%[a]\n\t" \ + "paddw %%xmm1,%%xmm4\n\t" \ + /*xmm0=_y[0]=u=r+s>>1 \ + The naive implementation could cause overflow, so we use \ + u=(r&s)+((r^s)>>1).*/ \ + "movdqa %%xmm0,%%xmm6\n\t" \ + "pxor %%xmm4,%%xmm0\n\t" \ + "pand %%xmm4,%%xmm6\n\t" \ + "psraw $1,%%xmm0\n\t" \ + "movd %[a],%%xmm13\n\t" \ + "paddw %%xmm6,%%xmm0\n\t" \ + /*xmm4=_y[4]=v=r-u*/ \ + "pshufd $00,%%xmm13,%%xmm13\n\t" \ + "psubw %%xmm0,%%xmm4\n\t" \ + /*xmm1,xmm6,xmm10,xmm11 are free.*/ \ + /*xmm6:xmm10=60547*t3''+0x6CB7*/ \ + "movdqa %%xmm3,%%xmm10\n\t" \ + "movdqa %%xmm3,%%xmm6\n\t" \ + "punpcklwd %%xmm3,%%xmm10\n\t" \ + "pmaddwd %%xmm13,%%xmm10\n\t" \ + "mov $0x61F861F8,%[a]\n\t" \ + "punpckhwd %%xmm3,%%xmm6\n\t" \ + "pmaddwd %%xmm13,%%xmm6\n\t" \ + "movd %[a],%%xmm13\n\t" \ + "paddd %%xmm12,%%xmm10\n\t" \ + "pshufd $00,%%xmm13,%%xmm13\n\t" \ + "paddd %%xmm12,%%xmm6\n\t" \ + /*xmm1:xmm2=25080*t2'' \ + xmm12=t2''*/ \ + "movdqa %%xmm2,%%xmm11\n\t" \ + "movdqa %%xmm2,%%xmm12\n\t" \ + "pmullw %%xmm13,%%xmm2\n\t" \ + "pmulhw %%xmm13,%%xmm11\n\t" \ + "movdqa %%xmm2,%%xmm1\n\t" \ + "punpcklwd %%xmm11,%%xmm2\n\t" \ + "punpckhwd %%xmm11,%%xmm1\n\t" \ + /*xmm10=u=(25080*t2''+60547*t3''+0x6CB7>>16)+(t3''!=0)*/ \ + "paddd %%xmm2,%%xmm10\n\t" \ + "paddd %%xmm1,%%xmm6\n\t" \ + "psrad $16,%%xmm10\n\t" \ + "pcmpeqw %%xmm15,%%xmm3\n\t" \ + "psrad $16,%%xmm6\n\t" \ + "psubw %%xmm14,%%xmm3\n\t" \ + "packssdw %%xmm6,%%xmm10\n\t" \ + "paddw %%xmm3,%%xmm10\n\t" \ + /*xmm2=_y[2]=u \ + xmm10=s=(25080*u>>16)-t2''*/ \ + "movdqa %%xmm10,%%xmm2\n\t" \ + "pmulhw %%xmm13,%%xmm10\n\t" \ + "psubw %%xmm12,%%xmm10\n\t" \ + /*xmm1:xmm6=s*21600+0x2800*/ \ + "pxor %%xmm12,%%xmm12\n\t" \ + "psubw %%xmm14,%%xmm12\n\t" \ + "mov $0x28005460,%[a]\n\t" \ + "movd %[a],%%xmm13\n\t" \ + "pshufd $00,%%xmm13,%%xmm13\n\t" \ + "movdqa %%xmm10,%%xmm6\n\t" \ + "movdqa %%xmm10,%%xmm1\n\t" \ + "punpcklwd %%xmm12,%%xmm6\n\t" \ + "pmaddwd %%xmm13,%%xmm6\n\t" \ + "mov $0x0E3D,%[a]\n\t" \ + "punpckhwd %%xmm12,%%xmm1\n\t" \ + "pmaddwd %%xmm13,%%xmm1\n\t" \ + /*xmm6=(s*21600+0x2800>>18)+s*/ \ + "psrad $18,%%xmm6\n\t" \ + "psrad $18,%%xmm1\n\t" \ + "movd %[a],%%xmm12\n\t" \ + "packssdw %%xmm1,%%xmm6\n\t" \ + "pshufd $00,%%xmm12,%%xmm12\n\t" \ + "paddw %%xmm10,%%xmm6\n\t" \ + /*xmm6=_y[6]=v=(s*21600+0x2800>>18)+s+(s!=0)*/ \ + "mov $0x7FFF54DC,%[a]\n\t" \ + "pcmpeqw %%xmm15,%%xmm10\n\t" \ + "movd %[a],%%xmm13\n\t" \ + "psubw %%xmm14,%%xmm10\n\t" \ + "pshufd $00,%%xmm13,%%xmm13\n\t" \ + "paddw %%xmm10,%%xmm6\n\t " \ + /*xmm1,xmm3,xmm10,xmm11 are free.*/ \ + /*xmm11:xmm10=54491*t5'''+0x0E3D*/ \ + "movdqa %%xmm5,%%xmm10\n\t" \ + "movdqa %%xmm5,%%xmm11\n\t" \ + "punpcklwd %%xmm5,%%xmm10\n\t" \ + "pmaddwd %%xmm13,%%xmm10\n\t" \ + "mov $0x8E3A8E3A,%[a]\n\t" \ + "punpckhwd %%xmm5,%%xmm11\n\t" \ + "pmaddwd %%xmm13,%%xmm11\n\t" \ + "movd %[a],%%xmm13\n\t" \ + "paddd %%xmm12,%%xmm10\n\t" \ + "pshufd $00,%%xmm13,%%xmm13\n\t" \ + "paddd %%xmm12,%%xmm11\n\t" \ + /*xmm7:xmm12=36410*t6''' \ + xmm1=t6'''*/ \ + "movdqa %%xmm7,%%xmm3\n\t" \ + "movdqa %%xmm7,%%xmm1\n\t" \ + "pmulhw %%xmm13,%%xmm3\n\t" \ + "pmullw %%xmm13,%%xmm7\n\t" \ + "paddw %%xmm1,%%xmm3\n\t" \ + "movdqa %%xmm7,%%xmm12\n\t" \ + "punpckhwd %%xmm3,%%xmm7\n\t" \ + "punpcklwd %%xmm3,%%xmm12\n\t" \ + /*xmm10=u=(54491*t5'''+36410*t6'''+0x0E3D>>16)+(t5'''!=0)*/ \ + "paddd %%xmm12,%%xmm10\n\t" \ + "paddd %%xmm7,%%xmm11\n\t" \ + "psrad $16,%%xmm10\n\t" \ + "pcmpeqw %%xmm15,%%xmm5\n\t" \ + "psrad $16,%%xmm11\n\t" \ + "psubw %%xmm14,%%xmm5\n\t" \ + "packssdw %%xmm11,%%xmm10\n\t" \ + "pxor %%xmm12,%%xmm12\n\t" \ + "paddw %%xmm5,%%xmm10\n\t" \ + /*xmm5=_y[5]=u \ + xmm1=s=t6'''-(36410*u>>16)*/ \ + "psubw %%xmm14,%%xmm12\n\t" \ + "movdqa %%xmm10,%%xmm5\n\t" \ + "mov $0x340067C8,%[a]\n\t" \ + "pmulhw %%xmm13,%%xmm10\n\t" \ + "movd %[a],%%xmm13\n\t" \ + "paddw %%xmm5,%%xmm10\n\t" \ + "pshufd $00,%%xmm13,%%xmm13\n\t" \ + "psubw %%xmm10,%%xmm1\n\t" \ + /*xmm11:xmm3=s*26568+0x3400*/ \ + "movdqa %%xmm1,%%xmm3\n\t" \ + "movdqa %%xmm1,%%xmm11\n\t" \ + "punpcklwd %%xmm12,%%xmm3\n\t" \ + "pmaddwd %%xmm13,%%xmm3\n\t" \ + "mov $0x7B1B,%[a]\n\t" \ + "punpckhwd %%xmm12,%%xmm11\n\t" \ + "pmaddwd %%xmm13,%%xmm11\n\t" \ + /*xmm3=(s*26568+0x3400>>17)+s*/ \ + "psrad $17,%%xmm3\n\t" \ + "psrad $17,%%xmm11\n\t" \ + "movd %[a],%%xmm12\n\t" \ + "packssdw %%xmm11,%%xmm3\n\t" \ + "pshufd $00,%%xmm12,%%xmm12\n\t" \ + "paddw %%xmm1,%%xmm3\n\t" \ + /*xmm3=_y[3]=v=(s*26568+0x3400>>17)+s+(s!=0)*/ \ + "mov $0x7FFF7B16,%[a]\n\t" \ + "pcmpeqw %%xmm15,%%xmm1\n\t" \ + "movd %[a],%%xmm13\n\t" \ + "psubw %%xmm14,%%xmm1\n\t" \ + "pshufd $00,%%xmm13,%%xmm13\n\t" \ + "paddw %%xmm1,%%xmm3\n\t " \ + /*xmm1,xmm7,xmm10,xmm11 are free.*/ \ + /*xmm11:xmm10=64277*t7''+0x7B1B*/ \ + "movdqa %%xmm9,%%xmm10\n\t" \ + "movdqa %%xmm9,%%xmm11\n\t" \ + "punpcklwd %%xmm9,%%xmm10\n\t" \ + "pmaddwd %%xmm13,%%xmm10\n\t" \ + "mov $0x31F131F1,%[a]\n\t" \ + "punpckhwd %%xmm9,%%xmm11\n\t" \ + "pmaddwd %%xmm13,%%xmm11\n\t" \ + "movd %[a],%%xmm13\n\t" \ + "paddd %%xmm12,%%xmm10\n\t" \ + "pshufd $00,%%xmm13,%%xmm13\n\t" \ + "paddd %%xmm12,%%xmm11\n\t" \ + /*xmm12:xmm7=12785*t4''*/ \ + "movdqa %%xmm8,%%xmm7\n\t" \ + "movdqa %%xmm8,%%xmm1\n\t" \ + "pmullw %%xmm13,%%xmm7\n\t" \ + "pmulhw %%xmm13,%%xmm1\n\t" \ + "movdqa %%xmm7,%%xmm12\n\t" \ + "punpcklwd %%xmm1,%%xmm7\n\t" \ + "punpckhwd %%xmm1,%%xmm12\n\t" \ + /*xmm10=u=(12785*t4''+64277*t7''+0x7B1B>>16)+(t7''!=0)*/ \ + "paddd %%xmm7,%%xmm10\n\t" \ + "paddd %%xmm12,%%xmm11\n\t" \ + "psrad $16,%%xmm10\n\t" \ + "pcmpeqw %%xmm15,%%xmm9\n\t" \ + "psrad $16,%%xmm11\n\t" \ + "psubw %%xmm14,%%xmm9\n\t" \ + "packssdw %%xmm11,%%xmm10\n\t" \ + "pxor %%xmm12,%%xmm12\n\t" \ + "paddw %%xmm9,%%xmm10\n\t" \ + /*xmm1=_y[1]=u \ + xmm10=s=(12785*u>>16)-t4''*/ \ + "psubw %%xmm14,%%xmm12\n\t" \ + "movdqa %%xmm10,%%xmm1\n\t" \ + "mov $0x3000503B,%[a]\n\t" \ + "pmulhw %%xmm13,%%xmm10\n\t" \ + "movd %[a],%%xmm13\n\t" \ + "psubw %%xmm8,%%xmm10\n\t" \ + "pshufd $00,%%xmm13,%%xmm13\n\t" \ + /*xmm8:xmm7=s*20539+0x3000*/ \ + "movdqa %%xmm10,%%xmm7\n\t" \ + "movdqa %%xmm10,%%xmm8\n\t" \ + "punpcklwd %%xmm12,%%xmm7\n\t" \ + "pmaddwd %%xmm13,%%xmm7\n\t" \ + "punpckhwd %%xmm12,%%xmm8\n\t" \ + "pmaddwd %%xmm13,%%xmm8\n\t" \ + /*xmm7=(s*20539+0x3000>>20)+s*/ \ + "psrad $20,%%xmm7\n\t" \ + "psrad $20,%%xmm8\n\t" \ + "packssdw %%xmm8,%%xmm7\n\t" \ + "paddw %%xmm10,%%xmm7\n\t" \ + /*xmm7=_y[7]=v=(s*20539+0x3000>>20)+s+(s!=0)*/ \ + "pcmpeqw %%xmm15,%%xmm10\n\t" \ + "psubw %%xmm14,%%xmm10\n\t" \ + "paddw %%xmm10,%%xmm7\n\t " \ + +# define OC_TRANSPOSE8x8 \ + "#OC_TRANSPOSE8x8\n\t" \ + "movdqa %%xmm4,%%xmm8\n\t" \ + /*xmm4 = f3 e3 f2 e2 f1 e1 f0 e0*/ \ + "punpcklwd %%xmm5,%%xmm4\n\t" \ + /*xmm8 = f7 e7 f6 e6 f5 e5 f4 e4*/ \ + "punpckhwd %%xmm5,%%xmm8\n\t" \ + /*xmm5 is free.*/ \ + "movdqa %%xmm0,%%xmm5\n\t" \ + /*xmm0 = b3 a3 b2 a2 b1 a1 b0 a0*/ \ + "punpcklwd %%xmm1,%%xmm0\n\t" \ + /*xmm5 = b7 a7 b6 a6 b5 a5 b4 a4*/ \ + "punpckhwd %%xmm1,%%xmm5\n\t" \ + /*xmm1 is free.*/ \ + "movdqa %%xmm6,%%xmm1\n\t" \ + /*xmm6 = h3 g3 h2 g2 h1 g1 h0 g0*/ \ + "punpcklwd %%xmm7,%%xmm6\n\t" \ + /*xmm1 = h7 g7 h6 g6 h5 g5 h4 g4*/ \ + "punpckhwd %%xmm7,%%xmm1\n\t" \ + /*xmm7 is free.*/ \ + "movdqa %%xmm2,%%xmm7\n\t" \ + /*xmm7 = d3 c3 d2 c2 d1 c1 d0 c0*/ \ + "punpcklwd %%xmm3,%%xmm7\n\t" \ + /*xmm2 = d7 c7 d6 c6 d5 c5 d4 c4*/ \ + "punpckhwd %%xmm3,%%xmm2\n\t" \ + /*xmm3 is free.*/ \ + "movdqa %%xmm0,%%xmm3\n\t" \ + /*xmm0 = d1 c1 b1 a1 d0 c0 b0 a0*/ \ + "punpckldq %%xmm7,%%xmm0\n\t" \ + /*xmm3 = d3 c3 b3 a3 d2 c2 b2 a2*/ \ + "punpckhdq %%xmm7,%%xmm3\n\t" \ + /*xmm7 is free.*/ \ + "movdqa %%xmm5,%%xmm7\n\t" \ + /*xmm5 = d5 c5 b5 a5 d4 c4 b4 a4*/ \ + "punpckldq %%xmm2,%%xmm5\n\t" \ + /*xmm7 = d7 c7 b7 a7 d6 c6 b6 a6*/ \ + "punpckhdq %%xmm2,%%xmm7\n\t" \ + /*xmm2 is free.*/ \ + "movdqa %%xmm4,%%xmm2\n\t" \ + /*xmm2 = h1 g1 f1 e1 h0 g0 f0 e0*/ \ + "punpckldq %%xmm6,%%xmm2\n\t" \ + /*xmm4 = h3 g3 f3 e3 h2 g2 f2 e2*/ \ + "punpckhdq %%xmm6,%%xmm4\n\t" \ + /*xmm6 is free.*/ \ + "movdqa %%xmm8,%%xmm6\n\t" \ + /*xmm6 = h5 g5 f5 e5 h4 g4 f4 e4*/ \ + "punpckldq %%xmm1,%%xmm6\n\t" \ + /*xmm8 = h7 g7 f7 e7 h6 g6 f6 e6*/ \ + "punpckhdq %%xmm1,%%xmm8\n\t" \ + /*xmm1 is free.*/ \ + "movdqa %%xmm0,%%xmm1\n\t" \ + /*xmm0 = h0 g0 f0 e0 d0 c0 b0 a0*/ \ + "punpcklqdq %%xmm2,%%xmm0\n\t" \ + /*xmm1 = h1 g1 f1 e1 d1 c1 b1 a1*/ \ + "punpckhqdq %%xmm2,%%xmm1\n\t" \ + /*xmm2 is free.*/ \ + "movdqa %%xmm3,%%xmm2\n\t" \ + /*xmm2 = h2 g2 f2 e2 d2 c2 b2 a2*/ \ + "punpcklqdq %%xmm4,%%xmm2\n\t" \ + /*xmm3 = h3 g3 f3 e3 d3 c3 b3 a3*/ \ + "punpckhqdq %%xmm4,%%xmm3\n\t" \ + /*xmm4 is free.*/ \ + "movdqa %%xmm5,%%xmm4\n\t" \ + /*xmm4 = h4 g4 f4 e4 d4 c4 b4 a4*/ \ + "punpcklqdq %%xmm6,%%xmm4\n\t" \ + /*xmm5 = h5 g5 f5 e5 d5 c5 b5 a5*/ \ + "punpckhqdq %%xmm6,%%xmm5\n\t" \ + /*xmm6 is free.*/ \ + "movdqa %%xmm7,%%xmm6\n\t" \ + /*xmm6 = h6 g6 f6 e6 d6 c6 b6 a6*/ \ + "punpcklqdq %%xmm8,%%xmm6\n\t" \ + /*xmm7 = h7 g7 f7 e7 d7 c7 b7 a7*/ \ + "punpckhqdq %%xmm8,%%xmm7\n\t" \ + /*xmm8 is free.*/ \ + +/*SSE2 implementation of the fDCT for x86-64 only. + Because of the 8 extra XMM registers on x86-64, this version can operate + without any temporary stack access at all.*/ +void oc_enc_fdct8x8_x86_64sse2(ogg_int16_t _y[64],const ogg_int16_t _x[64]){ + ptrdiff_t a; + __asm__ __volatile__( + /*Load the input.*/ + "movdqa 0x00(%[x]),%%xmm0\n\t" + "movdqa 0x10(%[x]),%%xmm1\n\t" + "movdqa 0x20(%[x]),%%xmm2\n\t" + "movdqa 0x30(%[x]),%%xmm3\n\t" + "movdqa 0x40(%[x]),%%xmm4\n\t" + "movdqa 0x50(%[x]),%%xmm5\n\t" + "movdqa 0x60(%[x]),%%xmm6\n\t" + "movdqa 0x70(%[x]),%%xmm7\n\t" + /*Add two extra bits of working precision to improve accuracy; any more and + we could overflow.*/ + /*We also add a few biases to correct for some systematic error that + remains in the full fDCT->iDCT round trip.*/ + /*xmm15={0}x8*/ + "pxor %%xmm15,%%xmm15\n\t" + /*xmm14={-1}x8*/ + "pcmpeqb %%xmm14,%%xmm14\n\t" + "psllw $2,%%xmm0\n\t" + /*xmm8=xmm0*/ + "movdqa %%xmm0,%%xmm8\n\t" + "psllw $2,%%xmm1\n\t" + /*xmm8={_x[7...0]==0}*/ + "pcmpeqw %%xmm15,%%xmm8\n\t" + "psllw $2,%%xmm2\n\t" + /*xmm8={_x[7...0]!=0}*/ + "psubw %%xmm14,%%xmm8\n\t" + "psllw $2,%%xmm3\n\t" + /*%[a]=1*/ + "mov $1,%[a]\n\t" + /*xmm8={_x[6]!=0,0,_x[4]!=0,0,_x[2]!=0,0,_x[0]!=0,0}*/ + "pslld $16,%%xmm8\n\t" + "psllw $2,%%xmm4\n\t" + /*xmm9={0,0,0,0,0,0,0,1}*/ + "movd %[a],%%xmm9\n\t" + /*xmm8={0,0,_x[2]!=0,0,_x[0]!=0,0}*/ + "pshufhw $0x00,%%xmm8,%%xmm8\n\t" + "psllw $2,%%xmm5\n\t" + /*%[a]={1}x2*/ + "mov $0x10001,%[a]\n\t" + /*xmm8={0,0,0,0,0,0,0,_x[0]!=0}*/ + "pshuflw $0x01,%%xmm8,%%xmm8\n\t" + "psllw $2,%%xmm6\n\t" + /*xmm10={0,0,0,0,0,0,1,1}*/ + "movd %[a],%%xmm10\n\t" + /*xmm0=_x[7...0]+{0,0,0,0,0,0,0,_x[0]!=0}*/ + "paddw %%xmm8,%%xmm0\n\t" + "psllw $2,%%xmm7\n\t" + /*xmm0=_x[7...0]+{0,0,0,0,0,0,1,(_x[0]!=0)+1}*/ + "paddw %%xmm10,%%xmm0\n\t" + /*xmm1=_x[15...8]-{0,0,0,0,0,0,0,1}*/ + "psubw %%xmm9,%%xmm1\n\t" + /*Transform columns.*/ + OC_FDCT8x8 + /*Transform rows.*/ + OC_TRANSPOSE8x8 + OC_FDCT8x8 + /*TODO: zig-zag ordering?*/ + OC_TRANSPOSE8x8 + /*xmm14={-2,-2,-2,-2,-2,-2,-2,-2}*/ + "paddw %%xmm14,%%xmm14\n\t" + "psubw %%xmm14,%%xmm0\n\t" + "psubw %%xmm14,%%xmm1\n\t" + "psraw $2,%%xmm0\n\t" + "psubw %%xmm14,%%xmm2\n\t" + "psraw $2,%%xmm1\n\t" + "psubw %%xmm14,%%xmm3\n\t" + "psraw $2,%%xmm2\n\t" + "psubw %%xmm14,%%xmm4\n\t" + "psraw $2,%%xmm3\n\t" + "psubw %%xmm14,%%xmm5\n\t" + "psraw $2,%%xmm4\n\t" + "psubw %%xmm14,%%xmm6\n\t" + "psraw $2,%%xmm5\n\t" + "psubw %%xmm14,%%xmm7\n\t" + "psraw $2,%%xmm6\n\t" + "psraw $2,%%xmm7\n\t" + /*Store the result.*/ + "movdqa %%xmm0,0x00(%[y])\n\t" + "movdqa %%xmm1,0x10(%[y])\n\t" + "movdqa %%xmm2,0x20(%[y])\n\t" + "movdqa %%xmm3,0x30(%[y])\n\t" + "movdqa %%xmm4,0x40(%[y])\n\t" + "movdqa %%xmm5,0x50(%[y])\n\t" + "movdqa %%xmm6,0x60(%[y])\n\t" + "movdqa %%xmm7,0x70(%[y])\n\t" + :[a]"=&r"(a) + :[y]"r"(_y),[x]"r"(_x) + :"memory" + ); +} +#endif diff --git a/Engine/lib/libtheora/lib/x86/x86enc.c b/Engine/lib/libtheora/lib/x86/x86enc.c new file mode 100644 index 000000000..43b7be3ea --- /dev/null +++ b/Engine/lib/libtheora/lib/x86/x86enc.c @@ -0,0 +1,49 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: x86state.c 15675 2009-02-06 09:43:27Z tterribe $ + + ********************************************************************/ +#include "x86enc.h" + +#if defined(OC_X86_ASM) + +#include "../cpu.c" + +void oc_enc_vtable_init_x86(oc_enc_ctx *_enc){ + ogg_uint32_t cpu_flags; + cpu_flags=oc_cpu_flags_get(); + oc_enc_vtable_init_c(_enc); + if(cpu_flags&OC_CPU_X86_MMX){ + _enc->opt_vtable.frag_sub=oc_enc_frag_sub_mmx; + _enc->opt_vtable.frag_sub_128=oc_enc_frag_sub_128_mmx; + _enc->opt_vtable.frag_recon_intra=oc_frag_recon_intra_mmx; + _enc->opt_vtable.frag_recon_inter=oc_frag_recon_inter_mmx; + _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_mmx; + } + if(cpu_flags&OC_CPU_X86_MMXEXT){ + _enc->opt_vtable.frag_sad=oc_enc_frag_sad_mmxext; + _enc->opt_vtable.frag_sad_thresh=oc_enc_frag_sad_thresh_mmxext; + _enc->opt_vtable.frag_sad2_thresh=oc_enc_frag_sad2_thresh_mmxext; + _enc->opt_vtable.frag_satd_thresh=oc_enc_frag_satd_thresh_mmxext; + _enc->opt_vtable.frag_satd2_thresh=oc_enc_frag_satd2_thresh_mmxext; + _enc->opt_vtable.frag_intra_satd=oc_enc_frag_intra_satd_mmxext; + _enc->opt_vtable.frag_copy2=oc_enc_frag_copy2_mmxext; + } + if(cpu_flags&OC_CPU_X86_SSE2){ +# if defined(OC_X86_64_ASM) + /*_enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_x86_64sse2;*/ +# endif + } +} +#endif diff --git a/Engine/lib/libtheora/lib/x86/x86enc.h b/Engine/lib/libtheora/lib/x86/x86enc.h new file mode 100644 index 000000000..06c3908bc --- /dev/null +++ b/Engine/lib/libtheora/lib/x86/x86enc.h @@ -0,0 +1,47 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: x86int.h 15675 2009-02-06 09:43:27Z tterribe $ + + ********************************************************************/ + +#if !defined(_x86_x86enc_H) +# define _x86_x86enc_H (1) +# include "../encint.h" +# include "x86int.h" + +void oc_enc_vtable_init_x86(oc_enc_ctx *_enc); + +unsigned oc_enc_frag_sad_mmxext(const unsigned char *_src, + const unsigned char *_ref,int _ystride); +unsigned oc_enc_frag_sad_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _thresh); +unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref1,const unsigned char *_ref2,int _ystride, + unsigned _thresh); +unsigned oc_enc_frag_satd_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _thresh); +unsigned oc_enc_frag_satd2_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref1,const unsigned char *_ref2,int _ystride, + unsigned _thresh); +unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,int _ystride); +void oc_enc_frag_sub_mmx(ogg_int16_t _diff[64], + const unsigned char *_x,const unsigned char *_y,int _stride); +void oc_enc_frag_sub_128_mmx(ogg_int16_t _diff[64], + const unsigned char *_x,int _stride); +void oc_enc_frag_copy2_mmxext(unsigned char *_dst, + const unsigned char *_src1,const unsigned char *_src2,int _ystride); +void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]); +void oc_enc_fdct8x8_x86_64sse2(ogg_int16_t _y[64],const ogg_int16_t _x[64]); + +#endif diff --git a/Engine/lib/libtheora/lib/x86/x86int.h b/Engine/lib/libtheora/lib/x86/x86int.h new file mode 100644 index 000000000..ede724f5a --- /dev/null +++ b/Engine/lib/libtheora/lib/x86/x86int.h @@ -0,0 +1,42 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: x86int.h 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ + +#if !defined(_x86_x86int_H) +# define _x86_x86int_H (1) +# include "../internal.h" + +void oc_state_vtable_init_x86(oc_theora_state *_state); + +void oc_frag_copy_mmx(unsigned char *_dst, + const unsigned char *_src,int _ystride); +void oc_frag_recon_intra_mmx(unsigned char *_dst,int _ystride, + const ogg_int16_t *_residue); +void oc_frag_recon_inter_mmx(unsigned char *_dst, + const unsigned char *_src,int _ystride,const ogg_int16_t *_residue); +void oc_frag_recon_inter2_mmx(unsigned char *_dst,const unsigned char *_src1, + const unsigned char *_src2,int _ystride,const ogg_int16_t *_residue); +void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi); +void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi, + int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant); +void oc_state_frag_copy_list_mmx(const oc_theora_state *_state, + const ptrdiff_t *_fragis,ptrdiff_t _nfragis, + int _dst_frame,int _src_frame,int _pli); +void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state, + int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end); +void oc_restore_fpu_mmx(void); + +#endif diff --git a/Engine/lib/libtheora/lib/dec/x86/x86state.c b/Engine/lib/libtheora/lib/x86/x86state.c similarity index 58% rename from Engine/lib/libtheora/lib/dec/x86/x86state.c rename to Engine/lib/libtheora/lib/x86/x86state.c index 28a559ba4..a786bec28 100644 --- a/Engine/lib/libtheora/lib/dec/x86/x86state.c +++ b/Engine/lib/libtheora/lib/x86/x86state.c @@ -5,33 +5,57 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: x86state.c 15427 2008-10-21 02:36:19Z xiphmont $ + last mod: $Id: x86state.c 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ #include "x86int.h" -#if defined(USE_ASM) +#if defined(OC_X86_ASM) -#include "../../cpu.c" +#include "../cpu.c" + +/*This table has been modified from OC_FZIG_ZAG by baking a 4x4 transpose into + each quadrant of the destination.*/ +static const unsigned char OC_FZIG_ZAG_MMX[128]={ + 0, 8, 1, 2, 9,16,24,17, + 10, 3,32,11,18,25, 4,12, + 5,26,19,40,33,34,41,48, + 27, 6,13,20,28,21,14, 7, + 56,49,42,35,43,50,57,36, + 15,22,29,30,23,44,37,58, + 51,59,38,45,52,31,60,53, + 46,39,47,54,61,62,55,63, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, +}; void oc_state_vtable_init_x86(oc_theora_state *_state){ _state->cpu_flags=oc_cpu_flags_get(); if(_state->cpu_flags&OC_CPU_X86_MMX){ + _state->opt_vtable.frag_copy=oc_frag_copy_mmx; _state->opt_vtable.frag_recon_intra=oc_frag_recon_intra_mmx; _state->opt_vtable.frag_recon_inter=oc_frag_recon_inter_mmx; _state->opt_vtable.frag_recon_inter2=oc_frag_recon_inter2_mmx; - _state->opt_vtable.state_frag_copy=oc_state_frag_copy_mmx; + _state->opt_vtable.idct8x8=oc_idct8x8_mmx; _state->opt_vtable.state_frag_recon=oc_state_frag_recon_mmx; + _state->opt_vtable.state_frag_copy_list=oc_state_frag_copy_list_mmx; _state->opt_vtable.state_loop_filter_frag_rows= oc_state_loop_filter_frag_rows_mmx; _state->opt_vtable.restore_fpu=oc_restore_fpu_mmx; + _state->opt_data.dct_fzig_zag=OC_FZIG_ZAG_MMX; } else oc_state_vtable_init_c(_state); } diff --git a/Engine/lib/libtheora/lib/x86_vc/mmxencfrag.c b/Engine/lib/libtheora/lib/x86_vc/mmxencfrag.c new file mode 100644 index 000000000..94f1d0651 --- /dev/null +++ b/Engine/lib/libtheora/lib/x86_vc/mmxencfrag.c @@ -0,0 +1,969 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: dsp_mmx.c 14579 2008-03-12 06:42:40Z xiphmont $ + + ********************************************************************/ +#include +#include "x86enc.h" + +#if defined(OC_X86_ASM) + +unsigned oc_enc_frag_sad_mmxext(const unsigned char *_src, + const unsigned char *_ref,int _ystride){ + ptrdiff_t ret; + __asm{ +#define SRC esi +#define REF edx +#define YSTRIDE ecx +#define YSTRIDE3 edi + mov YSTRIDE,_ystride + mov SRC,_src + mov REF,_ref + /*Load the first 4 rows of each block.*/ + movq mm0,[SRC] + movq mm1,[REF] + movq mm2,[SRC][YSTRIDE] + movq mm3,[REF][YSTRIDE] + lea YSTRIDE3,[YSTRIDE+YSTRIDE*2] + movq mm4,[SRC+YSTRIDE*2] + movq mm5,[REF+YSTRIDE*2] + movq mm6,[SRC+YSTRIDE3] + movq mm7,[REF+YSTRIDE3] + /*Compute their SADs and add them in mm0*/ + psadbw mm0,mm1 + psadbw mm2,mm3 + lea SRC,[SRC+YSTRIDE*4] + paddw mm0,mm2 + lea REF,[REF+YSTRIDE*4] + /*Load the next 3 rows as registers become available.*/ + movq mm2,[SRC] + movq mm3,[REF] + psadbw mm4,mm5 + psadbw mm6,mm7 + paddw mm0,mm4 + movq mm5,[REF+YSTRIDE] + movq mm4,[SRC+YSTRIDE] + paddw mm0,mm6 + movq mm7,[REF+YSTRIDE*2] + movq mm6,[SRC+YSTRIDE*2] + /*Start adding their SADs to mm0*/ + psadbw mm2,mm3 + psadbw mm4,mm5 + paddw mm0,mm2 + psadbw mm6,mm7 + /*Load last row as registers become available.*/ + movq mm2,[SRC+YSTRIDE3] + movq mm3,[REF+YSTRIDE3] + /*And finish adding up their SADs.*/ + paddw mm0,mm4 + psadbw mm2,mm3 + paddw mm0,mm6 + paddw mm0,mm2 + movd [ret],mm0 +#undef SRC +#undef REF +#undef YSTRIDE +#undef YSTRIDE3 + } + return (unsigned)ret; +} + +unsigned oc_enc_frag_sad_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _thresh){ + /*Early termination is for suckers.*/ + return oc_enc_frag_sad_mmxext(_src,_ref,_ystride); +} + +#define OC_SAD2_LOOP __asm{ \ + /*We want to compute (mm0+mm1>>1) on unsigned bytes without overflow, but \ + pavgb computes (mm0+mm1+1>>1). \ + The latter is exactly 1 too large when the low bit of two corresponding \ + bytes is only set in one of them. \ + Therefore we pxor the operands, pand to mask out the low bits, and psubb to \ + correct the output of pavgb.*/ \ + __asm movq mm6,mm0 \ + __asm lea REF1,[REF1+YSTRIDE*2] \ + __asm pxor mm0,mm1 \ + __asm pavgb mm6,mm1 \ + __asm lea REF2,[REF2+YSTRIDE*2] \ + __asm movq mm1,mm2 \ + __asm pand mm0,mm7 \ + __asm pavgb mm2,mm3 \ + __asm pxor mm1,mm3 \ + __asm movq mm3,[REF2+YSTRIDE] \ + __asm psubb mm6,mm0 \ + __asm movq mm0,[REF1] \ + __asm pand mm1,mm7 \ + __asm psadbw mm4,mm6 \ + __asm movd mm6,RET \ + __asm psubb mm2,mm1 \ + __asm movq mm1,[REF2] \ + __asm lea SRC,[SRC+YSTRIDE*2] \ + __asm psadbw mm5,mm2 \ + __asm movq mm2,[REF1+YSTRIDE] \ + __asm paddw mm5,mm4 \ + __asm movq mm4,[SRC] \ + __asm paddw mm6,mm5 \ + __asm movq mm5,[SRC+YSTRIDE] \ + __asm movd RET,mm6 \ +} + +/*Same as above, but does not pre-load the next two rows.*/ +#define OC_SAD2_TAIL __asm{ \ + __asm movq mm6,mm0 \ + __asm pavgb mm0,mm1 \ + __asm pxor mm6,mm1 \ + __asm movq mm1,mm2 \ + __asm pand mm6,mm7 \ + __asm pavgb mm2,mm3 \ + __asm pxor mm1,mm3 \ + __asm psubb mm0,mm6 \ + __asm pand mm1,mm7 \ + __asm psadbw mm4,mm0 \ + __asm psubb mm2,mm1 \ + __asm movd mm6,RET \ + __asm psadbw mm5,mm2 \ + __asm paddw mm5,mm4 \ + __asm paddw mm6,mm5 \ + __asm movd RET,mm6 \ +} + +unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref1,const unsigned char *_ref2,int _ystride, + unsigned _thresh){ + ptrdiff_t ret; + __asm{ +#define REF1 ecx +#define REF2 edi +#define YSTRIDE esi +#define SRC edx +#define RET eax + mov YSTRIDE,_ystride + mov SRC,_src + mov REF1,_ref1 + mov REF2,_ref2 + movq mm0,[REF1] + movq mm1,[REF2] + movq mm2,[REF1+YSTRIDE] + movq mm3,[REF2+YSTRIDE] + xor RET,RET + movq mm4,[SRC] + pxor mm7,mm7 + pcmpeqb mm6,mm6 + movq mm5,[SRC+YSTRIDE] + psubb mm7,mm6 + OC_SAD2_LOOP + OC_SAD2_LOOP + OC_SAD2_LOOP + OC_SAD2_TAIL + mov [ret],RET +#undef REF1 +#undef REF2 +#undef YSTRIDE +#undef SRC +#undef RET + } + return (unsigned)ret; +} + +/*Load an 8x4 array of pixel values from %[src] and %[ref] and compute their + 16-bit difference in mm0...mm7.*/ +#define OC_LOAD_SUB_8x4(_off) __asm{ \ + __asm movd mm0,[_off+SRC] \ + __asm movd mm4,[_off+REF] \ + __asm movd mm1,[_off+SRC+SRC_YSTRIDE] \ + __asm lea SRC,[SRC+SRC_YSTRIDE*2] \ + __asm movd mm5,[_off+REF+REF_YSTRIDE] \ + __asm lea REF,[REF+REF_YSTRIDE*2] \ + __asm movd mm2,[_off+SRC] \ + __asm movd mm7,[_off+REF] \ + __asm movd mm3,[_off+SRC+SRC_YSTRIDE] \ + __asm movd mm6,[_off+REF+REF_YSTRIDE] \ + __asm punpcklbw mm0,mm4 \ + __asm lea SRC,[SRC+SRC_YSTRIDE*2] \ + __asm punpcklbw mm4,mm4 \ + __asm lea REF,[REF+REF_YSTRIDE*2] \ + __asm psubw mm0,mm4 \ + __asm movd mm4,[_off+SRC] \ + __asm movq [_off*2+BUF],mm0 \ + __asm movd mm0,[_off+REF] \ + __asm punpcklbw mm1,mm5 \ + __asm punpcklbw mm5,mm5 \ + __asm psubw mm1,mm5 \ + __asm movd mm5,[_off+SRC+SRC_YSTRIDE] \ + __asm punpcklbw mm2,mm7 \ + __asm punpcklbw mm7,mm7 \ + __asm psubw mm2,mm7 \ + __asm movd mm7,[_off+REF+REF_YSTRIDE] \ + __asm punpcklbw mm3,mm6 \ + __asm lea SRC,[SRC+SRC_YSTRIDE*2] \ + __asm punpcklbw mm6,mm6 \ + __asm psubw mm3,mm6 \ + __asm movd mm6,[_off+SRC] \ + __asm punpcklbw mm4,mm0 \ + __asm lea REF,[REF+REF_YSTRIDE*2] \ + __asm punpcklbw mm0,mm0 \ + __asm lea SRC,[SRC+SRC_YSTRIDE*2] \ + __asm psubw mm4,mm0 \ + __asm movd mm0,[_off+REF] \ + __asm punpcklbw mm5,mm7 \ + __asm neg SRC_YSTRIDE \ + __asm punpcklbw mm7,mm7 \ + __asm psubw mm5,mm7 \ + __asm movd mm7,[_off+SRC+SRC_YSTRIDE] \ + __asm punpcklbw mm6,mm0 \ + __asm lea REF,[REF+REF_YSTRIDE*2] \ + __asm punpcklbw mm0,mm0 \ + __asm neg REF_YSTRIDE \ + __asm psubw mm6,mm0 \ + __asm movd mm0,[_off+REF+REF_YSTRIDE] \ + __asm lea SRC,[SRC+SRC_YSTRIDE*8] \ + __asm punpcklbw mm7,mm0 \ + __asm neg SRC_YSTRIDE \ + __asm punpcklbw mm0,mm0 \ + __asm lea REF,[REF+REF_YSTRIDE*8] \ + __asm psubw mm7,mm0 \ + __asm neg REF_YSTRIDE \ + __asm movq mm0,[_off*2+BUF] \ +} + +/*Load an 8x4 array of pixel values from %[src] into %%mm0...%%mm7.*/ +#define OC_LOAD_8x4(_off) __asm{ \ + __asm movd mm0,[_off+SRC] \ + __asm movd mm1,[_off+SRC+YSTRIDE] \ + __asm movd mm2,[_off+SRC+YSTRIDE*2] \ + __asm pxor mm7,mm7 \ + __asm movd mm3,[_off+SRC+YSTRIDE3] \ + __asm punpcklbw mm0,mm7 \ + __asm movd mm4,[_off+SRC4] \ + __asm punpcklbw mm1,mm7 \ + __asm movd mm5,[_off+SRC4+YSTRIDE] \ + __asm punpcklbw mm2,mm7 \ + __asm movd mm6,[_off+SRC4+YSTRIDE*2] \ + __asm punpcklbw mm3,mm7 \ + __asm movd mm7,[_off+SRC4+YSTRIDE3] \ + __asm punpcklbw mm4,mm4 \ + __asm punpcklbw mm5,mm5 \ + __asm psrlw mm4,8 \ + __asm psrlw mm5,8 \ + __asm punpcklbw mm6,mm6 \ + __asm punpcklbw mm7,mm7 \ + __asm psrlw mm6,8 \ + __asm psrlw mm7,8 \ +} + +/*Performs the first two stages of an 8-point 1-D Hadamard transform. + The transform is performed in place, except that outputs 0-3 are swapped with + outputs 4-7. + Outputs 2, 3, 6 and 7 from the second stage are negated (which allows us to + perform this stage in place with no temporary registers).*/ +#define OC_HADAMARD_AB_8x4 __asm{ \ + /*Stage A: \ + Outputs 0-3 are swapped with 4-7 here.*/ \ + __asm paddw mm5,mm1 \ + __asm paddw mm6,mm2 \ + __asm paddw mm1,mm1 \ + __asm paddw mm2,mm2 \ + __asm psubw mm1,mm5 \ + __asm psubw mm2,mm6 \ + __asm paddw mm7,mm3 \ + __asm paddw mm4,mm0 \ + __asm paddw mm3,mm3 \ + __asm paddw mm0,mm0 \ + __asm psubw mm3,mm7 \ + __asm psubw mm0,mm4 \ + /*Stage B:*/ \ + __asm paddw mm0,mm2 \ + __asm paddw mm1,mm3 \ + __asm paddw mm4,mm6 \ + __asm paddw mm5,mm7 \ + __asm paddw mm2,mm2 \ + __asm paddw mm3,mm3 \ + __asm paddw mm6,mm6 \ + __asm paddw mm7,mm7 \ + __asm psubw mm2,mm0 \ + __asm psubw mm3,mm1 \ + __asm psubw mm6,mm4 \ + __asm psubw mm7,mm5 \ +} + +/*Performs the last stage of an 8-point 1-D Hadamard transform in place. + Ouputs 1, 3, 5, and 7 are negated (which allows us to perform this stage in + place with no temporary registers).*/ +#define OC_HADAMARD_C_8x4 __asm{ \ + /*Stage C:*/ \ + __asm paddw mm0,mm1 \ + __asm paddw mm2,mm3 \ + __asm paddw mm4,mm5 \ + __asm paddw mm6,mm7 \ + __asm paddw mm1,mm1 \ + __asm paddw mm3,mm3 \ + __asm paddw mm5,mm5 \ + __asm paddw mm7,mm7 \ + __asm psubw mm1,mm0 \ + __asm psubw mm3,mm2 \ + __asm psubw mm5,mm4 \ + __asm psubw mm7,mm6 \ +} + +/*Performs an 8-point 1-D Hadamard transform. + The transform is performed in place, except that outputs 0-3 are swapped with + outputs 4-7. + Outputs 1, 2, 5 and 6 are negated (which allows us to perform the transform + in place with no temporary registers).*/ +#define OC_HADAMARD_8x4 __asm{ \ + OC_HADAMARD_AB_8x4 \ + OC_HADAMARD_C_8x4 \ +} + +/*Performs the first part of the final stage of the Hadamard transform and + summing of absolute values. + At the end of this part, mm1 will contain the DC coefficient of the + transform.*/ +#define OC_HADAMARD_C_ABS_ACCUM_A_8x4(_r6,_r7) __asm{ \ + /*We use the fact that \ + (abs(a+b)+abs(a-b))/2=max(abs(a),abs(b)) \ + to merge the final butterfly with the abs and the first stage of \ + accumulation. \ + Thus we can avoid using pabsw, which is not available until SSSE3. \ + Emulating pabsw takes 3 instructions, so the straightforward MMXEXT \ + implementation would be (3+3)*8+7=55 instructions (+4 for spilling \ + registers). \ + Even with pabsw, it would be (3+1)*8+7=39 instructions (with no spills). \ + This implementation is only 26 (+4 for spilling registers).*/ \ + __asm movq [_r7+BUF],mm7 \ + __asm movq [_r6+BUF],mm6 \ + /*mm7={0x7FFF}x4 \ + mm0=max(abs(mm0),abs(mm1))-0x7FFF*/ \ + __asm pcmpeqb mm7,mm7 \ + __asm movq mm6,mm0 \ + __asm psrlw mm7,1 \ + __asm paddw mm6,mm1 \ + __asm pmaxsw mm0,mm1 \ + __asm paddsw mm6,mm7 \ + __asm psubw mm0,mm6 \ + /*mm2=max(abs(mm2),abs(mm3))-0x7FFF \ + mm4=max(abs(mm4),abs(mm5))-0x7FFF*/ \ + __asm movq mm6,mm2 \ + __asm movq mm1,mm4 \ + __asm pmaxsw mm2,mm3 \ + __asm pmaxsw mm4,mm5 \ + __asm paddw mm6,mm3 \ + __asm paddw mm1,mm5 \ + __asm movq mm3,[_r7+BUF] \ +} + +/*Performs the second part of the final stage of the Hadamard transform and + summing of absolute values.*/ +#define OC_HADAMARD_C_ABS_ACCUM_B_8x4(_r6,_r7) __asm{ \ + __asm paddsw mm6,mm7 \ + __asm movq mm5,[_r6+BUF] \ + __asm paddsw mm1,mm7 \ + __asm psubw mm2,mm6 \ + __asm psubw mm4,mm1 \ + /*mm7={1}x4 (needed for the horizontal add that follows) \ + mm0+=mm2+mm4+max(abs(mm3),abs(mm5))-0x7FFF*/ \ + __asm movq mm6,mm3 \ + __asm pmaxsw mm3,mm5 \ + __asm paddw mm0,mm2 \ + __asm paddw mm6,mm5 \ + __asm paddw mm0,mm4 \ + __asm paddsw mm6,mm7 \ + __asm paddw mm0,mm3 \ + __asm psrlw mm7,14 \ + __asm psubw mm0,mm6 \ +} + +/*Performs the last stage of an 8-point 1-D Hadamard transform, takes the + absolute value of each component, and accumulates everything into mm0. + This is the only portion of SATD which requires MMXEXT (we could use plain + MMX, but it takes 4 instructions and an extra register to work around the + lack of a pmaxsw, which is a pretty serious penalty).*/ +#define OC_HADAMARD_C_ABS_ACCUM_8x4(_r6,_r7) __asm{ \ + OC_HADAMARD_C_ABS_ACCUM_A_8x4(_r6,_r7) \ + OC_HADAMARD_C_ABS_ACCUM_B_8x4(_r6,_r7) \ +} + +/*Performs an 8-point 1-D Hadamard transform, takes the absolute value of each + component, and accumulates everything into mm0. + Note that mm0 will have an extra 4 added to each column, and that after + removing this value, the remainder will be half the conventional value.*/ +#define OC_HADAMARD_ABS_ACCUM_8x4(_r6,_r7) __asm{ \ + OC_HADAMARD_AB_8x4 \ + OC_HADAMARD_C_ABS_ACCUM_8x4(_r6,_r7) \ +} + +/*Performs two 4x4 transposes (mostly) in place. + On input, {mm0,mm1,mm2,mm3} contains rows {e,f,g,h}, and {mm4,mm5,mm6,mm7} + contains rows {a,b,c,d}. + On output, {0x40,0x50,0x60,0x70}+_off+BUF contains {e,f,g,h}^T, and + {mm4,mm5,mm6,mm7} contains the transposed rows {a,b,c,d}^T.*/ +#define OC_TRANSPOSE_4x4x2(_off) __asm{ \ + /*First 4x4 transpose:*/ \ + __asm movq [0x10+_off+BUF],mm5 \ + /*mm0 = e3 e2 e1 e0 \ + mm1 = f3 f2 f1 f0 \ + mm2 = g3 g2 g1 g0 \ + mm3 = h3 h2 h1 h0*/ \ + __asm movq mm5,mm2 \ + __asm punpcklwd mm2,mm3 \ + __asm punpckhwd mm5,mm3 \ + __asm movq mm3,mm0 \ + __asm punpcklwd mm0,mm1 \ + __asm punpckhwd mm3,mm1 \ + /*mm0 = f1 e1 f0 e0 \ + mm3 = f3 e3 f2 e2 \ + mm2 = h1 g1 h0 g0 \ + mm5 = h3 g3 h2 g2*/ \ + __asm movq mm1,mm0 \ + __asm punpckldq mm0,mm2 \ + __asm punpckhdq mm1,mm2 \ + __asm movq mm2,mm3 \ + __asm punpckhdq mm3,mm5 \ + __asm movq [0x40+_off+BUF],mm0 \ + __asm punpckldq mm2,mm5 \ + /*mm0 = h0 g0 f0 e0 \ + mm1 = h1 g1 f1 e1 \ + mm2 = h2 g2 f2 e2 \ + mm3 = h3 g3 f3 e3*/ \ + __asm movq mm5,[0x10+_off+BUF] \ + /*Second 4x4 transpose:*/ \ + /*mm4 = a3 a2 a1 a0 \ + mm5 = b3 b2 b1 b0 \ + mm6 = c3 c2 c1 c0 \ + mm7 = d3 d2 d1 d0*/ \ + __asm movq mm0,mm6 \ + __asm punpcklwd mm6,mm7 \ + __asm movq [0x50+_off+BUF],mm1 \ + __asm punpckhwd mm0,mm7 \ + __asm movq mm7,mm4 \ + __asm punpcklwd mm4,mm5 \ + __asm movq [0x60+_off+BUF],mm2 \ + __asm punpckhwd mm7,mm5 \ + /*mm4 = b1 a1 b0 a0 \ + mm7 = b3 a3 b2 a2 \ + mm6 = d1 c1 d0 c0 \ + mm0 = d3 c3 d2 c2*/ \ + __asm movq mm5,mm4 \ + __asm punpckldq mm4,mm6 \ + __asm movq [0x70+_off+BUF],mm3 \ + __asm punpckhdq mm5,mm6 \ + __asm movq mm6,mm7 \ + __asm punpckhdq mm7,mm0 \ + __asm punpckldq mm6,mm0 \ + /*mm4 = d0 c0 b0 a0 \ + mm5 = d1 c1 b1 a1 \ + mm6 = d2 c2 b2 a2 \ + mm7 = d3 c3 b3 a3*/ \ +} + +static unsigned oc_int_frag_satd_thresh_mmxext(const unsigned char *_src, + int _src_ystride,const unsigned char *_ref,int _ref_ystride,unsigned _thresh){ + OC_ALIGN8(ogg_int16_t buf[64]); + ogg_int16_t *bufp; + unsigned ret1; + unsigned ret2; + bufp=buf; + __asm{ +#define SRC esi +#define REF eax +#define SRC_YSTRIDE ecx +#define REF_YSTRIDE edx +#define BUF edi +#define RET eax +#define RET2 edx + mov SRC,_src + mov SRC_YSTRIDE,_src_ystride + mov REF,_ref + mov REF_YSTRIDE,_ref_ystride + mov BUF,bufp + OC_LOAD_SUB_8x4(0x00) + OC_HADAMARD_8x4 + OC_TRANSPOSE_4x4x2(0x00) + /*Finish swapping out this 8x4 block to make room for the next one. + mm0...mm3 have been swapped out already.*/ + movq [0x00+BUF],mm4 + movq [0x10+BUF],mm5 + movq [0x20+BUF],mm6 + movq [0x30+BUF],mm7 + OC_LOAD_SUB_8x4(0x04) + OC_HADAMARD_8x4 + OC_TRANSPOSE_4x4x2(0x08) + /*Here the first 4x4 block of output from the last transpose is the second + 4x4 block of input for the next transform. + We have cleverly arranged that it already be in the appropriate place, so + we only have to do half the loads.*/ + movq mm1,[0x10+BUF] + movq mm2,[0x20+BUF] + movq mm3,[0x30+BUF] + movq mm0,[0x00+BUF] + OC_HADAMARD_ABS_ACCUM_8x4(0x28,0x38) + /*Up to this point, everything fit in 16 bits (8 input + 1 for the + difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1 + for the factor of two we dropped + 3 for the vertical accumulation). + Now we finally have to promote things to dwords. + We break this part out of OC_HADAMARD_ABS_ACCUM_8x4 to hide the long + latency of pmaddwd by starting the next series of loads now.*/ + mov RET2,_thresh + pmaddwd mm0,mm7 + movq mm1,[0x50+BUF] + movq mm5,[0x58+BUF] + movq mm4,mm0 + movq mm2,[0x60+BUF] + punpckhdq mm0,mm0 + movq mm6,[0x68+BUF] + paddd mm4,mm0 + movq mm3,[0x70+BUF] + movd RET,mm4 + movq mm7,[0x78+BUF] + /*The sums produced by OC_HADAMARD_ABS_ACCUM_8x4 each have an extra 4 + added to them, and a factor of two removed; correct the final sum here.*/ + lea RET,[RET+RET-32] + movq mm0,[0x40+BUF] + cmp RET,RET2 + movq mm4,[0x48+BUF] + jae at_end + OC_HADAMARD_ABS_ACCUM_8x4(0x68,0x78) + pmaddwd mm0,mm7 + /*There isn't much to stick in here to hide the latency this time, but the + alternative to pmaddwd is movq->punpcklwd->punpckhwd->paddd, whose + latency is even worse.*/ + sub RET,32 + movq mm4,mm0 + punpckhdq mm0,mm0 + paddd mm4,mm0 + movd RET2,mm4 + lea RET,[RET+RET2*2] + align 16 +at_end: + mov ret1,RET +#undef SRC +#undef REF +#undef SRC_YSTRIDE +#undef REF_YSTRIDE +#undef BUF +#undef RET +#undef RET2 + } + return ret1; +} + +unsigned oc_enc_frag_satd_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _thresh){ + return oc_int_frag_satd_thresh_mmxext(_src,_ystride,_ref,_ystride,_thresh); +} + + +/*Our internal implementation of frag_copy2 takes an extra stride parameter so + we can share code with oc_enc_frag_satd2_thresh_mmxext().*/ +static void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride, + const unsigned char *_src1,const unsigned char *_src2,int _src_ystride){ + __asm{ + /*Load the first 3 rows.*/ +#define DST_YSTRIDE edi +#define SRC_YSTRIDE esi +#define DST eax +#define SRC1 edx +#define SRC2 ecx + mov DST_YSTRIDE,_dst_ystride + mov SRC_YSTRIDE,_src_ystride + mov DST,_dst + mov SRC1,_src1 + mov SRC2,_src2 + movq mm0,[SRC1] + movq mm1,[SRC2] + movq mm2,[SRC1+SRC_YSTRIDE] + lea SRC1,[SRC1+SRC_YSTRIDE*2] + movq mm3,[SRC2+SRC_YSTRIDE] + lea SRC2,[SRC2+SRC_YSTRIDE*2] + pxor mm7,mm7 + movq mm4,[SRC1] + pcmpeqb mm6,mm6 + movq mm5,[SRC2] + /*mm7={1}x8.*/ + psubb mm7,mm6 + /*Start averaging mm0 and mm1 into mm6.*/ + movq mm6,mm0 + pxor mm0,mm1 + pavgb mm6,mm1 + /*mm1 is free, start averaging mm3 into mm2 using mm1.*/ + movq mm1,mm2 + pand mm0,mm7 + pavgb mm2,mm3 + pxor mm1,mm3 + /*mm3 is free.*/ + psubb mm6,mm0 + /*mm0 is free, start loading the next row.*/ + movq mm0,[SRC1+SRC_YSTRIDE] + /*Start averaging mm5 and mm4 using mm3.*/ + movq mm3,mm4 + /*mm6 [row 0] is done; write it out.*/ + movq [DST],mm6 + pand mm1,mm7 + pavgb mm4,mm5 + psubb mm2,mm1 + /*mm1 is free, continue loading the next row.*/ + movq mm1,[SRC2+SRC_YSTRIDE] + pxor mm3,mm5 + lea SRC1,[SRC1+SRC_YSTRIDE*2] + /*mm2 [row 1] is done; write it out.*/ + movq [DST+DST_YSTRIDE],mm2 + pand mm3,mm7 + /*Start loading the next row.*/ + movq mm2,[SRC1] + lea DST,[DST+DST_YSTRIDE*2] + psubb mm4,mm3 + lea SRC2,[SRC2+SRC_YSTRIDE*2] + /*mm4 [row 2] is done; write it out.*/ + movq [DST],mm4 + /*Continue loading the next row.*/ + movq mm3,[SRC2] + /*Start averaging mm0 and mm1 into mm6.*/ + movq mm6,mm0 + pxor mm0,mm1 + /*Start loading the next row.*/ + movq mm4,[SRC1+SRC_YSTRIDE] + pavgb mm6,mm1 + /*mm1 is free; start averaging mm3 into mm2 using mm1.*/ + movq mm1,mm2 + pand mm0,mm7 + /*Continue loading the next row.*/ + movq mm5,[SRC2+SRC_YSTRIDE] + pavgb mm2,mm3 + lea SRC1,[SRC1+SRC_YSTRIDE*2] + pxor mm1,mm3 + /*mm3 is free.*/ + psubb mm6,mm0 + /*mm0 is free, start loading the next row.*/ + movq mm0,[SRC1] + /*Start averaging mm5 into mm4 using mm3.*/ + movq mm3,mm4 + /*mm6 [row 3] is done; write it out.*/ + movq [DST+DST_YSTRIDE],mm6 + pand mm1,mm7 + lea SRC2,[SRC2+SRC_YSTRIDE*2] + pavgb mm4,mm5 + lea DST,[DST+DST_YSTRIDE*2] + psubb mm2,mm1 + /*mm1 is free; continue loading the next row.*/ + movq mm1,[SRC2] + pxor mm3,mm5 + /*mm2 [row 4] is done; write it out.*/ + movq [DST],mm2 + pand mm3,mm7 + /*Start loading the next row.*/ + movq mm2,[SRC1+SRC_YSTRIDE] + psubb mm4,mm3 + /*Start averaging mm0 and mm1 into mm6.*/ + movq mm6,mm0 + /*Continue loading the next row.*/ + movq mm3,[SRC2+SRC_YSTRIDE] + /*mm4 [row 5] is done; write it out.*/ + movq [DST+DST_YSTRIDE],mm4 + pxor mm0,mm1 + pavgb mm6,mm1 + /*mm4 is free; start averaging mm3 into mm2 using mm4.*/ + movq mm4,mm2 + pand mm0,mm7 + pavgb mm2,mm3 + pxor mm4,mm3 + lea DST,[DST+DST_YSTRIDE*2] + psubb mm6,mm0 + pand mm4,mm7 + /*mm6 [row 6] is done, write it out.*/ + movq [DST],mm6 + psubb mm2,mm4 + /*mm2 [row 7] is done, write it out.*/ + movq [DST+DST_YSTRIDE],mm2 +#undef SRC1 +#undef SRC2 +#undef SRC_YSTRIDE +#undef DST_YSTRIDE +#undef DST + } +} + +unsigned oc_enc_frag_satd2_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref1,const unsigned char *_ref2,int _ystride, + unsigned _thresh){ + OC_ALIGN8(unsigned char ref[64]); + oc_int_frag_copy2_mmxext(ref,8,_ref1,_ref2,_ystride); + return oc_int_frag_satd_thresh_mmxext(_src,_ystride,ref,8,_thresh); +} + +unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src, + int _ystride){ + OC_ALIGN8(ogg_int16_t buf[64]); + ogg_int16_t *bufp; + unsigned ret1; + unsigned ret2; + bufp=buf; + __asm{ +#define SRC eax +#define SRC4 esi +#define BUF edi +#define RET eax +#define RET_WORD ax +#define RET2 ecx +#define YSTRIDE edx +#define YSTRIDE3 ecx + mov SRC,_src + mov BUF,bufp + mov YSTRIDE,_ystride + /* src4 = src+4*ystride */ + lea SRC4,[SRC+YSTRIDE*4] + /* ystride3 = 3*ystride */ + lea YSTRIDE3,[YSTRIDE+YSTRIDE*2] + OC_LOAD_8x4(0x00) + OC_HADAMARD_8x4 + OC_TRANSPOSE_4x4x2(0x00) + /*Finish swapping out this 8x4 block to make room for the next one. + mm0...mm3 have been swapped out already.*/ + movq [0x00+BUF],mm4 + movq [0x10+BUF],mm5 + movq [0x20+BUF],mm6 + movq [0x30+BUF],mm7 + OC_LOAD_8x4(0x04) + OC_HADAMARD_8x4 + OC_TRANSPOSE_4x4x2(0x08) + /*Here the first 4x4 block of output from the last transpose is the second + 4x4 block of input for the next transform. + We have cleverly arranged that it already be in the appropriate place, so + we only have to do half the loads.*/ + movq mm1,[0x10+BUF] + movq mm2,[0x20+BUF] + movq mm3,[0x30+BUF] + movq mm0,[0x00+BUF] + /*We split out the stages here so we can save the DC coefficient in the + middle.*/ + OC_HADAMARD_AB_8x4 + OC_HADAMARD_C_ABS_ACCUM_A_8x4(0x28,0x38) + movd RET,mm1 + OC_HADAMARD_C_ABS_ACCUM_B_8x4(0x28,0x38) + /*Up to this point, everything fit in 16 bits (8 input + 1 for the + difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1 + for the factor of two we dropped + 3 for the vertical accumulation). + Now we finally have to promote things to dwords. + We break this part out of OC_HADAMARD_ABS_ACCUM_8x4 to hide the long + latency of pmaddwd by starting the next series of loads now.*/ + pmaddwd mm0,mm7 + movq mm1,[0x50+BUF] + movq mm5,[0x58+BUF] + movq mm2,[0x60+BUF] + movq mm4,mm0 + movq mm6,[0x68+BUF] + punpckhdq mm0,mm0 + movq mm3,[0x70+BUF] + paddd mm4,mm0 + movq mm7,[0x78+BUF] + movd RET2,mm4 + movq mm0,[0x40+BUF] + movq mm4,[0x48+BUF] + OC_HADAMARD_ABS_ACCUM_8x4(0x68,0x78) + pmaddwd mm0,mm7 + /*We assume that the DC coefficient is always positive (which is true, + because the input to the INTRA transform was not a difference).*/ + movzx RET,RET_WORD + add RET2,RET2 + sub RET2,RET + movq mm4,mm0 + punpckhdq mm0,mm0 + paddd mm4,mm0 + movd RET,mm4 + lea RET,[-64+RET2+RET*2] + mov [ret1],RET +#undef SRC +#undef SRC4 +#undef BUF +#undef RET +#undef RET_WORD +#undef RET2 +#undef YSTRIDE +#undef YSTRIDE3 + } + return ret1; +} + +void oc_enc_frag_sub_mmx(ogg_int16_t _residue[64], + const unsigned char *_src, const unsigned char *_ref,int _ystride){ + int i; + __asm pxor mm7,mm7 + for(i=4;i-->0;){ + __asm{ +#define SRC edx +#define YSTRIDE esi +#define RESIDUE eax +#define REF ecx + mov YSTRIDE,_ystride + mov RESIDUE,_residue + mov SRC,_src + mov REF,_ref + /*mm0=[src]*/ + movq mm0,[SRC] + /*mm1=[ref]*/ + movq mm1,[REF] + /*mm4=[src+ystride]*/ + movq mm4,[SRC+YSTRIDE] + /*mm5=[ref+ystride]*/ + movq mm5,[REF+YSTRIDE] + /*Compute [src]-[ref].*/ + movq mm2,mm0 + punpcklbw mm0,mm7 + movq mm3,mm1 + punpckhbw mm2,mm7 + punpcklbw mm1,mm7 + punpckhbw mm3,mm7 + psubw mm0,mm1 + psubw mm2,mm3 + /*Compute [src+ystride]-[ref+ystride].*/ + movq mm1,mm4 + punpcklbw mm4,mm7 + movq mm3,mm5 + punpckhbw mm1,mm7 + lea SRC,[SRC+YSTRIDE*2] + punpcklbw mm5,mm7 + lea REF,[REF+YSTRIDE*2] + punpckhbw mm3,mm7 + psubw mm4,mm5 + psubw mm1,mm3 + /*Write the answer out.*/ + movq [RESIDUE+0x00],mm0 + movq [RESIDUE+0x08],mm2 + movq [RESIDUE+0x10],mm4 + movq [RESIDUE+0x18],mm1 + lea RESIDUE,[RESIDUE+0x20] + mov _residue,RESIDUE + mov _src,SRC + mov _ref,REF +#undef SRC +#undef YSTRIDE +#undef RESIDUE +#undef REF + } + } +} + +void oc_enc_frag_sub_128_mmx(ogg_int16_t _residue[64], + const unsigned char *_src,int _ystride){ + __asm{ +#define YSTRIDE edx +#define YSTRIDE3 edi +#define RESIDUE ecx +#define SRC eax + mov YSTRIDE,_ystride + mov RESIDUE,_residue + mov SRC,_src + /*mm0=[src]*/ + movq mm0,[SRC] + /*mm1=[src+ystride]*/ + movq mm1,[SRC+YSTRIDE] + /*mm6={-1}x4*/ + pcmpeqw mm6,mm6 + /*mm2=[src+2*ystride]*/ + movq mm2,[SRC+YSTRIDE*2] + /*[ystride3]=3*[ystride]*/ + lea YSTRIDE3,[YSTRIDE+YSTRIDE*2] + /*mm6={1}x4*/ + psllw mm6,15 + /*mm3=[src+3*ystride]*/ + movq mm3,[SRC+YSTRIDE3] + /*mm6={128}x4*/ + psrlw mm6,8 + /*mm7=0*/ + pxor mm7,mm7 + /*[src]=[src]+4*[ystride]*/ + lea SRC,[SRC+YSTRIDE*4] + /*Compute [src]-128 and [src+ystride]-128*/ + movq mm4,mm0 + punpcklbw mm0,mm7 + movq mm5,mm1 + punpckhbw mm4,mm7 + psubw mm0,mm6 + punpcklbw mm1,mm7 + psubw mm4,mm6 + punpckhbw mm5,mm7 + psubw mm1,mm6 + psubw mm5,mm6 + /*Write the answer out.*/ + movq [RESIDUE+0x00],mm0 + movq [RESIDUE+0x08],mm4 + movq [RESIDUE+0x10],mm1 + movq [RESIDUE+0x18],mm5 + /*mm0=[src+4*ystride]*/ + movq mm0,[SRC] + /*mm1=[src+5*ystride]*/ + movq mm1,[SRC+YSTRIDE] + /*Compute [src+2*ystride]-128 and [src+3*ystride]-128*/ + movq mm4,mm2 + punpcklbw mm2,mm7 + movq mm5,mm3 + punpckhbw mm4,mm7 + psubw mm2,mm6 + punpcklbw mm3,mm7 + psubw mm4,mm6 + punpckhbw mm5,mm7 + psubw mm3,mm6 + psubw mm5,mm6 + /*Write the answer out.*/ + movq [RESIDUE+0x20],mm2 + movq [RESIDUE+0x28],mm4 + movq [RESIDUE+0x30],mm3 + movq [RESIDUE+0x38],mm5 + /*Compute [src+6*ystride]-128 and [src+7*ystride]-128*/ + movq mm2,[SRC+YSTRIDE*2] + movq mm3,[SRC+YSTRIDE3] + movq mm4,mm0 + punpcklbw mm0,mm7 + movq mm5,mm1 + punpckhbw mm4,mm7 + psubw mm0,mm6 + punpcklbw mm1,mm7 + psubw mm4,mm6 + punpckhbw mm5,mm7 + psubw mm1,mm6 + psubw mm5,mm6 + /*Write the answer out.*/ + movq [RESIDUE+0x40],mm0 + movq [RESIDUE+0x48],mm4 + movq [RESIDUE+0x50],mm1 + movq [RESIDUE+0x58],mm5 + /*Compute [src+6*ystride]-128 and [src+7*ystride]-128*/ + movq mm4,mm2 + punpcklbw mm2,mm7 + movq mm5,mm3 + punpckhbw mm4,mm7 + psubw mm2,mm6 + punpcklbw mm3,mm7 + psubw mm4,mm6 + punpckhbw mm5,mm7 + psubw mm3,mm6 + psubw mm5,mm6 + /*Write the answer out.*/ + movq [RESIDUE+0x60],mm2 + movq [RESIDUE+0x68],mm4 + movq [RESIDUE+0x70],mm3 + movq [RESIDUE+0x78],mm5 +#undef YSTRIDE +#undef YSTRIDE3 +#undef RESIDUE +#undef SRC + } +} + +void oc_enc_frag_copy2_mmxext(unsigned char *_dst, + const unsigned char *_src1,const unsigned char *_src2,int _ystride){ + oc_int_frag_copy2_mmxext(_dst,_ystride,_src1,_src2,_ystride); +} + +#endif diff --git a/Engine/lib/libtheora/lib/x86_vc/mmxfdct.c b/Engine/lib/libtheora/lib/x86_vc/mmxfdct.c new file mode 100644 index 000000000..d908ce241 --- /dev/null +++ b/Engine/lib/libtheora/lib/x86_vc/mmxfdct.c @@ -0,0 +1,670 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 1999-2006 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ********************************************************************/ + /*MMX fDCT implementation for x86_32*/ +/*$Id: fdct_ses2.c 14579 2008-03-12 06:42:40Z xiphmont $*/ +#include "x86enc.h" + +#if defined(OC_X86_ASM) + +#define OC_FDCT_STAGE1_8x4 __asm{ \ + /*Stage 1:*/ \ + /*mm0=t7'=t0-t7*/ \ + __asm psubw mm0,mm7 \ + __asm paddw mm7,mm7 \ + /*mm1=t6'=t1-t6*/ \ + __asm psubw mm1, mm6 \ + __asm paddw mm6,mm6 \ + /*mm2=t5'=t2-t5*/ \ + __asm psubw mm2,mm5 \ + __asm paddw mm5,mm5 \ + /*mm3=t4'=t3-t4*/ \ + __asm psubw mm3,mm4 \ + __asm paddw mm4,mm4 \ + /*mm7=t0'=t0+t7*/ \ + __asm paddw mm7,mm0 \ + /*mm6=t1'=t1+t6*/ \ + __asm paddw mm6,mm1 \ + /*mm5=t2'=t2+t5*/ \ + __asm paddw mm5,mm2 \ + /*mm4=t3'=t3+t4*/ \ + __asm paddw mm4,mm3\ +} + +#define OC_FDCT8x4(_r0,_r1,_r2,_r3,_r4,_r5,_r6,_r7) __asm{ \ + /*Stage 2:*/ \ + /*mm7=t3''=t0'-t3'*/ \ + __asm psubw mm7,mm4 \ + __asm paddw mm4,mm4 \ + /*mm6=t2''=t1'-t2'*/ \ + __asm psubw mm6,mm5 \ + __asm movq [Y+_r6],mm7 \ + __asm paddw mm5,mm5 \ + /*mm1=t5''=t6'-t5'*/ \ + __asm psubw mm1,mm2 \ + __asm movq [Y+_r2],mm6 \ + /*mm4=t0''=t0'+t3'*/ \ + __asm paddw mm4,mm7 \ + __asm paddw mm2,mm2 \ + /*mm5=t1''=t1'+t2'*/ \ + __asm movq [Y+_r0],mm4 \ + __asm paddw mm5,mm6 \ + /*mm2=t6''=t6'+t5'*/ \ + __asm paddw mm2,mm1 \ + __asm movq [Y+_r4],mm5 \ + /*mm0=t7', mm1=t5'', mm2=t6'', mm3=t4'.*/ \ + /*mm4, mm5, mm6, mm7 are free.*/ \ + /*Stage 3:*/ \ + /*mm6={2}x4, mm7={27146,0xB500>>1}x2*/ \ + __asm mov A,0x5A806A0A \ + __asm pcmpeqb mm6,mm6 \ + __asm movd mm7,A \ + __asm psrlw mm6,15 \ + __asm punpckldq mm7,mm7 \ + __asm paddw mm6,mm6 \ + /*mm0=0, m2={-1}x4 \ + mm5:mm4=t5''*27146+0xB500*/ \ + __asm movq mm4,mm1 \ + __asm movq mm5,mm1 \ + __asm punpcklwd mm4,mm6 \ + __asm movq [Y+_r3],mm2 \ + __asm pmaddwd mm4,mm7 \ + __asm movq [Y+_r7],mm0 \ + __asm punpckhwd mm5,mm6 \ + __asm pxor mm0,mm0 \ + __asm pmaddwd mm5,mm7 \ + __asm pcmpeqb mm2,mm2 \ + /*mm2=t6'', mm1=t5''+(t5''!=0) \ + mm4=(t5''*27146+0xB500>>16)*/ \ + __asm pcmpeqw mm0,mm1 \ + __asm psrad mm4,16 \ + __asm psubw mm0,mm2 \ + __asm movq mm2, [Y+_r3] \ + __asm psrad mm5,16 \ + __asm paddw mm1,mm0 \ + __asm packssdw mm4,mm5 \ + /*mm4=s=(t5''*27146+0xB500>>16)+t5''+(t5''!=0)>>1*/ \ + __asm paddw mm4,mm1 \ + __asm movq mm0, [Y+_r7] \ + __asm psraw mm4,1 \ + __asm movq mm1,mm3 \ + /*mm3=t4''=t4'+s*/ \ + __asm paddw mm3,mm4 \ + /*mm1=t5'''=t4'-s*/ \ + __asm psubw mm1,mm4 \ + /*mm1=0, mm3={-1}x4 \ + mm5:mm4=t6''*27146+0xB500*/ \ + __asm movq mm4,mm2 \ + __asm movq mm5,mm2 \ + __asm punpcklwd mm4,mm6 \ + __asm movq [Y+_r5],mm1 \ + __asm pmaddwd mm4,mm7 \ + __asm movq [Y+_r1],mm3 \ + __asm punpckhwd mm5,mm6 \ + __asm pxor mm1,mm1 \ + __asm pmaddwd mm5,mm7 \ + __asm pcmpeqb mm3,mm3 \ + /*mm2=t6''+(t6''!=0), mm4=(t6''*27146+0xB500>>16)*/ \ + __asm psrad mm4,16 \ + __asm pcmpeqw mm1,mm2 \ + __asm psrad mm5,16 \ + __asm psubw mm1,mm3 \ + __asm packssdw mm4,mm5 \ + __asm paddw mm2,mm1 \ + /*mm1=t1'' \ + mm4=s=(t6''*27146+0xB500>>16)+t6''+(t6''!=0)>>1*/ \ + __asm paddw mm4,mm2 \ + __asm movq mm1,[Y+_r4] \ + __asm psraw mm4,1 \ + __asm movq mm2,mm0 \ + /*mm7={54491-0x7FFF,0x7FFF}x2 \ + mm0=t7''=t7'+s*/ \ + __asm paddw mm0,mm4 \ + /*mm2=t6'''=t7'-s*/ \ + __asm psubw mm2,mm4 \ + /*Stage 4:*/ \ + /*mm0=0, mm2=t0'' \ + mm5:mm4=t1''*27146+0xB500*/ \ + __asm movq mm4,mm1 \ + __asm movq mm5,mm1 \ + __asm punpcklwd mm4,mm6 \ + __asm movq [Y+_r3],mm2 \ + __asm pmaddwd mm4,mm7 \ + __asm movq mm2,[Y+_r0] \ + __asm punpckhwd mm5,mm6 \ + __asm movq [Y+_r7],mm0 \ + __asm pmaddwd mm5,mm7 \ + __asm pxor mm0,mm0 \ + /*mm7={27146,0x4000>>1}x2 \ + mm0=s=(t1''*27146+0xB500>>16)+t1''+(t1''!=0)*/ \ + __asm psrad mm4,16 \ + __asm mov A,0x20006A0A \ + __asm pcmpeqw mm0,mm1 \ + __asm movd mm7,A \ + __asm psrad mm5,16 \ + __asm psubw mm0,mm3 \ + __asm packssdw mm4,mm5 \ + __asm paddw mm0,mm1 \ + __asm punpckldq mm7,mm7 \ + __asm paddw mm0,mm4 \ + /*mm6={0x00000E3D}x2 \ + mm1=-(t0''==0), mm5:mm4=t0''*27146+0x4000*/ \ + __asm movq mm4,mm2 \ + __asm movq mm5,mm2 \ + __asm punpcklwd mm4,mm6 \ + __asm mov A,0x0E3D \ + __asm pmaddwd mm4,mm7 \ + __asm punpckhwd mm5,mm6 \ + __asm movd mm6,A \ + __asm pmaddwd mm5,mm7 \ + __asm pxor mm1,mm1 \ + __asm punpckldq mm6,mm6 \ + __asm pcmpeqw mm1,mm2 \ + /*mm4=r=(t0''*27146+0x4000>>16)+t0''+(t0''!=0)*/ \ + __asm psrad mm4,16 \ + __asm psubw mm1,mm3 \ + __asm psrad mm5,16 \ + __asm paddw mm2,mm1 \ + __asm packssdw mm4,mm5 \ + __asm movq mm1,[Y+_r5] \ + __asm paddw mm4,mm2 \ + /*mm2=t6'', mm0=_y[0]=u=r+s>>1 \ + The naive implementation could cause overflow, so we use \ + u=(r&s)+((r^s)>>1).*/ \ + __asm movq mm2,[Y+_r3] \ + __asm movq mm7,mm0 \ + __asm pxor mm0,mm4 \ + __asm pand mm7,mm4 \ + __asm psraw mm0,1 \ + __asm mov A,0x7FFF54DC \ + __asm paddw mm0,mm7 \ + __asm movd mm7,A \ + /*mm7={54491-0x7FFF,0x7FFF}x2 \ + mm4=_y[4]=v=r-u*/ \ + __asm psubw mm4,mm0 \ + __asm punpckldq mm7,mm7 \ + __asm movq [Y+_r4],mm4 \ + /*mm0=0, mm7={36410}x4 \ + mm1=(t5'''!=0), mm5:mm4=54491*t5'''+0x0E3D*/ \ + __asm movq mm4,mm1 \ + __asm movq mm5,mm1 \ + __asm punpcklwd mm4,mm1 \ + __asm mov A,0x8E3A8E3A \ + __asm pmaddwd mm4,mm7 \ + __asm movq [Y+_r0],mm0 \ + __asm punpckhwd mm5,mm1 \ + __asm pxor mm0,mm0 \ + __asm pmaddwd mm5,mm7 \ + __asm pcmpeqw mm1,mm0 \ + __asm movd mm7,A \ + __asm psubw mm1,mm3 \ + __asm punpckldq mm7,mm7 \ + __asm paddd mm4,mm6 \ + __asm paddd mm5,mm6 \ + /*mm0=0 \ + mm3:mm1=36410*t6'''+((t5'''!=0)<<16)*/ \ + __asm movq mm6,mm2 \ + __asm movq mm3,mm2 \ + __asm pmulhw mm6,mm7 \ + __asm paddw mm1,mm2 \ + __asm pmullw mm3,mm7 \ + __asm pxor mm0,mm0 \ + __asm paddw mm6,mm1 \ + __asm movq mm1,mm3 \ + __asm punpckhwd mm3,mm6 \ + __asm punpcklwd mm1,mm6 \ + /*mm3={-1}x4, mm6={1}x4 \ + mm4=_y[5]=u=(54491*t5'''+36410*t6'''+0x0E3D>>16)+(t5'''!=0)*/ \ + __asm paddd mm5,mm3 \ + __asm paddd mm4,mm1 \ + __asm psrad mm5,16 \ + __asm pxor mm6,mm6 \ + __asm psrad mm4,16 \ + __asm pcmpeqb mm3,mm3 \ + __asm packssdw mm4,mm5 \ + __asm psubw mm6,mm3 \ + /*mm1=t7'', mm7={26568,0x3400}x2 \ + mm2=s=t6'''-(36410*u>>16)*/ \ + __asm movq mm1,mm4 \ + __asm mov A,0x340067C8 \ + __asm pmulhw mm4,mm7 \ + __asm movd mm7,A \ + __asm movq [Y+_r5],mm1 \ + __asm punpckldq mm7,mm7 \ + __asm paddw mm4,mm1 \ + __asm movq mm1,[Y+_r7] \ + __asm psubw mm2,mm4 \ + /*mm6={0x00007B1B}x2 \ + mm0=(s!=0), mm5:mm4=s*26568+0x3400*/ \ + __asm movq mm4,mm2 \ + __asm movq mm5,mm2 \ + __asm punpcklwd mm4,mm6 \ + __asm pcmpeqw mm0,mm2 \ + __asm pmaddwd mm4,mm7 \ + __asm mov A,0x7B1B \ + __asm punpckhwd mm5,mm6 \ + __asm movd mm6,A \ + __asm pmaddwd mm5,mm7 \ + __asm psubw mm0,mm3 \ + __asm punpckldq mm6,mm6 \ + /*mm7={64277-0x7FFF,0x7FFF}x2 \ + mm2=_y[3]=v=(s*26568+0x3400>>17)+s+(s!=0)*/ \ + __asm psrad mm4,17 \ + __asm paddw mm2,mm0 \ + __asm psrad mm5,17 \ + __asm mov A,0x7FFF7B16 \ + __asm packssdw mm4,mm5 \ + __asm movd mm7,A \ + __asm paddw mm2,mm4 \ + __asm punpckldq mm7,mm7 \ + /*mm0=0, mm7={12785}x4 \ + mm1=(t7''!=0), mm2=t4'', mm5:mm4=64277*t7''+0x7B1B*/ \ + __asm movq mm4,mm1 \ + __asm movq mm5,mm1 \ + __asm movq [Y+_r3],mm2 \ + __asm punpcklwd mm4,mm1 \ + __asm movq mm2,[Y+_r1] \ + __asm pmaddwd mm4,mm7 \ + __asm mov A,0x31F131F1 \ + __asm punpckhwd mm5,mm1 \ + __asm pxor mm0,mm0 \ + __asm pmaddwd mm5,mm7 \ + __asm pcmpeqw mm1,mm0 \ + __asm movd mm7,A \ + __asm psubw mm1,mm3 \ + __asm punpckldq mm7,mm7 \ + __asm paddd mm4,mm6 \ + __asm paddd mm5,mm6 \ + /*mm3:mm1=12785*t4'''+((t7''!=0)<<16)*/ \ + __asm movq mm6,mm2 \ + __asm movq mm3,mm2 \ + __asm pmulhw mm6,mm7 \ + __asm pmullw mm3,mm7 \ + __asm paddw mm6,mm1 \ + __asm movq mm1,mm3 \ + __asm punpckhwd mm3,mm6 \ + __asm punpcklwd mm1,mm6 \ + /*mm3={-1}x4, mm6={1}x4 \ + mm4=_y[1]=u=(12785*t4'''+64277*t7''+0x7B1B>>16)+(t7''!=0)*/ \ + __asm paddd mm5,mm3 \ + __asm paddd mm4,mm1 \ + __asm psrad mm5,16 \ + __asm pxor mm6,mm6 \ + __asm psrad mm4,16 \ + __asm pcmpeqb mm3,mm3 \ + __asm packssdw mm4,mm5 \ + __asm psubw mm6,mm3 \ + /*mm1=t3'', mm7={20539,0x3000}x2 \ + mm4=s=(12785*u>>16)-t4''*/ \ + __asm movq [Y+_r1],mm4 \ + __asm pmulhw mm4,mm7 \ + __asm mov A,0x3000503B \ + __asm movq mm1,[Y+_r6] \ + __asm movd mm7,A \ + __asm psubw mm4,mm2 \ + __asm punpckldq mm7,mm7 \ + /*mm6={0x00006CB7}x2 \ + mm0=(s!=0), mm5:mm4=s*20539+0x3000*/ \ + __asm movq mm5,mm4 \ + __asm movq mm2,mm4 \ + __asm punpcklwd mm4,mm6 \ + __asm pcmpeqw mm0,mm2 \ + __asm pmaddwd mm4,mm7 \ + __asm mov A,0x6CB7 \ + __asm punpckhwd mm5,mm6 \ + __asm movd mm6,A \ + __asm pmaddwd mm5,mm7 \ + __asm psubw mm0,mm3 \ + __asm punpckldq mm6,mm6 \ + /*mm7={60547-0x7FFF,0x7FFF}x2 \ + mm2=_y[7]=v=(s*20539+0x3000>>20)+s+(s!=0)*/ \ + __asm psrad mm4,20 \ + __asm paddw mm2,mm0 \ + __asm psrad mm5,20 \ + __asm mov A,0x7FFF6C84 \ + __asm packssdw mm4,mm5 \ + __asm movd mm7,A \ + __asm paddw mm2,mm4 \ + __asm punpckldq mm7,mm7 \ + /*mm0=0, mm7={25080}x4 \ + mm2=t2'', mm5:mm4=60547*t3''+0x6CB7*/ \ + __asm movq mm4,mm1 \ + __asm movq mm5,mm1 \ + __asm movq [Y+_r7],mm2 \ + __asm punpcklwd mm4,mm1 \ + __asm movq mm2,[Y+_r2] \ + __asm pmaddwd mm4,mm7 \ + __asm mov A,0x61F861F8 \ + __asm punpckhwd mm5,mm1 \ + __asm pxor mm0,mm0 \ + __asm pmaddwd mm5,mm7 \ + __asm movd mm7,A \ + __asm pcmpeqw mm1,mm0 \ + __asm psubw mm1,mm3 \ + __asm punpckldq mm7,mm7 \ + __asm paddd mm4,mm6 \ + __asm paddd mm5,mm6 \ + /*mm3:mm1=25080*t2''+((t3''!=0)<<16)*/ \ + __asm movq mm6,mm2 \ + __asm movq mm3,mm2 \ + __asm pmulhw mm6,mm7 \ + __asm pmullw mm3,mm7 \ + __asm paddw mm6,mm1 \ + __asm movq mm1,mm3 \ + __asm punpckhwd mm3,mm6 \ + __asm punpcklwd mm1,mm6 \ + /*mm1={-1}x4 \ + mm4=u=(25080*t2''+60547*t3''+0x6CB7>>16)+(t3''!=0)*/ \ + __asm paddd mm5,mm3 \ + __asm paddd mm4,mm1 \ + __asm psrad mm5,16 \ + __asm mov A,0x28005460 \ + __asm psrad mm4,16 \ + __asm pcmpeqb mm1,mm1 \ + __asm packssdw mm4,mm5 \ + /*mm5={1}x4, mm6=_y[2]=u, mm7={21600,0x2800}x2 \ + mm4=s=(25080*u>>16)-t2''*/ \ + __asm movq mm6,mm4 \ + __asm pmulhw mm4,mm7 \ + __asm pxor mm5,mm5 \ + __asm movd mm7,A \ + __asm psubw mm5,mm1 \ + __asm punpckldq mm7,mm7 \ + __asm psubw mm4,mm2 \ + /*mm2=s+(s!=0) \ + mm4:mm3=s*21600+0x2800*/ \ + __asm movq mm3,mm4 \ + __asm movq mm2,mm4 \ + __asm punpckhwd mm4,mm5 \ + __asm pcmpeqw mm0,mm2 \ + __asm pmaddwd mm4,mm7 \ + __asm psubw mm0,mm1 \ + __asm punpcklwd mm3,mm5 \ + __asm paddw mm2,mm0 \ + __asm pmaddwd mm3,mm7 \ + /*mm0=_y[4], mm1=_y[7], mm4=_y[0], mm5=_y[5] \ + mm3=_y[6]=v=(s*21600+0x2800>>18)+s+(s!=0)*/ \ + __asm movq mm0,[Y+_r4] \ + __asm psrad mm4,18 \ + __asm movq mm5,[Y+_r5] \ + __asm psrad mm3,18 \ + __asm movq mm1,[Y+_r7] \ + __asm packssdw mm3,mm4 \ + __asm movq mm4,[Y+_r0] \ + __asm paddw mm3,mm2 \ +} + +/*On input, mm4=_y[0], mm6=_y[2], mm0=_y[4], mm5=_y[5], mm3=_y[6], mm1=_y[7]. + On output, {_y[4],mm1,mm2,mm3} contains the transpose of _y[4...7] and + {mm4,mm5,mm6,mm7} contains the transpose of _y[0...3].*/ +#define OC_TRANSPOSE8x4(_r0,_r1,_r2,_r3,_r4,_r5,_r6,_r7) __asm{ \ + /*First 4x4 transpose:*/ \ + /*mm0 = e3 e2 e1 e0 \ + mm5 = f3 f2 f1 f0 \ + mm3 = g3 g2 g1 g0 \ + mm1 = h3 h2 h1 h0*/ \ + __asm movq mm2,mm0 \ + __asm punpcklwd mm0,mm5 \ + __asm punpckhwd mm2,mm5 \ + __asm movq mm5,mm3 \ + __asm punpcklwd mm3,mm1 \ + __asm punpckhwd mm5,mm1 \ + /*mm0 = f1 e1 f0 e0 \ + mm2 = f3 e3 f2 e2 \ + mm3 = h1 g1 h0 g0 \ + mm5 = h3 g3 h2 g2*/ \ + __asm movq mm1,mm0 \ + __asm punpckldq mm0,mm3 \ + __asm movq [Y+_r4],mm0 \ + __asm punpckhdq mm1,mm3 \ + __asm movq mm0,[Y+_r1] \ + __asm movq mm3,mm2 \ + __asm punpckldq mm2,mm5 \ + __asm punpckhdq mm3,mm5 \ + __asm movq mm5,[Y+_r3] \ + /*_y[4] = h0 g0 f0 e0 \ + mm1 = h1 g1 f1 e1 \ + mm2 = h2 g2 f2 e2 \ + mm3 = h3 g3 f3 e3*/ \ + /*Second 4x4 transpose:*/ \ + /*mm4 = a3 a2 a1 a0 \ + mm0 = b3 b2 b1 b0 \ + mm6 = c3 c2 c1 c0 \ + mm5 = d3 d2 d1 d0*/ \ + __asm movq mm7,mm4 \ + __asm punpcklwd mm4,mm0 \ + __asm punpckhwd mm7,mm0 \ + __asm movq mm0,mm6 \ + __asm punpcklwd mm6,mm5 \ + __asm punpckhwd mm0,mm5 \ + /*mm4 = b1 a1 b0 a0 \ + mm7 = b3 a3 b2 a2 \ + mm6 = d1 c1 d0 c0 \ + mm0 = d3 c3 d2 c2*/ \ + __asm movq mm5,mm4 \ + __asm punpckldq mm4,mm6 \ + __asm punpckhdq mm5,mm6 \ + __asm movq mm6,mm7 \ + __asm punpckhdq mm7,mm0 \ + __asm punpckldq mm6,mm0 \ + /*mm4 = d0 c0 b0 a0 \ + mm5 = d1 c1 b1 a1 \ + mm6 = d2 c2 b2 a2 \ + mm7 = d3 c3 b3 a3*/ \ +} + +/*MMX implementation of the fDCT.*/ +void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]){ + ptrdiff_t a; + __asm{ +#define Y eax +#define A ecx +#define X edx + /*Add two extra bits of working precision to improve accuracy; any more and + we could overflow.*/ + /*We also add biases to correct for some systematic error that remains in + the full fDCT->iDCT round trip.*/ + mov X, _x + mov Y, _y + movq mm0,[0x00+X] + movq mm1,[0x10+X] + movq mm2,[0x20+X] + movq mm3,[0x30+X] + pcmpeqb mm4,mm4 + pxor mm7,mm7 + movq mm5,mm0 + psllw mm0,2 + pcmpeqw mm5,mm7 + movq mm7,[0x70+X] + psllw mm1,2 + psubw mm5,mm4 + psllw mm2,2 + mov A,1 + pslld mm5,16 + movd mm6,A + psllq mm5,16 + mov A,0x10001 + psllw mm3,2 + movd mm4,A + punpckhwd mm5,mm6 + psubw mm1,mm6 + movq mm6,[0x60+X] + paddw mm0,mm5 + movq mm5,[0x50+X] + paddw mm0,mm4 + movq mm4,[0x40+X] + /*We inline stage1 of the transform here so we can get better instruction + scheduling with the shifts.*/ + /*mm0=t7'=t0-t7*/ + psllw mm7,2 + psubw mm0,mm7 + psllw mm6,2 + paddw mm7,mm7 + /*mm1=t6'=t1-t6*/ + psllw mm5,2 + psubw mm1,mm6 + psllw mm4,2 + paddw mm6,mm6 + /*mm2=t5'=t2-t5*/ + psubw mm2,mm5 + paddw mm5,mm5 + /*mm3=t4'=t3-t4*/ + psubw mm3,mm4 + paddw mm4,mm4 + /*mm7=t0'=t0+t7*/ + paddw mm7,mm0 + /*mm6=t1'=t1+t6*/ + paddw mm6,mm1 + /*mm5=t2'=t2+t5*/ + paddw mm5,mm2 + /*mm4=t3'=t3+t4*/ + paddw mm4,mm3 + OC_FDCT8x4(0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70) + OC_TRANSPOSE8x4(0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70) + /*Swap out this 8x4 block for the next one.*/ + movq mm0,[0x08+X] + movq [0x30+Y],mm7 + movq mm7,[0x78+X] + movq [0x50+Y],mm1 + movq mm1,[0x18+X] + movq [0x20+Y],mm6 + movq mm6,[0x68+X] + movq [0x60+Y],mm2 + movq mm2,[0x28+X] + movq [0x10+Y],mm5 + movq mm5,[0x58+X] + movq [0x70+Y],mm3 + movq mm3,[0x38+X] + /*And increase its working precision, too.*/ + psllw mm0,2 + movq [0x00+Y],mm4 + psllw mm7,2 + movq mm4,[0x48+X] + /*We inline stage1 of the transform here so we can get better instruction + scheduling with the shifts.*/ + /*mm0=t7'=t0-t7*/ + psubw mm0,mm7 + psllw mm1,2 + paddw mm7,mm7 + psllw mm6,2 + /*mm1=t6'=t1-t6*/ + psubw mm1,mm6 + psllw mm2,2 + paddw mm6,mm6 + psllw mm5,2 + /*mm2=t5'=t2-t5*/ + psubw mm2,mm5 + psllw mm3,2 + paddw mm5,mm5 + psllw mm4,2 + /*mm3=t4'=t3-t4*/ + psubw mm3,mm4 + paddw mm4,mm4 + /*mm7=t0'=t0+t7*/ + paddw mm7,mm0 + /*mm6=t1'=t1+t6*/ + paddw mm6,mm1 + /*mm5=t2'=t2+t5*/ + paddw mm5,mm2 + /*mm4=t3'=t3+t4*/ + paddw mm4,mm3 + OC_FDCT8x4(0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78) + OC_TRANSPOSE8x4(0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78) + /*Here the first 4x4 block of output from the last transpose is the second + 4x4 block of input for the next transform. + We have cleverly arranged that it already be in the appropriate place, + so we only have to do half the stores and loads.*/ + movq mm0,[0x00+Y] + movq [0x58+Y],mm1 + movq mm1,[0x10+Y] + movq [0x68+Y],mm2 + movq mm2,[0x20+Y] + movq [0x78+Y],mm3 + movq mm3,[0x30+Y] + OC_FDCT_STAGE1_8x4 + OC_FDCT8x4(0x00,0x10,0x20,0x30,0x08,0x18,0x28,0x38) + OC_TRANSPOSE8x4(0x00,0x10,0x20,0x30,0x08,0x18,0x28,0x38) + /*mm0={-2}x4*/ + pcmpeqw mm0,mm0 + paddw mm0,mm0 + /*Round the results.*/ + psubw mm1,mm0 + psubw mm2,mm0 + psraw mm1,2 + psubw mm3,mm0 + movq [0x18+Y],mm1 + psraw mm2,2 + psubw mm4,mm0 + movq mm1,[0x08+Y] + psraw mm3,2 + psubw mm5,mm0 + psraw mm4,2 + psubw mm6,mm0 + psraw mm5,2 + psubw mm7,mm0 + psraw mm6,2 + psubw mm1,mm0 + psraw mm7,2 + movq mm0,[0x40+Y] + psraw mm1,2 + movq [0x30+Y],mm7 + movq mm7,[0x78+Y] + movq [0x08+Y],mm1 + movq mm1,[0x50+Y] + movq [0x20+Y],mm6 + movq mm6,[0x68+Y] + movq [0x28+Y],mm2 + movq mm2,[0x60+Y] + movq [0x10+Y],mm5 + movq mm5,[0x58+Y] + movq [0x38+Y],mm3 + movq mm3,[0x70+Y] + movq [0x00+Y],mm4 + movq mm4,[0x48+Y] + OC_FDCT_STAGE1_8x4 + OC_FDCT8x4(0x40,0x50,0x60,0x70,0x48,0x58,0x68,0x78) + OC_TRANSPOSE8x4(0x40,0x50,0x60,0x70,0x48,0x58,0x68,0x78) + /*mm0={-2}x4*/ + pcmpeqw mm0,mm0 + paddw mm0,mm0 + /*Round the results.*/ + psubw mm1,mm0 + psubw mm2,mm0 + psraw mm1,2 + psubw mm3,mm0 + movq [0x58+Y],mm1 + psraw mm2,2 + psubw mm4,mm0 + movq mm1,[0x48+Y] + psraw mm3,2 + psubw mm5,mm0 + movq [0x68+Y],mm2 + psraw mm4,2 + psubw mm6,mm0 + movq [0x78+Y],mm3 + psraw mm5,2 + psubw mm7,mm0 + movq [0x40+Y],mm4 + psraw mm6,2 + psubw mm1,mm0 + movq [0x50+Y],mm5 + psraw mm7,2 + movq [0x60+Y],mm6 + psraw mm1,2 + movq [0x70+Y],mm7 + movq [0x48+Y],mm1 +#undef Y +#undef A +#undef X + } +} + +#endif diff --git a/Engine/lib/libtheora/lib/x86_vc/mmxfrag.c b/Engine/lib/libtheora/lib/x86_vc/mmxfrag.c new file mode 100644 index 000000000..4eb2084dc --- /dev/null +++ b/Engine/lib/libtheora/lib/x86_vc/mmxfrag.c @@ -0,0 +1,337 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: mmxfrag.c 16578 2009-09-25 19:50:48Z cristianadam $ + + ********************************************************************/ + +/*MMX acceleration of fragment reconstruction for motion compensation. + Originally written by Rudolf Marek. + Additional optimization by Nils Pipenbrinck. + Note: Loops are unrolled for best performance. + The iteration each instruction belongs to is marked in the comments as #i.*/ +#include +#include "x86int.h" +#include "mmxfrag.h" + +#if defined(OC_X86_ASM) + +/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes + between rows.*/ +void oc_frag_copy_mmx(unsigned char *_dst, + const unsigned char *_src,int _ystride){ +#define SRC edx +#define DST eax +#define YSTRIDE ecx +#define YSTRIDE3 esi + OC_FRAG_COPY_MMX(_dst,_src,_ystride); +#undef SRC +#undef DST +#undef YSTRIDE +#undef YSTRIDE3 +} + +void oc_frag_recon_intra_mmx(unsigned char *_dst,int _ystride, + const ogg_int16_t *_residue){ + __asm{ +#define DST edx +#define DST4 esi +#define YSTRIDE eax +#define YSTRIDE3 edi +#define RESIDUE ecx + mov DST,_dst + mov YSTRIDE,_ystride + mov RESIDUE,_residue + lea DST4,[DST+YSTRIDE*4] + lea YSTRIDE3,[YSTRIDE+YSTRIDE*2] + /*Set mm0 to 0xFFFFFFFFFFFFFFFF.*/ + pcmpeqw mm0,mm0 + /*#0 Load low residue.*/ + movq mm1,[0*8+RESIDUE] + /*#0 Load high residue.*/ + movq mm2,[1*8+RESIDUE] + /*Set mm0 to 0x8000800080008000.*/ + psllw mm0,15 + /*#1 Load low residue.*/ + movq mm3,[2*8+RESIDUE] + /*#1 Load high residue.*/ + movq mm4,[3*8+RESIDUE] + /*Set mm0 to 0x0080008000800080.*/ + psrlw mm0,8 + /*#2 Load low residue.*/ + movq mm5,[4*8+RESIDUE] + /*#2 Load high residue.*/ + movq mm6,[5*8+RESIDUE] + /*#0 Bias low residue.*/ + paddsw mm1,mm0 + /*#0 Bias high residue.*/ + paddsw mm2,mm0 + /*#0 Pack to byte.*/ + packuswb mm1,mm2 + /*#1 Bias low residue.*/ + paddsw mm3,mm0 + /*#1 Bias high residue.*/ + paddsw mm4,mm0 + /*#1 Pack to byte.*/ + packuswb mm3,mm4 + /*#2 Bias low residue.*/ + paddsw mm5,mm0 + /*#2 Bias high residue.*/ + paddsw mm6,mm0 + /*#2 Pack to byte.*/ + packuswb mm5,mm6 + /*#0 Write row.*/ + movq [DST],mm1 + /*#1 Write row.*/ + movq [DST+YSTRIDE],mm3 + /*#2 Write row.*/ + movq [DST+YSTRIDE*2],mm5 + /*#3 Load low residue.*/ + movq mm1,[6*8+RESIDUE] + /*#3 Load high residue.*/ + movq mm2,[7*8+RESIDUE] + /*#4 Load high residue.*/ + movq mm3,[8*8+RESIDUE] + /*#4 Load high residue.*/ + movq mm4,[9*8+RESIDUE] + /*#5 Load high residue.*/ + movq mm5,[10*8+RESIDUE] + /*#5 Load high residue.*/ + movq mm6,[11*8+RESIDUE] + /*#3 Bias low residue.*/ + paddsw mm1,mm0 + /*#3 Bias high residue.*/ + paddsw mm2,mm0 + /*#3 Pack to byte.*/ + packuswb mm1,mm2 + /*#4 Bias low residue.*/ + paddsw mm3,mm0 + /*#4 Bias high residue.*/ + paddsw mm4,mm0 + /*#4 Pack to byte.*/ + packuswb mm3,mm4 + /*#5 Bias low residue.*/ + paddsw mm5,mm0 + /*#5 Bias high residue.*/ + paddsw mm6,mm0 + /*#5 Pack to byte.*/ + packuswb mm5,mm6 + /*#3 Write row.*/ + movq [DST+YSTRIDE3],mm1 + /*#4 Write row.*/ + movq [DST4],mm3 + /*#5 Write row.*/ + movq [DST4+YSTRIDE],mm5 + /*#6 Load low residue.*/ + movq mm1,[12*8+RESIDUE] + /*#6 Load high residue.*/ + movq mm2,[13*8+RESIDUE] + /*#7 Load low residue.*/ + movq mm3,[14*8+RESIDUE] + /*#7 Load high residue.*/ + movq mm4,[15*8+RESIDUE] + /*#6 Bias low residue.*/ + paddsw mm1,mm0 + /*#6 Bias high residue.*/ + paddsw mm2,mm0 + /*#6 Pack to byte.*/ + packuswb mm1,mm2 + /*#7 Bias low residue.*/ + paddsw mm3,mm0 + /*#7 Bias high residue.*/ + paddsw mm4,mm0 + /*#7 Pack to byte.*/ + packuswb mm3,mm4 + /*#6 Write row.*/ + movq [DST4+YSTRIDE*2],mm1 + /*#7 Write row.*/ + movq [DST4+YSTRIDE3],mm3 +#undef DST +#undef DST4 +#undef YSTRIDE +#undef YSTRIDE3 +#undef RESIDUE + } +} + +void oc_frag_recon_inter_mmx(unsigned char *_dst,const unsigned char *_src, + int _ystride,const ogg_int16_t *_residue){ + int i; + /*Zero mm0.*/ + __asm pxor mm0,mm0; + for(i=4;i-->0;){ + __asm{ +#define DST edx +#define SRC ecx +#define YSTRIDE edi +#define RESIDUE eax + mov DST,_dst + mov SRC,_src + mov YSTRIDE,_ystride + mov RESIDUE,_residue + /*#0 Load source.*/ + movq mm3,[SRC] + /*#1 Load source.*/ + movq mm7,[SRC+YSTRIDE] + /*#0 Get copy of src.*/ + movq mm4,mm3 + /*#0 Expand high source.*/ + punpckhbw mm4,mm0 + /*#0 Expand low source.*/ + punpcklbw mm3,mm0 + /*#0 Add residue high.*/ + paddsw mm4,[8+RESIDUE] + /*#1 Get copy of src.*/ + movq mm2,mm7 + /*#0 Add residue low.*/ + paddsw mm3,[RESIDUE] + /*#1 Expand high source.*/ + punpckhbw mm2,mm0 + /*#0 Pack final row pixels.*/ + packuswb mm3,mm4 + /*#1 Expand low source.*/ + punpcklbw mm7,mm0 + /*#1 Add residue low.*/ + paddsw mm7,[16+RESIDUE] + /*#1 Add residue high.*/ + paddsw mm2,[24+RESIDUE] + /*Advance residue.*/ + lea RESIDUE,[32+RESIDUE] + /*#1 Pack final row pixels.*/ + packuswb mm7,mm2 + /*Advance src.*/ + lea SRC,[SRC+YSTRIDE*2] + /*#0 Write row.*/ + movq [DST],mm3 + /*#1 Write row.*/ + movq [DST+YSTRIDE],mm7 + /*Advance dst.*/ + lea DST,[DST+YSTRIDE*2] + mov _residue,RESIDUE + mov _dst,DST + mov _src,SRC +#undef DST +#undef SRC +#undef YSTRIDE +#undef RESIDUE + } + } +} + +void oc_frag_recon_inter2_mmx(unsigned char *_dst,const unsigned char *_src1, + const unsigned char *_src2,int _ystride,const ogg_int16_t *_residue){ + int i; + /*Zero mm7.*/ + __asm pxor mm7,mm7; + for(i=4;i-->0;){ + __asm{ +#define SRC1 ecx +#define SRC2 edi +#define YSTRIDE esi +#define RESIDUE edx +#define DST eax + mov YSTRIDE,_ystride + mov DST,_dst + mov RESIDUE,_residue + mov SRC1,_src1 + mov SRC2,_src2 + /*#0 Load src1.*/ + movq mm0,[SRC1] + /*#0 Load src2.*/ + movq mm2,[SRC2] + /*#0 Copy src1.*/ + movq mm1,mm0 + /*#0 Copy src2.*/ + movq mm3,mm2 + /*#1 Load src1.*/ + movq mm4,[SRC1+YSTRIDE] + /*#0 Unpack lower src1.*/ + punpcklbw mm0,mm7 + /*#1 Load src2.*/ + movq mm5,[SRC2+YSTRIDE] + /*#0 Unpack higher src1.*/ + punpckhbw mm1,mm7 + /*#0 Unpack lower src2.*/ + punpcklbw mm2,mm7 + /*#0 Unpack higher src2.*/ + punpckhbw mm3,mm7 + /*Advance src1 ptr.*/ + lea SRC1,[SRC1+YSTRIDE*2] + /*Advance src2 ptr.*/ + lea SRC2,[SRC2+YSTRIDE*2] + /*#0 Lower src1+src2.*/ + paddsw mm0,mm2 + /*#0 Higher src1+src2.*/ + paddsw mm1,mm3 + /*#1 Copy src1.*/ + movq mm2,mm4 + /*#0 Build lo average.*/ + psraw mm0,1 + /*#1 Copy src2.*/ + movq mm3,mm5 + /*#1 Unpack lower src1.*/ + punpcklbw mm4,mm7 + /*#0 Build hi average.*/ + psraw mm1,1 + /*#1 Unpack higher src1.*/ + punpckhbw mm2,mm7 + /*#0 low+=residue.*/ + paddsw mm0,[RESIDUE] + /*#1 Unpack lower src2.*/ + punpcklbw mm5,mm7 + /*#0 high+=residue.*/ + paddsw mm1,[8+RESIDUE] + /*#1 Unpack higher src2.*/ + punpckhbw mm3,mm7 + /*#1 Lower src1+src2.*/ + paddsw mm5,mm4 + /*#0 Pack and saturate.*/ + packuswb mm0,mm1 + /*#1 Higher src1+src2.*/ + paddsw mm3,mm2 + /*#0 Write row.*/ + movq [DST],mm0 + /*#1 Build lo average.*/ + psraw mm5,1 + /*#1 Build hi average.*/ + psraw mm3,1 + /*#1 low+=residue.*/ + paddsw mm5,[16+RESIDUE] + /*#1 high+=residue.*/ + paddsw mm3,[24+RESIDUE] + /*#1 Pack and saturate.*/ + packuswb mm5,mm3 + /*#1 Write row ptr.*/ + movq [DST+YSTRIDE],mm5 + /*Advance residue ptr.*/ + add RESIDUE,32 + /*Advance dest ptr.*/ + lea DST,[DST+YSTRIDE*2] + mov _dst,DST + mov _residue,RESIDUE + mov _src1,SRC1 + mov _src2,SRC2 +#undef SRC1 +#undef SRC2 +#undef YSTRIDE +#undef RESIDUE +#undef DST + } + } +} + +void oc_restore_fpu_mmx(void){ + __asm emms; +} + +#endif diff --git a/Engine/lib/libtheora/lib/x86_vc/mmxfrag.h b/Engine/lib/libtheora/lib/x86_vc/mmxfrag.h new file mode 100644 index 000000000..45ee93e77 --- /dev/null +++ b/Engine/lib/libtheora/lib/x86_vc/mmxfrag.h @@ -0,0 +1,61 @@ +#if !defined(_x86_vc_mmxfrag_H) +# define _x86_vc_mmxfrag_H (1) +# include +# include "x86int.h" + +#if defined(OC_X86_ASM) + +/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes + between rows.*/ +#define OC_FRAG_COPY_MMX(_dst,_src,_ystride) \ + do{ \ + const unsigned char *src; \ + unsigned char *dst; \ + src=(_src); \ + dst=(_dst); \ + __asm mov SRC,src \ + __asm mov DST,dst \ + __asm mov YSTRIDE,_ystride \ + /*src+0*ystride*/ \ + __asm movq mm0,[SRC] \ + /*src+1*ystride*/ \ + __asm movq mm1,[SRC+YSTRIDE] \ + /*ystride3=ystride*3*/ \ + __asm lea YSTRIDE3,[YSTRIDE+YSTRIDE*2] \ + /*src+2*ystride*/ \ + __asm movq mm2,[SRC+YSTRIDE*2] \ + /*src+3*ystride*/ \ + __asm movq mm3,[SRC+YSTRIDE3] \ + /*dst+0*ystride*/ \ + __asm movq [DST],mm0 \ + /*dst+1*ystride*/ \ + __asm movq [DST+YSTRIDE],mm1 \ + /*Pointer to next 4.*/ \ + __asm lea SRC,[SRC+YSTRIDE*4] \ + /*dst+2*ystride*/ \ + __asm movq [DST+YSTRIDE*2],mm2 \ + /*dst+3*ystride*/ \ + __asm movq [DST+YSTRIDE3],mm3 \ + /*Pointer to next 4.*/ \ + __asm lea DST,[DST+YSTRIDE*4] \ + /*src+0*ystride*/ \ + __asm movq mm0,[SRC] \ + /*src+1*ystride*/ \ + __asm movq mm1,[SRC+YSTRIDE] \ + /*src+2*ystride*/ \ + __asm movq mm2,[SRC+YSTRIDE*2] \ + /*src+3*ystride*/ \ + __asm movq mm3,[SRC+YSTRIDE3] \ + /*dst+0*ystride*/ \ + __asm movq [DST],mm0 \ + /*dst+1*ystride*/ \ + __asm movq [DST+YSTRIDE],mm1 \ + /*dst+2*ystride*/ \ + __asm movq [DST+YSTRIDE*2],mm2 \ + /*dst+3*ystride*/ \ + __asm movq [DST+YSTRIDE3],mm3 \ + } \ + while(0) + +# endif +#endif diff --git a/Engine/lib/libtheora/lib/x86_vc/mmxidct.c b/Engine/lib/libtheora/lib/x86_vc/mmxidct.c new file mode 100644 index 000000000..8f5ff6803 --- /dev/null +++ b/Engine/lib/libtheora/lib/x86_vc/mmxidct.c @@ -0,0 +1,562 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: mmxidct.c 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ + +/*MMX acceleration of Theora's iDCT. + Originally written by Rudolf Marek, based on code from On2's VP3.*/ +#include "x86int.h" +#include "../dct.h" + +#if defined(OC_X86_ASM) + +/*These are offsets into the table of constants below.*/ +/*7 rows of cosines, in order: pi/16 * (1 ... 7).*/ +#define OC_COSINE_OFFSET (0) +/*A row of 8's.*/ +#define OC_EIGHT_OFFSET (56) + + + +/*A table of constants used by the MMX routines.*/ +static const __declspec(align(16))ogg_uint16_t + OC_IDCT_CONSTS[(7+1)*4]={ + (ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7, + (ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7, + (ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6, + (ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6, + (ogg_uint16_t)OC_C3S5,(ogg_uint16_t)OC_C3S5, + (ogg_uint16_t)OC_C3S5,(ogg_uint16_t)OC_C3S5, + (ogg_uint16_t)OC_C4S4,(ogg_uint16_t)OC_C4S4, + (ogg_uint16_t)OC_C4S4,(ogg_uint16_t)OC_C4S4, + (ogg_uint16_t)OC_C5S3,(ogg_uint16_t)OC_C5S3, + (ogg_uint16_t)OC_C5S3,(ogg_uint16_t)OC_C5S3, + (ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2, + (ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2, + (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1, + (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1, + 8, 8, 8, 8 +}; + +/*38 cycles*/ +#define OC_IDCT_BEGIN __asm{ \ + __asm movq mm2,OC_I(3) \ + __asm movq mm6,OC_C(3) \ + __asm movq mm4,mm2 \ + __asm movq mm7,OC_J(5) \ + __asm pmulhw mm4,mm6 \ + __asm movq mm1,OC_C(5) \ + __asm pmulhw mm6,mm7 \ + __asm movq mm5,mm1 \ + __asm pmulhw mm1,mm2 \ + __asm movq mm3,OC_I(1) \ + __asm pmulhw mm5,mm7 \ + __asm movq mm0,OC_C(1) \ + __asm paddw mm4,mm2 \ + __asm paddw mm6,mm7 \ + __asm paddw mm2,mm1 \ + __asm movq mm1,OC_J(7) \ + __asm paddw mm7,mm5 \ + __asm movq mm5,mm0 \ + __asm pmulhw mm0,mm3 \ + __asm paddw mm4,mm7 \ + __asm pmulhw mm5,mm1 \ + __asm movq mm7,OC_C(7) \ + __asm psubw mm6,mm2 \ + __asm paddw mm0,mm3 \ + __asm pmulhw mm3,mm7 \ + __asm movq mm2,OC_I(2) \ + __asm pmulhw mm7,mm1 \ + __asm paddw mm5,mm1 \ + __asm movq mm1,mm2 \ + __asm pmulhw mm2,OC_C(2) \ + __asm psubw mm3,mm5 \ + __asm movq mm5,OC_J(6) \ + __asm paddw mm0,mm7 \ + __asm movq mm7,mm5 \ + __asm psubw mm0,mm4 \ + __asm pmulhw mm5,OC_C(2) \ + __asm paddw mm2,mm1 \ + __asm pmulhw mm1,OC_C(6) \ + __asm paddw mm4,mm4 \ + __asm paddw mm4,mm0 \ + __asm psubw mm3,mm6 \ + __asm paddw mm5,mm7 \ + __asm paddw mm6,mm6 \ + __asm pmulhw mm7,OC_C(6) \ + __asm paddw mm6,mm3 \ + __asm movq OC_I(1),mm4 \ + __asm psubw mm1,mm5 \ + __asm movq mm4,OC_C(4) \ + __asm movq mm5,mm3 \ + __asm pmulhw mm3,mm4 \ + __asm paddw mm7,mm2 \ + __asm movq OC_I(2),mm6 \ + __asm movq mm2,mm0 \ + __asm movq mm6,OC_I(0) \ + __asm pmulhw mm0,mm4 \ + __asm paddw mm5,mm3 \ + __asm movq mm3,OC_J(4) \ + __asm psubw mm5,mm1 \ + __asm paddw mm2,mm0 \ + __asm psubw mm6,mm3 \ + __asm movq mm0,mm6 \ + __asm pmulhw mm6,mm4 \ + __asm paddw mm3,mm3 \ + __asm paddw mm1,mm1 \ + __asm paddw mm3,mm0 \ + __asm paddw mm1,mm5 \ + __asm pmulhw mm4,mm3 \ + __asm paddw mm6,mm0 \ + __asm psubw mm6,mm2 \ + __asm paddw mm2,mm2 \ + __asm movq mm0,OC_I(1) \ + __asm paddw mm2,mm6 \ + __asm paddw mm4,mm3 \ + __asm psubw mm2,mm1 \ +} + +/*38+8=46 cycles.*/ +#define OC_ROW_IDCT __asm{ \ + OC_IDCT_BEGIN \ + /*r3=D'*/ \ + __asm movq mm3,OC_I(2) \ + /*r4=E'=E-G*/ \ + __asm psubw mm4,mm7 \ + /*r1=H'+H'*/ \ + __asm paddw mm1,mm1 \ + /*r7=G+G*/ \ + __asm paddw mm7,mm7 \ + /*r1=R1=A''+H'*/ \ + __asm paddw mm1,mm2 \ + /*r7=G'=E+G*/ \ + __asm paddw mm7,mm4 \ + /*r4=R4=E'-D'*/ \ + __asm psubw mm4,mm3 \ + __asm paddw mm3,mm3 \ + /*r6=R6=F'-B''*/ \ + __asm psubw mm6,mm5 \ + __asm paddw mm5,mm5 \ + /*r3=R3=E'+D'*/ \ + __asm paddw mm3,mm4 \ + /*r5=R5=F'+B''*/ \ + __asm paddw mm5,mm6 \ + /*r7=R7=G'-C'*/ \ + __asm psubw mm7,mm0 \ + __asm paddw mm0,mm0 \ + /*Save R1.*/ \ + __asm movq OC_I(1),mm1 \ + /*r0=R0=G.+C.*/ \ + __asm paddw mm0,mm7 \ +} + +/*The following macro does two 4x4 transposes in place. + At entry, we assume: + r0 = a3 a2 a1 a0 + I(1) = b3 b2 b1 b0 + r2 = c3 c2 c1 c0 + r3 = d3 d2 d1 d0 + + r4 = e3 e2 e1 e0 + r5 = f3 f2 f1 f0 + r6 = g3 g2 g1 g0 + r7 = h3 h2 h1 h0 + + At exit, we have: + I(0) = d0 c0 b0 a0 + I(1) = d1 c1 b1 a1 + I(2) = d2 c2 b2 a2 + I(3) = d3 c3 b3 a3 + + J(4) = h0 g0 f0 e0 + J(5) = h1 g1 f1 e1 + J(6) = h2 g2 f2 e2 + J(7) = h3 g3 f3 e3 + + I(0) I(1) I(2) I(3) is the transpose of r0 I(1) r2 r3. + J(4) J(5) J(6) J(7) is the transpose of r4 r5 r6 r7. + + Since r1 is free at entry, we calculate the Js first.*/ +/*19 cycles.*/ +#define OC_TRANSPOSE __asm{ \ + __asm movq mm1,mm4 \ + __asm punpcklwd mm4,mm5 \ + __asm movq OC_I(0),mm0 \ + __asm punpckhwd mm1,mm5 \ + __asm movq mm0,mm6 \ + __asm punpcklwd mm6,mm7 \ + __asm movq mm5,mm4 \ + __asm punpckldq mm4,mm6 \ + __asm punpckhdq mm5,mm6 \ + __asm movq mm6,mm1 \ + __asm movq OC_J(4),mm4 \ + __asm punpckhwd mm0,mm7 \ + __asm movq OC_J(5),mm5 \ + __asm punpckhdq mm6,mm0 \ + __asm movq mm4,OC_I(0) \ + __asm punpckldq mm1,mm0 \ + __asm movq mm5,OC_I(1) \ + __asm movq mm0,mm4 \ + __asm movq OC_J(7),mm6 \ + __asm punpcklwd mm0,mm5 \ + __asm movq OC_J(6),mm1 \ + __asm punpckhwd mm4,mm5 \ + __asm movq mm5,mm2 \ + __asm punpcklwd mm2,mm3 \ + __asm movq mm1,mm0 \ + __asm punpckldq mm0,mm2 \ + __asm punpckhdq mm1,mm2 \ + __asm movq mm2,mm4 \ + __asm movq OC_I(0),mm0 \ + __asm punpckhwd mm5,mm3 \ + __asm movq OC_I(1),mm1 \ + __asm punpckhdq mm4,mm5 \ + __asm punpckldq mm2,mm5 \ + __asm movq OC_I(3),mm4 \ + __asm movq OC_I(2),mm2 \ +} + +/*38+19=57 cycles.*/ +#define OC_COLUMN_IDCT __asm{ \ + OC_IDCT_BEGIN \ + __asm paddw mm2,OC_8 \ + /*r1=H'+H'*/ \ + __asm paddw mm1,mm1 \ + /*r1=R1=A''+H'*/ \ + __asm paddw mm1,mm2 \ + /*r2=NR2*/ \ + __asm psraw mm2,4 \ + /*r4=E'=E-G*/ \ + __asm psubw mm4,mm7 \ + /*r1=NR1*/ \ + __asm psraw mm1,4 \ + /*r3=D'*/ \ + __asm movq mm3,OC_I(2) \ + /*r7=G+G*/ \ + __asm paddw mm7,mm7 \ + /*Store NR2 at I(2).*/ \ + __asm movq OC_I(2),mm2 \ + /*r7=G'=E+G*/ \ + __asm paddw mm7,mm4 \ + /*Store NR1 at I(1).*/ \ + __asm movq OC_I(1),mm1 \ + /*r4=R4=E'-D'*/ \ + __asm psubw mm4,mm3 \ + __asm paddw mm4,OC_8 \ + /*r3=D'+D'*/ \ + __asm paddw mm3,mm3 \ + /*r3=R3=E'+D'*/ \ + __asm paddw mm3,mm4 \ + /*r4=NR4*/ \ + __asm psraw mm4,4 \ + /*r6=R6=F'-B''*/ \ + __asm psubw mm6,mm5 \ + /*r3=NR3*/ \ + __asm psraw mm3,4 \ + __asm paddw mm6,OC_8 \ + /*r5=B''+B''*/ \ + __asm paddw mm5,mm5 \ + /*r5=R5=F'+B''*/ \ + __asm paddw mm5,mm6 \ + /*r6=NR6*/ \ + __asm psraw mm6,4 \ + /*Store NR4 at J(4).*/ \ + __asm movq OC_J(4),mm4 \ + /*r5=NR5*/ \ + __asm psraw mm5,4 \ + /*Store NR3 at I(3).*/ \ + __asm movq OC_I(3),mm3 \ + /*r7=R7=G'-C'*/ \ + __asm psubw mm7,mm0 \ + __asm paddw mm7,OC_8 \ + /*r0=C'+C'*/ \ + __asm paddw mm0,mm0 \ + /*r0=R0=G'+C'*/ \ + __asm paddw mm0,mm7 \ + /*r7=NR7*/ \ + __asm psraw mm7,4 \ + /*Store NR6 at J(6).*/ \ + __asm movq OC_J(6),mm6 \ + /*r0=NR0*/ \ + __asm psraw mm0,4 \ + /*Store NR5 at J(5).*/ \ + __asm movq OC_J(5),mm5 \ + /*Store NR7 at J(7).*/ \ + __asm movq OC_J(7),mm7 \ + /*Store NR0 at I(0).*/ \ + __asm movq OC_I(0),mm0 \ +} + +#define OC_MID(_m,_i) [CONSTS+_m+(_i)*8] +#define OC_C(_i) OC_MID(OC_COSINE_OFFSET,_i-1) +#define OC_8 OC_MID(OC_EIGHT_OFFSET,0) + +static void oc_idct8x8_slow(ogg_int16_t _y[64]){ + /*This routine accepts an 8x8 matrix, but in partially transposed form. + Every 4x4 block is transposed.*/ + __asm{ +#define CONSTS eax +#define Y edx + mov CONSTS,offset OC_IDCT_CONSTS + mov Y,_y +#define OC_I(_k) [Y+_k*16] +#define OC_J(_k) [Y+(_k-4)*16+8] + OC_ROW_IDCT + OC_TRANSPOSE +#undef OC_I +#undef OC_J +#define OC_I(_k) [Y+(_k*16)+64] +#define OC_J(_k) [Y+(_k-4)*16+72] + OC_ROW_IDCT + OC_TRANSPOSE +#undef OC_I +#undef OC_J +#define OC_I(_k) [Y+_k*16] +#define OC_J(_k) OC_I(_k) + OC_COLUMN_IDCT +#undef OC_I +#undef OC_J +#define OC_I(_k) [Y+_k*16+8] +#define OC_J(_k) OC_I(_k) + OC_COLUMN_IDCT +#undef OC_I +#undef OC_J +#undef CONSTS +#undef Y + } +} + +/*25 cycles.*/ +#define OC_IDCT_BEGIN_10 __asm{ \ + __asm movq mm2,OC_I(3) \ + __asm nop \ + __asm movq mm6,OC_C(3) \ + __asm movq mm4,mm2 \ + __asm movq mm1,OC_C(5) \ + __asm pmulhw mm4,mm6 \ + __asm movq mm3,OC_I(1) \ + __asm pmulhw mm1,mm2 \ + __asm movq mm0,OC_C(1) \ + __asm paddw mm4,mm2 \ + __asm pxor mm6,mm6 \ + __asm paddw mm2,mm1 \ + __asm movq mm5,OC_I(2) \ + __asm pmulhw mm0,mm3 \ + __asm movq mm1,mm5 \ + __asm paddw mm0,mm3 \ + __asm pmulhw mm3,OC_C(7) \ + __asm psubw mm6,mm2 \ + __asm pmulhw mm5,OC_C(2) \ + __asm psubw mm0,mm4 \ + __asm movq mm7,OC_I(2) \ + __asm paddw mm4,mm4 \ + __asm paddw mm7,mm5 \ + __asm paddw mm4,mm0 \ + __asm pmulhw mm1,OC_C(6) \ + __asm psubw mm3,mm6 \ + __asm movq OC_I(1),mm4 \ + __asm paddw mm6,mm6 \ + __asm movq mm4,OC_C(4) \ + __asm paddw mm6,mm3 \ + __asm movq mm5,mm3 \ + __asm pmulhw mm3,mm4 \ + __asm movq OC_I(2),mm6 \ + __asm movq mm2,mm0 \ + __asm movq mm6,OC_I(0) \ + __asm pmulhw mm0,mm4 \ + __asm paddw mm5,mm3 \ + __asm paddw mm2,mm0 \ + __asm psubw mm5,mm1 \ + __asm pmulhw mm6,mm4 \ + __asm paddw mm6,OC_I(0) \ + __asm paddw mm1,mm1 \ + __asm movq mm4,mm6 \ + __asm paddw mm1,mm5 \ + __asm psubw mm6,mm2 \ + __asm paddw mm2,mm2 \ + __asm movq mm0,OC_I(1) \ + __asm paddw mm2,mm6 \ + __asm psubw mm2,mm1 \ + __asm nop \ +} + +/*25+8=33 cycles.*/ +#define OC_ROW_IDCT_10 __asm{ \ + OC_IDCT_BEGIN_10 \ + /*r3=D'*/ \ + __asm movq mm3,OC_I(2) \ + /*r4=E'=E-G*/ \ + __asm psubw mm4,mm7 \ + /*r1=H'+H'*/ \ + __asm paddw mm1,mm1 \ + /*r7=G+G*/ \ + __asm paddw mm7,mm7 \ + /*r1=R1=A''+H'*/ \ + __asm paddw mm1,mm2 \ + /*r7=G'=E+G*/ \ + __asm paddw mm7,mm4 \ + /*r4=R4=E'-D'*/ \ + __asm psubw mm4,mm3 \ + __asm paddw mm3,mm3 \ + /*r6=R6=F'-B''*/ \ + __asm psubw mm6,mm5 \ + __asm paddw mm5,mm5 \ + /*r3=R3=E'+D'*/ \ + __asm paddw mm3,mm4 \ + /*r5=R5=F'+B''*/ \ + __asm paddw mm5,mm6 \ + /*r7=R7=G'-C'*/ \ + __asm psubw mm7,mm0 \ + __asm paddw mm0,mm0 \ + /*Save R1.*/ \ + __asm movq OC_I(1),mm1 \ + /*r0=R0=G'+C'*/ \ + __asm paddw mm0,mm7 \ +} + +/*25+19=44 cycles'*/ +#define OC_COLUMN_IDCT_10 __asm{ \ + OC_IDCT_BEGIN_10 \ + __asm paddw mm2,OC_8 \ + /*r1=H'+H'*/ \ + __asm paddw mm1,mm1 \ + /*r1=R1=A''+H'*/ \ + __asm paddw mm1,mm2 \ + /*r2=NR2*/ \ + __asm psraw mm2,4 \ + /*r4=E'=E-G*/ \ + __asm psubw mm4,mm7 \ + /*r1=NR1*/ \ + __asm psraw mm1,4 \ + /*r3=D'*/ \ + __asm movq mm3,OC_I(2) \ + /*r7=G+G*/ \ + __asm paddw mm7,mm7 \ + /*Store NR2 at I(2).*/ \ + __asm movq OC_I(2),mm2 \ + /*r7=G'=E+G*/ \ + __asm paddw mm7,mm4 \ + /*Store NR1 at I(1).*/ \ + __asm movq OC_I(1),mm1 \ + /*r4=R4=E'-D'*/ \ + __asm psubw mm4,mm3 \ + __asm paddw mm4,OC_8 \ + /*r3=D'+D'*/ \ + __asm paddw mm3,mm3 \ + /*r3=R3=E'+D'*/ \ + __asm paddw mm3,mm4 \ + /*r4=NR4*/ \ + __asm psraw mm4,4 \ + /*r6=R6=F'-B''*/ \ + __asm psubw mm6,mm5 \ + /*r3=NR3*/ \ + __asm psraw mm3,4 \ + __asm paddw mm6,OC_8 \ + /*r5=B''+B''*/ \ + __asm paddw mm5,mm5 \ + /*r5=R5=F'+B''*/ \ + __asm paddw mm5,mm6 \ + /*r6=NR6*/ \ + __asm psraw mm6,4 \ + /*Store NR4 at J(4).*/ \ + __asm movq OC_J(4),mm4 \ + /*r5=NR5*/ \ + __asm psraw mm5,4 \ + /*Store NR3 at I(3).*/ \ + __asm movq OC_I(3),mm3 \ + /*r7=R7=G'-C'*/ \ + __asm psubw mm7,mm0 \ + __asm paddw mm7,OC_8 \ + /*r0=C'+C'*/ \ + __asm paddw mm0,mm0 \ + /*r0=R0=G'+C'*/ \ + __asm paddw mm0,mm7 \ + /*r7=NR7*/ \ + __asm psraw mm7,4 \ + /*Store NR6 at J(6).*/ \ + __asm movq OC_J(6),mm6 \ + /*r0=NR0*/ \ + __asm psraw mm0,4 \ + /*Store NR5 at J(5).*/ \ + __asm movq OC_J(5),mm5 \ + /*Store NR7 at J(7).*/ \ + __asm movq OC_J(7),mm7 \ + /*Store NR0 at I(0).*/ \ + __asm movq OC_I(0),mm0 \ +} + +static void oc_idct8x8_10(ogg_int16_t _y[64]){ + __asm{ +#define CONSTS eax +#define Y edx + mov CONSTS,offset OC_IDCT_CONSTS + mov Y,_y +#define OC_I(_k) [Y+_k*16] +#define OC_J(_k) [Y+(_k-4)*16+8] + /*Done with dequant, descramble, and partial transpose. + Now do the iDCT itself.*/ + OC_ROW_IDCT_10 + OC_TRANSPOSE +#undef OC_I +#undef OC_J +#define OC_I(_k) [Y+_k*16] +#define OC_J(_k) OC_I(_k) + OC_COLUMN_IDCT_10 +#undef OC_I +#undef OC_J +#define OC_I(_k) [Y+_k*16+8] +#define OC_J(_k) OC_I(_k) + OC_COLUMN_IDCT_10 +#undef OC_I +#undef OC_J +#undef CONSTS +#undef Y + } +} + +/*Performs an inverse 8x8 Type-II DCT transform. + The input is assumed to be scaled by a factor of 4 relative to orthonormal + version of the transform.*/ +void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi){ + /*_last_zzi is subtly different from an actual count of the number of + coefficients we decoded for this block. + It contains the value of zzi BEFORE the final token in the block was + decoded. + In most cases this is an EOB token (the continuation of an EOB run from a + previous block counts), and so this is the same as the coefficient count. + However, in the case that the last token was NOT an EOB token, but filled + the block up with exactly 64 coefficients, _last_zzi will be less than 64. + Provided the last token was not a pure zero run, the minimum value it can + be is 46, and so that doesn't affect any of the cases in this routine. + However, if the last token WAS a pure zero run of length 63, then _last_zzi + will be 1 while the number of coefficients decoded is 64. + Thus, we will trigger the following special case, where the real + coefficient count would not. + Note also that a zero run of length 64 will give _last_zzi a value of 0, + but we still process the DC coefficient, which might have a non-zero value + due to DC prediction. + Although convoluted, this is arguably the correct behavior: it allows us to + use a smaller transform when the block ends with a long zero run instead + of a normal EOB token. + It could be smarter... multiple separate zero runs at the end of a block + will fool it, but an encoder that generates these really deserves what it + gets. + Needless to say we inherited this approach from VP3.*/ + /*Perform the iDCT.*/ + if(_last_zzi<10)oc_idct8x8_10(_y); + else oc_idct8x8_slow(_y); +} + +#endif diff --git a/Engine/lib/libtheora/lib/x86_vc/mmxloop.h b/Engine/lib/libtheora/lib/x86_vc/mmxloop.h new file mode 100644 index 000000000..2561fca2a --- /dev/null +++ b/Engine/lib/libtheora/lib/x86_vc/mmxloop.h @@ -0,0 +1,219 @@ +#if !defined(_x86_vc_mmxloop_H) +# define _x86_vc_mmxloop_H (1) +# include +# include "x86int.h" + +#if defined(OC_X86_ASM) + +/*On entry, mm0={a0,...,a7}, mm1={b0,...,b7}, mm2={c0,...,c7}, mm3={d0,...d7}. + On exit, mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)} and + mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}; mm0 and mm3 are clobbered.*/ +#define OC_LOOP_FILTER8_MMX __asm{ \ + /*mm7=0*/ \ + __asm pxor mm7,mm7 \ + /*mm6:mm0={a0,...,a7}*/ \ + __asm movq mm6,mm0 \ + __asm punpcklbw mm0,mm7 \ + __asm punpckhbw mm6,mm7 \ + /*mm3:mm5={d0,...,d7}*/ \ + __asm movq mm5,mm3 \ + __asm punpcklbw mm3,mm7 \ + __asm punpckhbw mm5,mm7 \ + /*mm6:mm0={a0-d0,...,a7-d7}*/ \ + __asm psubw mm0,mm3 \ + __asm psubw mm6,mm5 \ + /*mm3:mm1={b0,...,b7}*/ \ + __asm movq mm3,mm1 \ + __asm punpcklbw mm1,mm7 \ + __asm movq mm4,mm2 \ + __asm punpckhbw mm3,mm7 \ + /*mm5:mm4={c0,...,c7}*/ \ + __asm movq mm5,mm2 \ + __asm punpcklbw mm4,mm7 \ + __asm punpckhbw mm5,mm7 \ + /*mm7={3}x4 \ + mm5:mm4={c0-b0,...,c7-b7}*/ \ + __asm pcmpeqw mm7,mm7 \ + __asm psubw mm4,mm1 \ + __asm psrlw mm7,14 \ + __asm psubw mm5,mm3 \ + /*Scale by 3.*/ \ + __asm pmullw mm4,mm7 \ + __asm pmullw mm5,mm7 \ + /*mm7={4}x4 \ + mm5:mm4=f={a0-d0+3*(c0-b0),...,a7-d7+3*(c7-b7)}*/ \ + __asm psrlw mm7,1 \ + __asm paddw mm4,mm0 \ + __asm psllw mm7,2 \ + __asm movq mm0,[LL] \ + __asm paddw mm5,mm6 \ + /*R_i has the range [-127,128], so we compute -R_i instead. \ + mm4=-R_i=-(f+4>>3)=0xFF^(f-4>>3)*/ \ + __asm psubw mm4,mm7 \ + __asm psubw mm5,mm7 \ + __asm psraw mm4,3 \ + __asm psraw mm5,3 \ + __asm pcmpeqb mm7,mm7 \ + __asm packsswb mm4,mm5 \ + __asm pxor mm6,mm6 \ + __asm pxor mm4,mm7 \ + __asm packuswb mm1,mm3 \ + /*Now compute lflim of -mm4 cf. Section 7.10 of the sepc.*/ \ + /*There's no unsigned byte+signed byte with unsigned saturation op code, so \ + we have to split things by sign (the other option is to work in 16 bits, \ + but working in 8 bits gives much better parallelism). \ + We compute abs(R_i), but save a mask of which terms were negative in mm6. \ + Then we compute mm4=abs(lflim(R_i,L))=min(abs(R_i),max(2*L-abs(R_i),0)). \ + Finally, we split mm4 into positive and negative pieces using the mask in \ + mm6, and add and subtract them as appropriate.*/ \ + /*mm4=abs(-R_i)*/ \ + /*mm7=255-2*L*/ \ + __asm pcmpgtb mm6,mm4 \ + __asm psubb mm7,mm0 \ + __asm pxor mm4,mm6 \ + __asm psubb mm7,mm0 \ + __asm psubb mm4,mm6 \ + /*mm7=255-max(2*L-abs(R_i),0)*/ \ + __asm paddusb mm7,mm4 \ + /*mm4=min(abs(R_i),max(2*L-abs(R_i),0))*/ \ + __asm paddusb mm4,mm7 \ + __asm psubusb mm4,mm7 \ + /*Now split mm4 by the original sign of -R_i.*/ \ + __asm movq mm5,mm4 \ + __asm pand mm4,mm6 \ + __asm pandn mm6,mm5 \ + /*mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)}*/ \ + /*mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}*/ \ + __asm paddusb mm1,mm4 \ + __asm psubusb mm2,mm4 \ + __asm psubusb mm1,mm6 \ + __asm paddusb mm2,mm6 \ +} + +#define OC_LOOP_FILTER_V_MMX(_pix,_ystride,_ll) \ + do{ \ + /*Used local variable pix__ in order to fix compilation errors like: \ + "error C2425: 'SHL' : non-constant expression in 'second operand'".*/ \ + unsigned char *pix__; \ + unsigned char *ll__; \ + ll__=(_ll); \ + pix__=(_pix); \ + __asm mov YSTRIDE,_ystride \ + __asm mov LL,ll__ \ + __asm mov PIX,pix__ \ + __asm sub PIX,YSTRIDE \ + __asm sub PIX,YSTRIDE \ + /*mm0={a0,...,a7}*/ \ + __asm movq mm0,[PIX] \ + /*ystride3=_ystride*3*/ \ + __asm lea YSTRIDE3,[YSTRIDE+YSTRIDE*2] \ + /*mm3={d0,...,d7}*/ \ + __asm movq mm3,[PIX+YSTRIDE3] \ + /*mm1={b0,...,b7}*/ \ + __asm movq mm1,[PIX+YSTRIDE] \ + /*mm2={c0,...,c7}*/ \ + __asm movq mm2,[PIX+YSTRIDE*2] \ + OC_LOOP_FILTER8_MMX \ + /*Write it back out.*/ \ + __asm movq [PIX+YSTRIDE],mm1 \ + __asm movq [PIX+YSTRIDE*2],mm2 \ + } \ + while(0) + +#define OC_LOOP_FILTER_H_MMX(_pix,_ystride,_ll) \ + do{ \ + /*Used local variable ll__ in order to fix compilation errors like: \ + "error C2443: operand size conflict".*/ \ + unsigned char *ll__; \ + unsigned char *pix__; \ + ll__=(_ll); \ + pix__=(_pix)-2; \ + __asm mov PIX,pix__ \ + __asm mov YSTRIDE,_ystride \ + __asm mov LL,ll__ \ + /*x x x x d0 c0 b0 a0*/ \ + __asm movd mm0,[PIX] \ + /*x x x x d1 c1 b1 a1*/ \ + __asm movd mm1,[PIX+YSTRIDE] \ + /*ystride3=_ystride*3*/ \ + __asm lea YSTRIDE3,[YSTRIDE+YSTRIDE*2] \ + /*x x x x d2 c2 b2 a2*/ \ + __asm movd mm2,[PIX+YSTRIDE*2] \ + /*x x x x d3 c3 b3 a3*/ \ + __asm lea D,[PIX+YSTRIDE*4] \ + __asm movd mm3,[PIX+YSTRIDE3] \ + /*x x x x d4 c4 b4 a4*/ \ + __asm movd mm4,[D] \ + /*x x x x d5 c5 b5 a5*/ \ + __asm movd mm5,[D+YSTRIDE] \ + /*x x x x d6 c6 b6 a6*/ \ + __asm movd mm6,[D+YSTRIDE*2] \ + /*x x x x d7 c7 b7 a7*/ \ + __asm movd mm7,[D+YSTRIDE3] \ + /*mm0=d1 d0 c1 c0 b1 b0 a1 a0*/ \ + __asm punpcklbw mm0,mm1 \ + /*mm2=d3 d2 c3 c2 b3 b2 a3 a2*/ \ + __asm punpcklbw mm2,mm3 \ + /*mm3=d1 d0 c1 c0 b1 b0 a1 a0*/ \ + __asm movq mm3,mm0 \ + /*mm0=b3 b2 b1 b0 a3 a2 a1 a0*/ \ + __asm punpcklwd mm0,mm2 \ + /*mm3=d3 d2 d1 d0 c3 c2 c1 c0*/ \ + __asm punpckhwd mm3,mm2 \ + /*mm1=b3 b2 b1 b0 a3 a2 a1 a0*/ \ + __asm movq mm1,mm0 \ + /*mm4=d5 d4 c5 c4 b5 b4 a5 a4*/ \ + __asm punpcklbw mm4,mm5 \ + /*mm6=d7 d6 c7 c6 b7 b6 a7 a6*/ \ + __asm punpcklbw mm6,mm7 \ + /*mm5=d5 d4 c5 c4 b5 b4 a5 a4*/ \ + __asm movq mm5,mm4 \ + /*mm4=b7 b6 b5 b4 a7 a6 a5 a4*/ \ + __asm punpcklwd mm4,mm6 \ + /*mm5=d7 d6 d5 d4 c7 c6 c5 c4*/ \ + __asm punpckhwd mm5,mm6 \ + /*mm2=d3 d2 d1 d0 c3 c2 c1 c0*/ \ + __asm movq mm2,mm3 \ + /*mm0=a7 a6 a5 a4 a3 a2 a1 a0*/ \ + __asm punpckldq mm0,mm4 \ + /*mm1=b7 b6 b5 b4 b3 b2 b1 b0*/ \ + __asm punpckhdq mm1,mm4 \ + /*mm2=c7 c6 c5 c4 c3 c2 c1 c0*/ \ + __asm punpckldq mm2,mm5 \ + /*mm3=d7 d6 d5 d4 d3 d2 d1 d0*/ \ + __asm punpckhdq mm3,mm5 \ + OC_LOOP_FILTER8_MMX \ + /*mm2={b0+R_0'',...,b7+R_7''}*/ \ + __asm movq mm0,mm1 \ + /*mm1={b0+R_0'',c0-R_0'',...,b3+R_3'',c3-R_3''}*/ \ + __asm punpcklbw mm1,mm2 \ + /*mm2={b4+R_4'',c4-R_4'',...,b7+R_7'',c7-R_7''}*/ \ + __asm punpckhbw mm0,mm2 \ + /*[d]=c1 b1 c0 b0*/ \ + __asm movd D,mm1 \ + __asm mov [PIX+1],D_WORD \ + __asm psrlq mm1,32 \ + __asm shr D,16 \ + __asm mov [PIX+YSTRIDE+1],D_WORD \ + /*[d]=c3 b3 c2 b2*/ \ + __asm movd D,mm1 \ + __asm mov [PIX+YSTRIDE*2+1],D_WORD \ + __asm shr D,16 \ + __asm mov [PIX+YSTRIDE3+1],D_WORD \ + __asm lea PIX,[PIX+YSTRIDE*4] \ + /*[d]=c5 b5 c4 b4*/ \ + __asm movd D,mm0 \ + __asm mov [PIX+1],D_WORD \ + __asm psrlq mm0,32 \ + __asm shr D,16 \ + __asm mov [PIX+YSTRIDE+1],D_WORD \ + /*[d]=c7 b7 c6 b6*/ \ + __asm movd D,mm0 \ + __asm mov [PIX+YSTRIDE*2+1],D_WORD \ + __asm shr D,16 \ + __asm mov [PIX+YSTRIDE3+1],D_WORD \ + } \ + while(0) + +# endif +#endif diff --git a/Engine/lib/libtheora/lib/x86_vc/mmxstate.c b/Engine/lib/libtheora/lib/x86_vc/mmxstate.c new file mode 100644 index 000000000..73bd1981c --- /dev/null +++ b/Engine/lib/libtheora/lib/x86_vc/mmxstate.c @@ -0,0 +1,211 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: mmxstate.c 16584 2009-09-26 19:35:55Z tterribe $ + + ********************************************************************/ + +/*MMX acceleration of complete fragment reconstruction algorithm. + Originally written by Rudolf Marek.*/ +#include +#include "x86int.h" +#include "mmxfrag.h" +#include "mmxloop.h" + +#if defined(OC_X86_ASM) + +void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi, + int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant){ + unsigned char *dst; + ptrdiff_t frag_buf_off; + int ystride; + int mb_mode; + /*Apply the inverse transform.*/ + /*Special case only having a DC component.*/ + if(_last_zzi<2){ + /*Note that this value must be unsigned, to keep the __asm__ block from + sign-extending it when it puts it in a register.*/ + ogg_uint16_t p; + /*We round this dequant product (and not any of the others) because there's + no iDCT rounding.*/ + p=(ogg_int16_t)(_dct_coeffs[0]*(ogg_int32_t)_dc_quant+15>>5); + /*Fill _dct_coeffs with p.*/ + __asm{ +#define Y eax +#define P ecx + mov Y,_dct_coeffs + movzx P,p + /*mm0=0000 0000 0000 AAAA*/ + movd mm0,P + /*mm0=0000 0000 AAAA AAAA*/ + punpcklwd mm0,mm0 + /*mm0=AAAA AAAA AAAA AAAA*/ + punpckldq mm0,mm0 + movq [Y],mm0 + movq [8+Y],mm0 + movq [16+Y],mm0 + movq [24+Y],mm0 + movq [32+Y],mm0 + movq [40+Y],mm0 + movq [48+Y],mm0 + movq [56+Y],mm0 + movq [64+Y],mm0 + movq [72+Y],mm0 + movq [80+Y],mm0 + movq [88+Y],mm0 + movq [96+Y],mm0 + movq [104+Y],mm0 + movq [112+Y],mm0 + movq [120+Y],mm0 +#undef Y +#undef P + } + } + else{ + /*Dequantize the DC coefficient.*/ + _dct_coeffs[0]=(ogg_int16_t)(_dct_coeffs[0]*(int)_dc_quant); + oc_idct8x8_mmx(_dct_coeffs,_last_zzi); + } + /*Fill in the target buffer.*/ + frag_buf_off=_state->frag_buf_offs[_fragi]; + mb_mode=_state->frags[_fragi].mb_mode; + ystride=_state->ref_ystride[_pli]; + dst=_state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_SELF]]+frag_buf_off; + if(mb_mode==OC_MODE_INTRA)oc_frag_recon_intra_mmx(dst,ystride,_dct_coeffs); + else{ + const unsigned char *ref; + int mvoffsets[2]; + ref= + _state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_FOR_MODE(mb_mode)]] + +frag_buf_off; + if(oc_state_get_mv_offsets(_state,mvoffsets,_pli, + _state->frag_mvs[_fragi][0],_state->frag_mvs[_fragi][1])>1){ + oc_frag_recon_inter2_mmx(dst,ref+mvoffsets[0],ref+mvoffsets[1],ystride, + _dct_coeffs); + } + else oc_frag_recon_inter_mmx(dst,ref+mvoffsets[0],ystride,_dct_coeffs); + } +} + +/*We copy these entire function to inline the actual MMX routines so that we + use only a single indirect call.*/ + +/*Copies the fragments specified by the lists of fragment indices from one + frame to another. + _fragis: A pointer to a list of fragment indices. + _nfragis: The number of fragment indices to copy. + _dst_frame: The reference frame to copy to. + _src_frame: The reference frame to copy from. + _pli: The color plane the fragments lie in.*/ +void oc_state_frag_copy_list_mmx(const oc_theora_state *_state, + const ptrdiff_t *_fragis,ptrdiff_t _nfragis, + int _dst_frame,int _src_frame,int _pli){ + const ptrdiff_t *frag_buf_offs; + const unsigned char *src_frame_data; + unsigned char *dst_frame_data; + ptrdiff_t fragii; + int ystride; + dst_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_dst_frame]]; + src_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_src_frame]]; + ystride=_state->ref_ystride[_pli]; + frag_buf_offs=_state->frag_buf_offs; + for(fragii=0;fragii<_nfragis;fragii++){ + ptrdiff_t frag_buf_off; + frag_buf_off=frag_buf_offs[_fragis[fragii]]; +#define SRC edx +#define DST eax +#define YSTRIDE ecx +#define YSTRIDE3 edi + OC_FRAG_COPY_MMX(dst_frame_data+frag_buf_off, + src_frame_data+frag_buf_off,ystride); +#undef SRC +#undef DST +#undef YSTRIDE +#undef YSTRIDE3 + } +} + +/*Apply the loop filter to a given set of fragment rows in the given plane. + The filter may be run on the bottom edge, affecting pixels in the next row of + fragments, so this row also needs to be available. + _bv: The bounding values array. + _refi: The index of the frame buffer to filter. + _pli: The color plane to filter. + _fragy0: The Y coordinate of the first fragment row to filter. + _fragy_end: The Y coordinate of the fragment row to stop filtering at.*/ +void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state, + int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end){ + OC_ALIGN8(unsigned char ll[8]); + const oc_fragment_plane *fplane; + const oc_fragment *frags; + const ptrdiff_t *frag_buf_offs; + unsigned char *ref_frame_data; + ptrdiff_t fragi_top; + ptrdiff_t fragi_bot; + ptrdiff_t fragi0; + ptrdiff_t fragi0_end; + int ystride; + int nhfrags; + memset(ll,_state->loop_filter_limits[_state->qis[0]],sizeof(ll)); + fplane=_state->fplanes+_pli; + nhfrags=fplane->nhfrags; + fragi_top=fplane->froffset; + fragi_bot=fragi_top+fplane->nfrags; + fragi0=fragi_top+_fragy0*(ptrdiff_t)nhfrags; + fragi0_end=fragi0+(_fragy_end-_fragy0)*(ptrdiff_t)nhfrags; + ystride=_state->ref_ystride[_pli]; + frags=_state->frags; + frag_buf_offs=_state->frag_buf_offs; + ref_frame_data=_state->ref_frame_data[_refi]; + /*The following loops are constructed somewhat non-intuitively on purpose. + The main idea is: if a block boundary has at least one coded fragment on + it, the filter is applied to it. + However, the order that the filters are applied in matters, and VP3 chose + the somewhat strange ordering used below.*/ + while(fragi0fragi0)OC_LOOP_FILTER_H_MMX(ref,ystride,ll); + if(fragi0>fragi_top)OC_LOOP_FILTER_V_MMX(ref,ystride,ll); + if(fragi+1opt_vtable.frag_sub=oc_enc_frag_sub_mmx; + _enc->opt_vtable.frag_sub_128=oc_enc_frag_sub_128_mmx; + _enc->opt_vtable.frag_recon_intra=oc_frag_recon_intra_mmx; + _enc->opt_vtable.frag_recon_inter=oc_frag_recon_inter_mmx; + _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_mmx; + } + if(cpu_flags&OC_CPU_X86_MMXEXT){ + _enc->opt_vtable.frag_sad=oc_enc_frag_sad_mmxext; + _enc->opt_vtable.frag_sad_thresh=oc_enc_frag_sad_thresh_mmxext; + _enc->opt_vtable.frag_sad2_thresh=oc_enc_frag_sad2_thresh_mmxext; + _enc->opt_vtable.frag_satd_thresh=oc_enc_frag_satd_thresh_mmxext; + _enc->opt_vtable.frag_satd2_thresh=oc_enc_frag_satd2_thresh_mmxext; + _enc->opt_vtable.frag_intra_satd=oc_enc_frag_intra_satd_mmxext; + _enc->opt_vtable.frag_copy2=oc_enc_frag_copy2_mmxext; + } + if(cpu_flags&OC_CPU_X86_SSE2){ +# if defined(OC_X86_64_ASM) + _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_x86_64sse2; +# endif + } +} +#endif diff --git a/Engine/lib/libtheora/lib/x86_vc/x86enc.h b/Engine/lib/libtheora/lib/x86_vc/x86enc.h new file mode 100644 index 000000000..581484641 --- /dev/null +++ b/Engine/lib/libtheora/lib/x86_vc/x86enc.h @@ -0,0 +1,47 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: x86int.h 15675 2009-02-06 09:43:27Z tterribe $ + + ********************************************************************/ + +#if !defined(_x86_vc_x86enc_H) +# define _x86_vc_x86enc_H (1) +# include "../encint.h" +# include "x86int.h" + +void oc_enc_vtable_init_x86(oc_enc_ctx *_enc); + +unsigned oc_enc_frag_sad_mmxext(const unsigned char *_src, + const unsigned char *_ref,int _ystride); +unsigned oc_enc_frag_sad_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _thresh); +unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref1,const unsigned char *_ref2,int _ystride, + unsigned _thresh); +unsigned oc_enc_frag_satd_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref,int _ystride,unsigned _thresh); +unsigned oc_enc_frag_satd2_thresh_mmxext(const unsigned char *_src, + const unsigned char *_ref1,const unsigned char *_ref2,int _ystride, + unsigned _thresh); +unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,int _ystride); +void oc_enc_frag_sub_mmx(ogg_int16_t _diff[64], + const unsigned char *_x,const unsigned char *_y,int _stride); +void oc_enc_frag_sub_128_mmx(ogg_int16_t _diff[64], + const unsigned char *_x,int _stride); +void oc_enc_frag_copy2_mmxext(unsigned char *_dst, + const unsigned char *_src1,const unsigned char *_src2,int _ystride); +void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]); +void oc_enc_fdct8x8_x86_64sse2(ogg_int16_t _y[64],const ogg_int16_t _x[64]); + +#endif diff --git a/Engine/lib/libtheora/lib/x86_vc/x86int.h b/Engine/lib/libtheora/lib/x86_vc/x86int.h new file mode 100644 index 000000000..4cca48531 --- /dev/null +++ b/Engine/lib/libtheora/lib/x86_vc/x86int.h @@ -0,0 +1,42 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: x86int.h 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ + +#if !defined(_x86_vc_x86int_H) +# define _x86_vc_x86int_H (1) +# include "../internal.h" + +void oc_state_vtable_init_x86(oc_theora_state *_state); + +void oc_frag_copy_mmx(unsigned char *_dst, + const unsigned char *_src,int _ystride); +void oc_frag_recon_intra_mmx(unsigned char *_dst,int _ystride, + const ogg_int16_t *_residue); +void oc_frag_recon_inter_mmx(unsigned char *_dst, + const unsigned char *_src,int _ystride,const ogg_int16_t *_residue); +void oc_frag_recon_inter2_mmx(unsigned char *_dst,const unsigned char *_src1, + const unsigned char *_src2,int _ystride,const ogg_int16_t *_residue); +void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi); +void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi, + int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant); +void oc_state_frag_copy_list_mmx(const oc_theora_state *_state, + const ptrdiff_t *_fragis,ptrdiff_t _nfragis, + int _dst_frame,int _src_frame,int _pli); +void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state, + int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end); +void oc_restore_fpu_mmx(void); + +#endif diff --git a/Engine/lib/libtheora/lib/dec/x86_vc/x86state.c b/Engine/lib/libtheora/lib/x86_vc/x86state.c similarity index 53% rename from Engine/lib/libtheora/lib/dec/x86_vc/x86state.c rename to Engine/lib/libtheora/lib/x86_vc/x86state.c index 735390823..a786bec28 100644 --- a/Engine/lib/libtheora/lib/dec/x86_vc/x86state.c +++ b/Engine/lib/libtheora/lib/x86_vc/x86state.c @@ -5,37 +5,58 @@ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2008 * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * * * ******************************************************************** function: - last mod: $Id: x86state.c 15427 2008-10-21 02:36:19Z xiphmont $ + last mod: $Id: x86state.c 16503 2009-08-22 18:14:02Z giles $ ********************************************************************/ -#if defined(USE_ASM) - #include "x86int.h" -#include "../../cpu.c" + +#if defined(OC_X86_ASM) + +#include "../cpu.c" + +/*This table has been modified from OC_FZIG_ZAG by baking a 4x4 transpose into + each quadrant of the destination.*/ +static const unsigned char OC_FZIG_ZAG_MMX[128]={ + 0, 8, 1, 2, 9,16,24,17, + 10, 3,32,11,18,25, 4,12, + 5,26,19,40,33,34,41,48, + 27, 6,13,20,28,21,14, 7, + 56,49,42,35,43,50,57,36, + 15,22,29,30,23,44,37,58, + 51,59,38,45,52,31,60,53, + 46,39,47,54,61,62,55,63, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64, +}; void oc_state_vtable_init_x86(oc_theora_state *_state){ _state->cpu_flags=oc_cpu_flags_get(); - - /* fill with defaults */ - oc_state_vtable_init_c(_state); - - /* patch MMX functions */ if(_state->cpu_flags&OC_CPU_X86_MMX){ + _state->opt_vtable.frag_copy=oc_frag_copy_mmx; _state->opt_vtable.frag_recon_intra=oc_frag_recon_intra_mmx; _state->opt_vtable.frag_recon_inter=oc_frag_recon_inter_mmx; _state->opt_vtable.frag_recon_inter2=oc_frag_recon_inter2_mmx; - _state->opt_vtable.restore_fpu=oc_restore_fpu_mmx; - _state->opt_vtable.state_frag_copy=oc_state_frag_copy_mmx; + _state->opt_vtable.idct8x8=oc_idct8x8_mmx; _state->opt_vtable.state_frag_recon=oc_state_frag_recon_mmx; - _state->opt_vtable.state_loop_filter_frag_rows=oc_state_loop_filter_frag_rows_mmx; + _state->opt_vtable.state_frag_copy_list=oc_state_frag_copy_list_mmx; + _state->opt_vtable.state_loop_filter_frag_rows= + oc_state_loop_filter_frag_rows_mmx; + _state->opt_vtable.restore_fpu=oc_restore_fpu_mmx; + _state->opt_data.dct_fzig_zag=OC_FZIG_ZAG_MMX; } + else oc_state_vtable_init_c(_state); } - #endif diff --git a/Engine/lib/opcode/Ice/IceFPU.h b/Engine/lib/opcode/Ice/IceFPU.h index a8dd69cc7..9cf2f2452 100644 --- a/Engine/lib/opcode/Ice/IceFPU.h +++ b/Engine/lib/opcode/Ice/IceFPU.h @@ -45,7 +45,7 @@ //! Fast square root for floating-point values. inline_ float FastSqrt(float square) { -#if defined( PLATFORM_WINDOWS ) +#if defined( PLATFORM_WINDOWS ) && !defined ( _WIN64 ) float retval; __asm { @@ -188,7 +188,7 @@ return x*x < epsilon; } -#ifdef PLATFORM_WINDOWS +#if defined( PLATFORM_WINDOWS ) && !defined ( _WIN64 ) #define FCOMI_ST0 _asm _emit 0xdb _asm _emit 0xf0 #define FCOMIP_ST0 _asm _emit 0xdf _asm _emit 0xf0 #define FCMOVB_ST0 _asm _emit 0xda _asm _emit 0xc0 diff --git a/Engine/lib/opcode/Ice/IceMemoryMacros.h b/Engine/lib/opcode/Ice/IceMemoryMacros.h index f0f27d5ed..f4d511189 100644 --- a/Engine/lib/opcode/Ice/IceMemoryMacros.h +++ b/Engine/lib/opcode/Ice/IceMemoryMacros.h @@ -47,7 +47,7 @@ //! \warning writes nb*4 bytes ! inline_ void StoreDwords(udword* dest, udword nb, udword value) { -#ifdef _WIN32 +#if defined( _WIN32 ) && !defined( _WIN64 ) // The asm code below **SHOULD** be equivalent to one of those C versions // or the other if your compiled is good: (checked on VC++ 6.0) // diff --git a/Engine/source/T3D/aiClient.cpp b/Engine/source/T3D/aiClient.cpp index 3decd3462..335ac6a15 100644 --- a/Engine/source/T3D/aiClient.cpp +++ b/Engine/source/T3D/aiClient.cpp @@ -63,7 +63,7 @@ AIClient::AIClient() { mMoveTolerance = 0.25f; // Clear the triggers - for( int i = 0; i < MaxTriggerKeys; i++ ) + for( S32 i = 0; i < MaxTriggerKeys; i++ ) mTriggers[i] = false; mAimToDestination = true; @@ -369,7 +369,7 @@ U32 AIClient::getMoveList( Move **movePtr,U32 *numMoves ) { } // Copy over the trigger status - for( int i = 0; i < MaxTriggerKeys; i++ ) { + for( S32 i = 0; i < MaxTriggerKeys; i++ ) { mMove.trigger[i] = mTriggers[i]; mTriggers[i] = false; } @@ -457,8 +457,9 @@ ConsoleMethod( AIClient, getAimLocation, const char *, 2, 2, "ai.getAimLocation( AIClient *ai = static_cast( object ); Point3F aimPoint = ai->getAimLocation(); - char *returnBuffer = Con::getReturnBuffer( 256 ); - dSprintf( returnBuffer, 256, "%f %f %f", aimPoint.x, aimPoint.y, aimPoint.z ); + static const U32 bufSize = 256; + char *returnBuffer = Con::getReturnBuffer( bufSize ); + dSprintf( returnBuffer, bufSize, "%f %f %f", aimPoint.x, aimPoint.y, aimPoint.z ); return returnBuffer; } @@ -470,8 +471,9 @@ ConsoleMethod( AIClient, getMoveDestination, const char *, 2, 2, "ai.getMoveDest AIClient *ai = static_cast( object ); Point3F movePoint = ai->getMoveDestination(); - char *returnBuffer = Con::getReturnBuffer( 256 ); - dSprintf( returnBuffer, 256, "%f %f %f", movePoint.x, movePoint.y, movePoint.z ); + static const U32 bufSize = 256; + char *returnBuffer = Con::getReturnBuffer( bufSize ); + dSprintf( returnBuffer, bufSize, "%f %f %f", movePoint.x, movePoint.y, movePoint.z ); return returnBuffer; } @@ -522,8 +524,9 @@ ConsoleMethod( AIClient, getLocation, const char *, 2, 2, "ai.getLocation();" ) AIClient *ai = static_cast( object ); Point3F locPoint = ai->getLocation(); - char *returnBuffer = Con::getReturnBuffer( 256 ); - dSprintf( returnBuffer, 256, "%f %f %f", locPoint.x, locPoint.y, locPoint.z ); + static const U32 bufSize = 256; + char *returnBuffer = Con::getReturnBuffer( bufSize ); + dSprintf( returnBuffer, bufSize, "%f %f %f", locPoint.x, locPoint.y, locPoint.z ); return returnBuffer; } diff --git a/Engine/source/T3D/aiPlayer.cpp b/Engine/source/T3D/aiPlayer.cpp index 725aaed29..31ada9970 100644 --- a/Engine/source/T3D/aiPlayer.cpp +++ b/Engine/source/T3D/aiPlayer.cpp @@ -28,6 +28,8 @@ #include "T3D/gameBase/moveManager.h" #include "console/engineAPI.h" +static U32 sAIPlayerLoSMask = TerrainObjectType | StaticShapeObjectType | StaticObjectType; + IMPLEMENT_CO_NETOBJECT_V1(AIPlayer); ConsoleDocClass( AIPlayer, @@ -417,33 +419,26 @@ bool AIPlayer::getAIMove(Move *movePtr) // Test for target location in sight if it's an object. The LOS is // run from the eye position to the center of the object's bounding, // which is not very accurate. - if (mAimObject) { - MatrixF eyeMat; - getEyeTransform(&eyeMat); - eyeMat.getColumn(3,&location); - Point3F targetLoc = mAimObject->getBoxCenter(); - - // This ray ignores non-static shapes. Cast Ray returns true - // if it hit something. - RayInfo dummy; - if (getContainer()->castRay( location, targetLoc, - StaticShapeObjectType | StaticObjectType | - TerrainObjectType, &dummy)) { - if (mTargetInLOS) { - throwCallback( "onTargetExitLOS" ); - mTargetInLOS = false; - } - } - else - if (!mTargetInLOS) { - throwCallback( "onTargetEnterLOS" ); + if (mAimObject) + { + if (checkInLos(mAimObject.getPointer())) + { + if (!mTargetInLOS) + { + throwCallback("onTargetEnterLOS"); mTargetInLOS = true; } + } + else if (mTargetInLOS) + { + throwCallback("onTargetExitLOS"); + mTargetInLOS = false; + } } // Replicate the trigger state into the move so that // triggers can be controlled from scripts. - for( int i = 0; i < MaxTriggerKeys; i++ ) + for( S32 i = 0; i < MaxTriggerKeys; i++ ) movePtr->trigger[i] = getImageTriggerState(i); mLastLocation = location; @@ -610,3 +605,112 @@ DefineEngineMethod( AIPlayer, getAimObject, S32, (),, GameBase* obj = object->getAimObject(); return obj? obj->getId(): -1; } + +bool AIPlayer::checkInLos(GameBase* target, bool _useMuzzle, bool _checkEnabled) +{ + if (!isServerObject()) return false; + if (!target) + { + target = mAimObject.getPointer(); + if (!target) + return false; + } + if (_checkEnabled) + { + if (target->getTypeMask() & ShapeBaseObjectType) + { + ShapeBase *shapeBaseCheck = static_cast(target); + if (shapeBaseCheck) + if (shapeBaseCheck->getDamageState() != Enabled) return false; + } + else + return false; + } + + RayInfo ri; + + disableCollision(); + + S32 mountCount = target->getMountedObjectCount(); + for (S32 i = 0; i < mountCount; i++) + { + target->getMountedObject(i)->disableCollision(); + } + + Point3F checkPoint ; + if (_useMuzzle) + getMuzzlePointAI(0, &checkPoint ); + else + { + MatrixF eyeMat; + getEyeTransform(&eyeMat); + eyeMat.getColumn(3, &checkPoint ); + } + + bool hit = !gServerContainer.castRay(checkPoint, target->getBoxCenter(), sAIPlayerLoSMask, &ri); + enableCollision(); + + for (S32 i = 0; i < mountCount; i++) + { + target->getMountedObject(i)->enableCollision(); + } + return hit; +} + +DefineEngineMethod(AIPlayer, checkInLos, bool, (ShapeBase* obj, bool useMuzzle, bool checkEnabled),(NULL, false, false), + "@brief Check whether an object is in line of sight.\n" + "@obj Object to check. (If blank, it will check the current target).\n" + "@useMuzzle Use muzzle position. Otherwise use eye position. (defaults to false).\n" + "@checkEnabled check whether the object can take damage and if so is still alive.(Defaults to false)\n") +{ + return object->checkInLos(obj, useMuzzle, checkEnabled); +} + +bool AIPlayer::checkInFoV(GameBase* target, F32 camFov, bool _checkEnabled) +{ + if (!isServerObject()) return false; + if (!target) + { + target = mAimObject.getPointer(); + if (!target) + return false; + } + if (_checkEnabled) + { + if (target->getTypeMask() & ShapeBaseObjectType) + { + ShapeBase *shapeBaseCheck = static_cast(target); + if (shapeBaseCheck) + if (shapeBaseCheck->getDamageState() != Enabled) return false; + } + else + return false; + } + + MatrixF cam = getTransform(); + Point3F camPos; + VectorF camDir; + + cam.getColumn(3, &camPos); + cam.getColumn(1, &camDir); + + camFov = mDegToRad(camFov) / 2; + + Point3F shapePos = target->getBoxCenter(); + VectorF shapeDir = shapePos - camPos; + // Test to see if it's within our viewcone, this test doesn't + // actually match the viewport very well, should consider + // projection and box test. + shapeDir.normalize(); + F32 dot = mDot(shapeDir, camDir); + return (dot > camFov); +} + +DefineEngineMethod(AIPlayer, checkInFoV, bool, (ShapeBase* obj, F32 fov, bool checkEnabled), (NULL, 45.0f, false), + "@brief Check whether an object is within a specified veiw cone.\n" + "@obj Object to check. (If blank, it will check the current target).\n" + "@fov view angle in degrees.(Defaults to 45)\n" + "@checkEnabled check whether the object can take damage and if so is still alive.(Defaults to false)\n") +{ + return object->checkInFoV(obj, fov, checkEnabled); +} \ No newline at end of file diff --git a/Engine/source/T3D/aiPlayer.h b/Engine/source/T3D/aiPlayer.h index 4e0bb5a3a..86da43edb 100644 --- a/Engine/source/T3D/aiPlayer.h +++ b/Engine/source/T3D/aiPlayer.h @@ -80,6 +80,8 @@ public: void setAimLocation( const Point3F &location ); Point3F getAimLocation() const { return mAimLocation; } void clearAim(); + bool checkInLos(GameBase* target = NULL, bool _useMuzzle = false, bool _checkEnabled = false); + bool checkInFoV(GameBase* target = NULL, F32 camFov = 45.0f, bool _checkEnabled = false); // Movement sets/gets void setMoveSpeed( const F32 speed ); diff --git a/Engine/source/T3D/camera.cpp b/Engine/source/T3D/camera.cpp index f7e5322d7..ef4541f6c 100644 --- a/Engine/source/T3D/camera.cpp +++ b/Engine/source/T3D/camera.cpp @@ -1546,7 +1546,7 @@ void Camera::_validateEyePoint(F32 pos, MatrixF *mat) float dot = mDot(dir, collision.normal); if (dot > 0.01f) { - float colDist = mDot(startPos - collision.point, dir) - (1 / dot) * CameraRadius; + F32 colDist = mDot(startPos - collision.point, dir) - (1 / dot) * CameraRadius; if (colDist > pos) colDist = pos; if (colDist < 0.0f) diff --git a/Engine/source/T3D/cameraSpline.cpp b/Engine/source/T3D/cameraSpline.cpp index 94d0055f5..03eff64ef 100644 --- a/Engine/source/T3D/cameraSpline.cpp +++ b/Engine/source/T3D/cameraSpline.cpp @@ -194,7 +194,7 @@ void CameraSpline::renderTimeMap() if(!ptr) return; MRandomLCG random(1376312589 * (U32)this); - int index = 0; + S32 index = 0; for(Vector::iterator itr=mTimeMap.begin(); itr != mTimeMap.end(); itr++) { Knot a; diff --git a/Engine/source/T3D/debris.cpp b/Engine/source/T3D/debris.cpp index 78526b7ad..495b5dbc2 100644 --- a/Engine/source/T3D/debris.cpp +++ b/Engine/source/T3D/debris.cpp @@ -41,7 +41,7 @@ #include "lighting/lightQuery.h" -const U32 csmStaticCollisionMask = TerrainObjectType; +const U32 csmStaticCollisionMask = TerrainObjectType | StaticShapeObjectType | StaticObjectType; const U32 csmDynamicCollisionMask = StaticShapeObjectType; @@ -122,7 +122,7 @@ bool DebrisData::onAdd() if(!Parent::onAdd()) return false; - for( int i=0; iwriteString( textureName ); stream->writeString( shapeName ); - for( int i=0; iwriteFlag( emitterList[i] != NULL ) ) { @@ -346,7 +346,7 @@ void DebrisData::unpackData(BitStream* stream) textureName = stream->readSTString(); shapeName = stream->readSTString(); - for( int i=0; ireadFlag() ) { @@ -511,8 +511,14 @@ bool Debris::onAdd() return false; } + if( !mDataBlock ) + { + Con::errorf("Debris::onAdd - Fail - No datablock"); + return false; + } + // create emitters - for( int i=0; iemitterList[i] != NULL ) { @@ -631,7 +637,7 @@ bool Debris::onAdd() void Debris::onRemove() { - for( int i=0; iremoveObjectFromScene(this); - getContainer()->removeObject(this); + if( getSceneManager() ) + getSceneManager()->removeObjectFromScene(this); + + if( getContainer() ) + getContainer()->removeObject(this); Parent::onRemove(); } @@ -848,7 +857,7 @@ void Debris::updateEmitters( Point3F &pos, Point3F &vel, U32 ms ) Point3F lastPos = mLastPos; - for( int i=0; imDataBlock) - ((char *)(*pd2)->mDataBlock)); } -int QSORT_CALLBACK cmpPointsXY( const void *p1, const void *p2 ) +S32 QSORT_CALLBACK cmpPointsXY( const void *p1, const void *p2 ) { const Point3F *pnt1 = (const Point3F*)p1; const Point3F *pnt2 = (const Point3F*)p2; @@ -142,7 +142,7 @@ int QSORT_CALLBACK cmpPointsXY( const void *p1, const void *p2 ) return 0; } -int QSORT_CALLBACK cmpQuadPointTheta( const void *p1, const void *p2 ) +S32 QSORT_CALLBACK cmpQuadPointTheta( const void *p1, const void *p2 ) { const Point4F *pnt1 = (const Point4F*)p1; const Point4F *pnt2 = (const Point4F*)p2; @@ -157,7 +157,7 @@ int QSORT_CALLBACK cmpQuadPointTheta( const void *p1, const void *p2 ) static Point3F gSortPoint; -int QSORT_CALLBACK cmpDecalDistance( const void *p1, const void *p2 ) +S32 QSORT_CALLBACK cmpDecalDistance( const void *p1, const void *p2 ) { const DecalInstance** pd1 = (const DecalInstance**)p1; const DecalInstance** pd2 = (const DecalInstance**)p2; @@ -168,7 +168,7 @@ int QSORT_CALLBACK cmpDecalDistance( const void *p1, const void *p2 ) return mSign( dist1 - dist2 ); } -int QSORT_CALLBACK cmpDecalRenderOrder( const void *p1, const void *p2 ) +S32 QSORT_CALLBACK cmpDecalRenderOrder( const void *p1, const void *p2 ) { const DecalInstance** pd1 = (const DecalInstance**)p1; const DecalInstance** pd2 = (const DecalInstance**)p2; @@ -179,14 +179,14 @@ int QSORT_CALLBACK cmpDecalRenderOrder( const void *p1, const void *p2 ) return 1; else { - int priority = (*pd1)->getRenderPriority() - (*pd2)->getRenderPriority(); + S32 priority = (*pd1)->getRenderPriority() - (*pd2)->getRenderPriority(); if ( priority != 0 ) return priority; if ( (*pd2)->mFlags & SaveDecal ) { - int id = ( (*pd1)->mDataBlock->getMaterial()->getId() - (*pd2)->mDataBlock->getMaterial()->getId() ); + S32 id = ( (*pd1)->mDataBlock->getMaterial()->getId() - (*pd2)->mDataBlock->getMaterial()->getId() ); if ( id != 0 ) return id; diff --git a/Engine/source/T3D/examples/renderMeshExample.cpp b/Engine/source/T3D/examples/renderMeshExample.cpp index a725fc2eb..880df57d0 100644 --- a/Engine/source/T3D/examples/renderMeshExample.cpp +++ b/Engine/source/T3D/examples/renderMeshExample.cpp @@ -108,6 +108,9 @@ bool RenderMeshExample::onAdd() // Add this object to the scene addToScene(); + // Refresh this object's material (if any) + updateMaterial(); + return true; } diff --git a/Engine/source/T3D/fx/cameraFXMgr.h b/Engine/source/T3D/fx/cameraFXMgr.h index 5a560bfc6..b40411f3a 100644 --- a/Engine/source/T3D/fx/cameraFXMgr.h +++ b/Engine/source/T3D/fx/cameraFXMgr.h @@ -45,6 +45,7 @@ protected: public: CameraFX(); + virtual ~CameraFX() { } MatrixF & getTrans(){ return mCamFXTrans; } virtual bool isExpired(){ return mElapsedTime >= mDuration; } diff --git a/Engine/source/T3D/fx/explosion.cpp b/Engine/source/T3D/fx/explosion.cpp index b84efad3f..dd81dcba8 100644 --- a/Engine/source/T3D/fx/explosion.cpp +++ b/Engine/source/T3D/fx/explosion.cpp @@ -106,18 +106,31 @@ ConsoleDocClass( Explosion, " lightEndBrightness = 0.0;\n" " lightNormalOffset = 2.0;\n" "};\n\n" - "function createExplosion()\n" + "function ServerPlayExplosion(%position, %datablock)\n" "{\n" - " // Create a new explosion - it will explode automatically\n" - " %pos = \"0 0 100\";\n" - " %obj = new Explosion()\n" + " // Play the given explosion on every client.\n" + " // The explosion will be transmitted as an event, not attached to any object.\n" + " for(%idx = 0; %idx < ClientGroup.getCount(); %idx++)\n" " {\n" - " position = %pos;\n" - " dataBlock = GrenadeLauncherExplosion;\n" - " };\n" + " %client = ClientGroup.getObject(%idx);\n" + " commandToClient(%client, 'PlayExplosion', %position, %datablock.getId());\n" + " }\n" + "}\n\n" + "function clientCmdPlayExplosion(%position, %effectDataBlock)\n" + "{\n" + " // Play an explosion sent by the server. Make sure this function is defined\n" + " // on the client.\n" + " if (isObject(%effectDataBlock))\n" + " {\n" + " new Explosion()\n" + " {\n" + " position = %position;\n" + " dataBlock = %effectDataBlock;\n" + " };\n" + " }\n" "}\n\n" "// schedule an explosion\n" - "schedule(1000, 0, createExplosion);\n" + "schedule(1000, 0, ServerPlayExplosion, \"0 0 0\", GrenadeLauncherExplosion);\n" "@endtsexample" ); @@ -736,9 +749,9 @@ bool ExplosionData::preload(bool server, String &errorStr) if( !server ) { - String errorStr; - if( !sfxResolve( &soundProfile, errorStr ) ) - Con::errorf(ConsoleLogEntry::General, "Error, unable to load sound profile for explosion datablock: %s", errorStr.c_str()); + String sfxErrorStr; + if( !sfxResolve( &soundProfile, sfxErrorStr ) ) + Con::errorf(ConsoleLogEntry::General, "Error, unable to load sound profile for explosion datablock: %s", sfxErrorStr.c_str()); if (!particleEmitter && particleEmitterId != 0) if (Sim::findObject(particleEmitterId, particleEmitter) == false) Con::errorf(ConsoleLogEntry::General, "Error, unable to load particle emitter for explosion datablock"); @@ -771,6 +784,7 @@ bool ExplosionData::preload(bool server, String &errorStr) //-------------------------------------- // Explosion::Explosion() + : mDataBlock( NULL ) { mTypeMask |= ExplosionObjectType | LightObjectType; @@ -831,6 +845,12 @@ bool Explosion::onAdd() if ( !conn || !Parent::onAdd() ) return false; + if( !mDataBlock ) + { + Con::errorf("Explosion::onAdd - Fail - No datablok"); + return false; + } + mDelayMS = mDataBlock->delayMS + sgRandom.randI( -mDataBlock->delayVariance, mDataBlock->delayVariance ); mEndingMS = mDataBlock->lifetimeMS + sgRandom.randI( -mDataBlock->lifetimeVariance, mDataBlock->lifetimeVariance ); @@ -929,7 +949,7 @@ bool Explosion::onAdd() void Explosion::onRemove() { - for( int i=0; idebrisList[j] ) { @@ -1160,7 +1180,7 @@ void Explosion::launchDebris( Point3F &axis ) U32 numDebris = mDataBlock->debrisNum + sgRandom.randI( -mDataBlock->debrisNumVariance, mDataBlock->debrisNumVariance ); - for( int i=0; idebrisThetaMin, mDataBlock->debrisThetaMax, @@ -1249,7 +1269,7 @@ bool Explosion::explode() Point3F::Zero, U32(mDataBlock->particleDensity * mFade)); } - for( int i=0; iemitterList[i] != NULL ) { diff --git a/Engine/source/T3D/fx/lightning.cpp b/Engine/source/T3D/fx/lightning.cpp index 338bd0a95..5c4c07bde 100644 --- a/Engine/source/T3D/fx/lightning.cpp +++ b/Engine/source/T3D/fx/lightning.cpp @@ -287,14 +287,14 @@ bool LightningData::preload(bool server, String &errorStr) if (server == false) { - String errorStr; + String sfxErrorStr; for (U32 i = 0; i < MaxThunders; i++) { - if( !sfxResolve( &thunderSounds[ i ], errorStr ) ) - Con::errorf(ConsoleLogEntry::General, "LightningData::preload: Invalid packet: %s", errorStr.c_str()); + if( !sfxResolve( &thunderSounds[ i ], sfxErrorStr ) ) + Con::errorf(ConsoleLogEntry::General, "LightningData::preload: Invalid packet: %s", sfxErrorStr.c_str()); } - if( !sfxResolve( &strikeSound, errorStr ) ) - Con::errorf(ConsoleLogEntry::General, "LightningData::preload: Invalid packet: %s", errorStr.c_str()); + if( !sfxResolve( &strikeSound, sfxErrorStr ) ) + Con::errorf(ConsoleLogEntry::General, "LightningData::preload: Invalid packet: %s", sfxErrorStr.c_str()); for (U32 i = 0; i < MaxTextures; i++) { @@ -1139,7 +1139,7 @@ void LightningBolt::generateMinorNodes() { mMinorNodes.clear(); - for( int i=0; inextSplashDrop; } if (drop->nextSplashDrop) diff --git a/Engine/source/T3D/fx/splash.cpp b/Engine/source/T3D/fx/splash.cpp index 7a3eda0f9..1558f2dbc 100644 --- a/Engine/source/T3D/fx/splash.cpp +++ b/Engine/source/T3D/fx/splash.cpp @@ -303,6 +303,7 @@ bool SplashData::preload(bool server, String &errorStr) // Splash //-------------------------------------------------------------------------- Splash::Splash() + : mDataBlock( NULL ) { dMemset( mEmitterList, 0, sizeof( mEmitterList ) ); @@ -353,6 +354,12 @@ bool Splash::onAdd() if(!conn || !Parent::onAdd()) return false; + if( !mDataBlock ) + { + Con::errorf("Splash::onAdd - Fail - No datablock"); + return false; + } + mDelayMS = mDataBlock->delayMS + sgRandom.randI( -mDataBlock->delayVariance, mDataBlock->delayVariance ); mEndingMS = mDataBlock->lifetimeMS + sgRandom.randI( -mDataBlock->lifetimeVariance, mDataBlock->lifetimeVariance ); @@ -408,8 +415,11 @@ void Splash::onRemove() ringList.clear(); - getSceneManager()->removeObjectFromScene(this); - getContainer()->removeObject(this); + if( getSceneManager() ) + getSceneManager()->removeObjectFromScene(this); + + if( getContainer() ) + getContainer()->removeObject(this); Parent::onRemove(); } diff --git a/Engine/source/T3D/gameBase/gameBase.cpp b/Engine/source/T3D/gameBase/gameBase.cpp index bc796383e..c0e4ee704 100644 --- a/Engine/source/T3D/gameBase/gameBase.cpp +++ b/Engine/source/T3D/gameBase/gameBase.cpp @@ -614,7 +614,7 @@ void GameBase::onUnmount( SceneObject *obj, S32 node ) bool GameBase::setDataBlockProperty( void *obj, const char *index, const char *db) { - if( db == NULL || !db || !db[ 0 ] ) + if( db == NULL || !db[ 0 ] ) { Con::errorf( "GameBase::setDataBlockProperty - Can't unset datablock on GameBase objects" ); return false; diff --git a/Engine/source/T3D/gameBase/std/stdMoveList.cpp b/Engine/source/T3D/gameBase/std/stdMoveList.cpp index 1fd0ffdfb..15961f633 100644 --- a/Engine/source/T3D/gameBase/std/stdMoveList.cpp +++ b/Engine/source/T3D/gameBase/std/stdMoveList.cpp @@ -92,7 +92,7 @@ void StdMoveList::clientWriteMovePacket(BitStream *bstream) bstream->writeInt(start,32); bstream->writeInt(count,MoveCountBits); Move * prevMove = NULL; - for (int i = 0; i < count; i++) + for (S32 i = 0; i < count; i++) { move[offset + i].sendCount++; move[offset + i].pack(bstream,prevMove); @@ -112,7 +112,7 @@ void StdMoveList::serverReadMovePacket(BitStream *bstream) // Skip forward (must be starting up), or over the moves // we already have. - int skip = mLastMoveAck - start; + S32 skip = mLastMoveAck - start; if (skip < 0) { mLastMoveAck = start; @@ -121,7 +121,7 @@ void StdMoveList::serverReadMovePacket(BitStream *bstream) { if (skip > count) skip = count; - for (int i = 0; i < skip; i++) + for (S32 i = 0; i < skip; i++) { prevMoveHolder.unpack(bstream,prevMove); prevMoveHolder.checksum = bstream->readInt(Move::ChecksumBits); @@ -141,7 +141,7 @@ void StdMoveList::serverReadMovePacket(BitStream *bstream) } // Put the rest on the move list. - int index = mMoveVec.size(); + S32 index = mMoveVec.size(); mMoveVec.increment(count); while (index < mMoveVec.size()) { diff --git a/Engine/source/T3D/gameFunctions.cpp b/Engine/source/T3D/gameFunctions.cpp index 1196ea030..e16acf1ec 100644 --- a/Engine/source/T3D/gameFunctions.cpp +++ b/Engine/source/T3D/gameFunctions.cpp @@ -145,9 +145,10 @@ ConsoleFunction(containerFindFirst, const char*, 6, 6, "(int mask, Point3F point //return the first element sgServerQueryIndex = 0; - char *buff = Con::getReturnBuffer(100); + static const U32 bufSize = 100; + char *buff = Con::getReturnBuffer(bufSize); if (sgServerQueryList.mList.size()) - dSprintf(buff, 100, "%d", sgServerQueryList.mList[sgServerQueryIndex++]->getId()); + dSprintf(buff, bufSize, "%d", sgServerQueryList.mList[sgServerQueryIndex++]->getId()); else buff[0] = '\0'; @@ -162,9 +163,10 @@ ConsoleFunction( containerFindNext, const char*, 1, 1, "()" "@ingroup Game") { //return the next element - char *buff = Con::getReturnBuffer(100); + static const U32 bufSize = 100; + char *buff = Con::getReturnBuffer(bufSize); if (sgServerQueryIndex < sgServerQueryList.mList.size()) - dSprintf(buff, 100, "%d", sgServerQueryList.mList[sgServerQueryIndex++]->getId()); + dSprintf(buff, bufSize, "%d", sgServerQueryList.mList[sgServerQueryIndex++]->getId()); else buff[0] = '\0'; diff --git a/Engine/source/T3D/item.cpp b/Engine/source/T3D/item.cpp index 50a43c1e8..10ce867a9 100644 --- a/Engine/source/T3D/item.cpp +++ b/Engine/source/T3D/item.cpp @@ -893,7 +893,7 @@ void Item::updatePos(const U32 /*mask*/, const F32 dt) // Pick the most resistant surface F32 bd = 0; const Collision* collision = 0; - for (int c = 0; c < collisionList.getCount(); c++) { + for (S32 c = 0; c < collisionList.getCount(); c++) { const Collision &cp = collisionList[c]; F32 dot = -mDot(mVelocity,cp.normal); if (dot > bd) { @@ -1204,7 +1204,7 @@ DefineEngineMethod( Item, isRotating, bool, (),, return object->isRotating(); } -DefineEngineMethod( Item, setCollisionTimeout, bool, (int ignoreColObj),(NULL), +DefineEngineMethod( Item, setCollisionTimeout, bool, (S32 ignoreColObj),(NULL), "@brief Temporarily disable collisions against a specific ShapeBase object.\n\n" "This is useful to prevent a player from immediately picking up an Item they have " @@ -1241,9 +1241,10 @@ DefineEngineMethod( Item, getLastStickyPos, const char*, (),, "@note Server side only.\n" ) { - char* ret = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char* ret = Con::getReturnBuffer(bufSize); if (object->isServerObject()) - dSprintf(ret, 255, "%g %g %g", + dSprintf(ret, bufSize, "%g %g %g", object->mStickyCollisionPos.x, object->mStickyCollisionPos.y, object->mStickyCollisionPos.z); @@ -1263,9 +1264,10 @@ DefineEngineMethod( Item, getLastStickyNormal, const char *, (),, "@note Server side only.\n" ) { - char* ret = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char* ret = Con::getReturnBuffer(bufSize); if (object->isServerObject()) - dSprintf(ret, 255, "%g %g %g", + dSprintf(ret, bufSize, "%g %g %g", object->mStickyCollisionNormal.x, object->mStickyCollisionNormal.y, object->mStickyCollisionNormal.z); diff --git a/Engine/source/T3D/missionArea.cpp b/Engine/source/T3D/missionArea.cpp index d11aa91ce..4e66dde8a 100644 --- a/Engine/source/T3D/missionArea.cpp +++ b/Engine/source/T3D/missionArea.cpp @@ -176,10 +176,11 @@ DefineEngineFunction(getMissionAreaServerObject, MissionArea*, (),, DefineEngineMethod( MissionArea, getArea, const char *, (),, "Returns 4 fields: starting x, starting y, extents x, extents y.\n") { - char* returnBuffer = Con::getReturnBuffer(48); + static const U32 bufSize = 48; + char* returnBuffer = Con::getReturnBuffer(bufSize); RectI area = object->getArea(); - dSprintf(returnBuffer, sizeof(returnBuffer), "%d %d %d %d", area.point.x, area.point.y, area.extent.x, area.extent.y); + dSprintf(returnBuffer, bufSize, "%d %d %d %d", area.point.x, area.point.y, area.extent.x, area.extent.y); return(returnBuffer); } diff --git a/Engine/source/T3D/missionMarker.cpp b/Engine/source/T3D/missionMarker.cpp index bff79e962..f7207df36 100644 --- a/Engine/source/T3D/missionMarker.cpp +++ b/Engine/source/T3D/missionMarker.cpp @@ -304,8 +304,9 @@ ConsoleType( WayPointTeam, TypeWayPointTeam, WayPointTeam ) ConsoleGetType( TypeWayPointTeam ) { - char * buf = Con::getReturnBuffer(32); - dSprintf(buf, 32, "%d", ((WayPointTeam*)dptr)->mTeamId); + static const U32 bufSize = 32; + char * buf = Con::getReturnBuffer(bufSize); + dSprintf(buf, bufSize, "%d", ((WayPointTeam*)dptr)->mTeamId); return(buf); } diff --git a/Engine/source/T3D/pathCamera.cpp b/Engine/source/T3D/pathCamera.cpp index 185e7a675..43e6f9273 100644 --- a/Engine/source/T3D/pathCamera.cpp +++ b/Engine/source/T3D/pathCamera.cpp @@ -429,7 +429,7 @@ U32 PathCamera::packUpdate(NetConnection *con, U32 mask, BitStream *stream) if (stream->writeFlag(mask & WindowMask)) { stream->write(mNodeBase); stream->write(mNodeCount); - for (int i = 0; i < mNodeCount; i++) { + for (S32 i = 0; i < mNodeCount; i++) { CameraSpline::Knot *knot = mSpline.getKnot(i); mathWrite(*stream, knot->mPosition); mathWrite(*stream, knot->mRotation); @@ -477,7 +477,7 @@ void PathCamera::unpackUpdate(NetConnection *con, BitStream *stream) mSpline.removeAll(); stream->read(&mNodeBase); stream->read(&mNodeCount); - for (int i = 0; i < mNodeCount; i++) + for (S32 i = 0; i < mNodeCount; i++) { CameraSpline::Knot *knot = new CameraSpline::Knot(); mathRead(*stream, &knot->mPosition); diff --git a/Engine/source/T3D/pathCamera.h b/Engine/source/T3D/pathCamera.h index c94e2ad57..685118e6e 100644 --- a/Engine/source/T3D/pathCamera.h +++ b/Engine/source/T3D/pathCamera.h @@ -83,7 +83,7 @@ private: S32 mNodeBase; S32 mNodeCount; F32 mPosition; - int mState; + S32 mState; F32 mTarget; bool mTargetSet; diff --git a/Engine/source/T3D/physics/bullet/bt.h b/Engine/source/T3D/physics/bullet/bt.h index 45ae15414..b2c514ff5 100644 --- a/Engine/source/T3D/physics/bullet/bt.h +++ b/Engine/source/T3D/physics/bullet/bt.h @@ -24,7 +24,7 @@ #define _BULLET_H_ // NOTE: We set these defines which bullet needs here. -#ifdef TORQUE_OS_WIN32 +#ifdef TORQUE_OS_WIN #define WIN32 #endif diff --git a/Engine/source/T3D/physics/physicsDebris.cpp b/Engine/source/T3D/physics/physicsDebris.cpp index 38549980a..ba9c7e4b6 100644 --- a/Engine/source/T3D/physics/physicsDebris.cpp +++ b/Engine/source/T3D/physics/physicsDebris.cpp @@ -311,7 +311,8 @@ PhysicsDebris* PhysicsDebris::create( PhysicsDebrisData *datablock, } PhysicsDebris::PhysicsDebris() - : mLifetime( 0.0f ), + : mDataBlock( NULL ), + mLifetime( 0.0f ), mShapeInstance( NULL ), mWorld( NULL ), mInitialLinVel( Point3F::Zero ) @@ -342,6 +343,12 @@ bool PhysicsDebris::onAdd() if ( !Parent::onAdd() ) return false; + if( !mDataBlock ) + { + Con::errorf("PhysicsDebris::onAdd - Fail - No datablock"); + return false; + } + // If it has a fixed lifetime then calculate it. if ( mDataBlock->lifetime > 0.0f ) { diff --git a/Engine/source/T3D/physics/physx/px.h b/Engine/source/T3D/physics/physx/px.h index c4dd9dccb..856035cf7 100644 --- a/Engine/source/T3D/physics/physx/px.h +++ b/Engine/source/T3D/physics/physx/px.h @@ -46,7 +46,7 @@ #define __APPLE__ #elif defined(TORQUE_OS_LINUX) && !defined(LINUX) #define LINUX -#elif defined(TORQUE_OS_WIN32) && !defined(WIN32) +#elif defined(TORQUE_OS_WIN) && !defined(WIN32) #define WIN32 #endif diff --git a/Engine/source/T3D/physics/physx/pxMultiActor.cpp b/Engine/source/T3D/physics/physx/pxMultiActor.cpp index 8692afcec..6abdcdaad 100644 --- a/Engine/source/T3D/physics/physx/pxMultiActor.cpp +++ b/Engine/source/T3D/physics/physx/pxMultiActor.cpp @@ -527,7 +527,7 @@ bool PxMultiActorData::preload( bool server, String &errorBuffer ) return false; } - if (!shapeName || shapeName == '\0') + if (!shapeName || shapeName[0] == '\0') { errorBuffer = "PxMultiActorDatas::preload: no shape name!"; return false; diff --git a/Engine/source/T3D/physics/physx/pxPlugin.cpp b/Engine/source/T3D/physics/physx/pxPlugin.cpp index 7fff0559e..bb3352983 100644 --- a/Engine/source/T3D/physics/physx/pxPlugin.cpp +++ b/Engine/source/T3D/physics/physx/pxPlugin.cpp @@ -39,7 +39,7 @@ AFTER_MODULE_INIT( Sim ) { NamedFactory::add( "PhysX", &PxPlugin::create ); - #if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) + #if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) NamedFactory::add( "default", &PxPlugin::create ); #endif diff --git a/Engine/source/T3D/physics/physx/pxWorld.cpp b/Engine/source/T3D/physics/physx/pxWorld.cpp index c4f33a21d..0ec3d7fea 100644 --- a/Engine/source/T3D/physics/physx/pxWorld.cpp +++ b/Engine/source/T3D/physics/physx/pxWorld.cpp @@ -448,9 +448,8 @@ void PxWorld::releaseActor( NxActor &actor ) // Clear the userdata. actor.userData = NULL; - // If the scene is not simulating then we have the - // write lock and can safely delete it now. - if ( !mIsSimulating ) + // actors are one of the few objects that are stable removing this way in physx 2.8 + if (mScene->isWritable() ) { mScene->releaseActor( actor ); } diff --git a/Engine/source/T3D/player.cpp b/Engine/source/T3D/player.cpp index da29b63e0..5a30fb77b 100644 --- a/Engine/source/T3D/player.cpp +++ b/Engine/source/T3D/player.cpp @@ -427,9 +427,9 @@ bool PlayerData::preload(bool server, String &errorStr) { for( U32 i = 0; i < MaxSounds; ++ i ) { - String errorStr; - if( !sfxResolve( &sound[ i ], errorStr ) ) - Con::errorf( "PlayerData::preload: %s", errorStr.c_str() ); + String sfxErrorStr; + if( !sfxResolve( &sound[ i ], sfxErrorStr ) ) + Con::errorf( "PlayerData::preload: %s", sfxErrorStr.c_str() ); } } @@ -467,7 +467,7 @@ bool PlayerData::preload(bool server, String &errorStr) // Extract ground transform velocity from animations // Get the named ones first so they can be indexed directly. ActionAnimation *dp = &actionList[0]; - for (int i = 0; i < NumTableActionAnims; i++,dp++) + for (S32 i = 0; i < NumTableActionAnims; i++,dp++) { ActionAnimationDef *sp = &ActionAnimationList[i]; dp->name = sp->name; @@ -487,12 +487,8 @@ bool PlayerData::preload(bool server, String &errorStr) dp->death = false; if (dp->sequence != -1) getGroundInfo(si,thread,dp); - - // No real reason to spam the console about a missing jet animation - if (dStricmp(sp->name, "jet") != 0) - AssertWarn(dp->sequence != -1, avar("PlayerData::preload - Unable to find named animation sequence '%s'!", sp->name)); } - for (int b = 0; b < mShape->sequences.size(); b++) + for (S32 b = 0; b < mShape->sequences.size(); b++) { if (!isTableSequence(b)) { @@ -509,7 +505,7 @@ bool PlayerData::preload(bool server, String &errorStr) // Resolve lookAction index dp = &actionList[0]; String lookName("look"); - for (int c = 0; c < actionCount; c++,dp++) + for (S32 c = 0; c < actionCount; c++,dp++) if( dStricmp( dp->name, lookName ) == 0 ) lookAction = c; @@ -557,7 +553,7 @@ bool PlayerData::preload(bool server, String &errorStr) if (!Sim::findObject(dustID, dustEmitter)) Con::errorf(ConsoleLogEntry::General, "PlayerData::preload - Invalid packet, bad datablockId(dustEmitter): 0x%x", dustID); - for (int i=0; igetChecksum(); @@ -647,7 +646,7 @@ bool PlayerData::isTableSequence(S32 seq) { // The sequences from the table must already have // been loaded for this to work. - for (int i = 0; i < NumTableActionAnims; i++) + for (S32 i = 0; i < NumTableActionAnims; i++) if (actionList[i].sequence == seq) return true; return false; @@ -1944,7 +1943,7 @@ void Player::reSkin() Vector skins; String(mSkinNameHandle.getString()).split( ";", skins ); - for ( int i = 0; i < skins.size(); i++ ) + for ( S32 i = 0; i < skins.size(); i++ ) { String oldSkin( mAppliedSkinName.c_str() ); String newSkin( skins[i] ); @@ -1961,7 +1960,7 @@ void Player::reSkin() // Apply skin to both 3rd person and 1st person shape instances mShapeInstance->reSkin( newSkin, oldSkin ); - for ( int j = 0; j < ShapeBase::MaxMountedImages; j++ ) + for ( S32 j = 0; j < ShapeBase::MaxMountedImages; j++ ) { if (mShapeFPInstance[j]) mShapeFPInstance[j]->reSkin( newSkin, oldSkin ); @@ -2952,7 +2951,7 @@ void Player::updateMove(const Move* move) // Clamp acceleration. F32 maxAcc = (mDataBlock->swimForce / getMass()) * TickSec; - if ( false && swimSpeed > maxAcc ) + if ( swimSpeed > maxAcc ) swimAcc *= maxAcc / swimSpeed; acc += swimAcc; @@ -5822,7 +5821,7 @@ bool Player::castRay(const Point3F &start, const Point3F &end, RayInfo* info) F32 const *si = &start.x; F32 const *ei = &end.x; - for (int i = 0; i < 3; i++) { + for (S32 i = 0; i < 3; i++) { if (*si < *ei) { if (*si > *bmax || *ei < *bmin) return false; @@ -6507,8 +6506,9 @@ DefineEngineMethod( Player, getDamageLocation, const char*, ( Point3F pos ),, object->getDamageLocation(pos, buffer1, buffer2); - char *buff = Con::getReturnBuffer(128); - dSprintf(buff, 128, "%s %s", buffer1, buffer2); + static const U32 bufSize = 128; + char *buff = Con::getReturnBuffer(bufSize); + dSprintf(buff, bufSize, "%s %s", buffer1, buffer2); return buff; } diff --git a/Engine/source/T3D/projectile.cpp b/Engine/source/T3D/projectile.cpp index 86886c2b5..b59535366 100644 --- a/Engine/source/T3D/projectile.cpp +++ b/Engine/source/T3D/projectile.cpp @@ -320,9 +320,9 @@ bool ProjectileData::preload(bool server, String &errorStr) if (Sim::findObject(decalId, decal) == false) Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet, bad datablockId(decal): %d", decalId); - String errorStr; - if( !sfxResolve( &sound, errorStr ) ) - Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet: %s", errorStr.c_str()); + String sfxErrorStr; + if( !sfxResolve( &sound, sfxErrorStr ) ) + Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet: %s", sfxErrorStr.c_str()); if (!lightDesc && lightDescId != 0) if (Sim::findObject(lightDescId, lightDesc) == false) @@ -550,6 +550,7 @@ S32 ProjectileData::scaleValue( S32 value, bool down ) // Projectile::Projectile() : mPhysicsWorld( NULL ), + mDataBlock( NULL ), mCurrPosition( 0, 0, 0 ), mCurrVelocity( 0, 0, 1 ), mSourceObjectId( -1 ), @@ -697,6 +698,12 @@ bool Projectile::onAdd() if(!Parent::onAdd()) return false; + if( !mDataBlock ) + { + Con::errorf("Projectile::onAdd - Fail - Not datablock"); + return false; + } + if (isServerObject()) { ShapeBase* ptr; @@ -1011,7 +1018,7 @@ void Projectile::explode( const Point3F &p, const Point3F &n, const U32 collideT // Client (impact) decal. if ( mDataBlock->decal ) - gDecalManager->addDecal( p, n, 0.0f, mDataBlock->decal ); + gDecalManager->addDecal(p, n, mRandF(0.0f, M_2PI_F), mDataBlock->decal); // Client object updateSound(); diff --git a/Engine/source/T3D/projectile.h b/Engine/source/T3D/projectile.h index fa7c9ffbf..17c90cfbc 100644 --- a/Engine/source/T3D/projectile.h +++ b/Engine/source/T3D/projectile.h @@ -215,9 +215,9 @@ public: void updateSound(); - virtual bool calculateImpact( float simTime, + virtual bool calculateImpact( F32 simTime, Point3F &pointOfImpact, - float &impactTime ); + F32 &impactTime ); void setInitialPosition( const Point3F& pos ); void setInitialVelocity( const Point3F& vel ); diff --git a/Engine/source/T3D/proximityMine.cpp b/Engine/source/T3D/proximityMine.cpp index c37947a16..89ffe9577 100644 --- a/Engine/source/T3D/proximityMine.cpp +++ b/Engine/source/T3D/proximityMine.cpp @@ -136,11 +136,11 @@ bool ProximityMineData::preload( bool server, String& errorStr ) if ( !server ) { // Resolve sounds - String errorStr; - if( !sfxResolve( &armingSound, errorStr ) ) - Con::errorf( ConsoleLogEntry::General, "ProximityMineData::preload: Invalid packet: %s", errorStr.c_str() ); - if( !sfxResolve( &triggerSound, errorStr ) ) - Con::errorf( ConsoleLogEntry::General, "ProximityMineData::preload: Invalid packet: %s", errorStr.c_str() ); + String sfxErrorStr; + if( !sfxResolve( &armingSound, sfxErrorStr ) ) + Con::errorf( ConsoleLogEntry::General, "ProximityMineData::preload: Invalid packet: %s", sfxErrorStr.c_str() ); + if( !sfxResolve( &triggerSound, sfxErrorStr ) ) + Con::errorf( ConsoleLogEntry::General, "ProximityMineData::preload: Invalid packet: %s", sfxErrorStr.c_str() ); } if ( mShape ) @@ -451,7 +451,7 @@ void ProximityMine::processTick( const Move* move ) SimpleQueryList sql; getContainer()->findObjects( triggerBox, sTriggerCollisionMask, SimpleQueryList::insertionCallback, &sql ); - for ( int i = 0; i < sql.mList.size(); i++ ) + for ( S32 i = 0; i < sql.mList.size(); i++ ) { // Detect movement in the trigger area if ( ( sql.mList[i] == mOwner && !mDataBlock->triggerOnOwner ) || diff --git a/Engine/source/T3D/rigid.cpp b/Engine/source/T3D/rigid.cpp index 079f97caf..e2441441f 100644 --- a/Engine/source/T3D/rigid.cpp +++ b/Engine/source/T3D/rigid.cpp @@ -265,8 +265,8 @@ void Rigid::translateCenterOfMass(const Point3F &oldPos,const Point3F &newPos) MatrixF oldx,newx; oldx.setCrossProduct(oldPos); newx.setCrossProduct(newPos); - for (int row = 0; row < 3; row++) - for (int col = 0; col < 3; col++) { + for (S32 row = 0; row < 3; row++) + for (S32 col = 0; col < 3; col++) { F32 n = newx(row,col), o = oldx(row,col); objectInertia(row,col) += mass * ((o * o) - (n * n)); } diff --git a/Engine/source/T3D/rigidShape.cpp b/Engine/source/T3D/rigidShape.cpp index 5d21d97c8..f0545d054 100644 --- a/Engine/source/T3D/rigidShape.cpp +++ b/Engine/source/T3D/rigidShape.cpp @@ -196,7 +196,7 @@ namespace { // Physics and collision constants static F32 sRestTol = 0.5; // % of gravity energy to be at rest - static int sRestCount = 10; // Consecutive ticks before comming to rest + static S32 sRestCount = 10; // Consecutive ticks before comming to rest const U32 sCollisionMoveMask = ( TerrainObjectType | PlayerObjectType | StaticShapeObjectType | VehicleObjectType | @@ -302,6 +302,7 @@ bool RigidShapeData::preload(bool server, String &errorStr) if (!collisionDetails.size() || collisionDetails[0] == -1) { Con::errorf("RigidShapeData::preload failed: Rigid shapes must define a collision-1 detail"); + errorStr = String::ToString("RigidShapeData: Couldn't load shape \"%s\"",shapeName); return false; } @@ -1140,11 +1141,11 @@ void RigidShape::updatePos(F32 dt) void RigidShape::updateForces(F32 /*dt*/) { + if (mDisableMove) return; Point3F gravForce(0, 0, sRigidShapeGravity * mRigid.mass * mGravityMod); MatrixF currTransform; mRigid.getTransform(&currTransform); - mRigid.atRest = false; Point3F torque(0, 0, 0); Point3F force(0, 0, 0); @@ -1652,7 +1653,7 @@ void RigidShape::_renderMassAndContacts( ObjectRenderInst *ri, SceneRenderState GFX->getDrawUtil()->drawCube( desc, Point3F(0.1f,0.1f,0.1f), mDataBlock->massCenter, ColorI(255, 255, 255), &mRenderObjToWorld ); // Collision points... - for (int i = 0; i < mCollisionList.getCount(); i++) + for (S32 i = 0; i < mCollisionList.getCount(); i++) { const Collision& collision = mCollisionList[i]; GFX->getDrawUtil()->drawCube( desc, Point3F(0.05f,0.05f,0.05f), collision.point, ColorI(0, 0, 255) ); @@ -1660,7 +1661,7 @@ void RigidShape::_renderMassAndContacts( ObjectRenderInst *ri, SceneRenderState // Render the normals as one big batch... PrimBuild::begin(GFXLineList, mCollisionList.getCount() * 2); - for (int i = 0; i < mCollisionList.getCount(); i++) + for (S32 i = 0; i < mCollisionList.getCount(); i++) { const Collision& collision = mCollisionList[i]; diff --git a/Engine/source/T3D/rigidShape.h b/Engine/source/T3D/rigidShape.h index 180b0d0ad..ca846dd40 100644 --- a/Engine/source/T3D/rigidShape.h +++ b/Engine/source/T3D/rigidShape.h @@ -195,7 +195,7 @@ class RigidShape: public ShapeBase CollisionList mContacts; Rigid mRigid; ShapeBaseConvex mConvex; - int restCount; + S32 restCount; SimObjectPtr mDustEmitterList[RigidShapeData::VC_NUM_DUST_EMITTERS]; SimObjectPtr mSplashEmitterList[RigidShapeData::VC_NUM_SPLASH_EMITTERS]; diff --git a/Engine/source/T3D/shapeBase.cpp b/Engine/source/T3D/shapeBase.cpp index 0ecde5097..fc0f76998 100644 --- a/Engine/source/T3D/shapeBase.cpp +++ b/Engine/source/T3D/shapeBase.cpp @@ -114,11 +114,12 @@ IMPLEMENT_CALLBACK( ShapeBaseData, onTrigger, void, ( ShapeBase* obj, S32 index, "@param index Index of the trigger that changed\n" "@param state New state of the trigger\n" ); -IMPLEMENT_CALLBACK( ShapeBaseData, onEndSequence, void, ( ShapeBase* obj, S32 slot ), ( obj, slot ), +IMPLEMENT_CALLBACK(ShapeBaseData, onEndSequence, void, (ShapeBase* obj, S32 slot, const char* name), (obj, slot, name), "@brief Called when a thread playing a non-cyclic sequence reaches the end of the " "sequence.\n\n" "@param obj The ShapeBase object\n" - "@param slot Thread slot that finished playing\n" ); + "@param slot Thread slot that finished playing\n" + "@param name Thread name that finished playing\n"); IMPLEMENT_CALLBACK( ShapeBaseData, onForceUncloak, void, ( ShapeBase* obj, const char* reason ), ( obj, reason ), "@brief Called when the object is forced to uncloak.\n\n" @@ -306,7 +307,10 @@ bool ShapeBaseData::preload(bool server, String &errorStr) Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(mShape.getPath()); if (!fileRef) + { + errorStr = String::ToString("ShapeBaseData: Couldn't load shape \"%s\"",shapeName); return false; + } if(server) mCRC = fileRef->getChecksum(); @@ -898,17 +902,9 @@ ShapeBase::ShapeBase() mCloakLevel( 0.0f ), mDamageFlash( 0.0f ), mWhiteOut( 0.0f ), - mInvincibleEffect( 0.0f ), - mInvincibleDelta( 0.0f ), - mInvincibleCount( 0.0f ), - mInvincibleSpeed( 0.0f ), - mInvincibleTime( 0.0f ), - mInvincibleFade( 0.1f ), - mInvincibleOn( false ), mIsControlled( false ), mConvexList( new Convex ), mCameraFov( 90.0f ), - mShieldNormal( 0.0f, 0.0f, 1.0f ), mFadeOut( true ), mFading( false ), mFadeVal( 1.0f ), @@ -936,7 +932,6 @@ ShapeBase::ShapeBase() for (i = 0; i < MaxScriptThreads; i++) { mScriptThread[i].sequence = -1; mScriptThread[i].thread = 0; - mScriptThread[i].sound = 0; mScriptThread[i].state = Thread::Stop; mScriptThread[i].atEnd = false; mScriptThread[i].timescale = 1.f; @@ -1282,7 +1277,7 @@ void ShapeBase::processTick(const Move* move) { mMoveMotion = true; } - for (int i = 0; i < MaxMountedImages; i++) + for (S32 i = 0; i < MaxMountedImages; i++) { setImageMotionState(i, mMoveMotion); } @@ -1305,7 +1300,7 @@ void ShapeBase::processTick(const Move* move) // Advance images if (isServerObject()) { - for (int i = 0; i < MaxMountedImages; i++) + for (S32 i = 0; i < MaxMountedImages; i++) { if (mMountedImageList[i].dataBlock) updateImageState(i, TickSec); @@ -1347,7 +1342,7 @@ void ShapeBase::advanceTime(F32 dt) // advanced at framerate. advanceThreads(dt); updateAudioPos(); - for (int i = 0; i < MaxMountedImages; i++) + for (S32 i = 0; i < MaxMountedImages; i++) if (mMountedImageList[i].dataBlock) { updateImageState(i, dt); @@ -1382,9 +1377,6 @@ void ShapeBase::advanceTime(F32 dt) mCloakLevel = 0.0; } } - if(mInvincibleOn) - updateInvincibleEffect(dt); - if(mFading) { mFadeElapsedTime += dt; @@ -1987,119 +1979,6 @@ void ShapeBase::getCameraTransform(F32* pos,MatrixF* mat) mat->mul( gCamFXMgr.getTrans() ); } -// void ShapeBase::getCameraTransform(F32* pos,MatrixF* mat) -// { -// // Returns camera to world space transform -// // Handles first person / third person camera position - -// if (isServerObject() && mShapeInstance) -// mShapeInstance->animateNodeSubtrees(true); - -// if (*pos != 0) { -// F32 min,max; -// Point3F offset; -// MatrixF eye,rot; -// getCameraParameters(&min,&max,&offset,&rot); -// getRenderEyeTransform(&eye); -// mat->mul(eye,rot); - -// // Use the eye transform to orient the camera -// VectorF vp,vec; -// vp.x = vp.z = 0; -// vp.y = -(max - min) * *pos; -// eye.mulV(vp,&vec); - -// // Use the camera node's pos. -// Point3F osp,sp; -// if (mDataBlock->cameraNode != -1) { -// mShapeInstance->mNodeTransforms[mDataBlock->cameraNode].getColumn(3,&osp); -// getRenderTransform().mulP(osp,&sp); -// } -// else -// getRenderTransform().getColumn(3,&sp); - -// // Make sure we don't extend the camera into anything solid -// Point3F ep = sp + vec; -// ep += offset; -// disableCollision(); -// if (isMounted()) -// getObjectMount()->disableCollision(); -// RayInfo collision; -// if (mContainer->castRay(sp,ep,(0xFFFFFFFF & ~(WaterObjectType|ForceFieldObjectType|GameBaseObjectType|DefaultObjectType)),&collision)) { -// *pos = collision.t *= 0.9; -// if (*pos == 0) -// eye.getColumn(3,&ep); -// else -// ep = sp + vec * *pos; -// } -// mat->setColumn(3,ep); -// if (isMounted()) -// getObjectMount()->enableCollision(); -// enableCollision(); -// } -// else -// { -// getRenderEyeTransform(mat); -// } -// } - - -// void ShapeBase::getRenderCameraTransform(F32* pos,MatrixF* mat) -// { -// // Returns camera to world space transform -// // Handles first person / third person camera position - -// if (isServerObject() && mShapeInstance) -// mShapeInstance->animateNodeSubtrees(true); - -// if (*pos != 0) { -// F32 min,max; -// Point3F offset; -// MatrixF eye,rot; -// getCameraParameters(&min,&max,&offset,&rot); -// getRenderEyeTransform(&eye); -// mat->mul(eye,rot); - -// // Use the eye transform to orient the camera -// VectorF vp,vec; -// vp.x = vp.z = 0; -// vp.y = -(max - min) * *pos; -// eye.mulV(vp,&vec); - -// // Use the camera node's pos. -// Point3F osp,sp; -// if (mDataBlock->cameraNode != -1) { -// mShapeInstance->mNodeTransforms[mDataBlock->cameraNode].getColumn(3,&osp); -// getRenderTransform().mulP(osp,&sp); -// } -// else -// getRenderTransform().getColumn(3,&sp); - -// // Make sure we don't extend the camera into anything solid -// Point3F ep = sp + vec; -// ep += offset; -// disableCollision(); -// if (isMounted()) -// getObjectMount()->disableCollision(); -// RayInfo collision; -// if (mContainer->castRay(sp,ep,(0xFFFFFFFF & ~(WaterObjectType|ForceFieldObjectType|GameBaseObjectType|DefaultObjectType)),&collision)) { -// *pos = collision.t *= 0.9; -// if (*pos == 0) -// eye.getColumn(3,&ep); -// else -// ep = sp + vec * *pos; -// } -// mat->setColumn(3,ep); -// if (isMounted()) -// getObjectMount()->enableCollision(); -// enableCollision(); -// } -// else -// { -// getRenderEyeTransform(mat); -// } -// } - void ShapeBase::getCameraParameters(F32 *min,F32* max,Point3F* off,MatrixF* rot) { *min = mDataBlock->cameraMinDist; @@ -2153,52 +2032,6 @@ bool ShapeBase::useObjsEyePoint() const return mDataBlock->useEyePoint; } - -//---------------------------------------------------------------------------- -F32 ShapeBase::getInvincibleEffect() const -{ - return mInvincibleEffect; -} - -void ShapeBase::setupInvincibleEffect(F32 time, F32 speed) -{ - if(isClientObject()) - { - mInvincibleCount = mInvincibleTime = time; - mInvincibleSpeed = mInvincibleDelta = speed; - mInvincibleEffect = 0.0f; - mInvincibleOn = true; - mInvincibleFade = 1.0f; - } - else - { - mInvincibleTime = time; - mInvincibleSpeed = speed; - setMaskBits(InvincibleMask); - } -} - -void ShapeBase::updateInvincibleEffect(F32 dt) -{ - if(mInvincibleCount > 0.0f ) - { - if(mInvincibleEffect >= ((0.3 * mInvincibleFade) + 0.05f) && mInvincibleDelta > 0.0f) - mInvincibleDelta = -mInvincibleSpeed; - else if(mInvincibleEffect <= 0.05f && mInvincibleDelta < 0.0f) - { - mInvincibleDelta = mInvincibleSpeed; - mInvincibleFade = mInvincibleCount / mInvincibleTime; - } - mInvincibleEffect += mInvincibleDelta; - mInvincibleCount -= dt; - } - else - { - mInvincibleEffect = 0.0f; - mInvincibleOn = false; - } -} - //---------------------------------------------------------------------------- void ShapeBase::setVelocity(const VectorF&) { @@ -2240,7 +2073,7 @@ void ShapeBase::stopAudio(U32 slot) void ShapeBase::updateServerAudio() { // Timeout non-looping sounds - for (int i = 0; i < MaxSoundThreads; i++) { + for (S32 i = 0; i < MaxSoundThreads; i++) { Sound& st = mSoundThread[i]; if (st.play && st.timeout && st.timeout < Sim::getCurrentTime()) { clearMaskBits(SoundMaskN << i); @@ -2280,7 +2113,7 @@ void ShapeBase::updateAudioState(Sound& st) void ShapeBase::updateAudioPos() { - for (int i = 0; i < MaxSoundThreads; i++) + for (S32 i = 0; i < MaxSoundThreads; i++) { SFXSource* source = mSoundThread[i].sound; if ( source ) @@ -2322,14 +2155,13 @@ bool ShapeBase::setThreadSequence(U32 slot, S32 seq, bool reset) if (reset) { st.state = Thread::Play; st.atEnd = false; - st.timescale = 1.f; - st.position = 0.f; + st.timescale = 1.f; + st.position = 0.f; } if (mShapeInstance) { if (!st.thread) st.thread = mShapeInstance->addThread(); - mShapeInstance->setSequence(st.thread,seq,0); - stopThreadSound(st); + mShapeInstance->setSequence(st.thread,seq,st.position); updateThread(st); } return true; @@ -2344,19 +2176,12 @@ void ShapeBase::updateThread(Thread& st) case Thread::Stop: { mShapeInstance->setTimeScale( st.thread, 1.f ); - mShapeInstance->setPos( st.thread, ( st.timescale > 0.f ) ? 0.0f : 1.0f ); + mShapeInstance->setPos( st.thread, ( st.timescale > 0.f ) ? 1.0f : 0.0f ); } // Drop through to pause state case Thread::Pause: { - if ( st.position != -1.f ) - { - mShapeInstance->setTimeScale( st.thread, 1.f ); - mShapeInstance->setPos( st.thread, st.position ); - } - mShapeInstance->setTimeScale( st.thread, 0.f ); - stopThreadSound( st ); } break; case Thread::Play: @@ -2366,7 +2191,6 @@ void ShapeBase::updateThread(Thread& st) mShapeInstance->setTimeScale(st.thread,1); mShapeInstance->setPos( st.thread, ( st.timescale > 0.f ) ? 1.0f : 0.0f ); mShapeInstance->setTimeScale(st.thread,0); - stopThreadSound(st); st.state = Thread::Stop; } else @@ -2378,16 +2202,11 @@ void ShapeBase::updateThread(Thread& st) } mShapeInstance->setTimeScale(st.thread, st.timescale ); - if (!st.sound) - { - startSequenceSound(st); - } } } break; case Thread::Destroy: { - stopThreadSound(st); st.atEnd = true; st.sequence = -1; if(st.thread) @@ -2495,19 +2314,6 @@ bool ShapeBase::setThreadTimeScale( U32 slot, F32 timeScale ) return false; } -void ShapeBase::stopThreadSound(Thread& thread) -{ - if (thread.sound) { - } -} - -void ShapeBase::startSequenceSound(Thread& thread) -{ - if (!isGhost() || !thread.thread) - return; - stopThreadSound(thread); -} - void ShapeBase::advanceThreads(F32 dt) { for (U32 i = 0; i < MaxScriptThreads; i++) { @@ -2519,7 +2325,7 @@ void ShapeBase::advanceThreads(F32 dt) st.atEnd = true; updateThread(st); if (!isGhost()) { - mDataBlock->onEndSequence_callback( this, i ); + mDataBlock->onEndSequence_callback(this, i, this->getThreadSequenceName(i)); } } @@ -2528,6 +2334,7 @@ void ShapeBase::advanceThreads(F32 dt) if(st.thread) { mShapeInstance->advanceTime(dt,st.thread); + st.position = mShapeInstance->getPos(st.thread); } } } @@ -3102,8 +2909,7 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream) } if(!stream->writeFlag(mask & (NameMask | DamageMask | SoundMask | MeshHiddenMask | - ThreadMask | ImageMask | CloakMask | InvincibleMask | - ShieldMask | SkinMask))) + ThreadMask | ImageMask | CloakMask | SkinMask))) return retMask; if (stream->writeFlag(mask & DamageMask)) { @@ -3113,7 +2919,7 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream) } if (stream->writeFlag(mask & ThreadMask)) { - for (int i = 0; i < MaxScriptThreads; i++) { + for (S32 i = 0; i < MaxScriptThreads; i++) { Thread& st = mScriptThread[i]; if (stream->writeFlag( (st.sequence != -1 || st.state == Thread::Destroy) && (mask & (ThreadMaskN << i)) ) ) { stream->writeInt(st.sequence,ThreadSequenceBits); @@ -3126,7 +2932,7 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream) } if (stream->writeFlag(mask & SoundMask)) { - for (int i = 0; i < MaxSoundThreads; i++) { + for (S32 i = 0; i < MaxSoundThreads; i++) { Sound& st = mSoundThread[i]; if (stream->writeFlag(mask & (SoundMaskN << i))) if (stream->writeFlag(st.play)) @@ -3136,7 +2942,7 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream) } if (stream->writeFlag(mask & ImageMask)) { - for (int i = 0; i < MaxMountedImages; i++) + for (S32 i = 0; i < MaxMountedImages; i++) if (stream->writeFlag(mask & (ImageMaskN << i))) { MountedImage& image = mMountedImageList[i]; if (stream->writeFlag(image.dataBlock)) @@ -3158,9 +2964,9 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream) stream->writeFlag(image.triggerDown); stream->writeFlag(image.altTriggerDown); - for (U32 i=0; iwriteFlag(image.genericTrigger[i]); + stream->writeFlag(image.genericTrigger[j]); } stream->writeInt(image.fireCount,3); @@ -3173,7 +2979,7 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream) } // Group some of the uncommon stuff together. - if (stream->writeFlag(mask & (NameMask | ShieldMask | CloakMask | InvincibleMask | SkinMask | MeshHiddenMask ))) { + if (stream->writeFlag(mask & (NameMask | CloakMask | SkinMask | MeshHiddenMask ))) { if (stream->writeFlag(mask & CloakMask)) { @@ -3194,14 +3000,6 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream) if (stream->writeFlag(mask & NameMask)) { con->packNetStringHandleU(stream, mShapeNameHandle); } - if (stream->writeFlag(mask & ShieldMask)) { - stream->writeNormalVector(mShieldNormal, ShieldNormalBits); - stream->writeFloat( getEnergyValue(), EnergyLevelBits ); - } - if (stream->writeFlag(mask & InvincibleMask)) { - stream->write(mInvincibleTime); - stream->write(mInvincibleSpeed); - } if ( stream->writeFlag( mask & MeshHiddenMask ) ) stream->writeBits( mMeshHidden ); @@ -3237,9 +3035,9 @@ void ShapeBase::unpackUpdate(NetConnection *con, BitStream *stream) if (stream->readFlag()) { Thread& st = mScriptThread[i]; U32 seq = stream->readInt(ThreadSequenceBits); - st.state = stream->readInt(2); - stream->read( &st.timescale ); - stream->read( &st.position ); + st.state = Thread::State(stream->readInt(2)); + stream->read( &st.timescale ); + stream->read( &st.position ); st.atEnd = stream->readFlag(); if (st.sequence != seq && st.state != Thread::Destroy) setThreadSequence(i,seq,false); @@ -3271,7 +3069,7 @@ void ShapeBase::unpackUpdate(NetConnection *con, BitStream *stream) // Mounted Images if (stream->readFlag()) { - for (int i = 0; i < MaxMountedImages; i++) { + for (S32 i = 0; i < MaxMountedImages; i++) { if (stream->readFlag()) { MountedImage& image = mMountedImageList[i]; ShapeBaseImageData* imageData = 0; @@ -3303,14 +3101,14 @@ void ShapeBase::unpackUpdate(NetConnection *con, BitStream *stream) image.triggerDown = stream->readFlag(); image.altTriggerDown = stream->readFlag(); - for (U32 i=0; ireadFlag(); + image.genericTrigger[j] = stream->readFlag(); } - int count = stream->readInt(3); - int altCount = stream->readInt(3); - int reloadCount = stream->readInt(3); + S32 count = stream->readInt(3); + S32 altCount = stream->readInt(3); + S32 reloadCount = stream->readInt(3); bool datablockChange = image.dataBlock != imageData; if (datablockChange || (image.skinNameHandle != skinDesiredNameHandle)) @@ -3443,25 +3241,6 @@ void ShapeBase::unpackUpdate(NetConnection *con, BitStream *stream) if (stream->readFlag()) { // NameMask mShapeNameHandle = con->unpackNetStringHandleU(stream); } - if(stream->readFlag()) // ShieldMask - { - // Cloaking, Shield, and invul masking - Point3F shieldNormal; - stream->readNormalVector(&shieldNormal, ShieldNormalBits); - - // CodeReview [bjg 4/6/07] This is our energy level - why aren't we storing it? Was in a - // local variable called energyPercent. - stream->readFloat(EnergyLevelBits); - } - - if (stream->readFlag()) - { - // InvincibleMask - F32 time, speed; - stream->read(&time); - stream->read(&speed); - setupInvincibleEffect(time, speed); - } if ( stream->readFlag() ) // MeshHiddenMask { @@ -3742,7 +3521,7 @@ void ShapeBase::reSkin() Vector skins; String(mSkinNameHandle.getString()).split( ";", skins ); - for (int i = 0; i < skins.size(); i++) + for (S32 i = 0; i < skins.size(); i++) { String oldSkin( mAppliedSkinName.c_str() ); String newSkin( skins[i] ); @@ -4826,18 +4605,6 @@ DefineEngineMethod( ShapeBase, setCameraFov, void, ( F32 fov ),, object->setCameraFov( fov ); } -DefineEngineMethod( ShapeBase, setInvincibleMode, void, ( F32 time, F32 speed ),, - "@brief Setup the invincible effect.\n\n" - - "This effect is used for HUD feedback to the user that they are invincible.\n" - "@note Currently not implemented\n" - - "@param time duration in seconds for the invincible effect\n" - "@param speed speed at which the invincible effect progresses\n" ) -{ - object->setupInvincibleEffect( time, speed ); -} - DefineEngineMethod( ShapeBase, startFade, void, ( S32 time, S32 delay, bool fadeOut ),, "@brief Fade the object in or out without removing it from the scene.\n\n" diff --git a/Engine/source/T3D/shapeBase.h b/Engine/source/T3D/shapeBase.h index 2987163df..a46a41580 100644 --- a/Engine/source/T3D/shapeBase.h +++ b/Engine/source/T3D/shapeBase.h @@ -648,7 +648,7 @@ public: DECLARE_CALLBACK( void, onCollision, ( ShapeBase* obj, SceneObject* collObj, VectorF vec, F32 len ) ); DECLARE_CALLBACK( void, onDamage, ( ShapeBase* obj, F32 delta ) ); DECLARE_CALLBACK( void, onTrigger, ( ShapeBase* obj, S32 index, bool state ) ); - DECLARE_CALLBACK( void, onEndSequence, ( ShapeBase* obj, S32 slot ) ); + DECLARE_CALLBACK(void, onEndSequence, (ShapeBase* obj, S32 slot, const char* name)); DECLARE_CALLBACK( void, onForceUncloak, ( ShapeBase* obj, const char* reason ) ); /// @} }; @@ -689,7 +689,6 @@ public: MaxMountedImages = 4, ///< Should be a power of 2 MaxImageEmitters = 3, NumImageBits = 3, - ShieldNormalBits = 8, CollisionTimeoutValue = 250 ///< Timeout in ms. }; @@ -730,12 +729,9 @@ protected: Play, Stop, Pause, Destroy }; TSThread* thread; ///< Pointer to 3space data. - U32 state; ///< State of the thread - /// - /// @see Thread::State + State state; ///< State of the thread S32 sequence; ///< The animation sequence which is running in this thread. - F32 timescale; ///< Timescale - U32 sound; ///< Handle to sound. + F32 timescale; ///< Timescale bool atEnd; ///< Are we at the end of this thread? F32 position; }; @@ -743,17 +739,6 @@ protected: /// @} - /// @name Invincibility - /// @{ - F32 mInvincibleCount; - F32 mInvincibleTime; - F32 mInvincibleSpeed; - F32 mInvincibleDelta; - F32 mInvincibleEffect; - F32 mInvincibleFade; - bool mInvincibleOn; - /// @} - /// @name Motion /// @{ bool mMoveMotion; ///< Indicates that a Move has come in requesting x, y or z motion @@ -918,9 +903,6 @@ protected: bool mFlipFadeVal; - /// Last shield direction (cur. unused) - Point3F mShieldNormal; - /// Camera shake caused by weapon fire. CameraShake *mWeaponCamShake; @@ -1156,11 +1138,9 @@ public: DamageMask = Parent::NextFreeMask << 1, NoWarpMask = Parent::NextFreeMask << 2, CloakMask = Parent::NextFreeMask << 3, - ShieldMask = Parent::NextFreeMask << 4, - InvincibleMask = Parent::NextFreeMask << 5, - SkinMask = Parent::NextFreeMask << 6, - MeshHiddenMask = Parent::NextFreeMask << 7, - SoundMaskN = Parent::NextFreeMask << 8, ///< Extends + MaxSoundThreads bits + SkinMask = Parent::NextFreeMask << 4, + MeshHiddenMask = Parent::NextFreeMask << 5, + SoundMaskN = Parent::NextFreeMask << 6, ///< Extends + MaxSoundThreads bits ThreadMaskN = SoundMaskN << MaxSoundThreads, ///< Extends + MaxScriptThreads bits ImageMaskN = ThreadMaskN << MaxScriptThreads, ///< Extends + MaxMountedImage bits NextFreeMask = ImageMaskN << MaxMountedImages @@ -1371,14 +1351,6 @@ public: /// @param timescale Timescale bool setThreadTimeScale( U32 slot, F32 timeScale ); - /// Start the sound associated with an animation thread - /// @param thread Thread - void startSequenceSound(Thread& thread); - - /// Stop the sound associated with an animation thread - /// @param thread Thread - void stopThreadSound(Thread& thread); - /// Advance all animation threads attached to this shapebase /// @param dt Change in time from last call to this function void advanceThreads(F32 dt); @@ -1702,26 +1674,6 @@ public: virtual void setWhiteOut(const F32); /// @} - /// @name Invincibility effect - /// This is the screen effect when invincible in the HUD - /// @see GameRenderFilters() - /// @{ - - /// Returns the level of invincibility effect - virtual F32 getInvincibleEffect() const; - - /// Initializes invincibility effect and interpolation parameters - /// - /// @param time Time it takes to become invincible - /// @param speed Speed at which invincibility effects progress - virtual void setupInvincibleEffect(F32 time, F32 speed); - - /// Advance invincibility effect animation - /// @param dt Time since last call of this function - virtual void updateInvincibleEffect(F32 dt); - - /// @} - /// @name Movement & velocity /// @{ diff --git a/Engine/source/T3D/shapeImage.cpp b/Engine/source/T3D/shapeImage.cpp index 554eeb55b..548984ca8 100644 --- a/Engine/source/T3D/shapeImage.cpp +++ b/Engine/source/T3D/shapeImage.cpp @@ -203,7 +203,7 @@ ShapeBaseImageData::ShapeBaseImageData() scriptAnimTransitionTime = 0.25f; // - for (int i = 0; i < MaxStates; i++) { + for (S32 i = 0; i < MaxStates; i++) { stateName[i] = 0; stateTransitionLoaded[i] = 0; @@ -462,7 +462,10 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr) Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(shape[i].getPath()); if (!fileRef) + { + errorStr = String::ToString("ShapeBaseImageData: Couldn't load shape \"%s\"",name); return false; + } if(server) { @@ -3057,7 +3060,7 @@ TICKAGAIN: if (image.spinThread[i]) { - float timeScale; + F32 timeScale; switch (stateData.spin) { diff --git a/Engine/source/T3D/trigger.cpp b/Engine/source/T3D/trigger.cpp index 019b0c45c..7dbcba618 100644 --- a/Engine/source/T3D/trigger.cpp +++ b/Engine/source/T3D/trigger.cpp @@ -188,7 +188,7 @@ bool Trigger::castRay(const Point3F &start, const Point3F &end, RayInfo* info) F32 const *si = &start.x; F32 const *ei = &end.x; - for (int i = 0; i < 3; i++) + for (S32 i = 0; i < 3; i++) { if (*si < *ei) { @@ -259,8 +259,9 @@ ConsoleGetType( TypeTriggerPolyhedron ) AssertFatal(currVec == 3, "Internal error: Bad trigger polyhedron"); // Build output string. - char* retBuf = Con::getReturnBuffer(1024); - dSprintf(retBuf, 1023, "%7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f", + static const U32 bufSize = 1024; + char* retBuf = Con::getReturnBuffer(bufSize); + dSprintf(retBuf, bufSize, "%7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f", origin.x, origin.y, origin.z, vecs[0].x, vecs[0].y, vecs[0].z, vecs[2].x, vecs[2].y, vecs[2].z, diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index f2e666c4f..1474bf96d 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -442,7 +442,7 @@ void TSStatic::reSkin() Vector skins; String(mSkinNameHandle.getString()).split( ";", skins ); - for (int i = 0; i < skins.size(); i++) + for (S32 i = 0; i < skins.size(); i++) { String oldSkin( mAppliedSkinName.c_str() ); String newSkin( skins[i] ); diff --git a/Engine/source/T3D/turret/aiTurretShape.cpp b/Engine/source/T3D/turret/aiTurretShape.cpp index f4da6522d..068523e0f 100644 --- a/Engine/source/T3D/turret/aiTurretShape.cpp +++ b/Engine/source/T3D/turret/aiTurretShape.cpp @@ -99,7 +99,7 @@ AITurretShapeData::AITurretShapeData() weaponLeadVelocity = 0; - for (int i = 0; i < MaxStates; i++) { + for (S32 i = 0; i < MaxStates; i++) { stateName[i] = 0; stateTransitionAtRest[i] = 0; stateTransitionNotAtRest[i] = 0; diff --git a/Engine/source/T3D/vehicles/vehicle.cpp b/Engine/source/T3D/vehicles/vehicle.cpp index f4b58ac61..df10b2cdc 100644 --- a/Engine/source/T3D/vehicles/vehicle.cpp +++ b/Engine/source/T3D/vehicles/vehicle.cpp @@ -69,7 +69,7 @@ const F32 sVehicleGravity = -20; // Physics and collision constants static F32 sRestTol = 0.5; // % of gravity energy to be at rest -static int sRestCount = 10; // Consecutive ticks before comming to rest +static S32 sRestCount = 10; // Consecutive ticks before comming to rest } // namespace {} @@ -218,6 +218,7 @@ bool VehicleData::preload(bool server, String &errorStr) if (!collisionDetails.size() || collisionDetails[0] == -1) { Con::errorf("VehicleData::preload failed: Vehicle models must define a collision-1 detail"); + errorStr = String::ToString("VehicleData: Couldn't load shape \"%s\"",shapeName); return false; } @@ -341,14 +342,14 @@ void VehicleData::packData(BitStream* stream) } } - for (int j = 0; j < VC_NUM_DAMAGE_EMITTER_AREAS; j++) + for (S32 j = 0; j < VC_NUM_DAMAGE_EMITTER_AREAS; j++) { stream->write( damageEmitterOffset[j].x ); stream->write( damageEmitterOffset[j].y ); stream->write( damageEmitterOffset[j].z ); } - for (int k = 0; k < VC_NUM_DAMAGE_LEVELS; k++) + for (S32 k = 0; k < VC_NUM_DAMAGE_LEVELS; k++) { stream->write( damageLevelTolerance[k] ); } @@ -440,14 +441,14 @@ void VehicleData::unpackData(BitStream* stream) } } - for( int j=0; jread( &damageEmitterOffset[j].x ); stream->read( &damageEmitterOffset[j].y ); stream->read( &damageEmitterOffset[j].z ); } - for( int k=0; kread( &damageLevelTolerance[k] ); } @@ -718,7 +719,7 @@ bool Vehicle::onAdd() { if( mDataBlock->dustEmitter ) { - for( int i=0; ionNewDataBlock( mDataBlock->dustEmitter, false ); @@ -1804,7 +1805,7 @@ void Vehicle::updateDamageSmoke( F32 dt ) F32 damagePercent = mDamage / mDataBlock->maxDamage; if( damagePercent >= mDataBlock->damageLevelTolerance[j] ) { - for( int i=0; inumDmgEmitterAreas; i++ ) + for( S32 i=0; inumDmgEmitterAreas; i++ ) { MatrixF trans = getTransform(); Point3F offset = mDataBlock->damageEmitterOffset[i]; @@ -1935,7 +1936,7 @@ void Vehicle::_renderMassAndContacts( ObjectRenderInst *ri, SceneRenderState *st GFX->getDrawUtil()->drawCube(desc, Point3F(0.1f,0.1f,0.1f),mDataBlock->massCenter, ColorI(255, 255, 255), &mRenderObjToWorld); // Now render all the contact points. - for (int i = 0; i < mCollisionList.getCount(); i++) + for (S32 i = 0; i < mCollisionList.getCount(); i++) { const Collision& collision = mCollisionList[i]; GFX->getDrawUtil()->drawCube(desc, Point3F(0.05f,0.05f,0.05f),collision.point, ColorI(0, 0, 255)); @@ -1943,7 +1944,7 @@ void Vehicle::_renderMassAndContacts( ObjectRenderInst *ri, SceneRenderState *st // Finally render the normals as one big batch. PrimBuild::begin(GFXLineList, mCollisionList.getCount() * 2); - for (int i = 0; i < mCollisionList.getCount(); i++) + for (S32 i = 0; i < mCollisionList.getCount(); i++) { const Collision& collision = mCollisionList[i]; PrimBuild::color3f(1, 1, 1); diff --git a/Engine/source/T3D/vehicles/vehicle.h b/Engine/source/T3D/vehicles/vehicle.h index da3b62eeb..695c16686 100644 --- a/Engine/source/T3D/vehicles/vehicle.h +++ b/Engine/source/T3D/vehicles/vehicle.h @@ -202,7 +202,7 @@ class Vehicle: public ShapeBase CollisionList mContacts; Rigid mRigid; ShapeBaseConvex mConvex; - int restCount; + S32 restCount; SimObjectPtr mDustEmitterList[VehicleData::VC_NUM_DUST_EMITTERS]; SimObjectPtr mDamageEmitterList[VehicleData::VC_NUM_DAMAGE_EMITTERS]; diff --git a/Engine/source/T3D/vehicles/vehicleBlocker.cpp b/Engine/source/T3D/vehicles/vehicleBlocker.cpp index e85d44ff9..a31969d1b 100644 --- a/Engine/source/T3D/vehicles/vehicleBlocker.cpp +++ b/Engine/source/T3D/vehicles/vehicleBlocker.cpp @@ -71,6 +71,12 @@ bool VehicleBlocker::onAdd() mObjBox.minExtents.set(-mDimensions.x, -mDimensions.y, 0); mObjBox.maxExtents.set( mDimensions.x, mDimensions.y, mDimensions.z); + if( !mObjBox.isValidBox() ) + { + Con::errorf("VehicleBlocker::onAdd - Fail - No valid object box"); + return false; + } + resetWorldBox(); setRenderTransform(mObjToWorld); diff --git a/Engine/source/app/net/httpObject.cpp b/Engine/source/app/net/httpObject.cpp index c75faed8e..d521d5000 100644 --- a/Engine/source/app/net/httpObject.cpp +++ b/Engine/source/app/net/httpObject.cpp @@ -298,7 +298,7 @@ void HTTPObject::onDisconnect() Parent::onDisconnect(); } -bool HTTPObject::processLine(U8 *line) +bool HTTPObject::processLine(UTF8 *line) { if(mParseState == ParsingStatusLine) { diff --git a/Engine/source/app/net/httpObject.h b/Engine/source/app/net/httpObject.h index 76647401a..ac12690aa 100644 --- a/Engine/source/app/net/httpObject.h +++ b/Engine/source/app/net/httpObject.h @@ -72,7 +72,7 @@ public: virtual void onConnected(); virtual void onConnectFailed(); virtual void onDisconnect(); - bool processLine(U8 *line); + bool processLine(UTF8 *line); DECLARE_CONOBJECT(HTTPObject); }; diff --git a/Engine/source/app/net/net.cpp b/Engine/source/app/net/net.cpp index 922a6b808..390799907 100644 --- a/Engine/source/app/net/net.cpp +++ b/Engine/source/app/net/net.cpp @@ -382,10 +382,11 @@ ConsoleFunction( buildTaggedString, const char*, 2, 11, "(string format, ...)" if (*indexPtr == StringTagPrefixByte) indexPtr++; const char *fmtString = gNetStringTable->lookupString(dAtoi(indexPtr)); - char *strBuffer = Con::getReturnBuffer(512); + static const U32 bufSize = 512; + char *strBuffer = Con::getReturnBuffer(bufSize); const char *fmtStrPtr = fmtString; char *strBufPtr = strBuffer; - S32 strMaxLength = 511; + S32 strMaxLength = bufSize - 1; if (!fmtString) goto done; diff --git a/Engine/source/app/net/tcpObject.cpp b/Engine/source/app/net/tcpObject.cpp index 37ee3ccd4..92b67df1d 100644 --- a/Engine/source/app/net/tcpObject.cpp +++ b/Engine/source/app/net/tcpObject.cpp @@ -421,7 +421,7 @@ DefineEngineMethod(TCPObject, send, void, (const char *data),, object->send( (const U8*)data, dStrlen(data) ); } -DefineEngineMethod(TCPObject, listen, void, (int port),, +DefineEngineMethod(TCPObject, listen, void, (U32 port),, "@brief Start listening on the specified port for connections.\n\n" "This method starts a listener which looks for incoming TCP connections to a port. " diff --git a/Engine/source/app/version.h b/Engine/source/app/version.h index 03051c512..ab035793d 100644 --- a/Engine/source/app/version.h +++ b/Engine/source/app/version.h @@ -41,10 +41,10 @@ /// code version, the game name, and which type of game it is (TGB, TGE, TGEA, etc.). /// /// Version number is major * 1000 + minor * 100 + revision * 10. -#define TORQUE_GAME_ENGINE 3501 +#define TORQUE_GAME_ENGINE 3600 /// Human readable engine version string. -#define TORQUE_GAME_ENGINE_VERSION_STRING "3.5.1" +#define TORQUE_GAME_ENGINE_VERSION_STRING "3.6" /// Gets the engine version number. The version number is specified as a global in version.cc U32 getVersionNumber(); diff --git a/Engine/source/cinterface/c_consoleInterface.cpp b/Engine/source/cinterface/c_consoleInterface.cpp index b23c0b56d..21a2e48fd 100644 --- a/Engine/source/cinterface/c_consoleInterface.cpp +++ b/Engine/source/cinterface/c_consoleInterface.cpp @@ -43,7 +43,7 @@ extern "C" { return so->getClassName(); } - void *SimObject_GetFieldList(SimObject *so, int &outNumFields) + void *SimObject_GetFieldList(SimObject *so, S32 &outNumFields) { const AbstractClassRep::FieldList &fl = so->getFieldList(); outNumFields = fl.size(); diff --git a/Engine/source/cinterface/c_scripting.cpp b/Engine/source/cinterface/c_scripting.cpp index e6448089b..1f9aa2281 100644 --- a/Engine/source/cinterface/c_scripting.cpp +++ b/Engine/source/cinterface/c_scripting.cpp @@ -29,7 +29,7 @@ // External scripting cinterface, suitable for import into any scripting system which support "C" interfaces (C#, Python, Lua, Java, etc) -#ifdef TORQUE_OS_WIN32 +#ifdef TORQUE_OS_WIN #include "windowManager/win32/win32Window.h" #include "windowManager/win32/winDispatch.h" #endif @@ -164,7 +164,7 @@ extern "C" { return false; } - void script_simobject_setfield_int(U32 objectId, const char* fieldName, int v) + void script_simobject_setfield_int(U32 objectId, const char* fieldName, S32 v) { SimObject *object = Sim::findObject( objectId ); if( object ) @@ -222,7 +222,7 @@ extern "C" { { // maxArgs improper on a number of console function/methods if (argc < entry->mMinArgs)// || argc > entry->mMaxArgs) - return ""; + return false; SimObject* o = NULL; @@ -230,7 +230,7 @@ extern "C" { { o = Sim::findObject(dAtoi(argv[1])); if (!o) - return ""; + return false; } return entry->cb.mBoolCallbackFunc(o, argc, argv); @@ -291,12 +291,12 @@ extern "C" { entry->cb.mVoidCallbackFunc(o, argc, argv); } - int script_simobject_get_id(SimObject* so) + S32 script_simobject_get_id(SimObject* so) { return so->getId(); } - int script_simobject_find(const char* classname, const char* name) + S32 script_simobject_find(const char* classname, const char* name) { SimObject *object; if( Sim::findObject( name, object ) ) @@ -383,9 +383,9 @@ extern "C" { } -#ifdef TORQUE_OS_WIN32 +#ifdef TORQUE_OS_WIN - void script_input_event(int type, int value1, int value2) + void script_input_event(S32 type, S32 value1, S32 value2) { if (PlatformWindowManager::get() && PlatformWindowManager::get()->getFirstWindow()) { diff --git a/Engine/source/cinterface/cinterface.cpp b/Engine/source/cinterface/cinterface.cpp index f5b1c1412..2d9a729d3 100644 --- a/Engine/source/cinterface/cinterface.cpp +++ b/Engine/source/cinterface/cinterface.cpp @@ -29,7 +29,7 @@ #include "windowManager/platformWindow.h" #include "windowManager/platformWindowMgr.h" -#ifdef TORQUE_OS_WIN32 +#ifdef TORQUE_OS_WIN #include "windowManager/win32/win32Window.h" #include "windowManager/win32/winDispatch.h" extern void createFontInit(void); @@ -37,7 +37,7 @@ extern void createFontShutdown(void); #endif #if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) - extern INT CreateMiniDump(LPEXCEPTION_POINTERS ExceptionInfo); + extern S32 CreateMiniDump(LPEXCEPTION_POINTERS ExceptionInfo); #endif static HashTable gSecureScript; @@ -47,7 +47,7 @@ static HashTable gSecureScript; // ObjC hooks for shared library support // See: macMain.mm -void torque_mac_engineinit(int argc, const char **argv); +void torque_mac_engineinit(S32 argc, const char **argv); void torque_mac_enginetick(); void torque_mac_engineshutdown(); @@ -64,7 +64,7 @@ extern "C" { } // initialize Torque 3D including argument handling - int torque_engineinit(S32 argc, const char **argv) + S32 torque_engineinit(S32 argc, const char **argv) { #if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) @@ -105,7 +105,7 @@ extern "C" { } // tick Torque 3D's main loop - int torque_enginetick() + S32 torque_enginetick() { #if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) @@ -139,7 +139,7 @@ extern "C" { } // shutdown the engine - int torque_engineshutdown() + S32 torque_engineshutdown() { #if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) @@ -181,7 +181,7 @@ extern "C" { } - int torque_getconsolebool(const char* name) + S32 torque_getconsolebool(const char* name) { return Con::getBoolVariable(name); } @@ -303,7 +303,7 @@ extern "C" { Namespace::Entry* entry = GetEntry(nameSpace, name); if (!entry) - return ""; + return false; return entry->cb.mBoolCallbackFunc(NULL, argc, argv); } @@ -415,7 +415,7 @@ extern "C" { PlatformWindowManager::get()->getFirstWindow()->setSize(Point2I(width,height)); } -#ifdef TORQUE_OS_WIN32 +#ifdef TORQUE_OS_WIN // retrieve the hwnd of our render window void* torque_gethwnd() { @@ -468,9 +468,10 @@ ConsoleFunction(testJavaScriptBridge, const char *, 4, 4, "testBridge(arg1, arg2 if (dStrcmp(jret,"42")) failed = 3; - char *ret = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char *ret = Con::getReturnBuffer(bufSize); - dSprintf(ret, 256, "%i", failed); + dSprintf(ret, bufSize, "%i", failed); return ret; } diff --git a/Engine/source/collision/collision.h b/Engine/source/collision/collision.h index a2a69df23..8dec9791c 100644 --- a/Engine/source/collision/collision.h +++ b/Engine/source/collision/collision.h @@ -96,7 +96,7 @@ public: } // Accessors - int getCount() const { return mCount; } + S32 getCount() const { return mCount; } F32 getTime() const { return mT; } F32 getMaxHeight() const { return mMaxHeight; } diff --git a/Engine/source/collision/gjk.cpp b/Engine/source/collision/gjk.cpp index bd84e6d4f..5dff5ec92 100644 --- a/Engine/source/collision/gjk.cpp +++ b/Engine/source/collision/gjk.cpp @@ -69,21 +69,21 @@ void GjkCollisionState::swap() void GjkCollisionState::compute_det() { // Dot new point with current set - for (int i = 0, bit = 1; i < 4; ++i, bit <<=1) + for (S32 i = 0, bit = 1; i < 4; ++i, bit <<=1) if (bits & bit) dp[i][last] = dp[last][i] = mDot(y[i], y[last]); dp[last][last] = mDot(y[last], y[last]); // Calulate the determinent det[last_bit][last] = 1; - for (int j = 0, sj = 1; j < 4; ++j, sj <<= 1) { + for (S32 j = 0, sj = 1; j < 4; ++j, sj <<= 1) { if (bits & sj) { - int s2 = sj | last_bit; + S32 s2 = sj | last_bit; det[s2][j] = dp[last][last] - dp[last][j]; det[s2][last] = dp[j][j] - dp[j][last]; - for (int k = 0, sk = 1; k < j; ++k, sk <<= 1) { + for (S32 k = 0, sk = 1; k < j; ++k, sk <<= 1) { if (bits & sk) { - int s3 = sk | s2; + S32 s3 = sk | s2; det[s3][k] = det[s2][j] * (dp[j][j] - dp[j][k]) + det[s2][last] * (dp[last][j] - dp[last][k]); det[s3][j] = det[sk | last_bit][k] * (dp[k][k] - dp[k][j]) + @@ -114,11 +114,11 @@ void GjkCollisionState::compute_det() //---------------------------------------------------------------------------- -inline void GjkCollisionState::compute_vector(int bits, VectorF& v) +inline void GjkCollisionState::compute_vector(S32 bits, VectorF& v) { F32 sum = 0; v.set(0, 0, 0); - for (int i = 0, bit = 1; i < 4; ++i, bit <<= 1) { + for (S32 i = 0, bit = 1; i < 4; ++i, bit <<= 1) { if (bits & bit) { sum += det[bits][i]; v += y[i] * det[bits][i]; @@ -130,9 +130,9 @@ inline void GjkCollisionState::compute_vector(int bits, VectorF& v) //---------------------------------------------------------------------------- -inline bool GjkCollisionState::valid(int s) +inline bool GjkCollisionState::valid(S32 s) { - for (int i = 0, bit = 1; i < 4; ++i, bit <<= 1) { + for (S32 i = 0, bit = 1; i < 4; ++i, bit <<= 1) { if (all_bits & bit) { if (s & bit) { if (det[s][i] <= 0) @@ -152,7 +152,7 @@ inline bool GjkCollisionState::valid(int s) inline bool GjkCollisionState::closest(VectorF& v) { compute_det(); - for (int s = bits; s; --s) { + for (S32 s = bits; s; --s) { if ((s & bits) == s) { if (valid(s | last_bit)) { bits = s | last_bit; @@ -175,7 +175,7 @@ inline bool GjkCollisionState::closest(VectorF& v) inline bool GjkCollisionState::degenerate(const VectorF& w) { - for (int i = 0, bit = 1; i < 4; ++i, bit <<= 1) + for (S32 i = 0, bit = 1; i < 4; ++i, bit <<= 1) if ((all_bits & bit) && y[i] == w) return true; return false; @@ -256,7 +256,7 @@ void GjkCollisionState::getClosestPoints(Point3F& p1, Point3F& p2) F32 sum = 0; p1.set(0, 0, 0); p2.set(0, 0, 0); - for (int i = 0, bit = 1; i < 4; ++i, bit <<= 1) { + for (S32 i = 0, bit = 1; i < 4; ++i, bit <<= 1) { if (bits & bit) { sum += det[bits][i]; p1 += p[i] * det[bits][i]; diff --git a/Engine/source/collision/gjk.h b/Engine/source/collision/gjk.h index d78555f72..b35f4570d 100644 --- a/Engine/source/collision/gjk.h +++ b/Engine/source/collision/gjk.h @@ -58,8 +58,8 @@ struct GjkCollisionState: public CollisionState /// void compute_det(); - bool valid(int s); - void compute_vector(int bits, VectorF& v); + bool valid(S32 s); + void compute_vector(S32 bits, VectorF& v); bool closest(VectorF& v); bool degenerate(const VectorF& w); void nextBit(); diff --git a/Engine/source/collision/polytope.cpp b/Engine/source/collision/polytope.cpp index 21d9d6a8e..f07116583 100644 --- a/Engine/source/collision/polytope.cpp +++ b/Engine/source/collision/polytope.cpp @@ -280,7 +280,7 @@ bool Polytope::intersect(const PlaneF& plane,const Point3F& sp,const Point3F& ep //---------------------------------------------------------------------------- -void Polytope::extrudeFace(int faceIdx,const VectorF& vec,Polytope* out) +void Polytope::extrudeFace(S32 faceIdx,const VectorF& vec,Polytope* out) { // Assumes the face belongs to the first volume. out->mVertexList.clear(); @@ -373,7 +373,7 @@ bool Polytope::findCollision(const VectorF& vec,Polytope::Collision *best) return false; if (!best->object) best->distance = 1.0E30f; - int bestVertex = -1; + S32 bestVertex = -1; Polytope::Volume* bestVolume = NULL; sideCount++; diff --git a/Engine/source/collision/polytope.h b/Engine/source/collision/polytope.h index a28f08854..c96a54979 100644 --- a/Engine/source/collision/polytope.h +++ b/Engine/source/collision/polytope.h @@ -102,7 +102,7 @@ public: void buildBox(const MatrixF& transform,const Box3F& box); void intersect(SimObject*, const BSPNode* node); inline bool didIntersect() { return mVolumeList.size() > 1; } - void extrudeFace(int fi,const VectorF& vec,Polytope* out); + void extrudeFace(S32 fi,const VectorF& vec,Polytope* out); bool findCollision(const VectorF& vec,Polytope::Collision *best); }; diff --git a/Engine/source/component/dynamicConsoleMethodComponent.cpp b/Engine/source/component/dynamicConsoleMethodComponent.cpp index c76cae60a..fa7adf896 100644 --- a/Engine/source/component/dynamicConsoleMethodComponent.cpp +++ b/Engine/source/component/dynamicConsoleMethodComponent.cpp @@ -139,7 +139,7 @@ const char *DynamicConsoleMethodComponent::_callMethod( U32 argc, const char *ar if( getComponentCount() > 0 ) { lockComponentList(); - for( int i = getComponentCount() - 1; i >= 0; i-- ) + for( S32 i = getComponentCount() - 1; i >= 0; i-- ) //for( SimComponentIterator nItr = componentList.end(); nItr != componentList.begin(); nItr-- ) { argv[0] = cbName; diff --git a/Engine/source/component/moreAdvancedComponent.cpp b/Engine/source/component/moreAdvancedComponent.cpp index 02f8f4fe8..7ddfac688 100644 --- a/Engine/source/component/moreAdvancedComponent.cpp +++ b/Engine/source/component/moreAdvancedComponent.cpp @@ -21,7 +21,6 @@ //----------------------------------------------------------------------------- #include "component/moreAdvancedComponent.h" -#include "unit/test.h" // unitTest_runTests("Component/MoreAdvancedComponent"); @@ -58,50 +57,4 @@ bool MoreAdvancedComponent::testDependentInterface() return false; return mSCInterface->isFortyTwo( 42 ); -} - -////////////////////////////////////////////////////////////////////////// - -using namespace UnitTesting; - -CreateUnitTest(MoreAdvancedComponentTest, "Component/MoreAdvancedComponent") -{ - void run() - { - // Create component instances and compose them. - SimComponent *parentComponent = new SimComponent(); - SimpleComponent *simpleComponent = new SimpleComponent(); - MoreAdvancedComponent *moreAdvComponent = new MoreAdvancedComponent(); - // CodeReview note that the interface pointer isn't initialized in a ctor - // on the components, so it's bad memory against which you might - // be checking in testDependentInterface [3/3/2007 justind] - parentComponent->addComponent( simpleComponent ); - parentComponent->addComponent( moreAdvComponent ); - - simpleComponent->registerObject(); - moreAdvComponent->registerObject(); - - // Put a break-point here, follow the onAdd call, and observe the order in - // which the SimComponent::onAdd function executes. You will see the interfaces - // get cached, and the dependent interface query being made. - parentComponent->registerObject(); - - // If the MoreAdvancedComponent found an interface, than the parentComponent - // should have returned true, from onAdd, and should therefore be registered - // properly with the Sim - test( parentComponent->isProperlyAdded(), "Parent component not properly added!" ); - - // Now lets test the interface. You can step through this, as well. - test( moreAdvComponent->testDependentInterface(), "Dependent interface test failed." ); - - // CodeReview is there a reason we can't just delete the parentComponent here? [3/3/2007 justind] - // - // Clean up - parentComponent->removeComponent( simpleComponent ); - parentComponent->removeComponent( moreAdvComponent ); - - parentComponent->deleteObject(); - moreAdvComponent->deleteObject(); - simpleComponent->deleteObject(); - } -}; \ No newline at end of file +} \ No newline at end of file diff --git a/Engine/source/component/simpleComponent.cpp b/Engine/source/component/simpleComponent.cpp index aa1147c63..246672c28 100644 --- a/Engine/source/component/simpleComponent.cpp +++ b/Engine/source/component/simpleComponent.cpp @@ -28,124 +28,4 @@ ConsoleDocClass( SimpleComponent, "@brief The purpose of this component is to provide a minimalistic component that " "exposes a simple, cached interface\n\n" "Soon to be deprecated, internal only.\n\n " - "@internal"); - -////////////////////////////////////////////////////////////////////////// -// It may seem like some weak sauce to use a unit test for this, however -// it is very, very easy to set breakpoints in a unit test, and trace -// execution in the debugger, so I will use a unit test. -// -// Note I am not using much actual 'test' functionality, just providing -// an easy place to examine the functionality that was described and implemented -// in the header file. -// -// If you want to run this code, simply run Torque, pull down the console, and -// type: -// unitTest_runTests("Components/SimpleComponent"); - -#include "unit/test.h" -using namespace UnitTesting; - -CreateUnitTest(TestSimpleComponent, "Components/SimpleComponent") -{ - void run() - { - // When instantiating, and working with a SimObject in C++ code, such as - // a unit test, you *may not* allocate a SimObject off of the stack. - // - // For example: - // SimpleComponent sc; - // is a stack allocation. This memory is allocated off of the program stack - // when the function is called. SimObject deletion is done via SimObject::deleteObject() - // and the last command of this method is 'delete this;' That command will - // cause an assert if it is called on stack-allocated memory. Therefor, when - // instantiating SimObjects in C++ code, it is imperitive that you keep in - // mind that if any script calls 'delete()' on that SimObject, or any other - // C++ code calls 'deleteObject()' on that SimObject, it will crash. - SimpleComponent *sc = new SimpleComponent(); - - // SimObject::registerObject must be called on a SimObject before it is - // fully 'hooked in' to the engine. - // - // Tracing execution of this function will let you see onAdd get called on - // the component, and you will see it cache the interface we exposed. - sc->registerObject(); - - // It is *not* required that a component always be owned by a component (obviously) - // however I am using an owner so that you can trace execution of recursive - // calls to cache interfaces and such. - SimComponent *testOwner = new SimComponent(); - - // Add the test component to it's owner. This will set the 'mOwner' field - // of 'sc' to the address of 'testOwner' - testOwner->addComponent( sc ); - - // If you step-into this registerObject the same way as the previous one, - // you will be able to see the recursive caching of the exposed interface. - testOwner->registerObject(); - - // Now to prove that object composition is working properly, lets ask - // both of these components for their interface lists... - - // The ComponentInterfaceList is a typedef for type 'VectorPtr' - // and it will be used by getInterfaces() to store the results of the interface - // query. This is the "complete" way to obtain an interface, and it is too - // heavy-weight for most cases. A simplified query will be performed next, - // to demonstrate the usage of both. - ComponentInterfaceList iLst; - - // This query requests all interfaces, on all components, regardless of name - // or owner. - sc->getInterfaces( &iLst, - // This is the type field. I am passing NULL here to signify that the query - // should match all values of 'type' in the list. - NULL, - - // The name field, let's pass NULL again just so when you trace execution - // you can see how queries work in the simple case, first. - NULL ); - - // Lets process the list that we've gotten back, and find the interface that - // we want. - SimpleComponentInterface *scQueriedInterface = NULL; - - for( ComponentInterfaceListIterator i = iLst.begin(); i != iLst.end(); i++ ) - { - scQueriedInterface = dynamic_cast( *i ); - - if( scQueriedInterface != NULL ) - break; - } - - AssertFatal( scQueriedInterface != NULL, "No valid SimpleComponentInterface was found in query" ); - - // Lets do it again, only we will execute the query on the parent instead, - // in a simplified way. Remember the parent component doesn't expose any - // interfaces at all, so the success of this behavior is entirely dependent - // on the recursive registration that occurs in registerInterfaces() - SimpleComponentInterface *ownerQueriedInterface = testOwner->getInterface(); - - AssertFatal( ownerQueriedInterface != NULL, "No valid SimpleComponentInterface was found in query" ); - - // We should now have two pointers to the same interface obtained by querying - // different components. - test( ownerQueriedInterface == scQueriedInterface, "This really shouldn't be possible to fail given the setup of the test" ); - - // Lets call the method that was exposed on the component via the interface. - // Trace the execution of this function, if you wish. - test( ownerQueriedInterface->isFortyTwo( 42 ), "Don't panic, but it's a bad day in the component system." ); - test( scQueriedInterface->isFortyTwo( 42 ), "Don't panic, but it's a bad day in the component system." ); - - // So there you have it. Writing a simple component that exposes a cached - // interface, and testing it. It's time to clean up. - testOwner->removeComponent( sc ); - - sc->deleteObject(); - testOwner->deleteObject(); - - // Interfaces do not need to be freed. In Juggernaught, these will be ref-counted - // for more robust behavior. Right now, however, the values of our two interface - // pointers, scQueriedInterface and ownerQueriedInterface, reference invalid - // memory. - } -}; \ No newline at end of file + "@internal"); \ No newline at end of file diff --git a/Engine/source/component/test/moreAdvancedComponentTest.cpp b/Engine/source/component/test/moreAdvancedComponentTest.cpp new file mode 100644 index 000000000..a6a7335f4 --- /dev/null +++ b/Engine/source/component/test/moreAdvancedComponentTest.cpp @@ -0,0 +1,68 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "component/moreAdvancedComponent.h" + +TEST(MoreAdvancedComponent, MoreAdvancedComponent) +{ + // Create component instances and compose them. + SimComponent *parentComponent = new SimComponent(); + SimpleComponent *simpleComponent = new SimpleComponent(); + MoreAdvancedComponent *moreAdvComponent = new MoreAdvancedComponent(); + // CodeReview note that the interface pointer isn't initialized in a ctor + // on the components, so it's bad memory against which you might + // be checking in testDependentInterface [3/3/2007 justind] + parentComponent->addComponent( simpleComponent ); + parentComponent->addComponent( moreAdvComponent ); + + simpleComponent->registerObject(); + moreAdvComponent->registerObject(); + + // Put a break-point here, follow the onAdd call, and observe the order in + // which the SimComponent::onAdd function executes. You will see the interfaces + // get cached, and the dependent interface query being made. + parentComponent->registerObject(); + + // If the MoreAdvancedComponent found an interface, than the parentComponent + // should have returned true, from onAdd, and should therefore be registered + // properly with the Sim + EXPECT_TRUE( parentComponent->isProperlyAdded() ) + << "Parent component not properly added!"; + + // Now lets test the interface. You can step through this, as well. + EXPECT_TRUE( moreAdvComponent->testDependentInterface() ) + << "Dependent interface test failed."; + + // CodeReview is there a reason we can't just delete the parentComponent here? [3/3/2007 justind] + // + // Clean up + parentComponent->removeComponent( simpleComponent ); + parentComponent->removeComponent( moreAdvComponent ); + + parentComponent->deleteObject(); + moreAdvComponent->deleteObject(); + simpleComponent->deleteObject(); +}; + +#endif \ No newline at end of file diff --git a/Engine/source/unit/tests/testComponents.cpp b/Engine/source/component/test/simComponentTest.cpp similarity index 60% rename from Engine/source/unit/tests/testComponents.cpp rename to Engine/source/component/test/simComponentTest.cpp index 12297bb08..407e3adce 100644 --- a/Engine/source/unit/tests/testComponents.cpp +++ b/Engine/source/component/test/simComponentTest.cpp @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC +// Copyright (c) 2014 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to @@ -20,14 +20,10 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "unit/test.h" -#include "unit/memoryTester.h" +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" #include "component/simComponent.h" -using namespace UnitTesting; - -////////////////////////////////////////////////////////////////////////// - class CachedInterfaceExampleComponent : public SimComponent { typedef SimComponent Parent; @@ -51,10 +47,10 @@ public: public: ////////////////////////////////////////////////////////////////////////// - virtual void registerInterfaces( const SimComponent *owner ) + virtual void registerInterfaces( SimComponent *owner ) { // Register a cached interface for this - registerCachedInterface( NULL, "aU32", this, &mMyId ); + owner->registerCachedInterface( NULL, "aU32", this, &mMyId ); } ////////////////////////////////////////////////////////////////////////// @@ -70,7 +66,7 @@ public: ComponentInterfaceList list; // Enumerate the interfaces on the owner, only ignore interfaces that this object owns - if( !_getOwner()->getInterfaces( &list, NULL, "aU32", this, true ) ) + if( !owner->getInterfaces( &list, NULL, "aU32", this, true ) ) return false; // Sanity check before just assigning all willy-nilly @@ -89,11 +85,17 @@ public: // CodeReview [patw, 2, 17, 2007] I'm going to make another lightweight interface // for this functionality later - void unit_test( UnitTest *test ) + void unit_test() { - test->test( mpU32 != NULL, "Pointer to dependent interface is NULL" ); - test->test( *(*mpU32) & ( 1 << 24 ), "Pointer to interface data is bogus." ); - test->test( *(*mpU32) != *mMyId, "Two of me have the same ID, bad!" ); + EXPECT_TRUE( mpU32 != NULL ) + << "Pointer to dependent interface is NULL"; + if( mpU32 ) + { + EXPECT_TRUE( *(*mpU32) & ( 1 << 24 ) ) + << "Pointer to interface data is bogus."; + EXPECT_TRUE( *(*mpU32) != *mMyId ) + << "Two of me have the same ID, bad!"; + } } }; @@ -105,39 +107,43 @@ ConsoleDocClass( CachedInterfaceExampleComponent, "Not intended for game development, for editors or internal use only.\n\n " "@internal"); -////////////////////////////////////////////////////////////////////////// - -CreateUnitTest(TestComponentInterfacing, "Components/Composition") +TEST(SimComponent, Composition) { - void run() + SimComponent *testComponent = new SimComponent(); + CachedInterfaceExampleComponent *componentA = new CachedInterfaceExampleComponent(); + CachedInterfaceExampleComponent *componentB = new CachedInterfaceExampleComponent(); + + // Register sub-components + EXPECT_TRUE( componentA->registerObject() ) + << "Failed to register componentA"; + EXPECT_TRUE( componentB->registerObject() ) + << "Failed to register componentB"; + + // Add the components + EXPECT_TRUE( testComponent->addComponent( componentA ) ) + << "Failed to add component a to testComponent"; + EXPECT_TRUE( testComponent->addComponent( componentB ) ) + << "Failed to add component b to testComponent"; + + EXPECT_EQ( componentA->getOwner(), testComponent ) + << "testComponent did not properly set the mOwner field of componentA to NULL."; + EXPECT_EQ( componentB->getOwner(), testComponent ) + << "testComponent did not properly set the mOwner field of componentB to NULL."; + + // Register the object with the simulation, kicking off the interface registration + ASSERT_TRUE( testComponent->registerObject() ) + << "Failed to register testComponent"; + { - MemoryTester m; - m.mark(); - - SimComponent *testComponent = new SimComponent(); - CachedInterfaceExampleComponent *componentA = new CachedInterfaceExampleComponent(); - CachedInterfaceExampleComponent *componentB = new CachedInterfaceExampleComponent(); - - // Register sub-components - test( componentA->registerObject(), "Failed to register componentA" ); - test( componentB->registerObject(), "Failed to register componentB" ); - - // Add the components - test( testComponent->addComponent( componentA ), "Failed to add component a to testComponent" ); - test( testComponent->addComponent( componentB ), "Failed to add component b to testComponent" ); - - test( componentA->getOwner() == testComponent, "testComponent did not properly set the mOwner field of componentA to NULL." ); - test( componentB->getOwner() == testComponent, "testComponent did not properly set the mOwner field of componentB to NULL." ); - - // Register the object with the simulation, kicking off the interface registration - test( testComponent->registerObject(), "Failed to register testComponent" ); - - // Interface tests - componentA->unit_test( this ); - componentB->unit_test( this ); - - testComponent->deleteObject(); - - test( m.check(), "Component composition test leaked memory." ); + SCOPED_TRACE("componentA"); + componentA->unit_test(); } -}; \ No newline at end of file + { + SCOPED_TRACE("componentB"); + componentB->unit_test(); + } + + testComponent->deleteObject(); +}; + +#endif \ No newline at end of file diff --git a/Engine/source/component/test/simpleComponentTest.cpp b/Engine/source/component/test/simpleComponentTest.cpp new file mode 100644 index 000000000..a528e918f --- /dev/null +++ b/Engine/source/component/test/simpleComponentTest.cpp @@ -0,0 +1,131 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "component/simpleComponent.h" + +TEST(SimpleComponent, SimpleComponent) +{ + // When instantiating, and working with a SimObject in C++ code, such as + // a unit test, you *may not* allocate a SimObject off of the stack. + // + // For example: + // SimpleComponent sc; + // is a stack allocation. This memory is allocated off of the program stack + // when the function is called. SimObject deletion is done via SimObject::deleteObject() + // and the last command of this method is 'delete this;' That command will + // cause an assert if it is called on stack-allocated memory. Therefor, when + // instantiating SimObjects in C++ code, it is imperitive that you keep in + // mind that if any script calls 'delete()' on that SimObject, or any other + // C++ code calls 'deleteObject()' on that SimObject, it will crash. + SimpleComponent *sc = new SimpleComponent(); + + // SimObject::registerObject must be called on a SimObject before it is + // fully 'hooked in' to the engine. + // + // Tracing execution of this function will let you see onAdd get called on + // the component, and you will see it cache the interface we exposed. + sc->registerObject(); + + // It is *not* required that a component always be owned by a component (obviously) + // however I am using an owner so that you can trace execution of recursive + // calls to cache interfaces and such. + SimComponent *testOwner = new SimComponent(); + + // Add the test component to it's owner. This will set the 'mOwner' field + // of 'sc' to the address of 'testOwner' + testOwner->addComponent( sc ); + + // If you step-into this registerObject the same way as the previous one, + // you will be able to see the recursive caching of the exposed interface. + testOwner->registerObject(); + + // Now to prove that object composition is working properly, lets ask + // both of these components for their interface lists... + + // The ComponentInterfaceList is a typedef for type 'VectorPtr' + // and it will be used by getInterfaces() to store the results of the interface + // query. This is the "complete" way to obtain an interface, and it is too + // heavy-weight for most cases. A simplified query will be performed next, + // to demonstrate the usage of both. + ComponentInterfaceList iLst; + + // This query requests all interfaces, on all components, regardless of name + // or owner. + sc->getInterfaces( &iLst, + // This is the type field. I am passing NULL here to signify that the query + // should match all values of 'type' in the list. + NULL, + + // The name field, let's pass NULL again just so when you trace execution + // you can see how queries work in the simple case, first. + NULL ); + + // Lets process the list that we've gotten back, and find the interface that + // we want. + SimpleComponentInterface *scQueriedInterface = NULL; + + for( ComponentInterfaceListIterator i = iLst.begin(); i != iLst.end(); i++ ) + { + scQueriedInterface = dynamic_cast( *i ); + + if( scQueriedInterface != NULL ) + break; + } + + AssertFatal( scQueriedInterface != NULL, "No valid SimpleComponentInterface was found in query" ); + + // Lets do it again, only we will execute the query on the parent instead, + // in a simplified way. Remember the parent component doesn't expose any + // interfaces at all, so the success of this behavior is entirely dependent + // on the recursive registration that occurs in registerInterfaces() + SimpleComponentInterface *ownerQueriedInterface = testOwner->getInterface(); + + AssertFatal( ownerQueriedInterface != NULL, "No valid SimpleComponentInterface was found in query" ); + + // We should now have two pointers to the same interface obtained by querying + // different components. + EXPECT_EQ( ownerQueriedInterface, scQueriedInterface ) + << "This really shouldn't be possible to fail given the setup of the test"; + + // Lets call the method that was exposed on the component via the interface. + // Trace the execution of this function, if you wish. + EXPECT_TRUE( ownerQueriedInterface->isFortyTwo( 42 ) ) + << "Don't panic, but it's a bad day in the component system."; + EXPECT_TRUE( scQueriedInterface->isFortyTwo( 42 ) ) + << "Don't panic, but it's a bad day in the component system."; + + // So there you have it. Writing a simple component that exposes a cached + // interface, and testing it. It's time to clean up. + testOwner->removeComponent( sc ); + + sc->deleteObject(); + testOwner->deleteObject(); + + // Interfaces do not need to be freed. In Juggernaught, these will be ref-counted + // for more robust behavior. Right now, however, the values of our two interface + // pointers, scQueriedInterface and ownerQueriedInterface, reference invalid + // memory. +}; + +#endif \ No newline at end of file diff --git a/Engine/source/console/CMDscan.cpp b/Engine/source/console/CMDscan.cpp index 4ce606638..24f118d2d 100644 --- a/Engine/source/console/CMDscan.cpp +++ b/Engine/source/console/CMDscan.cpp @@ -1910,8 +1910,7 @@ extern int isatty (int ); b->yy_bs_column = 0; } - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; - + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } @@ -2355,7 +2354,7 @@ void CMDerror(char *format, ...) char tempBuf[BUFMAX]; va_list args; va_start( args, format ); -#ifdef TORQUE_OS_WIN32 +#ifdef TORQUE_OS_WIN _vsnprintf( tempBuf, BUFMAX, format, args ); #else vsnprintf( tempBuf, BUFMAX, format, args ); diff --git a/Engine/source/console/CMDscan.l b/Engine/source/console/CMDscan.l index d6d37a5c6..cef682e89 100644 --- a/Engine/source/console/CMDscan.l +++ b/Engine/source/console/CMDscan.l @@ -245,7 +245,7 @@ void CMDerror(char *format, ...) char tempBuf[BUFMAX]; va_list args; va_start( args, format ); -#ifdef TORQUE_OS_WIN32 +#ifdef TORQUE_OS_WIN _vsnprintf( tempBuf, BUFMAX, format, args ); #else vsnprintf( tempBuf, BUFMAX, format, args ); diff --git a/Engine/source/console/SimXMLDocument.cpp b/Engine/source/console/SimXMLDocument.cpp index 6076b9711..31e2f9906 100644 --- a/Engine/source/console/SimXMLDocument.cpp +++ b/Engine/source/console/SimXMLDocument.cpp @@ -348,7 +348,7 @@ bool SimXMLDocument::pushFirstChildElement(const char* rName) TiXmlElement* pElement; if(!m_paNode.empty()) { - const int iLastElement = m_paNode.size() - 1; + const S32 iLastElement = m_paNode.size() - 1; TiXmlElement* pNode = m_paNode[iLastElement]; if(!pNode) { @@ -412,7 +412,7 @@ bool SimXMLDocument::pushChildElement(S32 index) TiXmlElement* pElement; if(!m_paNode.empty()) { - const int iLastElement = m_paNode.size() - 1; + const S32 iLastElement = m_paNode.size() - 1; TiXmlElement* pNode = m_paNode[iLastElement]; if(!pNode) { @@ -472,7 +472,7 @@ bool SimXMLDocument::nextSiblingElement(const char* rName) { return false; } - const int iLastElement = m_paNode.size() - 1; + const S32 iLastElement = m_paNode.size() - 1; TiXmlElement*& pElement = m_paNode[iLastElement]; if(!pElement) { @@ -506,7 +506,7 @@ const char* SimXMLDocument::elementValue() { return StringTable->insert(""); } - const int iLastElement = m_paNode.size() - 1; + const S32 iLastElement = m_paNode.size() - 1; TiXmlElement* pNode = m_paNode[iLastElement]; if(!pNode) { @@ -547,7 +547,7 @@ const char* SimXMLDocument::attribute(const char* rAttribute) { return StringTable->insert(""); } - const int iLastElement = m_paNode.size() - 1; + const S32 iLastElement = m_paNode.size() - 1; TiXmlElement* pNode = m_paNode[iLastElement]; if(!pNode) { @@ -597,7 +597,7 @@ bool SimXMLDocument::attributeExists(const char* rAttribute) { return false; } - const int iLastElement = m_paNode.size() - 1; + const S32 iLastElement = m_paNode.size() - 1; TiXmlElement* pNode = m_paNode[iLastElement]; if(!pNode) { @@ -630,7 +630,7 @@ const char* SimXMLDocument::firstAttribute() { return StringTable->insert(""); } - const int iLastElement = m_paNode.size() - 1; + const S32 iLastElement = m_paNode.size() - 1; TiXmlElement* pNode = m_paNode[iLastElement]; if(!pNode) { @@ -667,7 +667,7 @@ const char* SimXMLDocument::lastAttribute() { return StringTable->insert(""); } - const int iLastElement = m_paNode.size() - 1; + const S32 iLastElement = m_paNode.size() - 1; TiXmlElement* pNode = m_paNode[iLastElement]; if(!pNode) { @@ -766,7 +766,7 @@ void SimXMLDocument::setAttribute(const char* rAttribute, const char* rVal) return; } - const int iLastElement = m_paNode.size() - 1; + const S32 iLastElement = m_paNode.size() - 1; TiXmlElement* pElement = m_paNode[iLastElement]; if(!pElement) { @@ -798,7 +798,7 @@ void SimXMLDocument::setObjectAttributes(const char* objectID) if( pObject == NULL ) return; - const int iLastElement = m_paNode.size() - 1; + const S32 iLastElement = m_paNode.size() - 1; TiXmlElement* pElement = m_paNode[iLastElement]; if(!pElement) return; @@ -925,7 +925,7 @@ void SimXMLDocument::pushNewElement(const char* rName) } else { - const int iFinalElement = m_paNode.size() - 1; + const S32 iFinalElement = m_paNode.size() - 1; TiXmlElement* pNode = m_paNode[iFinalElement]; if(!pNode) { @@ -975,7 +975,7 @@ void SimXMLDocument::addNewElement(const char* rName) return; } - const int iParentElement = m_paNode.size() - 2; + const S32 iParentElement = m_paNode.size() - 2; if(iParentElement < 0) { pStackTop = dynamic_cast @@ -1002,7 +1002,7 @@ void SimXMLDocument::addNewElement(const char* rName) } // Overwrite top stack position. - const int iFinalElement = m_paNode.size() - 1; + const S32 iFinalElement = m_paNode.size() - 1; m_paNode[iFinalElement] = pStackTop; //pNode = pStackTop; } @@ -1091,7 +1091,7 @@ const char* SimXMLDocument::readComment( S32 index ) // Push the first element found under the current element of the given name if(!m_paNode.empty()) { - const int iLastElement = m_paNode.size() - 1; + const S32 iLastElement = m_paNode.size() - 1; TiXmlElement* pNode = m_paNode[iLastElement]; if(!pNode) { @@ -1159,7 +1159,7 @@ void SimXMLDocument::addText(const char* text) if(m_paNode.empty()) return; - const int iFinalElement = m_paNode.size() - 1; + const S32 iFinalElement = m_paNode.size() - 1; TiXmlElement* pNode = m_paNode[iFinalElement]; if(!pNode) return; @@ -1204,7 +1204,7 @@ const char* SimXMLDocument::getText() if(m_paNode.empty()) return ""; - const int iFinalElement = m_paNode.size() - 1; + const S32 iFinalElement = m_paNode.size() - 1; TiXmlNode* pNode = m_paNode[iFinalElement]; if(!pNode) return ""; @@ -1264,7 +1264,7 @@ void SimXMLDocument::removeText() if(m_paNode.empty()) return; - const int iFinalElement = m_paNode.size() - 1; + const S32 iFinalElement = m_paNode.size() - 1; TiXmlElement* pNode = m_paNode[iFinalElement]; if(!pNode) return; @@ -1300,7 +1300,7 @@ void SimXMLDocument::addData(const char* text) if(m_paNode.empty()) return; - const int iFinalElement = m_paNode.size() - 1; + const S32 iFinalElement = m_paNode.size() - 1; TiXmlElement* pNode = m_paNode[iFinalElement]; if(!pNode) return; @@ -1346,7 +1346,7 @@ const char* SimXMLDocument::getData() if(m_paNode.empty()) return ""; - const int iFinalElement = m_paNode.size() - 1; + const S32 iFinalElement = m_paNode.size() - 1; TiXmlNode* pNode = m_paNode[iFinalElement]; if(!pNode) return ""; diff --git a/Engine/source/console/ast.h b/Engine/source/console/ast.h index 71cfbeec0..45126e2b4 100644 --- a/Engine/source/console/ast.h +++ b/Engine/source/console/ast.h @@ -27,6 +27,7 @@ class ExprEvalState; class Namespace; class SimObject; class SimGroup; +class CodeStream; /// Enable this #define if you are seeing the message "precompile size mismatch" in the console. /// This will help track down which node type is causing the error. It could be @@ -77,15 +78,13 @@ struct StmtNode /// @name Breaking /// @{ - void addBreakCount(); - void addBreakLine(U32 ip); + void addBreakLine(CodeStream &codeStream); /// @} /// @name Compilation /// @{ - virtual U32 precompileStmt(U32 loopCount) = 0; - virtual U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint) = 0; + virtual U32 compileStmt(CodeStream &codeStream, U32 ip) = 0; virtual void setPackage(StringTableEntry packageName); /// @} }; @@ -101,27 +100,26 @@ struct BreakStmtNode : StmtNode { static BreakStmtNode *alloc( S32 lineNumber ); - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); DBG_STMT_TYPE(BreakStmtNode); }; struct ContinueStmtNode : StmtNode { static ContinueStmtNode *alloc( S32 lineNumber ); - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); DBG_STMT_TYPE(ContinueStmtNode); }; /// A mathematical expression. struct ExprNode : StmtNode { - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); - virtual U32 precompile(TypeReq type) = 0; - virtual U32 compile(U32 *codeStream, U32 ip, TypeReq type) = 0; + virtual U32 compile(CodeStream &codeStream, U32 ip, TypeReq type) = 0; virtual TypeReq getPreferredType() = 0; }; @@ -130,8 +128,8 @@ struct ReturnStmtNode : StmtNode ExprNode *expr; static ReturnStmtNode *alloc( S32 lineNumber, ExprNode *expr ); - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); DBG_STMT_TYPE(ReturnStmtNode); }; @@ -147,8 +145,8 @@ struct IfStmtNode : StmtNode static IfStmtNode *alloc( S32 lineNumber, ExprNode *testExpr, StmtNode *ifBlock, StmtNode *elseBlock, bool propagateThrough ); void propagateSwitchExpr(ExprNode *left, bool string); ExprNode *getSwitchOR(ExprNode *left, ExprNode *list, bool string); - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); DBG_STMT_TYPE(IfStmtNode); }; @@ -165,8 +163,8 @@ struct LoopStmtNode : StmtNode bool integer; static LoopStmtNode *alloc( S32 lineNumber, ExprNode *testExpr, ExprNode *initExpr, ExprNode *endLoopExpr, StmtNode *loopBlock, bool isDoLoop ); - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); DBG_STMT_TYPE(LoopStmtNode); }; @@ -190,8 +188,7 @@ struct IterStmtNode : StmtNode static IterStmtNode* alloc( S32 lineNumber, StringTableEntry varName, ExprNode* containerExpr, StmtNode* body, bool isStringIter ); - U32 precompileStmt( U32 loopCount ); - U32 compileStmt( U32* codeStream, U32 ip, U32 continuePoint, U32 breakPoint ); + U32 compileStmt( CodeStream &codeStream, U32 ip ); }; /// A binary mathematical expression (ie, left op right). @@ -205,8 +202,8 @@ struct BinaryExprNode : ExprNode struct FloatBinaryExprNode : BinaryExprNode { static FloatBinaryExprNode *alloc( S32 lineNumber, S32 op, ExprNode *left, ExprNode *right ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(FloatBinaryExprNode); }; @@ -218,8 +215,8 @@ struct ConditionalExprNode : ExprNode ExprNode *falseExpr; bool integer; static ConditionalExprNode *alloc( S32 lineNumber, ExprNode *testExpr, ExprNode *trueExpr, ExprNode *falseExpr ); - virtual U32 precompile(TypeReq type); - virtual U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + virtual U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); virtual TypeReq getPreferredType(); DBG_STMT_TYPE(ConditionalExprNode); }; @@ -232,8 +229,8 @@ struct IntBinaryExprNode : BinaryExprNode static IntBinaryExprNode *alloc( S32 lineNumber, S32 op, ExprNode *left, ExprNode *right ); void getSubTypeOperand(); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(IntBinaryExprNode); }; @@ -242,18 +239,18 @@ struct StreqExprNode : BinaryExprNode { bool eq; static StreqExprNode *alloc( S32 lineNumber, ExprNode *left, ExprNode *right, bool eq ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(StreqExprNode); }; struct StrcatExprNode : BinaryExprNode { - int appendChar; - static StrcatExprNode *alloc( S32 lineNumber, ExprNode *left, ExprNode *right, int appendChar ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + S32 appendChar; + static StrcatExprNode *alloc( S32 lineNumber, ExprNode *left, ExprNode *right, S32 appendChar ); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(StrcatExprNode); }; @@ -262,8 +259,8 @@ struct CommaCatExprNode : BinaryExprNode { static CommaCatExprNode *alloc( S32 lineNumber, ExprNode *left, ExprNode *right ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(CommaCatExprNode); }; @@ -275,8 +272,8 @@ struct IntUnaryExprNode : ExprNode bool integer; static IntUnaryExprNode *alloc( S32 lineNumber, S32 op, ExprNode *expr ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(IntUnaryExprNode); }; @@ -287,8 +284,8 @@ struct FloatUnaryExprNode : ExprNode ExprNode *expr; static FloatUnaryExprNode *alloc( S32 lineNumber, S32 op, ExprNode *expr ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(FloatUnaryExprNode); }; @@ -299,8 +296,8 @@ struct VarNode : ExprNode ExprNode *arrayIndex; static VarNode *alloc( S32 lineNumber, StringTableEntry varName, ExprNode *arrayIndex ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(VarNode); }; @@ -311,8 +308,8 @@ struct IntNode : ExprNode U32 index; // if it's converted to float/string static IntNode *alloc( S32 lineNumber, S32 value ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(IntNode); }; @@ -323,8 +320,8 @@ struct FloatNode : ExprNode U32 index; static FloatNode *alloc( S32 lineNumber, F64 value ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(FloatNode); }; @@ -338,8 +335,8 @@ struct StrConstNode : ExprNode bool doc; // Specifies that this string is a documentation block. static StrConstNode *alloc( S32 lineNumber, char *str, bool tag, bool doc = false ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(StrConstNode); }; @@ -351,8 +348,8 @@ struct ConstantNode : ExprNode U32 index; static ConstantNode *alloc( S32 lineNumber, StringTableEntry value ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(ConstantNode); }; @@ -365,8 +362,8 @@ struct AssignExprNode : ExprNode TypeReq subType; static AssignExprNode *alloc( S32 lineNumber, StringTableEntry varName, ExprNode *arrayIndex, ExprNode *expr ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(AssignExprNode); }; @@ -389,8 +386,8 @@ struct AssignOpExprNode : ExprNode TypeReq subType; static AssignOpExprNode *alloc( S32 lineNumber, StringTableEntry varName, ExprNode *arrayIndex, ExprNode *expr, S32 op ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(AssignOpExprNode); }; @@ -402,8 +399,8 @@ struct TTagSetStmtNode : StmtNode ExprNode *stringExpr; static TTagSetStmtNode *alloc( S32 lineNumber, StringTableEntry tag, ExprNode *valueExpr, ExprNode *stringExpr ); - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); DBG_STMT_TYPE(TTagSetStmtNode); }; @@ -412,8 +409,8 @@ struct TTagDerefNode : ExprNode ExprNode *expr; static TTagDerefNode *alloc( S32 lineNumber, ExprNode *expr ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(TTagDerefNode); }; @@ -423,8 +420,8 @@ struct TTagExprNode : ExprNode StringTableEntry tag; static TTagExprNode *alloc( S32 lineNumber, StringTableEntry tag ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(TTagExprNode); }; @@ -442,8 +439,8 @@ struct FuncCallExprNode : ExprNode }; static FuncCallExprNode *alloc( S32 lineNumber, StringTableEntry funcName, StringTableEntry nameSpace, ExprNode *args, bool dot ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(FuncCallExprNode); }; @@ -455,8 +452,8 @@ struct AssertCallExprNode : ExprNode U32 messageIndex; static AssertCallExprNode *alloc( S32 lineNumber, ExprNode *testExpr, const char *message ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(AssertCallExprNode); }; @@ -475,8 +472,8 @@ struct SlotAccessNode : ExprNode StringTableEntry slotName; static SlotAccessNode *alloc( S32 lineNumber, ExprNode *objectExpr, ExprNode *arrayExpr, StringTableEntry slotName ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(SlotAccessNode); }; @@ -495,8 +492,8 @@ struct InternalSlotAccessNode : ExprNode bool recurse; static InternalSlotAccessNode *alloc( S32 lineNumber, ExprNode *objectExpr, ExprNode *slotExpr, bool recurse ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(InternalSlotAccessNode); }; @@ -509,8 +506,8 @@ struct SlotAssignNode : ExprNode U32 typeID; static SlotAssignNode *alloc( S32 lineNumber, ExprNode *objectExpr, ExprNode *arrayExpr, StringTableEntry slotName, ExprNode *valueExpr, U32 typeID = -1 ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(SlotAssignNode); }; @@ -525,8 +522,8 @@ struct SlotAssignOpNode : ExprNode TypeReq subType; static SlotAssignOpNode *alloc( S32 lineNumber, ExprNode *objectExpr, StringTableEntry slotName, ExprNode *arrayExpr, S32 op, ExprNode *valueExpr ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(SlotAssignOpNode); }; @@ -545,10 +542,10 @@ struct ObjectDeclNode : ExprNode bool isSingleton; static ObjectDeclNode *alloc( S32 lineNumber, ExprNode *classNameExpr, ExprNode *objectNameExpr, ExprNode *argList, StringTableEntry parentObject, SlotAssignNode *slotDecls, ObjectDeclNode *subObjects, bool isDatablock, bool classNameInternal, bool isSingleton ); - U32 precompile(TypeReq type); + U32 precompileSubObject(bool); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); - U32 compileSubObject(U32 *codeStream, U32 ip, bool); + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); + U32 compileSubObject(CodeStream &codeStream, U32 ip, bool); TypeReq getPreferredType(); DBG_STMT_TYPE(ObjectDeclNode); }; @@ -570,18 +567,13 @@ struct FunctionDeclStmtNode : StmtNode U32 argc; static FunctionDeclStmtNode *alloc( S32 lineNumber, StringTableEntry fnName, StringTableEntry nameSpace, VarNode *args, StmtNode *stmts ); - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); void setPackage(StringTableEntry packageName); DBG_STMT_TYPE(FunctionDeclStmtNode); }; extern StmtNode *gStatementList; -extern void createFunction(const char *fnName, VarNode *args, StmtNode *statements); -extern ExprEvalState gEvalState; -extern bool lookupFunction(const char *fnName, VarNode **args, StmtNode **statements); -typedef const char *(*cfunc)(S32 argc, char **argv); -extern bool lookupCFunction(const char *fnName, cfunc *f); - +extern ExprEvalState gEvalState;; #endif diff --git a/Engine/source/console/astAlloc.cpp b/Engine/source/console/astAlloc.cpp index 842429822..19809a1e2 100644 --- a/Engine/source/console/astAlloc.cpp +++ b/Engine/source/console/astAlloc.cpp @@ -149,7 +149,7 @@ StreqExprNode *StreqExprNode::alloc( S32 lineNumber, ExprNode *left, ExprNode *r return ret; } -StrcatExprNode *StrcatExprNode::alloc( S32 lineNumber, ExprNode *left, ExprNode *right, int appendChar ) +StrcatExprNode *StrcatExprNode::alloc( S32 lineNumber, ExprNode *left, ExprNode *right, S32 appendChar ) { StrcatExprNode *ret = (StrcatExprNode *) consoleAlloc(sizeof(StrcatExprNode)); constructInPlace(ret); diff --git a/Engine/source/console/astNodes.cpp b/Engine/source/console/astNodes.cpp index 11cc44f90..666589f6a 100644 --- a/Engine/source/console/astNodes.cpp +++ b/Engine/source/console/astNodes.cpp @@ -45,26 +45,11 @@ struct Token namespace Compiler { - U32 precompileBlock(StmtNode *block, U32 loopCount) - { - U32 sum = 0; - for(StmtNode *walk = block; walk; walk = walk->getNext()) - { - const U32 temp = walk->precompileStmt(loopCount); -#ifdef DEBUG_AST_NODES - if(temp > 1000) - Con::printf("suspect %s '%s' line %d", walk->dbgStmtType().c_str(), walk->dbgFileName, walk->dbgLineNumber); -#endif - sum += temp; - } - return sum; - } - - U32 compileBlock(StmtNode *block, U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint) + U32 compileBlock(StmtNode *block, CodeStream &codeStream, U32 ip) { for(StmtNode *walk = block; walk; walk = walk->getNext()) - ip = walk->compileStmt(codeStream, ip, continuePoint, breakPoint); - return ip; + ip = walk->compileStmt(codeStream, ip); + return codeStream.tell(); } } @@ -72,21 +57,9 @@ using namespace Compiler; //----------------------------------------------------------------------------- -void StmtNode::addBreakCount() +void StmtNode::addBreakLine(CodeStream &code) { - CodeBlock::smBreakLineCount++; -} - -void StmtNode::addBreakLine(U32 ip) -{ - U32 line = CodeBlock::smBreakLineCount * 2; - CodeBlock::smBreakLineCount++; - - if(getBreakCodeBlock()->lineBreakPairs) - { - getBreakCodeBlock()->lineBreakPairs[line] = dbgLineNumber; - getBreakCodeBlock()->lineBreakPairs[line+1] = ip; - } + code.addBreakLine(dbgLineNumber, code.tell()); } //------------------------------------------------------------ @@ -170,85 +143,59 @@ static U32 conversionOp(TypeReq src, TypeReq dst) //------------------------------------------------------------ -U32 BreakStmtNode::precompileStmt(U32 loopCount) +U32 BreakStmtNode::compileStmt(CodeStream &codeStream, U32 ip) { - if(loopCount) + if(codeStream.inLoop()) { - addBreakCount(); - return 2; + addBreakLine(codeStream); + codeStream.emit(OP_JMP); + codeStream.emitFix(CodeStream::FIXTYPE_BREAK); } - Con::warnf(ConsoleLogEntry::General, "%s (%d): break outside of loop... ignoring.", dbgFileName, dbgLineNumber); - return 0; -} - -U32 BreakStmtNode::compileStmt(U32 *codeStream, U32 ip, U32, U32 breakPoint) -{ - if(breakPoint) + else { - addBreakLine(ip); - codeStream[ip++] = OP_JMP; - codeStream[ip++] = breakPoint; + Con::warnf(ConsoleLogEntry::General, "%s (%d): break outside of loop... ignoring.", dbgFileName, dbgLineNumber); } - return ip; + return codeStream.tell(); } //------------------------------------------------------------ -U32 ContinueStmtNode::precompileStmt(U32 loopCount) +U32 ContinueStmtNode::compileStmt(CodeStream &codeStream, U32 ip) { - if(loopCount) + if(codeStream.inLoop()) { - addBreakCount(); - return 2; + addBreakLine(codeStream); + codeStream.emit(OP_JMP); + codeStream.emitFix(CodeStream::FIXTYPE_CONTINUE); } - Con::warnf(ConsoleLogEntry::General, "%s (%d): continue outside of loop... ignoring.", dbgFileName, dbgLineNumber); - return 0; -} - -U32 ContinueStmtNode::compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32) -{ - if(continuePoint) + else { - addBreakLine(ip); - codeStream[ip++] = OP_JMP; - codeStream[ip++] = continuePoint; + Con::warnf(ConsoleLogEntry::General, "%s (%d): continue outside of loop... ignoring.", dbgFileName, dbgLineNumber); } - return ip; + return codeStream.tell(); } //------------------------------------------------------------ -U32 ExprNode::precompileStmt(U32) +U32 ExprNode::compileStmt(CodeStream &codeStream, U32 ip) { - addBreakCount(); - return precompile(TypeReqNone); -} - -U32 ExprNode::compileStmt(U32 *codeStream, U32 ip, U32, U32) -{ - addBreakLine(ip); + addBreakLine(codeStream); return compile(codeStream, ip, TypeReqNone); } //------------------------------------------------------------ -U32 ReturnStmtNode::precompileStmt(U32) +U32 ReturnStmtNode::compileStmt(CodeStream &codeStream, U32 ip) { - addBreakCount(); - return 1 + (expr ? expr->precompile(TypeReqString) : 0); -} - -U32 ReturnStmtNode::compileStmt(U32 *codeStream, U32 ip, U32, U32) -{ - addBreakLine(ip); + addBreakLine(codeStream); if(!expr) - codeStream[ip++] = OP_RETURN_VOID; + codeStream.emit(OP_RETURN_VOID); else { ip = expr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_RETURN; + codeStream.emit(OP_RETURN); } - return ip; + return codeStream.tell(); } //------------------------------------------------------------ @@ -273,87 +220,60 @@ void IfStmtNode::propagateSwitchExpr(ExprNode *left, bool string) ((IfStmtNode *) elseBlock)->propagateSwitchExpr(left, string); } -U32 IfStmtNode::precompileStmt(U32 loopCount) +U32 IfStmtNode::compileStmt(CodeStream &codeStream, U32 ip) { - U32 exprSize; - addBreakCount(); - + U32 start = ip; + U32 endifIp, elseIp; + addBreakLine(codeStream); + if(testExpr->getPreferredType() == TypeReqUInt) { - exprSize = testExpr->precompile(TypeReqUInt); integer = true; } else { - exprSize = testExpr->precompile(TypeReqFloat); integer = false; } - // next is the JMPIFNOT or JMPIFFNOT - size of 2 - U32 ifSize = precompileBlock(ifBlock, loopCount); - if(!elseBlock) - endifOffset = ifSize + 2 + exprSize; - else - { - elseOffset = exprSize + 2 + ifSize + 2; - U32 elseSize = precompileBlock(elseBlock, loopCount); - endifOffset = elseOffset + elseSize; - } - return endifOffset; -} - -U32 IfStmtNode::compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint) -{ - U32 start = ip; - addBreakLine(ip); ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat); - codeStream[ip++] = integer ? OP_JMPIFNOT : OP_JMPIFFNOT; + codeStream.emit(integer ? OP_JMPIFNOT : OP_JMPIFFNOT); if(elseBlock) { - codeStream[ip++] = start + elseOffset; - ip = compileBlock(ifBlock, codeStream, ip, continuePoint, breakPoint); - codeStream[ip++] = OP_JMP; - codeStream[ip++] = start + endifOffset; - ip = compileBlock(elseBlock, codeStream, ip, continuePoint, breakPoint); + elseIp = codeStream.emit(0); + elseOffset = compileBlock(ifBlock, codeStream, ip) + 2; + codeStream.emit(OP_JMP); + endifIp = codeStream.emit(0); + endifOffset = compileBlock(elseBlock, codeStream, ip); + + codeStream.patch(endifIp, endifOffset); + codeStream.patch(elseIp, elseOffset); } else { - codeStream[ip++] = start + endifOffset; - ip = compileBlock(ifBlock, codeStream, ip, continuePoint, breakPoint); + endifIp = codeStream.emit(0); + endifOffset = compileBlock(ifBlock, codeStream, ip); + + codeStream.patch(endifIp, endifOffset); } - return ip; + + // Resolve fixes + return codeStream.tell(); } //------------------------------------------------------------ -U32 LoopStmtNode::precompileStmt(U32 loopCount) +U32 LoopStmtNode::compileStmt(CodeStream &codeStream, U32 ip) { - U32 initSize = 0; - addBreakCount(); - - if(initExpr) - initSize = initExpr->precompile(TypeReqNone); - - U32 testSize; - if(testExpr->getPreferredType() == TypeReqUInt) { integer = true; - testSize = testExpr->precompile(TypeReqUInt); } else { integer = false; - testSize = testExpr->precompile(TypeReqFloat); } - - U32 blockSize = precompileBlock(loopBlock, loopCount + 1); - - U32 endLoopSize = 0; - if(endLoopExpr) - endLoopSize = endLoopExpr->precompile(TypeReqNone); - + // if it's a for loop or a while loop it goes: // initExpr // testExpr @@ -365,7 +285,7 @@ U32 LoopStmtNode::precompileStmt(U32 loopCount) // testExpr // OP_JMPIF loopStartPoint // breakPoint: - + // otherwise if it's a do ... while() it goes: // initExpr // loopStartPoint: @@ -375,25 +295,15 @@ U32 LoopStmtNode::precompileStmt(U32 loopCount) // testExpr // OP_JMPIF loopStartPoint // breakPoint: - - if(!isDoLoop) - { - loopBlockStartOffset = initSize + testSize + 2; - continueOffset = loopBlockStartOffset + blockSize; - breakOffset = continueOffset + endLoopSize + testSize + 2; - } - else - { - loopBlockStartOffset = initSize; - continueOffset = initSize + blockSize; - breakOffset = continueOffset + endLoopSize + testSize + 2; - } - return breakOffset; -} - -U32 LoopStmtNode::compileStmt(U32 *codeStream, U32 ip, U32, U32) -{ - addBreakLine(ip); + + // loopBlockStart == start of loop block + // continue == skip to end + // break == exit loop + + + addBreakLine(codeStream); + codeStream.pushFixScope(true); + U32 start = ip; if(initExpr) ip = initExpr->compile(codeStream, ip, TypeReqNone); @@ -401,30 +311,34 @@ U32 LoopStmtNode::compileStmt(U32 *codeStream, U32 ip, U32, U32) if(!isDoLoop) { ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat); - codeStream[ip++] = integer ? OP_JMPIFNOT : OP_JMPIFFNOT; - codeStream[ip++] = start + breakOffset; + codeStream.emit(integer ? OP_JMPIFNOT : OP_JMPIFFNOT); + codeStream.emitFix(CodeStream::FIXTYPE_BREAK); } // Compile internals of loop. - ip = compileBlock(loopBlock, codeStream, ip, start + continueOffset, start + breakOffset); + loopBlockStartOffset = codeStream.tell(); + continueOffset = compileBlock(loopBlock, codeStream, ip); if(endLoopExpr) ip = endLoopExpr->compile(codeStream, ip, TypeReqNone); ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat); - codeStream[ip++] = integer ? OP_JMPIF : OP_JMPIFF; - codeStream[ip++] = start + loopBlockStartOffset; - - return ip; + codeStream.emit(integer ? OP_JMPIF : OP_JMPIFF); + codeStream.emitFix(CodeStream::FIXTYPE_LOOPBLOCKSTART); + + breakOffset = codeStream.tell(); // exit loop + + codeStream.fixLoop(loopBlockStartOffset, breakOffset, continueOffset); + codeStream.popFixScope(); + + return codeStream.tell(); } //------------------------------------------------------------ -U32 IterStmtNode::precompileStmt( U32 loopCount ) +U32 IterStmtNode::compileStmt( CodeStream &codeStream, U32 ip ) { - addBreakCount(); - // Instruction sequence: // // containerExpr @@ -436,86 +350,66 @@ U32 IterStmtNode::precompileStmt( U32 loopCount ) // .break: // OP_ITER_END // .fail: - - U32 exprSize = containerExpr->precompile( TypeReqString ); - bodySize = precompileBlock( body, loopCount + 1 ); - return - exprSize - + 3 // OP_ITER_BEGIN - + 2 // OP_ITER - + bodySize - + 2 // OP_JMP - + 1 // OP_ITER_END - ; -} - -U32 IterStmtNode::compileStmt( U32* codeStream, U32 ip, U32 continuePoint, U32 breakPoint ) -{ - addBreakLine( ip ); + addBreakLine(codeStream); + + codeStream.pushFixScope(true); const U32 startIp = ip; - const U32 iterBeginIp = containerExpr->compile( codeStream, startIp, TypeReqString ); - - const U32 continueIp = iterBeginIp + 3; - const U32 bodyIp = continueIp + 2; - const U32 jmpIp = bodyIp + bodySize; + containerExpr->compile( codeStream, startIp, TypeReqString ); + + codeStream.emit(isStringIter ? OP_ITER_BEGIN_STR : OP_ITER_BEGIN); + codeStream.emitSTE( varName ); + const U32 finalFix = codeStream.emit(0); + const U32 continueIp = codeStream.emit(OP_ITER); + codeStream.emitFix(CodeStream::FIXTYPE_BREAK); + const U32 bodyIp = codeStream.tell(); + + const U32 jmpIp = compileBlock( body, codeStream, bodyIp); const U32 breakIp = jmpIp + 2; const U32 finalIp = breakIp + 1; - codeStream[ iterBeginIp ] = isStringIter ? OP_ITER_BEGIN_STR : OP_ITER_BEGIN; - codeStream[ iterBeginIp + 1 ] = STEtoU32( varName, iterBeginIp + 1 ); - codeStream[ iterBeginIp + 2 ] = finalIp; - codeStream[ continueIp ] = OP_ITER; - codeStream[ continueIp + 1 ] = breakIp; - - compileBlock( body, codeStream, bodyIp, continueIp, breakIp ); + codeStream.emit(OP_JMP); + codeStream.emitFix(CodeStream::FIXTYPE_CONTINUE); + codeStream.emit(OP_ITER_END); - codeStream[ jmpIp ] = OP_JMP; - codeStream[ jmpIp + 1 ] = continueIp; - codeStream[ breakIp ] = OP_ITER_END; + codeStream.patch(finalFix, finalIp); + codeStream.fixLoop(bodyIp, breakIp, continueIp); + codeStream.popFixScope(); - return finalIp; + return codeStream.tell(); } //------------------------------------------------------------ -U32 ConditionalExprNode::precompile(TypeReq type) +U32 ConditionalExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // code is testExpr // JMPIFNOT falseStart // trueExpr // JMP end // falseExpr - U32 exprSize; - if(testExpr->getPreferredType() == TypeReqUInt) { - exprSize = testExpr->precompile(TypeReqUInt); integer = true; } else { - exprSize = testExpr->precompile(TypeReqFloat); integer = false; } - return exprSize + - trueExpr->precompile(type) + - falseExpr->precompile(type) + 4; -} - -U32 ConditionalExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat); - codeStream[ip++] = integer ? OP_JMPIFNOT : OP_JMPIFFNOT; - U32 jumpElseIp = ip++; + codeStream.emit(integer ? OP_JMPIFNOT : OP_JMPIFFNOT); + + U32 jumpElseIp = codeStream.emit(0); ip = trueExpr->compile(codeStream, ip, type); - codeStream[ip++] = OP_JMP; - U32 jumpEndIp = ip++; - codeStream[jumpElseIp] = ip; + codeStream.emit(OP_JMP); + U32 jumpEndIp = codeStream.emit(0); + codeStream.patch(jumpElseIp, codeStream.tell()); ip = falseExpr->compile(codeStream, ip, type); - codeStream[jumpEndIp] = ip; - return ip; + codeStream.patch(jumpEndIp, codeStream.tell()); + + return codeStream.tell(); } TypeReq ConditionalExprNode::getPreferredType() @@ -525,16 +419,7 @@ TypeReq ConditionalExprNode::getPreferredType() //------------------------------------------------------------ -U32 FloatBinaryExprNode::precompile(TypeReq type) -{ - U32 addSize = left->precompile(TypeReqFloat) + right->precompile(TypeReqFloat) + 1; - if(type != TypeReqFloat) - addSize++; - - return addSize; -} - -U32 FloatBinaryExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) +U32 FloatBinaryExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { ip = right->compile(codeStream, ip, TypeReqFloat); ip = left->compile(codeStream, ip, TypeReqFloat); @@ -554,10 +439,10 @@ U32 FloatBinaryExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) operand = OP_MUL; break; } - codeStream[ip++] = operand; + codeStream.emit(operand); if(type != TypeReqFloat) - codeStream[ip++] =conversionOp(TypeReqFloat, type); - return ip; + codeStream.emit(conversionOp(TypeReqFloat, type)); + return codeStream.tell(); } TypeReq FloatBinaryExprNode::getPreferredType() @@ -623,38 +508,27 @@ void IntBinaryExprNode::getSubTypeOperand() } } -U32 IntBinaryExprNode::precompile(TypeReq type) +U32 IntBinaryExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { getSubTypeOperand(); - U32 addSize = left->precompile(subType) + right->precompile(subType) + 1; - if(operand == OP_OR || operand == OP_AND) - addSize++; - - if(type != TypeReqUInt) - addSize++; - - return addSize; -} - -U32 IntBinaryExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + if(operand == OP_OR || operand == OP_AND) { ip = left->compile(codeStream, ip, subType); - codeStream[ip++] = operand == OP_OR ? OP_JMPIF_NP : OP_JMPIFNOT_NP; - U32 jmpIp = ip++; + codeStream.emit(operand == OP_OR ? OP_JMPIF_NP : OP_JMPIFNOT_NP); + U32 jmpIp = codeStream.emit(0); ip = right->compile(codeStream, ip, subType); - codeStream[jmpIp] = ip; + codeStream.patch(jmpIp, ip); } else { ip = right->compile(codeStream, ip, subType); ip = left->compile(codeStream, ip, subType); - codeStream[ip++] = operand; + codeStream.emit(operand); } if(type != TypeReqUInt) - codeStream[ip++] =conversionOp(TypeReqUInt, type); - return ip; + codeStream.emit(conversionOp(TypeReqUInt, type)); + return codeStream.tell(); } TypeReq IntBinaryExprNode::getPreferredType() @@ -664,32 +538,23 @@ TypeReq IntBinaryExprNode::getPreferredType() //------------------------------------------------------------ -U32 StreqExprNode::precompile(TypeReq type) +U32 StreqExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // eval str left // OP_ADVANCE_STR_NUL // eval str right // OP_COMPARE_STR // optional conversion - U32 addSize = left->precompile(TypeReqString) + right->precompile(TypeReqString) + 2; - if(!eq) - addSize ++; - if(type != TypeReqUInt) - addSize ++; - return addSize; -} - -U32 StreqExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + ip = left->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_ADVANCE_STR_NUL; + codeStream.emit(OP_ADVANCE_STR_NUL); ip = right->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_COMPARE_STR; + codeStream.emit(OP_COMPARE_STR); if(!eq) - codeStream[ip++] = OP_NOT; + codeStream.emit(OP_NOT); if(type != TypeReqUInt) - codeStream[ip++] = conversionOp(TypeReqUInt, type); - return ip; + codeStream.emit(conversionOp(TypeReqUInt, type)); + return codeStream.tell(); } TypeReq StreqExprNode::getPreferredType() @@ -699,34 +564,23 @@ TypeReq StreqExprNode::getPreferredType() //------------------------------------------------------------ -U32 StrcatExprNode::precompile(TypeReq type) -{ - U32 addSize = left->precompile(TypeReqString) + right->precompile(TypeReqString) + 2; - if(appendChar) - addSize++; - - if(type != TypeReqString) - addSize ++; - return addSize; -} - -U32 StrcatExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) +U32 StrcatExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { ip = left->compile(codeStream, ip, TypeReqString); if(!appendChar) - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_ADVANCE_STR); else { - codeStream[ip++] = OP_ADVANCE_STR_APPENDCHAR; - codeStream[ip++] = appendChar; + codeStream.emit(OP_ADVANCE_STR_APPENDCHAR); + codeStream.emit(appendChar); } ip = right->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_REWIND_STR; + codeStream.emit(OP_REWIND_STR); if(type == TypeReqUInt) - codeStream[ip++] = OP_STR_TO_UINT; + codeStream.emit(OP_STR_TO_UINT); else if(type == TypeReqFloat) - codeStream[ip++] = OP_STR_TO_FLT; - return ip; + codeStream.emit(OP_STR_TO_FLT); + return codeStream.tell(); } TypeReq StrcatExprNode::getPreferredType() @@ -736,20 +590,12 @@ TypeReq StrcatExprNode::getPreferredType() //------------------------------------------------------------ -U32 CommaCatExprNode::precompile(TypeReq type) -{ - U32 addSize = left->precompile(TypeReqString) + right->precompile(TypeReqString) + 2; - if(type != TypeReqString) - addSize ++; - return addSize; -} - -U32 CommaCatExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) +U32 CommaCatExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { ip = left->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_ADVANCE_STR_COMMA; + codeStream.emit(OP_ADVANCE_STR_COMMA); ip = right->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_REWIND_STR; + codeStream.emit(OP_REWIND_STR); // At this point the stack has the concatenated string. @@ -757,10 +603,10 @@ U32 CommaCatExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) if(type == TypeReqUInt || type == TypeReqFloat) Con::warnf(ConsoleLogEntry::General, "%s (%d): converting comma string to a number... probably wrong.", dbgFileName, dbgLineNumber); if(type == TypeReqUInt) - codeStream[ip++] = OP_STR_TO_UINT; + codeStream.emit(OP_STR_TO_UINT); else if(type == TypeReqFloat) - codeStream[ip++] = OP_STR_TO_FLT; - return ip; + codeStream.emit(OP_STR_TO_FLT); + return codeStream.tell(); } TypeReq CommaCatExprNode::getPreferredType() @@ -770,30 +616,21 @@ TypeReq CommaCatExprNode::getPreferredType() //------------------------------------------------------------ -U32 IntUnaryExprNode::precompile(TypeReq type) +U32 IntUnaryExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { integer = true; TypeReq prefType = expr->getPreferredType(); if(op == '!' && (prefType == TypeReqFloat || prefType == TypeReqString)) integer = false; - - U32 exprSize = expr->precompile(integer ? TypeReqUInt : TypeReqFloat); - if(type != TypeReqUInt) - return exprSize + 2; - else - return exprSize + 1; -} - -U32 IntUnaryExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + ip = expr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat); if(op == '!') - codeStream[ip++] = integer ? OP_NOT : OP_NOTF; + codeStream.emit(integer ? OP_NOT : OP_NOTF); else if(op == '~') - codeStream[ip++] = OP_ONESCOMPLEMENT; + codeStream.emit(OP_ONESCOMPLEMENT); if(type != TypeReqUInt) - codeStream[ip++] =conversionOp(TypeReqUInt, type); - return ip; + codeStream.emit(conversionOp(TypeReqUInt, type)); + return codeStream.tell(); } TypeReq IntUnaryExprNode::getPreferredType() @@ -803,22 +640,13 @@ TypeReq IntUnaryExprNode::getPreferredType() //------------------------------------------------------------ -U32 FloatUnaryExprNode::precompile(TypeReq type) -{ - U32 exprSize = expr->precompile(TypeReqFloat); - if(type != TypeReqFloat) - return exprSize + 2; - else - return exprSize + 1; -} - -U32 FloatUnaryExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) +U32 FloatUnaryExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { ip = expr->compile(codeStream, ip, TypeReqFloat); - codeStream[ip++] = OP_NEG; + codeStream.emit(OP_NEG); if(type != TypeReqFloat) - codeStream[ip++] =conversionOp(TypeReqFloat, type); - return ip; + codeStream.emit(conversionOp(TypeReqFloat, type)); + return codeStream.tell(); } TypeReq FloatUnaryExprNode::getPreferredType() @@ -828,7 +656,7 @@ TypeReq FloatUnaryExprNode::getPreferredType() //------------------------------------------------------------ -U32 VarNode::precompile(TypeReq type) +U32 VarNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // if this has an arrayIndex... // OP_LOADIMMED_IDENT @@ -838,48 +666,42 @@ U32 VarNode::precompile(TypeReq type) // OP_REWIND_STR // OP_SETCURVAR_ARRAY // OP_LOADVAR (type) - + // else // OP_SETCURVAR // varName // OP_LOADVAR (type) + if(type == TypeReqNone) - return 0; - + return codeStream.tell(); + precompileIdent(varName); - return (arrayIndex ? arrayIndex->precompile(TypeReqString) + 6 : 3); -} -U32 VarNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ - if(type == TypeReqNone) - return ip; - - codeStream[ip++] = arrayIndex ? OP_LOADIMMED_IDENT : OP_SETCURVAR; - codeStream[ip] = STEtoU32(varName, ip); - ip++; + codeStream.emit(arrayIndex ? OP_LOADIMMED_IDENT : OP_SETCURVAR); + codeStream.emitSTE(varName); + if(arrayIndex) { - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_ADVANCE_STR); ip = arrayIndex->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_REWIND_STR; - codeStream[ip++] = OP_SETCURVAR_ARRAY; + codeStream.emit(OP_REWIND_STR); + codeStream.emit(OP_SETCURVAR_ARRAY); } switch(type) { case TypeReqUInt: - codeStream[ip++] = OP_LOADVAR_UINT; + codeStream.emit(OP_LOADVAR_UINT); break; case TypeReqFloat: - codeStream[ip++] = OP_LOADVAR_FLT; + codeStream.emit(OP_LOADVAR_FLT); break; case TypeReqString: - codeStream[ip++] = OP_LOADVAR_STR; + codeStream.emit(OP_LOADVAR_STR); break; case TypeReqNone: break; } - return ip; + return codeStream.tell(); } TypeReq VarNode::getPreferredType() @@ -889,37 +711,31 @@ TypeReq VarNode::getPreferredType() //------------------------------------------------------------ -U32 IntNode::precompile(TypeReq type) +U32 IntNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { - if(type == TypeReqNone) - return 0; if(type == TypeReqString) index = getCurrentStringTable()->addIntString(value); else if(type == TypeReqFloat) index = getCurrentFloatTable()->add(value); - return 2; -} - -U32 IntNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + switch(type) { case TypeReqUInt: - codeStream[ip++] = OP_LOADIMMED_UINT; - codeStream[ip++] = value; + codeStream.emit(OP_LOADIMMED_UINT); + codeStream.emit(value); break; case TypeReqString: - codeStream[ip++] = OP_LOADIMMED_STR; - codeStream[ip++] = index; + codeStream.emit(OP_LOADIMMED_STR); + codeStream.emit(index); break; case TypeReqFloat: - codeStream[ip++] = OP_LOADIMMED_FLT; - codeStream[ip++] = index; + codeStream.emit(OP_LOADIMMED_FLT); + codeStream.emit(index); break; case TypeReqNone: break; } - return ip; + return codeStream.tell(); } TypeReq IntNode::getPreferredType() @@ -929,37 +745,31 @@ TypeReq IntNode::getPreferredType() //------------------------------------------------------------ -U32 FloatNode::precompile(TypeReq type) +U32 FloatNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { - if(type == TypeReqNone) - return 0; if(type == TypeReqString) index = getCurrentStringTable()->addFloatString(value); else if(type == TypeReqFloat) index = getCurrentFloatTable()->add(value); - return 2; -} - -U32 FloatNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + switch(type) { case TypeReqUInt: - codeStream[ip++] = OP_LOADIMMED_UINT; - codeStream[ip++] = U32(value); + codeStream.emit(OP_LOADIMMED_UINT); + codeStream.emit(U32(value)); break; case TypeReqString: - codeStream[ip++] = OP_LOADIMMED_STR; - codeStream[ip++] = index; + codeStream.emit(OP_LOADIMMED_STR); + codeStream.emit(index); break; case TypeReqFloat: - codeStream[ip++] = OP_LOADIMMED_FLT; - codeStream[ip++] = index; + codeStream.emit(OP_LOADIMMED_FLT); + codeStream.emit(index); break; case TypeReqNone: break; } - return ip; + return codeStream.tell(); } TypeReq FloatNode::getPreferredType() @@ -969,38 +779,31 @@ TypeReq FloatNode::getPreferredType() //------------------------------------------------------------ -U32 StrConstNode::precompile(TypeReq type) +U32 StrConstNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // Early out for documentation block. if( doc ) { index = getCurrentStringTable()->add(str, true, tag); - return 2; } - - if(type == TypeReqString) + else if(type == TypeReqString) { index = getCurrentStringTable()->add(str, true, tag); - return 2; } - else if(type == TypeReqNone) + else if (type != TypeReqNone) { - return 0; + fVal = consoleStringToNumber(str, dbgFileName, dbgLineNumber); + if(type == TypeReqFloat) + { + index = getCurrentFloatTable()->add(fVal); + } } - - fVal = consoleStringToNumber(str, dbgFileName, dbgLineNumber); - if(type == TypeReqFloat) - index = getCurrentFloatTable()->add(fVal); - return 2; -} - -U32 StrConstNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + // If this is a DOCBLOCK, then process w/ appropriate op... if( doc ) { - codeStream[ip++] = OP_DOCBLOCK_STR; - codeStream[ip++] = index; + codeStream.emit(OP_DOCBLOCK_STR); + codeStream.emit(index); return ip; } @@ -1008,21 +811,21 @@ U32 StrConstNode::compile(U32 *codeStream, U32 ip, TypeReq type) switch(type) { case TypeReqString: - codeStream[ip++] = tag ? OP_TAG_TO_STR : OP_LOADIMMED_STR; - codeStream[ip++] = index; + codeStream.emit(tag ? OP_TAG_TO_STR : OP_LOADIMMED_STR); + codeStream.emit(index); break; case TypeReqUInt: - codeStream[ip++] = OP_LOADIMMED_UINT; - codeStream[ip++] = U32(fVal); + codeStream.emit(OP_LOADIMMED_UINT); + codeStream.emit(U32(fVal)); break; case TypeReqFloat: - codeStream[ip++] = OP_LOADIMMED_FLT; - codeStream[ip++] = index; + codeStream.emit(OP_LOADIMMED_FLT); + codeStream.emit(index); break; case TypeReqNone: break; } - return ip; + return codeStream.tell(); } TypeReq StrConstNode::getPreferredType() @@ -1032,38 +835,32 @@ TypeReq StrConstNode::getPreferredType() //------------------------------------------------------------ -U32 ConstantNode::precompile(TypeReq type) +U32 ConstantNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { if(type == TypeReqString) { precompileIdent(value); - return 2; } - else if(type == TypeReqNone) - return 0; - - fVal = consoleStringToNumber(value, dbgFileName, dbgLineNumber); - if(type == TypeReqFloat) - index = getCurrentFloatTable()->add(fVal); - return 2; -} - -U32 ConstantNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + else if (type != TypeReqNone) + { + fVal = consoleStringToNumber(value, dbgFileName, dbgLineNumber); + if(type == TypeReqFloat) + index = getCurrentFloatTable()->add(fVal); + } + switch(type) { case TypeReqString: - codeStream[ip++] = OP_LOADIMMED_IDENT; - codeStream[ip] = STEtoU32(value, ip); - ip++; + codeStream.emit(OP_LOADIMMED_IDENT); + codeStream.emitSTE(value); break; case TypeReqUInt: - codeStream[ip++] = OP_LOADIMMED_UINT; - codeStream[ip++] = U32(fVal); + codeStream.emit(OP_LOADIMMED_UINT); + codeStream.emit(U32(fVal)); break; case TypeReqFloat: - codeStream[ip++] = OP_LOADIMMED_FLT; - codeStream[ip++] = index; + codeStream.emit(OP_LOADIMMED_FLT); + codeStream.emit(index); break; case TypeReqNone: break; @@ -1078,7 +875,7 @@ TypeReq ConstantNode::getPreferredType() //------------------------------------------------------------ -U32 AssignExprNode::precompile(TypeReq type) +U32 AssignExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { subType = expr->getPreferredType(); if(subType == TypeReqNone) @@ -1096,65 +893,52 @@ U32 AssignExprNode::precompile(TypeReq type) // OP_SETCURVAR_ARRAY_CREATE // OP_TERMINATE_REWIND_STR // OP_SAVEVAR - + //else // eval expr // OP_SETCURVAR_CREATE // varname // OP_SAVEVAR - const U32 addSize = (type != subType ? 1 : 0); - const U32 retSize = expr->precompile(subType); - -#ifdef DEBUG_AST_NODES - if(retSize > 1000) - Con::printf("Bad expr %s", expr->dbgStmtType().c_str()); -#endif - + precompileIdent(varName); - - return retSize + addSize + (arrayIndex ? arrayIndex->precompile(TypeReqString) + (subType == TypeReqString ? 8 : 6 ) : 3); -} - -U32 AssignExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + ip = expr->compile(codeStream, ip, subType); if(arrayIndex) { if(subType == TypeReqString) - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_ADVANCE_STR); - codeStream[ip++] = OP_LOADIMMED_IDENT; - codeStream[ip] = STEtoU32(varName, ip); - ip++; - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_LOADIMMED_IDENT); + codeStream.emitSTE(varName); + + codeStream.emit(OP_ADVANCE_STR); ip = arrayIndex->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_REWIND_STR; - codeStream[ip++] = OP_SETCURVAR_ARRAY_CREATE; + codeStream.emit(OP_REWIND_STR); + codeStream.emit(OP_SETCURVAR_ARRAY_CREATE); if(subType == TypeReqString) - codeStream[ip++] = OP_TERMINATE_REWIND_STR; + codeStream.emit(OP_TERMINATE_REWIND_STR); } else { - codeStream[ip++] = OP_SETCURVAR_CREATE; - codeStream[ip] = STEtoU32(varName, ip); - ip++; + codeStream.emit(OP_SETCURVAR_CREATE); + codeStream.emitSTE(varName); } switch(subType) { case TypeReqString: - codeStream[ip++] = OP_SAVEVAR_STR; + codeStream.emit(OP_SAVEVAR_STR); break; case TypeReqUInt: - codeStream[ip++] = OP_SAVEVAR_UINT; + codeStream.emit(OP_SAVEVAR_UINT); break; case TypeReqFloat: - codeStream[ip++] = OP_SAVEVAR_FLT; + codeStream.emit(OP_SAVEVAR_FLT); break; case TypeReqNone: break; } if(type != subType) - codeStream[ip++] = conversionOp(subType, type); + codeStream.emit(conversionOp(subType, type)); return ip; } @@ -1212,67 +996,54 @@ static void getAssignOpTypeOp(S32 op, TypeReq &type, U32 &operand) } } -U32 AssignOpExprNode::precompile(TypeReq type) +U32 AssignOpExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { + // goes like this... // eval expr as float or int // if there's an arrayIndex - + // OP_LOADIMMED_IDENT // varName // OP_ADVANCE_STR // eval arrayIndex stringwise // OP_REWIND_STR // OP_SETCURVAR_ARRAY_CREATE - + // else // OP_SETCURVAR_CREATE // varName - + // OP_LOADVAR_FLT or UINT // operand // OP_SAVEVAR_FLT or UINT - + // conversion OP if necessary. getAssignOpTypeOp(op, subType, operand); precompileIdent(varName); - U32 size = expr->precompile(subType); - if(type != subType) - size++; - if(!arrayIndex) - return size + 5; - else - { - size += arrayIndex->precompile(TypeReqString); - return size + 8; - } -} - -U32 AssignOpExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + ip = expr->compile(codeStream, ip, subType); if(!arrayIndex) { - codeStream[ip++] = OP_SETCURVAR_CREATE; - codeStream[ip] = STEtoU32(varName, ip); - ip++; + codeStream.emit(OP_SETCURVAR_CREATE); + codeStream.emitSTE(varName); } else { - codeStream[ip++] = OP_LOADIMMED_IDENT; - codeStream[ip] = STEtoU32(varName, ip); - ip++; - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_LOADIMMED_IDENT); + codeStream.emitSTE(varName); + + codeStream.emit(OP_ADVANCE_STR); ip = arrayIndex->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_REWIND_STR; - codeStream[ip++] = OP_SETCURVAR_ARRAY_CREATE; + codeStream.emit(OP_REWIND_STR); + codeStream.emit(OP_SETCURVAR_ARRAY_CREATE); } - codeStream[ip++] = (subType == TypeReqFloat) ? OP_LOADVAR_FLT : OP_LOADVAR_UINT; - codeStream[ip++] = operand; - codeStream[ip++] = (subType == TypeReqFloat) ? OP_SAVEVAR_FLT : OP_SAVEVAR_UINT; + codeStream.emit((subType == TypeReqFloat) ? OP_LOADVAR_FLT : OP_LOADVAR_UINT); + codeStream.emit(operand); + codeStream.emit((subType == TypeReqFloat) ? OP_SAVEVAR_FLT : OP_SAVEVAR_UINT); if(subType != type) - codeStream[ip++] = conversionOp(subType, type); - return ip; + codeStream.emit(conversionOp(subType, type)); + return codeStream.tell(); } TypeReq AssignOpExprNode::getPreferredType() @@ -1283,25 +1054,14 @@ TypeReq AssignOpExprNode::getPreferredType() //------------------------------------------------------------ -U32 TTagSetStmtNode::precompileStmt(U32 loopCount) -{ - TORQUE_UNUSED(loopCount); - return 0; -} - -U32 TTagSetStmtNode::compileStmt(U32*, U32 ip, U32, U32) +U32 TTagSetStmtNode::compileStmt(CodeStream&, U32 ip) { return ip; } //------------------------------------------------------------ -U32 TTagDerefNode::precompile(TypeReq) -{ - return 0; -} - -U32 TTagDerefNode::compile(U32*, U32 ip, TypeReq) +U32 TTagDerefNode::compile(CodeStream&, U32 ip, TypeReq) { return ip; } @@ -1313,12 +1073,7 @@ TypeReq TTagDerefNode::getPreferredType() //------------------------------------------------------------ -U32 TTagExprNode::precompile(TypeReq) -{ - return 0; -} - -U32 TTagExprNode::compile(U32*, U32 ip, TypeReq) +U32 TTagExprNode::compile(CodeStream&, U32 ip, TypeReq) { return ip; } @@ -1330,48 +1085,38 @@ TypeReq TTagExprNode::getPreferredType() //------------------------------------------------------------ -U32 FuncCallExprNode::precompile(TypeReq type) +U32 FuncCallExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // OP_PUSH_FRAME // arg OP_PUSH arg OP_PUSH arg OP_PUSH // eval all the args, then call the function. - + // OP_CALLFUNC // function // namespace // isDot - - U32 size = 0; - if(type != TypeReqString) - size++; + precompileIdent(funcName); precompileIdent(nameSpace); - for(ExprNode *walk = args; walk; walk = (ExprNode *) walk->getNext()) - size += walk->precompile(TypeReqString) + 1; - return size + 5; -} - -U32 FuncCallExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ - codeStream[ip++] = OP_PUSH_FRAME; + + codeStream.emit(OP_PUSH_FRAME); for(ExprNode *walk = args; walk; walk = (ExprNode *) walk->getNext()) { ip = walk->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_PUSH; + codeStream.emit(OP_PUSH); } if(callType == MethodCall || callType == ParentCall) - codeStream[ip++] = OP_CALLFUNC; + codeStream.emit(OP_CALLFUNC); else - codeStream[ip++] = OP_CALLFUNC_RESOLVE; + codeStream.emit(OP_CALLFUNC_RESOLVE); - codeStream[ip] = STEtoU32(funcName, ip); - ip++; - codeStream[ip] = STEtoU32(nameSpace, ip); - ip++; - codeStream[ip++] = callType; + codeStream.emitSTE(funcName); + codeStream.emitSTE(nameSpace); + + codeStream.emit(callType); if(type != TypeReqString) - codeStream[ip++] = conversionOp(TypeReqString, type); - return ip; + codeStream.emit(conversionOp(TypeReqString, type)); + return codeStream.tell(); } TypeReq FuncCallExprNode::getPreferredType() @@ -1382,33 +1127,19 @@ TypeReq FuncCallExprNode::getPreferredType() //------------------------------------------------------------ -U32 AssertCallExprNode::precompile( TypeReq type ) +U32 AssertCallExprNode::compile( CodeStream &codeStream, U32 ip, TypeReq type ) { #ifdef TORQUE_ENABLE_SCRIPTASSERTS - + messageIndex = getCurrentStringTable()->add( message, true, false ); - - U32 exprSize = testExpr->precompile(TypeReqUInt); - return exprSize + 2; - - #else - - return 0; - - #endif -} - -U32 AssertCallExprNode::compile( U32 *codeStream, U32 ip, TypeReq type ) -{ - #ifdef TORQUE_ENABLE_SCRIPTASSERTS - + ip = testExpr->compile( codeStream, ip, TypeReqUInt ); - codeStream[ip++] = OP_ASSERT; - codeStream[ip++] = messageIndex; + codeStream.emit(OP_ASSERT); + codeStream.emit(messageIndex); #endif - return ip; + return codeStream.tell(); } TypeReq AssertCallExprNode::getPreferredType() @@ -1418,12 +1149,13 @@ TypeReq AssertCallExprNode::getPreferredType() //------------------------------------------------------------ -U32 SlotAccessNode::precompile(TypeReq type) +U32 SlotAccessNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { if(type == TypeReqNone) - return 0; - U32 size = 0; + return ip; + precompileIdent(slotName); + if(arrayExpr) { // eval array @@ -1432,54 +1164,38 @@ U32 SlotAccessNode::precompile(TypeReq type) // OP_TERMINATE_REWIND_STR // OP_SETCURFIELDARRAY // total add of 4 + array precomp - size += 3 + arrayExpr->precompile(TypeReqString); - } - // eval object expression sub + 3 (op_setCurField + OP_SETCUROBJECT) - size += objectExpr->precompile(TypeReqString) + 3; - - // get field in desired type: - return size + 1; -} - -U32 SlotAccessNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ - if(type == TypeReqNone) - return ip; - - if(arrayExpr) - { + ip = arrayExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_ADVANCE_STR); } ip = objectExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_SETCUROBJECT; + codeStream.emit(OP_SETCUROBJECT); - codeStream[ip++] = OP_SETCURFIELD; + codeStream.emit(OP_SETCURFIELD); - codeStream[ip] = STEtoU32(slotName, ip); - ip++; + codeStream.emitSTE(slotName); if(arrayExpr) { - codeStream[ip++] = OP_TERMINATE_REWIND_STR; - codeStream[ip++] = OP_SETCURFIELD_ARRAY; + codeStream.emit(OP_TERMINATE_REWIND_STR); + codeStream.emit(OP_SETCURFIELD_ARRAY); } switch(type) { case TypeReqUInt: - codeStream[ip++] = OP_LOADFIELD_UINT; + codeStream.emit(OP_LOADFIELD_UINT); break; case TypeReqFloat: - codeStream[ip++] = OP_LOADFIELD_FLT; + codeStream.emit(OP_LOADFIELD_FLT); break; case TypeReqString: - codeStream[ip++] = OP_LOADFIELD_STR; + codeStream.emit(OP_LOADFIELD_STR); break; case TypeReqNone: break; } - return ip; + return codeStream.tell(); } TypeReq SlotAccessNode::getPreferredType() @@ -1489,38 +1205,21 @@ TypeReq SlotAccessNode::getPreferredType() //----------------------------------------------------------------------------- -U32 InternalSlotAccessNode::precompile(TypeReq type) -{ - if(type == TypeReqNone) - return 0; - - U32 size = 3; - - // eval object expression sub + 3 (op_setCurField + OP_SETCUROBJECT) - size += objectExpr->precompile(TypeReqString); - size += slotExpr->precompile(TypeReqString); - if(type != TypeReqUInt) - size++; - - // get field in desired type: - return size; -} - -U32 InternalSlotAccessNode::compile(U32 *codeStream, U32 ip, TypeReq type) +U32 InternalSlotAccessNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { if(type == TypeReqNone) return ip; ip = objectExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_SETCUROBJECT; + codeStream.emit(OP_SETCUROBJECT); ip = slotExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_SETCUROBJECT_INTERNAL; - codeStream[ip++] = recurse; + codeStream.emit(OP_SETCUROBJECT_INTERNAL); + codeStream.emit(recurse); if(type != TypeReqUInt) - codeStream[ip++] = conversionOp(TypeReqUInt, type); - return ip; + codeStream.emit(conversionOp(TypeReqUInt, type)); + return codeStream.tell(); } TypeReq InternalSlotAccessNode::getPreferredType() @@ -1530,27 +1229,25 @@ TypeReq InternalSlotAccessNode::getPreferredType() //----------------------------------------------------------------------------- -//------------------------------------------------------------ - -U32 SlotAssignNode::precompile(TypeReq type) +U32 SlotAssignNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // first eval the expression TypeReqString - + // if it's an array: - + // if OP_ADVANCE_STR 1 // eval array - + // OP_ADVANCE_STR 1 // evaluate object expr // OP_SETCUROBJECT 1 // OP_SETCURFIELD 1 // fieldName 1 // OP_TERMINATE_REWIND_STR 1 - + // OP_SETCURFIELDARRAY 1 // OP_TERMINATE_REWIND_STR 1 - + // else // OP_ADVANCE_STR // evaluate object expr @@ -1558,69 +1255,47 @@ U32 SlotAssignNode::precompile(TypeReq type) // OP_SETCURFIELD // fieldName // OP_TERMINATE_REWIND_STR - + // OP_SAVEFIELD // convert to return type if necessary. - - U32 size = 0; - if(type != TypeReqString) - size++; - + precompileIdent(slotName); - - size += valueExpr->precompile(TypeReqString); - - if(objectExpr) - size += objectExpr->precompile(TypeReqString) + 5; - else - size += 5; - - if(arrayExpr) - size += arrayExpr->precompile(TypeReqString) + 3; - - if(typeID != -1) - size += 2; - - return size + 1; -} - -U32 SlotAssignNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + ip = valueExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_ADVANCE_STR); if(arrayExpr) { ip = arrayExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_ADVANCE_STR); } if(objectExpr) { ip = objectExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_SETCUROBJECT; + codeStream.emit(OP_SETCUROBJECT); } else - codeStream[ip++] = OP_SETCUROBJECT_NEW; - codeStream[ip++] = OP_SETCURFIELD; - codeStream[ip] = STEtoU32(slotName, ip); - ip++; + codeStream.emit(OP_SETCUROBJECT_NEW); + codeStream.emit(OP_SETCURFIELD); + codeStream.emitSTE(slotName); + if(arrayExpr) { - codeStream[ip++] = OP_TERMINATE_REWIND_STR; - codeStream[ip++] = OP_SETCURFIELD_ARRAY; + codeStream.emit(OP_TERMINATE_REWIND_STR); + codeStream.emit(OP_SETCURFIELD_ARRAY); } - codeStream[ip++] = OP_TERMINATE_REWIND_STR; - codeStream[ip++] = OP_SAVEFIELD_STR; + codeStream.emit(OP_TERMINATE_REWIND_STR); + codeStream.emit(OP_SAVEFIELD_STR); if(typeID != -1) { - codeStream[ip++] = OP_SETCURFIELD_TYPE; - codeStream[ip++] = typeID; + codeStream.emit(OP_SETCURFIELD_TYPE); + codeStream.emit(typeID); } if(type != TypeReqString) - codeStream[ip++] = conversionOp(TypeReqString, type); - return ip; + codeStream.emit(conversionOp(TypeReqString, type)); + return codeStream.tell(); } TypeReq SlotAssignNode::getPreferredType() @@ -1630,10 +1305,10 @@ TypeReq SlotAssignNode::getPreferredType() //------------------------------------------------------------ -U32 SlotAssignOpNode::precompile(TypeReq type) +U32 SlotAssignOpNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // first eval the expression as its type - + // if it's an array: // eval array // OP_ADVANCE_STR @@ -1643,53 +1318,43 @@ U32 SlotAssignOpNode::precompile(TypeReq type) // fieldName // OP_TERMINATE_REWIND_STR // OP_SETCURFIELDARRAY - + // else // evaluate object expr // OP_SETCUROBJECT // OP_SETCURFIELD // fieldName - + // OP_LOADFIELD of appropriate type // operand // OP_SAVEFIELD of appropriate type // convert to return type if necessary. - + getAssignOpTypeOp(op, subType, operand); precompileIdent(slotName); - U32 size = valueExpr->precompile(subType); - if(type != subType) - size++; - if(arrayExpr) - return size + 9 + arrayExpr->precompile(TypeReqString) + objectExpr->precompile(TypeReqString); - else - return size + 6 + objectExpr->precompile(TypeReqString); -} - -U32 SlotAssignOpNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + ip = valueExpr->compile(codeStream, ip, subType); if(arrayExpr) { ip = arrayExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_ADVANCE_STR); } ip = objectExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_SETCUROBJECT; - codeStream[ip++] = OP_SETCURFIELD; - codeStream[ip] = STEtoU32(slotName, ip); - ip++; + codeStream.emit(OP_SETCUROBJECT); + codeStream.emit(OP_SETCURFIELD); + codeStream.emitSTE(slotName); + if(arrayExpr) { - codeStream[ip++] = OP_TERMINATE_REWIND_STR; - codeStream[ip++] = OP_SETCURFIELD_ARRAY; + codeStream.emit(OP_TERMINATE_REWIND_STR); + codeStream.emit(OP_SETCURFIELD_ARRAY); } - codeStream[ip++] = (subType == TypeReqFloat) ? OP_LOADFIELD_FLT : OP_LOADFIELD_UINT; - codeStream[ip++] = operand; - codeStream[ip++] = (subType == TypeReqFloat) ? OP_SAVEFIELD_FLT : OP_SAVEFIELD_UINT; + codeStream.emit((subType == TypeReqFloat) ? OP_LOADFIELD_FLT : OP_LOADFIELD_UINT); + codeStream.emit(operand); + codeStream.emit((subType == TypeReqFloat) ? OP_SAVEFIELD_FLT : OP_SAVEFIELD_UINT); if(subType != type) - codeStream[ip++] = conversionOp(subType, type); - return ip; + codeStream.emit(conversionOp(subType, type)); + return codeStream.tell(); } TypeReq SlotAssignOpNode::getPreferredType() @@ -1700,10 +1365,10 @@ TypeReq SlotAssignOpNode::getPreferredType() //------------------------------------------------------------ -U32 ObjectDeclNode::precompileSubObject(bool) +U32 ObjectDeclNode::compileSubObject(CodeStream &codeStream, U32 ip, bool root) { // goes - + // OP_PUSHFRAME 1 // name expr // OP_PUSH 1 @@ -1715,98 +1380,69 @@ U32 ObjectDeclNode::precompileSubObject(bool) // isSingleton 1 // lineNumber 1 // fail point 1 - + // for each field, eval // OP_ADD_OBJECT (to UINT[0]) 1 // root? 1 - + // add all the sub objects. // OP_END_OBJECT 1 // root? 1 // To fix the stack issue [7/9/2007 Black] // OP_FINISH_OBJECT <-- fail point jumps to this opcode + + codeStream.emit(OP_PUSH_FRAME); + ip = classNameExpr->compile(codeStream, ip, TypeReqString); + codeStream.emit(OP_PUSH); - U32 argSize = 0; - precompileIdent(parentObject); + ip = objectNameExpr->compile(codeStream, ip, TypeReqString); + codeStream.emit(OP_PUSH); for(ExprNode *exprWalk = argList; exprWalk; exprWalk = (ExprNode *) exprWalk->getNext()) - argSize += exprWalk->precompile(TypeReqString) + 1; - argSize += classNameExpr->precompile(TypeReqString) + 1; + { + ip = exprWalk->compile(codeStream, ip, TypeReqString); + codeStream.emit(OP_PUSH); + } + codeStream.emit(OP_CREATE_OBJECT); + codeStream.emitSTE(parentObject); - U32 nameSize = objectNameExpr->precompile(TypeReqString) + 1; - - U32 slotSize = 0; + codeStream.emit(isDatablock); + codeStream.emit(isClassNameInternal); + codeStream.emit(isSingleton); + codeStream.emit(dbgLineNumber); + const U32 failIp = codeStream.emit(0); for(SlotAssignNode *slotWalk = slotDecls; slotWalk; slotWalk = (SlotAssignNode *) slotWalk->getNext()) - slotSize += slotWalk->precompile(TypeReqNone); - - // OP_ADD_OBJECT - U32 subObjSize = 0; + ip = slotWalk->compile(codeStream, ip, TypeReqNone); + codeStream.emit(OP_ADD_OBJECT); + codeStream.emit(root); for(ObjectDeclNode *objectWalk = subObjects; objectWalk; objectWalk = (ObjectDeclNode *) objectWalk->getNext()) - subObjSize += objectWalk->precompileSubObject(false); - - failOffset = 12 + nameSize + argSize + slotSize + subObjSize; - // +1 because the failOffset should jump to OP_FINISH_OBJECT [7/9/2007 Black] - return failOffset + 1; + ip = objectWalk->compileSubObject(codeStream, ip, false); + codeStream.emit(OP_END_OBJECT); + codeStream.emit(root || isDatablock); + // Added to fix the object creation issue [7/9/2007 Black] + failOffset = codeStream.emit(OP_FINISH_OBJECT); + + codeStream.patch(failIp, failOffset); + + return codeStream.tell(); } -U32 ObjectDeclNode::precompile(TypeReq type) +U32 ObjectDeclNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // root object decl does: - + // push 0 onto the UINT stack OP_LOADIMMED_UINT // precompiles the subObject(true) // UINT stack now has object id // type conv to type - - U32 ret = 2 + precompileSubObject(true); - if(type != TypeReqUInt) - return ret + 1; - return ret; -} - -U32 ObjectDeclNode::compileSubObject(U32 *codeStream, U32 ip, bool root) -{ - U32 start = ip; - codeStream[ip++] = OP_PUSH_FRAME; - ip = classNameExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_PUSH; - - ip = objectNameExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_PUSH; - for(ExprNode *exprWalk = argList; exprWalk; exprWalk = (ExprNode *) exprWalk->getNext()) - { - ip = exprWalk->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_PUSH; - } - codeStream[ip++] = OP_CREATE_OBJECT; - codeStream[ip] = STEtoU32(parentObject, ip); - ip++; - codeStream[ip++] = isDatablock; - codeStream[ip++] = isClassNameInternal; - codeStream[ip++] = isSingleton; - codeStream[ip++] = dbgLineNumber; - codeStream[ip++] = start + failOffset; - for(SlotAssignNode *slotWalk = slotDecls; slotWalk; slotWalk = (SlotAssignNode *) slotWalk->getNext()) - ip = slotWalk->compile(codeStream, ip, TypeReqNone); - codeStream[ip++] = OP_ADD_OBJECT; - codeStream[ip++] = root; - for(ObjectDeclNode *objectWalk = subObjects; objectWalk; objectWalk = (ObjectDeclNode *) objectWalk->getNext()) - ip = objectWalk->compileSubObject(codeStream, ip, false); - codeStream[ip++] = OP_END_OBJECT; - codeStream[ip++] = root || isDatablock; - // Added to fix the object creation issue [7/9/2007 Black] - codeStream[ip++] = OP_FINISH_OBJECT; - return ip; -} - -U32 ObjectDeclNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ - codeStream[ip++] = OP_LOADIMMED_UINT; - codeStream[ip++] = 0; + + codeStream.emit(OP_LOADIMMED_UINT); + codeStream.emit(0); ip = compileSubObject(codeStream, ip, true); if(type != TypeReqUInt) - codeStream[ip++] = conversionOp(TypeReqUInt, type); - return ip; -} + codeStream.emit(conversionOp(TypeReqUInt, type)); + return codeStream.tell(); +} + TypeReq ObjectDeclNode::getPreferredType() { return TypeReqUInt; @@ -1814,7 +1450,7 @@ TypeReq ObjectDeclNode::getPreferredType() //------------------------------------------------------------ -U32 FunctionDeclStmtNode::precompileStmt(U32) +U32 FunctionDeclStmtNode::compileStmt(CodeStream &codeStream, U32 ip) { // OP_FUNC_DECL // func name @@ -1828,10 +1464,13 @@ U32 FunctionDeclStmtNode::precompileStmt(U32) // OP_RETURN_VOID setCurrentStringTable(&getFunctionStringTable()); setCurrentFloatTable(&getFunctionFloatTable()); - + argc = 0; for(VarNode *walk = args; walk; walk = (VarNode *)((StmtNode*)walk)->getNext()) + { + precompileIdent(walk->varName); argc++; + } CodeBlock::smInFunction = true; @@ -1839,44 +1478,36 @@ U32 FunctionDeclStmtNode::precompileStmt(U32) precompileIdent(nameSpace); precompileIdent(package); - U32 subSize = precompileBlock(stmts, 0); CodeBlock::smInFunction = false; - - addBreakCount(); - - setCurrentStringTable(&getGlobalStringTable()); - setCurrentFloatTable(&getGlobalFloatTable()); - - endOffset = argc + subSize + 8; - return endOffset; -} - -U32 FunctionDeclStmtNode::compileStmt(U32 *codeStream, U32 ip, U32, U32) -{ + + U32 start = ip; - codeStream[ip++] = OP_FUNC_DECL; - codeStream[ip] = STEtoU32(fnName, ip); - ip++; - codeStream[ip] = STEtoU32(nameSpace, ip); - ip++; - codeStream[ip] = STEtoU32(package, ip); - ip++; - codeStream[ip++] = U32( bool(stmts != NULL) ? 1 : 0 ) + U32( dbgLineNumber << 1 ); - codeStream[ip++] = start + endOffset; - codeStream[ip++] = argc; + codeStream.emit(OP_FUNC_DECL); + codeStream.emitSTE(fnName); + codeStream.emitSTE(nameSpace); + codeStream.emitSTE(package); + + codeStream.emit(U32( bool(stmts != NULL) ? 1 : 0 ) + U32( dbgLineNumber << 1 )); + const U32 endIp = codeStream.emit(0); + codeStream.emit(argc); for(VarNode *walk = args; walk; walk = (VarNode *)((StmtNode*)walk)->getNext()) { - codeStream[ip] = STEtoU32(walk->varName, ip); - ip++; + codeStream.emitSTE(walk->varName); } CodeBlock::smInFunction = true; - ip = compileBlock(stmts, codeStream, ip, 0, 0); + ip = compileBlock(stmts, codeStream, ip); // Add break so breakpoint can be set at closing brace or // in empty function. - addBreakLine( ip ); + addBreakLine(codeStream); CodeBlock::smInFunction = false; - codeStream[ip++] = OP_RETURN_VOID; + codeStream.emit(OP_RETURN_VOID); + + codeStream.patch(endIp, codeStream.tell()); + + setCurrentStringTable(&getGlobalStringTable()); + setCurrentFloatTable(&getGlobalFloatTable()); + return ip; } diff --git a/Engine/source/console/cmdgram.cpp b/Engine/source/console/cmdgram.cpp index 35ed58bd0..33dc24203 100644 --- a/Engine/source/console/cmdgram.cpp +++ b/Engine/source/console/cmdgram.cpp @@ -2059,12 +2059,6 @@ yydestruct (yymsg, yytype, yyvaluep) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - switch (yytype) - { - - default: - break; - } } diff --git a/Engine/source/console/codeBlock.cpp b/Engine/source/console/codeBlock.cpp index 896d2a4cf..9dec41417 100644 --- a/Engine/source/console/codeBlock.cpp +++ b/Engine/source/console/codeBlock.cpp @@ -33,7 +33,6 @@ using namespace Compiler; bool CodeBlock::smInFunction = false; -U32 CodeBlock::smBreakLineCount = 0; CodeBlock * CodeBlock::smCodeBlockList = NULL; CodeBlock * CodeBlock::smCurrentCodeBlock = NULL; ConsoleParser *CodeBlock::smCurrentParser = NULL; @@ -403,14 +402,14 @@ bool CodeBlock::read(StringTableEntry fileName, Stream &st) for(U32 i = 0; i < size; i++) st.read(&functionFloats[i]); } - U32 codeSize; - st.read(&codeSize); + U32 codeLength; + st.read(&codeLength); st.read(&lineBreakPairCount); - U32 totSize = codeSize + lineBreakPairCount * 2; + U32 totSize = codeLength + lineBreakPairCount * 2; code = new U32[totSize]; - for(i = 0; i < codeSize; i++) + for(i = 0; i < codeLength; i++) { U8 b; st.read(&b); @@ -420,10 +419,10 @@ bool CodeBlock::read(StringTableEntry fileName, Stream &st) code[i] = b; } - for(i = codeSize; i < totSize; i++) + for(i = codeLength; i < totSize; i++) st.read(&code[i]); - lineBreakPairs = code + codeSize; + lineBreakPairs = code + codeLength; // StringTable-ize our identifiers. U32 identCount; @@ -456,6 +455,8 @@ bool CodeBlock::read(StringTableEntry fileName, Stream &st) bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, const char *inScript, bool overrideNoDso) { + AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread"); + // This will return true, but return value is ignored char *script; chompUTF8BOM( inScript, &script ); @@ -464,7 +465,7 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con consoleAllocReset(); - STEtoU32 = compileSTEtoU32; + STEtoCode = compileSTEtoCode; gStatementList = NULL; @@ -497,17 +498,23 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con resetTables(); smInFunction = false; - smBreakLineCount = 0; - setBreakCodeBlock(this); + CodeStream codeStream; + U32 lastIp; if(gStatementList) - codeSize = precompileBlock(gStatementList, 0) + 1; + { + lastIp = compileBlock(gStatementList, codeStream, 0) + 1; + } else + { codeSize = 1; - - lineBreakPairCount = smBreakLineCount; - code = new U32[codeSize + smBreakLineCount * 2]; - lineBreakPairs = code + codeSize; + lastIp = 0; + } + + codeStream.emit(OP_RETURN); + codeStream.emitCodeStream(&codeSize, &code, &lineBreakPairs); + + lineBreakPairCount = codeStream.getNumLineBreaks(); // Write string table data... getGlobalStringTable().write(st); @@ -517,18 +524,10 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con getGlobalFloatTable().write(st); getFunctionFloatTable().write(st); - smBreakLineCount = 0; - U32 lastIp; - if(gStatementList) - lastIp = compileBlock(gStatementList, code, 0, 0, 0); - else - lastIp = 0; - - if(lastIp != codeSize - 1) + if(lastIp != codeSize) Con::errorf(ConsoleLogEntry::General, "CodeBlock::compile - precompile size mismatch, a precompile/compile function pair is probably mismatched."); - - code[lastIp++] = OP_RETURN; - U32 totSize = codeSize + smBreakLineCount * 2; + + U32 totSize = codeSize + codeStream.getNumLineBreaks() * 2; st.write(codeSize); st.write(lineBreakPairCount); @@ -559,13 +558,15 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con } -const char *CodeBlock::compileExec(StringTableEntry fileName, const char *inString, bool noCalls, int setFrame) +const char *CodeBlock::compileExec(StringTableEntry fileName, const char *inString, bool noCalls, S32 setFrame) { + AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread"); + // Check for a UTF8 script file char *string; chompUTF8BOM( inString, &string ); - STEtoU32 = evalSTEtoU32; + STEtoCode = evalSTEtoCode; consoleAllocReset(); name = fileName; @@ -617,12 +618,11 @@ const char *CodeBlock::compileExec(StringTableEntry fileName, const char *inStri resetTables(); smInFunction = false; - smBreakLineCount = 0; - setBreakCodeBlock(this); + + CodeStream codeStream; + U32 lastIp = compileBlock(gStatementList, codeStream, 0); - codeSize = precompileBlock(gStatementList, 0) + 1; - - lineBreakPairCount = smBreakLineCount; + lineBreakPairCount = codeStream.getNumLineBreaks(); globalStrings = getGlobalStringTable().build(); globalStringsMaxLen = getGlobalStringTable().totalLen; @@ -632,20 +632,18 @@ const char *CodeBlock::compileExec(StringTableEntry fileName, const char *inStri globalFloats = getGlobalFloatTable().build(); functionFloats = getFunctionFloatTable().build(); - - code = new U32[codeSize + lineBreakPairCount * 2]; - lineBreakPairs = code + codeSize; - - smBreakLineCount = 0; - U32 lastIp = compileBlock(gStatementList, code, 0, 0, 0); - code[lastIp++] = OP_RETURN; + + codeStream.emit(OP_RETURN); + codeStream.emitCodeStream(&codeSize, &code, &lineBreakPairs); + + //dumpInstructions(0, false); consoleAllocReset(); if(lineBreakPairCount && fileName) calcBreakList(); - if(lastIp != codeSize) + if(lastIp+1 != codeSize) Con::warnf(ConsoleLogEntry::General, "precompile size mismatch, precompile: %d compile: %d", codeSize, lastIp); return exec(0, fileName, NULL, 0, 0, noCalls, NULL, setFrame); @@ -674,7 +672,7 @@ String CodeBlock::getFunctionArgs( U32 ip ) U32 fnArgc = code[ ip + 5 ]; for( U32 i = 0; i < fnArgc; ++ i ) { - StringTableEntry var = U32toSTE( code[ ip + i + 6 ] ); + StringTableEntry var = CodeToSTE(code, ip + (i*2) + 6); if( i != 0 ) str.append( ", " ); @@ -696,41 +694,52 @@ String CodeBlock::getFunctionArgs( U32 ip ) void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) { U32 ip = startIp; + smInFunction = false; + U32 endFuncIp = 0; + while( ip < codeSize ) { + if (ip > endFuncIp) + { + smInFunction = false; + } + switch( code[ ip ++ ] ) { + case OP_FUNC_DECL: { - StringTableEntry fnName = U32toSTE(code[ip]); - StringTableEntry fnNamespace = U32toSTE(code[ip+1]); - StringTableEntry fnPackage = U32toSTE(code[ip+2]); - bool hasBody = bool(code[ip+3]); - U32 newIp = code[ ip + 4 ]; - U32 argc = code[ ip + 5 ]; + StringTableEntry fnName = CodeToSTE(code, ip); + StringTableEntry fnNamespace = CodeToSTE(code, ip+2); + StringTableEntry fnPackage = CodeToSTE(code, ip+4); + bool hasBody = bool(code[ip+6]); + U32 newIp = code[ ip + 7 ]; + U32 argc = code[ ip + 8 ]; + endFuncIp = newIp; Con::printf( "%i: OP_FUNC_DECL name=%s nspace=%s package=%s hasbody=%i newip=%i argc=%i", ip - 1, fnName, fnNamespace, fnPackage, hasBody, newIp, argc ); // Skip args. - ip += 6 + argc; + ip += 9 + (argc * 2); + smInFunction = true; break; } case OP_CREATE_OBJECT: { - StringTableEntry objParent = U32toSTE(code[ip ]); - bool isDataBlock = code[ip + 1]; - bool isInternal = code[ip + 2]; - bool isSingleton = code[ip + 3]; - U32 lineNumber = code[ip + 4]; - U32 failJump = code[ip + 5]; + StringTableEntry objParent = CodeToSTE(code, ip); + bool isDataBlock = code[ip + 2]; + bool isInternal = code[ip + 3]; + bool isSingleton = code[ip + 4]; + U32 lineNumber = code[ip + 5]; + U32 failJump = code[ip + 6]; Con::printf( "%i: OP_CREATE_OBJECT objParent=%s isDataBlock=%i isInternal=%i isSingleton=%i lineNumber=%i failJump=%i", ip - 1, objParent, isDataBlock, isInternal, isSingleton, lineNumber, failJump ); - ip += 6; + ip += 7; break; } @@ -957,19 +966,19 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_SETCURVAR: { - StringTableEntry var = U32toSTE(code[ip]); + StringTableEntry var = CodeToSTE(code, ip); Con::printf( "%i: OP_SETCURVAR var=%s", ip - 1, var ); - ip++; + ip += 2; break; } case OP_SETCURVAR_CREATE: { - StringTableEntry var = U32toSTE(code[ip]); + StringTableEntry var = CodeToSTE(code, ip); Con::printf( "%i: OP_SETCURVAR_CREATE var=%s", ip - 1, var ); - ip++; + ip += 2; break; } @@ -1042,9 +1051,10 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_SETCURFIELD: { - StringTableEntry curField = U32toSTE(code[ip]); + StringTableEntry curField = CodeToSTE(code, ip); Con::printf( "%i: OP_SETCURFIELD field=%s", ip - 1, curField ); - ++ ip; + ip += 2; + break; } case OP_SETCURFIELD_ARRAY: @@ -1161,7 +1171,7 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_LOADIMMED_FLT: { - F64 val = functionFloats[ code[ ip ] ]; + F64 val = (smInFunction ? functionFloats : globalFloats)[ code[ ip ] ]; Con::printf( "%i: OP_LOADIMMED_FLT val=%f", ip - 1, val ); ++ ip; break; @@ -1169,7 +1179,7 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_TAG_TO_STR: { - const char* str = functionStrings + code[ ip ]; + const char* str = (smInFunction ? functionStrings : globalStrings) + code[ ip ]; Con::printf( "%i: OP_TAG_TO_STR str=%s", ip - 1, str ); ++ ip; break; @@ -1177,7 +1187,7 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_LOADIMMED_STR: { - const char* str = functionStrings + code[ ip ]; + const char* str = (smInFunction ? functionStrings : globalStrings) + code[ ip ]; Con::printf( "%i: OP_LOADIMMED_STR str=%s", ip - 1, str ); ++ ip; break; @@ -1185,7 +1195,7 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_DOCBLOCK_STR: { - const char* str = functionStrings + code[ ip ]; + const char* str = (smInFunction ? functionStrings : globalStrings) + code[ ip ]; Con::printf( "%i: OP_DOCBLOCK_STR str=%s", ip - 1, str ); ++ ip; break; @@ -1193,37 +1203,37 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_LOADIMMED_IDENT: { - StringTableEntry str = U32toSTE( code[ ip ] ); + StringTableEntry str = CodeToSTE(code, ip); Con::printf( "%i: OP_LOADIMMED_IDENT str=%s", ip - 1, str ); - ++ ip; + ip += 2; break; } case OP_CALLFUNC_RESOLVE: { - StringTableEntry fnNamespace = U32toSTE(code[ip+1]); - StringTableEntry fnName = U32toSTE(code[ip]); + StringTableEntry fnNamespace = CodeToSTE(code, ip+2); + StringTableEntry fnName = CodeToSTE(code, ip); U32 callType = code[ip+2]; Con::printf( "%i: OP_CALLFUNC_RESOLVE name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace, callType == FuncCallExprNode::FunctionCall ? "FunctionCall" : callType == FuncCallExprNode::MethodCall ? "MethodCall" : "ParentCall" ); - ip += 3; + ip += 5; break; } case OP_CALLFUNC: { - StringTableEntry fnNamespace = U32toSTE(code[ip+1]); - StringTableEntry fnName = U32toSTE(code[ip]); - U32 callType = code[ip+2]; + StringTableEntry fnNamespace = CodeToSTE(code, ip+2); + StringTableEntry fnName = CodeToSTE(code, ip); + U32 callType = code[ip+4]; Con::printf( "%i: OP_CALLFUNC name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace, callType == FuncCallExprNode::FunctionCall ? "FunctionCall" : callType == FuncCallExprNode::MethodCall ? "MethodCall" : "ParentCall" ); - ip += 3; + ip += 5; break; } @@ -1285,7 +1295,7 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_ASSERT: { - const char* message = functionStrings + code[ ip ]; + const char* message = (smInFunction ? functionStrings : globalStrings) + code[ ip ]; Con::printf( "%i: OP_ASSERT message=%s", ip - 1, message ); ++ ip; break; @@ -1299,31 +1309,34 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_ITER_BEGIN: { - StringTableEntry varName = U32toSTE( code[ ip ] ); - U32 failIp = code[ ip + 1 ]; + StringTableEntry varName = CodeToSTE(code, ip); + U32 failIp = code[ ip + 2 ]; - Con::printf( "%i: OP_ITER_BEGIN varName=%s failIp=%i", varName, failIp ); + Con::printf( "%i: OP_ITER_BEGIN varName=%s failIp=%i", ip - 1, varName, failIp ); - ++ ip; + ip += 3; + break; } case OP_ITER_BEGIN_STR: { - StringTableEntry varName = U32toSTE( code[ ip ] ); - U32 failIp = code[ ip + 1 ]; + StringTableEntry varName = CodeToSTE(code, ip); + U32 failIp = code[ ip + 2 ]; - Con::printf( "%i: OP_ITER_BEGIN varName=%s failIp=%i", varName, failIp ); + Con::printf( "%i: OP_ITER_BEGIN varName=%s failIp=%i", ip - 1, varName, failIp ); - ip += 2; + ip += 3; + break; } case OP_ITER: { U32 breakIp = code[ ip ]; - Con::printf( "%i: OP_ITER breakIp=%i", breakIp ); + Con::printf( "%i: OP_ITER breakIp=%i", ip - 1, breakIp ); ++ ip; + break; } case OP_ITER_END: @@ -1337,4 +1350,6 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) break; } } + + smInFunction = false; } diff --git a/Engine/source/console/codeBlock.h b/Engine/source/console/codeBlock.h index 98e581e46..555d7b624 100644 --- a/Engine/source/console/codeBlock.h +++ b/Engine/source/console/codeBlock.h @@ -38,7 +38,6 @@ private: static CodeBlock* smCurrentCodeBlock; public: - static U32 smBreakLineCount; static bool smInFunction; static Compiler::ConsoleParser * smCurrentParser; @@ -129,7 +128,7 @@ public: /// -1 a new frame is created. If the index is out of range the /// top stack frame is used. const char *compileExec(StringTableEntry fileName, const char *script, - bool noCalls, int setFrame = -1 ); + bool noCalls, S32 setFrame = -1 ); /// Executes the existing code in the CodeBlock. The return string is any /// result of the code executed, if any, or an empty string. diff --git a/Engine/source/console/compiledEval.cpp b/Engine/source/console/compiledEval.cpp index 37f621997..7eb5efe24 100644 --- a/Engine/source/console/compiledEval.cpp +++ b/Engine/source/console/compiledEval.cpp @@ -45,6 +45,9 @@ #include "materials/materialManager.h" #endif +// Uncomment to optimize function calls at the expense of potential invalid package lookups +//#define COMPILER_OPTIMIZE_FUNCTION_CALLS + using namespace Compiler; enum EvalConstants { @@ -422,8 +425,8 @@ const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNam if(argv) { // assume this points into a function decl: - U32 fnArgc = code[ip + 5]; - thisFunctionName = U32toSTE(code[ip]); + U32 fnArgc = code[ip + 2 + 6]; + thisFunctionName = CodeToSTE(code, ip); argc = getMin(argc-1, fnArgc); // argv[0] is func name if(gEvalState.traceOn) { @@ -458,11 +461,11 @@ const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNam popFrame = true; for(i = 0; i < argc; i++) { - StringTableEntry var = U32toSTE(code[ip + i + 6]); + StringTableEntry var = CodeToSTE(code, ip + (2 + 6 + 1) + (i * 2)); gEvalState.setCurVarNameCreate(var); gEvalState.setStringVariable(argv[i+1]); } - ip = ip + fnArgc + 6; + ip = ip + (fnArgc * 2) + (2 + 6 + 1); curFloatTable = functionFloats; curStringTable = functionStrings; curStringTableLen = functionStringsMaxLen; @@ -559,11 +562,11 @@ breakContinue: case OP_FUNC_DECL: if(!noCalls) { - fnName = U32toSTE(code[ip]); - fnNamespace = U32toSTE(code[ip+1]); - fnPackage = U32toSTE(code[ip+2]); - bool hasBody = ( code[ ip + 3 ] & 0x01 ) != 0; - U32 lineNumber = code[ ip + 3 ] >> 1; + fnName = CodeToSTE(code, ip); + fnNamespace = CodeToSTE(code, ip+2); + fnPackage = CodeToSTE(code, ip+4); + bool hasBody = ( code[ ip + 6 ] & 0x01 ) != 0; + U32 lineNumber = code[ ip + 6 ] >> 1; Namespace::unlinkPackages(); ns = Namespace::find(fnNamespace, fnPackage); @@ -586,18 +589,18 @@ breakContinue: //Con::printf("Adding function %s::%s (%d)", fnNamespace, fnName, ip); } - ip = code[ip + 4]; + ip = code[ip + 7]; break; case OP_CREATE_OBJECT: { // Read some useful info. - objParent = U32toSTE(code[ip ]); - bool isDataBlock = code[ip + 1]; - bool isInternal = code[ip + 2]; - bool isSingleton = code[ip + 3]; - U32 lineNumber = code[ip + 4]; - failJump = code[ip + 5]; + objParent = CodeToSTE(code, ip); + bool isDataBlock = code[ip + 2]; + bool isInternal = code[ip + 3]; + bool isSingleton = code[ip + 4]; + U32 lineNumber = code[ip + 5]; + failJump = code[ip + 6]; // If we don't allow calls, we certainly don't allow creating objects! // Moved this to after failJump is set. Engine was crashing when @@ -848,7 +851,7 @@ breakContinue: } // Advance the IP past the create info... - ip += 6; + ip += 7; break; } @@ -1170,8 +1173,8 @@ breakContinue: break; case OP_SETCURVAR: - var = U32toSTE(code[ip]); - ip++; + var = CodeToSTE(code, ip); + ip += 2; // If a variable is set, then these must be NULL. It is necessary // to set this here so that the vector parser can appropriately @@ -1190,8 +1193,8 @@ breakContinue: break; case OP_SETCURVAR_CREATE: - var = U32toSTE(code[ip]); - ip++; + var = CodeToSTE(code, ip); + ip += 2; // See OP_SETCURVAR prevField = NULL; @@ -1310,9 +1313,9 @@ breakContinue: // Save the previous field for parsing vector fields. prevField = curField; dStrcpy( prevFieldArray, curFieldArray ); - curField = U32toSTE(code[ip]); + curField = CodeToSTE(code, ip); curFieldArray[0] = 0; - ip++; + ip += 2; break; case OP_SETCURFIELD_ARRAY: @@ -1504,28 +1507,40 @@ breakContinue: break; case OP_LOADIMMED_IDENT: - STR.setStringValue(U32toSTE(code[ip++])); + STR.setStringValue(CodeToSTE(code, ip)); + ip += 2; break; case OP_CALLFUNC_RESOLVE: // This deals with a function that is potentially living in a namespace. - fnNamespace = U32toSTE(code[ip+1]); - fnName = U32toSTE(code[ip]); + fnNamespace = CodeToSTE(code, ip+2); + fnName = CodeToSTE(code, ip); // Try to look it up. ns = Namespace::find(fnNamespace); nsEntry = ns->lookup(fnName); if(!nsEntry) { - ip+= 3; + ip+= 5; Con::warnf(ConsoleLogEntry::General, "%s: Unable to find function %s%s%s", - getFileLine(ip-4), fnNamespace ? fnNamespace : "", + getFileLine(ip-7), fnNamespace ? fnNamespace : "", fnNamespace ? "::" : "", fnName); STR.popFrame(); break; } + +#ifdef COMPILER_OPTIMIZE_FUNCTION_CALLS // Now fall through to OP_CALLFUNC... + // Now, rewrite our code a bit (ie, avoid future lookups) and fall + // through to OP_CALLFUNC +#ifdef TORQUE_CPU_X64 + *((U64*)(code+ip+2)) = ((U64)nsEntry); +#else + code[ip+2] = ((U32)nsEntry); +#endif + code[ip-1] = OP_CALLFUNC; +#endif case OP_CALLFUNC: { @@ -1535,7 +1550,7 @@ breakContinue: // or just on the object. S32 routingId = 0; - fnName = U32toSTE(code[ip]); + fnName = CodeToSTE(code, ip); //if this is called from inside a function, append the ip and codeptr if( gEvalState.getStackDepth() > 0 ) @@ -1544,9 +1559,9 @@ breakContinue: gEvalState.getCurrentFrame().ip = ip - 1; } - U32 callType = code[ip+2]; + U32 callType = code[ip+4]; - ip += 3; + ip += 5; STR.getArgcArgv(fnName, &callArgc, &callArgv); const char *componentReturnValue = ""; @@ -1555,9 +1570,16 @@ breakContinue: { if( !nsEntry ) { - // We must not have come from OP_CALLFUNC_RESOLVE, so figure out - // our own entry. +#ifdef COMPILER_OPTIMIZE_FUNCTION_CALLS +#ifdef TORQUE_CPU_X64 + nsEntry = ((Namespace::Entry *) *((U64*)(code+ip-3))); +#else + nsEntry = ((Namespace::Entry *) *(code+ip-3)); +#endif +#else nsEntry = Namespace::global()->lookup( fnName ); +#endif + ns = NULL; } ns = NULL; } @@ -1618,7 +1640,7 @@ breakContinue: { if(!noCalls && !( routingId == MethodOnComponent ) ) { - Con::warnf(ConsoleLogEntry::General,"%s: Unknown command %s.", getFileLine(ip-4), fnName); + Con::warnf(ConsoleLogEntry::General,"%s: Unknown command %s.", getFileLine(ip-6), fnName); if(callType == FuncCallExprNode::MethodCall) { Con::warnf(ConsoleLogEntry::General, " Object %s(%d) %s", @@ -1652,16 +1674,16 @@ breakContinue: // which is useful behavior when debugging so I'm ifdefing this out for debug builds. if(nsEntry->mToolOnly && ! Con::isCurrentScriptToolScript()) { - Con::errorf(ConsoleLogEntry::Script, "%s: %s::%s - attempting to call tools only function from outside of tools.", getFileLine(ip-4), nsName, fnName); + Con::errorf(ConsoleLogEntry::Script, "%s: %s::%s - attempting to call tools only function from outside of tools.", getFileLine(ip-6), nsName, fnName); } else #endif if((nsEntry->mMinArgs && S32(callArgc) < nsEntry->mMinArgs) || (nsEntry->mMaxArgs && S32(callArgc) > nsEntry->mMaxArgs)) { Con::warnf(ConsoleLogEntry::Script, "%s: %s::%s - wrong number of arguments (got %i, expected min %i and max %i).", - getFileLine(ip-4), nsName, fnName, + getFileLine(ip-6), nsName, fnName, callArgc, nsEntry->mMinArgs, nsEntry->mMaxArgs); - Con::warnf(ConsoleLogEntry::Script, "%s: usage: %s", getFileLine(ip-4), nsEntry->mUsage); + Con::warnf(ConsoleLogEntry::Script, "%s: usage: %s", getFileLine(ip-6), nsEntry->mUsage); STR.popFrame(); } else @@ -1725,7 +1747,7 @@ breakContinue: case Namespace::Entry::VoidCallbackType: nsEntry->cb.mVoidCallbackFunc(gEvalState.thisObject, callArgc, callArgv); if( code[ ip ] != OP_STR_TO_NONE && Con::getBoolVariable( "$Con::warnVoidAssignment", true ) ) - Con::warnf(ConsoleLogEntry::General, "%s: Call to %s in %s uses result of void function call.", getFileLine(ip-4), fnName, functionName); + Con::warnf(ConsoleLogEntry::General, "%s: Call to %s in %s uses result of void function call.", getFileLine(ip-6), fnName, functionName); STR.popFrame(); STR.setStringValue(""); @@ -1844,8 +1866,8 @@ breakContinue: case OP_ITER_BEGIN: { - StringTableEntry varName = U32toSTE( code[ ip ] ); - U32 failIp = code[ ip + 1 ]; + StringTableEntry varName = CodeToSTE(code, ip); + U32 failIp = code[ ip + 2 ]; IterStackRecord& iter = iterStack[ _ITER ]; @@ -1880,7 +1902,7 @@ breakContinue: STR.push(); - ip += 2; + ip += 3; break; } diff --git a/Engine/source/console/compiler.cpp b/Engine/source/console/compiler.cpp index ba8a0c314..49125389f 100644 --- a/Engine/source/console/compiler.cpp +++ b/Engine/source/console/compiler.cpp @@ -60,29 +60,27 @@ namespace Compiler CompilerFloatTable *gCurrentFloatTable, gGlobalFloatTable, gFunctionFloatTable; DataChunker gConsoleAllocator; CompilerIdentTable gIdentTable; - CodeBlock *gCurBreakBlock; //------------------------------------------------------------ - - CodeBlock *getBreakCodeBlock() { return gCurBreakBlock; } - void setBreakCodeBlock(CodeBlock *cb) { gCurBreakBlock = cb; } - - //------------------------------------------------------------ - - U32 evalSTEtoU32(StringTableEntry ste, U32) + void evalSTEtoCode(StringTableEntry ste, U32 ip, U32 *ptr) { - return *((U32 *) &ste); +#ifdef TORQUE_CPU_X64 + *(U64*)(ptr) = (U64)ste; +#else + *ptr = (U32)ste; +#endif } - - U32 compileSTEtoU32(StringTableEntry ste, U32 ip) + + void compileSTEtoCode(StringTableEntry ste, U32 ip, U32 *ptr) { if(ste) getIdentTable().add(ste, ip); - return 0; + *ptr = 0; + *(ptr+1) = 0; } - - U32 (*STEtoU32)(StringTableEntry ste, U32 ip) = evalSTEtoU32; + + void (*STEtoCode)(StringTableEntry ste, U32 ip, U32 *ptr) = evalSTEtoCode; //------------------------------------------------------------ @@ -286,3 +284,131 @@ void CompilerIdentTable::write(Stream &st) st.write(el->ip); } } + +//------------------------------------------------------------------------- + +U8 *CodeStream::allocCode(U32 sz) +{ + U8 *ptr = NULL; + if (mCodeHead) + { + const U32 bytesLeft = BlockSize - mCodeHead->size; + if (bytesLeft > sz) + { + ptr = mCodeHead->data + mCodeHead->size; + mCodeHead->size += sz; + return ptr; + } + } + + CodeData *data = new CodeData; + data->data = (U8*)dMalloc(BlockSize); + data->size = sz; + data->next = NULL; + + if (mCodeHead) + mCodeHead->next = data; + mCodeHead = data; + if (mCode == NULL) + mCode = data; + return data->data; +} + +//------------------------------------------------------------------------- + +void CodeStream::fixLoop(U32 loopBlockStart, U32 breakPoint, U32 continuePoint) +{ + AssertFatal(mFixStack.size() > 0, "Fix stack mismatch"); + + U32 fixStart = mFixStack[mFixStack.size()-1]; + for (U32 i=fixStart; inext) + { + U32 bytesToCopy = itr->size > outBytes ? outBytes : itr->size; + dMemcpy(outPtr, itr->data, bytesToCopy); + outPtr += bytesToCopy; + outBytes -= bytesToCopy; + } + + *lineBreaks = *stream + mCodePos; + dMemcpy(*lineBreaks, mBreakLines.address(), sizeof(U32) * mBreakLines.size()); + + // Apply patches on top + for (U32 i=0; inext : NULL; + while (itr != NULL) + { + CodeData *next = itr->next; + dFree(itr->data); + dFree(itr); + itr = next; + } + + if (mCode) + { + mCode->size = 0; + mCode->next = NULL; + mCodeHead = mCode; + } +} + diff --git a/Engine/source/console/compiler.h b/Engine/source/console/compiler.h index 66e3966b9..fc7f56e8a 100644 --- a/Engine/source/console/compiler.h +++ b/Engine/source/console/compiler.h @@ -24,6 +24,12 @@ #ifndef _COMPILER_H_ #define _COMPILER_H_ +//#define DEBUG_CODESTREAM + +#ifdef DEBUG_CODESTREAM +#include +#endif + class Stream; class DataChunker; @@ -31,6 +37,9 @@ class DataChunker; #include "console/ast.h" #include "console/codeBlock.h" +#ifndef _TVECTOR_H_ +#include "core/util/tVector.h" +#endif namespace Compiler { @@ -49,7 +58,7 @@ namespace Compiler OP_JMPIFF, OP_JMPIF, OP_JMPIFNOT_NP, - OP_JMPIF_NP, + OP_JMPIF_NP, // 10 OP_JMP, OP_RETURN, // fixes a bug when not explicitly returning a value @@ -60,7 +69,7 @@ namespace Compiler OP_CMPLT, OP_CMPLE, OP_CMPNE, - OP_XOR, + OP_XOR, // 20 OP_MOD, OP_BITAND, OP_BITOR, @@ -71,7 +80,7 @@ namespace Compiler OP_SHR, OP_SHL, OP_AND, - OP_OR, + OP_OR, // 30 OP_ADD, OP_SUB, @@ -84,7 +93,7 @@ namespace Compiler OP_SETCURVAR_ARRAY, OP_SETCURVAR_ARRAY_CREATE, - OP_LOADVAR_UINT, + OP_LOADVAR_UINT,// 40 OP_LOADVAR_FLT, OP_LOADVAR_STR, @@ -97,7 +106,7 @@ namespace Compiler OP_SETCUROBJECT_INTERNAL, OP_SETCURFIELD, - OP_SETCURFIELD_ARRAY, + OP_SETCURFIELD_ARRAY, // 50 OP_SETCURFIELD_TYPE, OP_LOADFIELD_UINT, @@ -110,7 +119,7 @@ namespace Compiler OP_STR_TO_UINT, OP_STR_TO_FLT, - OP_STR_TO_NONE, + OP_STR_TO_NONE, // 60 OP_FLT_TO_UINT, OP_FLT_TO_STR, OP_FLT_TO_NONE, @@ -121,7 +130,7 @@ namespace Compiler OP_LOADIMMED_UINT, OP_LOADIMMED_FLT, OP_TAG_TO_STR, - OP_LOADIMMED_STR, + OP_LOADIMMED_STR, // 70 OP_DOCBLOCK_STR, OP_LOADIMMED_IDENT, @@ -133,7 +142,7 @@ namespace Compiler OP_ADVANCE_STR_COMMA, OP_ADVANCE_STR_NUL, OP_REWIND_STR, - OP_TERMINATE_REWIND_STR, + OP_TERMINATE_REWIND_STR, // 80 OP_COMPARE_STR, OP_PUSH, @@ -147,14 +156,14 @@ namespace Compiler OP_ITER, ///< Enter foreach loop. OP_ITER_END, ///< End foreach loop. - OP_INVALID + OP_INVALID // 90 }; //------------------------------------------------------------ F64 consoleStringToNumber(const char *str, StringTableEntry file = 0, U32 line = 0); - U32 precompileBlock(StmtNode *block, U32 loopCount); - U32 compileBlock(StmtNode *block, U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileBlock(StmtNode *block, CodeStream &codeStream, U32 ip); //------------------------------------------------------------ @@ -218,15 +227,19 @@ namespace Compiler //------------------------------------------------------------ - inline StringTableEntry U32toSTE(U32 u) + inline StringTableEntry CodeToSTE(U32 *code, U32 ip) { - return *((StringTableEntry *) &u); +#ifdef TORQUE_CPU_X64 + return (StringTableEntry)(*((U64*)(code+ip))); +#else + return (StringTableEntry)(*(code+ip)); +#endif } - extern U32 (*STEtoU32)(StringTableEntry ste, U32 ip); - - U32 evalSTEtoU32(StringTableEntry ste, U32); - U32 compileSTEtoU32(StringTableEntry ste, U32 ip); + extern void (*STEtoCode)(StringTableEntry ste, U32 ip, U32 *ptr); + + void evalSTEtoCode(StringTableEntry ste, U32 ip, U32 *ptr); + void compileSTEtoCode(StringTableEntry ste, U32 ip, U32 *ptr); CompilerStringTable *getCurrentStringTable(); CompilerStringTable &getGlobalStringTable(); @@ -244,9 +257,6 @@ namespace Compiler void precompileIdent(StringTableEntry ident); - CodeBlock *getBreakCodeBlock(); - void setBreakCodeBlock(CodeBlock *cb); - /// Helper function to reset the float, string, and ident tables to a base /// starting state. void resetTables(); @@ -257,4 +267,170 @@ namespace Compiler extern bool gSyntaxError; }; +/// Utility class to emit and patch bytecode +class CodeStream +{ +public: + + enum FixType + { + // For loops + FIXTYPE_LOOPBLOCKSTART, + FIXTYPE_BREAK, + FIXTYPE_CONTINUE + }; + + enum Constants + { + BlockSize = 16384, + }; + +protected: + + typedef struct PatchEntry + { + U32 addr; ///< Address to patch + U32 value; ///< Value to place at addr + + PatchEntry() {;} + PatchEntry(U32 a, U32 v) : addr(a), value(v) {;} + } PatchEntry; + + typedef struct CodeData + { + U8 *data; ///< Allocated data (size is BlockSize) + U32 size; ///< Bytes used in data + CodeData *next; ///< Next block + }; + + /// @name Emitted code + /// { + CodeData *mCode; + CodeData *mCodeHead; + U32 mCodePos; + /// } + + /// @name Code fixing stacks + /// { + Vector mFixList; + Vector mFixStack; + Vector mFixLoopStack; + Vector mPatchList; + /// } + + Vector mBreakLines; ///< Line numbers + +public: + + CodeStream() : mCode(0), mCodeHead(NULL), mCodePos(0) + { + } + + ~CodeStream() + { + reset(); + + if (mCode) + { + dFree(mCode->data); + delete mCode; + } + } + + U8 *allocCode(U32 sz); + + inline U32 emit(U32 code) + { + U32 *ptr = (U32*)allocCode(4); + *ptr = code; +#ifdef DEBUG_CODESTREAM + printf("code[%u] = %u\n", mCodePos, code); +#endif + return mCodePos++; + } + + inline void patch(U32 addr, U32 code) + { +#ifdef DEBUG_CODESTREAM + printf("patch[%u] = %u\n", addr, code); +#endif + mPatchList.push_back(PatchEntry(addr, code)); + } + + inline U32 emitSTE(const char *code) + { + U64 *ptr = (U64*)allocCode(8); + *ptr = 0; + Compiler::STEtoCode(code, mCodePos, (U32*)ptr); +#ifdef DEBUG_CODESTREAM + printf("code[%u] = %s\n", mCodePos, code); +#endif + mCodePos += 2; + return mCodePos-2; + } + + inline U32 tell() + { + return mCodePos; + } + + inline bool inLoop() + { + for (U32 i=0; i 0, "Fix stack mismatch"); + + U32 newSize = mFixStack[mFixStack.size()-1]; + while (mFixList.size() > newSize) + mFixList.pop_back(); + mFixStack.pop_back(); + mFixLoopStack.pop_back(); + } + + void fixLoop(U32 loopBlockStart, U32 breakPoint, U32 continuePoint); + + inline void addBreakLine(U32 lineNumber, U32 ip) + { + mBreakLines.push_back(lineNumber); + mBreakLines.push_back(ip); + } + + inline U32 getNumLineBreaks() + { + return mBreakLines.size() / 2; + } + + void emitCodeStream(U32 *size, U32 **stream, U32 **lineBreaks); + + void reset(); +}; + #endif diff --git a/Engine/source/console/console.cpp b/Engine/source/console/console.cpp index 0e7099ff2..fa1e8b7e5 100644 --- a/Engine/source/console/console.cpp +++ b/Engine/source/console/console.cpp @@ -248,7 +248,7 @@ static bool active = false; static bool newLogFile; static const char *logFileName; -static const int MaxCompletionBufferSize = 4096; +static const S32 MaxCompletionBufferSize = 4096; static char completionBuffer[MaxCompletionBufferSize]; static char tabBuffer[MaxCompletionBufferSize] = {0}; static SimObjectPtr tabObject; @@ -1313,8 +1313,9 @@ const char *getFormattedData(S32 type, const char *data, const EnumTable *tbl, B Con::setData(type, variable, 0, 1, &data, tbl, flag); const char* formattedVal = Con::getData(type, variable, 0, tbl, flag); - char* returnBuffer = Con::getReturnBuffer(2048); - dSprintf(returnBuffer, 2048, "%s\0", formattedVal ); + static const U32 bufSize = 2048; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%s\0", formattedVal ); cbt->deleteNativeVariable(variable); diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index 3c5718c48..5d530f01a 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -182,7 +182,8 @@ namespace Con /// 09/12/07 - CAF - 43->44 remove newmsg operator /// 09/27/07 - RDB - 44->45 Patch from Andreas Kirsch: Added opcode to support correct void return /// 01/13/09 - TMS - 45->46 Added script assert - DSOVersion = 46, + /// 09/07/14 - jamesu - 46->47 64bit support + DSOVersion = 47, MaxLineLength = 512, ///< Maximum length of a line of console input. MaxDataTypes = 256 ///< Maximum number of registered data types. @@ -696,7 +697,7 @@ namespace Con extern void expandEscape(char *dest, const char *src); extern bool collapseEscape(char *buf); -extern S32 HashPointer(StringTableEntry ptr); +extern U32 HashPointer(StringTableEntry ptr); /// Extended information about a console function. diff --git a/Engine/source/console/consoleDoc.cpp b/Engine/source/console/consoleDoc.cpp index 1170b256d..41c5e8027 100644 --- a/Engine/source/console/consoleDoc.cpp +++ b/Engine/source/console/consoleDoc.cpp @@ -223,7 +223,7 @@ void Namespace::printNamespaceEntries(Namespace * g, bool dumpScript, bool dumpE // Iterate through the methods of the namespace... for(Entry *ewalk = g->mEntryList; ewalk; ewalk = ewalk->mNext) { - int eType = ewalk->mType; + S32 eType = ewalk->mType; const char * funcName = ewalk->mFunctionName; if( ( eType == Entry::ConsoleFunctionType ) && !dumpScript ) diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index 537f583ba..2dea93f44 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -75,7 +75,8 @@ DefineConsoleFunction( strformat, const char*, ( const char* format, const char* "@ingroup Strings\n" "@see http://en.wikipedia.org/wiki/Printf" ) { - char* pBuffer = Con::getReturnBuffer(64); + static const U32 bufSize = 64; + char* pBuffer = Con::getReturnBuffer(bufSize); const char *pch = format; pBuffer[0] = '\0'; @@ -99,7 +100,7 @@ DefineConsoleFunction( strformat, const char*, ( const char* format, const char* case 'u': case 'x': case 'X': - dSprintf( pBuffer, 64, format, dAtoi( value ) ); + dSprintf( pBuffer, bufSize, format, dAtoi( value ) ); break; case 'e': @@ -107,7 +108,7 @@ DefineConsoleFunction( strformat, const char*, ( const char* format, const char* case 'f': case 'g': case 'G': - dSprintf( pBuffer, 64, format, dAtof( value ) ); + dSprintf( pBuffer, bufSize, format, dAtof( value ) ); break; default: @@ -259,7 +260,7 @@ DefineConsoleFunction( strstr, S32, ( const char* string, const char* substring //----------------------------------------------------------------------------- -DefineConsoleFunction( strpos, S32, ( const char* haystack, const char* needle, int offset ), ( 0 ), +DefineConsoleFunction( strpos, S32, ( const char* haystack, const char* needle, S32 offset ), ( 0 ), "Find the start of @a needle in @a haystack searching from left to right beginning at the given offset.\n" "@param haystack The string to search.\n" "@param needle The string to search for.\n" @@ -479,7 +480,7 @@ DefineConsoleFunction( strreplace, const char*, ( const char* source, const char if(!scan) { dStrcpy(ret + dstp, source + scanp); - return ret; + break; } U32 len = scan - (source + scanp); dStrncpy(ret + dstp, source + scanp, len); @@ -1588,6 +1589,13 @@ DefineEngineFunction( displaySplashWindow, bool, (const char* path), ("art/gui/s return Platform::displaySplashWindow(path); } +DefineEngineFunction( closeSplashWindow, void, (),, + "Close our startup splash window.\n\n" + "@note This is currently only implemented on Windows.\n\n" + "@ingroup Platform" ) +{ + Platform::closeSplashWindow(); +} //----------------------------------------------------------------------------- DefineEngineFunction( getWebDeployment, bool, (),, diff --git a/Engine/source/console/consoleInternal.cpp b/Engine/source/console/consoleInternal.cpp index 250326460..2e91da6d7 100644 --- a/Engine/source/console/consoleInternal.cpp +++ b/Engine/source/console/consoleInternal.cpp @@ -262,9 +262,9 @@ void Dictionary::deleteVariables(const char *varString) } } -S32 HashPointer(StringTableEntry ptr) +U32 HashPointer(StringTableEntry ptr) { - return (S32)(((dsize_t)ptr) >> 2); + return (U32)(((dsize_t)ptr) >> 2); } Dictionary::Entry *Dictionary::lookup(StringTableEntry name) diff --git a/Engine/source/console/consoleInternal.h b/Engine/source/console/consoleInternal.h index 0a9c9060e..07c336d98 100644 --- a/Engine/source/console/consoleInternal.h +++ b/Engine/source/console/consoleInternal.h @@ -311,6 +311,8 @@ public: // NOTE: This is protected to ensure no one outside // of this structure is messing with it. + friend class Dictionary; + #pragma warning( push ) #pragma warning( disable : 4201 ) // warning C4201: nonstandard extension used : nameless struct/union diff --git a/Engine/source/console/consoleLogger.cpp b/Engine/source/console/consoleLogger.cpp index aedc9baab..ec3408001 100644 --- a/Engine/source/console/consoleLogger.cpp +++ b/Engine/source/console/consoleLogger.cpp @@ -175,7 +175,7 @@ bool ConsoleLogger::detach() mStream.close(); // Remove this object from the list of active loggers - for( int i = 0; i < mActiveLoggers.size(); i++ ) + for( S32 i = 0; i < mActiveLoggers.size(); i++ ) { if( mActiveLoggers[i] == this ) { diff --git a/Engine/source/console/consoleTypes.cpp b/Engine/source/console/consoleTypes.cpp index a948686a4..5f0abcbb6 100644 --- a/Engine/source/console/consoleTypes.cpp +++ b/Engine/source/console/consoleTypes.cpp @@ -29,6 +29,7 @@ #include "core/color.h" #include "console/simBase.h" #include "math/mRect.h" +#include "core/strings/stringUnit.h" //----------------------------------------------------------------------------- // TypeString @@ -288,8 +289,9 @@ ImplementConsoleTypeCasters( TypeS8, S8 ) ConsoleGetType( TypeS8 ) { - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%d", *((U8 *) dptr) ); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%d", *((U8 *) dptr) ); return returnBuffer; } @@ -309,8 +311,9 @@ ImplementConsoleTypeCasters(TypeS32, S32) ConsoleGetType( TypeS32 ) { - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%d", *((S32 *) dptr) ); + static const U32 bufSize = 512; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%d", *((S32 *) dptr) ); return returnBuffer; } @@ -388,8 +391,9 @@ ImplementConsoleTypeCasters(TypeF32, F32) ConsoleGetType( TypeF32 ) { - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%g", *((F32 *) dptr) ); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%g", *((F32 *) dptr) ); return returnBuffer; } ConsoleSetType( TypeF32 ) @@ -486,8 +490,9 @@ ImplementConsoleTypeCasters( TypeBoolVector, Vector< bool > ) ConsoleGetType( TypeBoolVector ) { Vector *vec = (Vector*)dptr; - char* returnBuffer = Con::getReturnBuffer(1024); - S32 maxReturn = 1024; + static const U32 bufSize = 1024; + char* returnBuffer = Con::getReturnBuffer(bufSize); + S32 maxReturn = bufSize; returnBuffer[0] = '\0'; S32 returnLeng = 0; for (Vector::iterator itr = vec->begin(); itr < vec->end(); itr++) @@ -567,9 +572,20 @@ ImplementConsoleTypeCasters( TypeColorF, ColorF ) ConsoleGetType( TypeColorF ) { - ColorF * color = (ColorF*)dptr; - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%g %g %g %g", color->red, color->green, color->blue, color->alpha); + // Fetch color. + const ColorF* color = (ColorF*)dptr; + + // Fetch stock color name. + StringTableEntry colorName = StockColor::name( *color ); + + // Write as color name if was found. + if ( colorName != StringTable->EmptyString() ) + return colorName; + + // Format as color components. + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%g %g %g %g", color->red, color->green, color->blue, color->alpha); return(returnBuffer); } @@ -578,6 +594,22 @@ ConsoleSetType( TypeColorF ) ColorF *tmpColor = (ColorF *) dptr; if(argc == 1) { + // Is only a single argument passed? + if ( StringUnit::getUnitCount( argv[0], " " ) == 1 ) + { + // Is this a stock color name? + if ( !StockColor::isColor(argv[0]) ) + { + // No, so warn. + Con::warnf( "TypeColorF() - Invalid single argument of '%s' could not be interpreted as a stock color name. Using default.", argv[0] ); + } + + // Set stock color (if it's invalid we'll get the default. + tmpColor->set( argv[0] ); + + return; + } + tmpColor->set(0, 0, 0, 1); F32 r,g,b,a; S32 args = dSscanf(argv[0], "%g %g %g %g", &r, &g, &b, &a); @@ -602,7 +634,7 @@ ConsoleSetType( TypeColorF ) tmpColor->alpha = dAtof(argv[3]); } else - Con::printf("Color must be set as { r, g, b [,a] }"); + Con::printf("Color must be set as { r, g, b [,a] }, { r g b [b] } or { stockColorName }"); } //----------------------------------------------------------------------------- @@ -613,9 +645,20 @@ ImplementConsoleTypeCasters( TypeColorI, ColorI ) ConsoleGetType( TypeColorI ) { - ColorI *color = (ColorI *) dptr; - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%d %d %d %d", color->red, color->green, color->blue, color->alpha); + // Fetch color. + ColorI* color = (ColorI*)dptr; + + // Fetch stock color name. + StringTableEntry colorName = StockColor::name( *color ); + + // Write as color name if was found. + if ( colorName != StringTable->EmptyString() ) + return colorName; + + // Format as color components. + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%d %d %d %d", color->red, color->green, color->blue, color->alpha); return returnBuffer; } @@ -624,6 +667,22 @@ ConsoleSetType( TypeColorI ) ColorI *tmpColor = (ColorI *) dptr; if(argc == 1) { + // Is only a single argument passed? + if ( StringUnit::getUnitCount( argv[0], " " ) == 1 ) + { + // Is this a stock color name? + if ( !StockColor::isColor(argv[0]) ) + { + // No, so warn. + Con::warnf( "TypeColorF() - Invalid single argument of '%s' could not be interpreted as a stock color name. Using default.", argv[0] ); + } + + // Set stock color (if it's invalid we'll get the default. + tmpColor->set( argv[0] ); + + return; + } + tmpColor->set(0, 0, 0, 255); S32 r,g,b,a; S32 args = dSscanf(argv[0], "%d %d %d %d", &r, &g, &b, &a); @@ -648,7 +707,7 @@ ConsoleSetType( TypeColorI ) tmpColor->alpha = dAtoi(argv[3]); } else - Con::printf("Color must be set as { r, g, b [,a] }"); + Con::printf("Color must be set as { r, g, b [,a] }, { r g b [b] } or { stockColorName }"); } //----------------------------------------------------------------------------- @@ -670,8 +729,9 @@ ConsoleSetType( TypeSimObjectName ) ConsoleGetType( TypeSimObjectName ) { SimObject **obj = (SimObject**)dptr; - char* returnBuffer = Con::getReturnBuffer(128); - dSprintf(returnBuffer, 128, "%s", *obj && (*obj)->getName() ? (*obj)->getName() : ""); + static const U32 bufSize = 128; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%s", *obj && (*obj)->getName() ? (*obj)->getName() : ""); return returnBuffer; } @@ -738,8 +798,9 @@ ConsoleType( int, TypeTerrainMaterialIndex, S32 ) ConsoleGetType( TypeTerrainMaterialIndex ) { - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%d", *((S32 *) dptr) ); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%d", *((S32 *) dptr) ); return returnBuffer; } @@ -800,8 +861,9 @@ ConsoleType( RectF, TypeRectUV, RectF ) ConsoleGetType( TypeRectUV ) { RectF *rect = (RectF *) dptr; - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%g %g %g %g", rect->point.x, rect->point.y, + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%g %g %g %g", rect->point.x, rect->point.y, rect->extent.x, rect->extent.y); return returnBuffer; } diff --git a/Engine/source/console/consoleXMLExport.cpp b/Engine/source/console/consoleXMLExport.cpp index f6764ac77..1b498a089 100644 --- a/Engine/source/console/consoleXMLExport.cpp +++ b/Engine/source/console/consoleXMLExport.cpp @@ -255,7 +255,7 @@ namespace Con { mXML->pushNewElement("EnumTables"); // write out the used EnumTables - for (int i = 0; i < enumTables.size(); i++) + for (S32 i = 0; i < enumTables.size(); i++) { mXML->pushNewElement("EnumTable"); @@ -267,7 +267,7 @@ namespace Con { mXML->pushNewElement("Enums"); - for (int j = 0; j < table->size; j++) + for (S32 j = 0; j < table->size; j++) { mXML->pushNewElement("Enum"); diff --git a/Engine/source/console/dynamicTypes.h b/Engine/source/console/dynamicTypes.h index a10ab0def..105b2f1ef 100644 --- a/Engine/source/console/dynamicTypes.h +++ b/Engine/source/console/dynamicTypes.h @@ -211,8 +211,9 @@ class BitfieldConsoleBaseType : public ConsoleBaseType virtual const char* getData( void* dptr, const EnumTable*, BitSet32 ) { - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "0x%08x", *((S32 *) dptr) ); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "0x%08x", *((S32 *) dptr) ); return returnBuffer; } virtual void setData( void* dptr, S32 argc, const char** argv, const EnumTable*, BitSet32 ) diff --git a/Engine/source/console/engineAPI.h b/Engine/source/console/engineAPI.h index 4358844b4..2923c8bb4 100644 --- a/Engine/source/console/engineAPI.h +++ b/Engine/source/console/engineAPI.h @@ -76,6 +76,7 @@ // Disable some VC warnings that are irrelevant to us. +#pragma warning( push ) #pragma warning( disable : 4510 ) // default constructor could not be generated; all the Args structures are never constructed by us #pragma warning( disable : 4610 ) // can never be instantiated; again Args is never constructed by us @@ -1383,14 +1384,14 @@ struct _EngineConsoleThunkCountArgs // Encapsulation of a legacy console function invocation. -template< int startArgc, typename T > +template< S32 startArgc, typename T > struct _EngineConsoleThunk {}; -template< int startArgc, typename R > +template< S32 startArgc, typename R > struct _EngineConsoleThunk< startArgc, R() > { typedef typename _EngineConsoleThunkType< R >::ReturnType ReturnType; - static const int NUM_ARGS = 0; + static const S32 NUM_ARGS = 0; static ReturnType thunk( S32 argc, const char** argv, R ( *fn )(), const _EngineFunctionDefaultArguments< void() >& ) { return _EngineConsoleThunkReturnValue( fn() ); @@ -1401,11 +1402,11 @@ struct _EngineConsoleThunk< startArgc, R() > return _EngineConsoleThunkReturnValue( ( frame->*fn )() ); } }; -template< int startArgc > +template< S32 startArgc > struct _EngineConsoleThunk< startArgc, void() > { typedef void ReturnType; - static const int NUM_ARGS = 0; + static const S32 NUM_ARGS = 0; static void thunk( S32 argc, const char** argv, void ( *fn )(), const _EngineFunctionDefaultArguments< void() >& ) { fn(); @@ -1417,11 +1418,11 @@ struct _EngineConsoleThunk< startArgc, void() > } }; -template< int startArgc, typename R, typename A > +template< S32 startArgc, typename R, typename A > struct _EngineConsoleThunk< startArgc, R( A ) > { typedef typename _EngineConsoleThunkType< R >::ReturnType ReturnType; - static const int NUM_ARGS = 1 + startArgc; + static const S32 NUM_ARGS = 1 + startArgc; static ReturnType thunk( S32 argc, const char** argv, R ( *fn )( A ), const _EngineFunctionDefaultArguments< void( A ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1434,11 +1435,11 @@ struct _EngineConsoleThunk< startArgc, R( A ) > return _EngineConsoleThunkReturnValue( ( frame->*fn )( a ) ); } }; -template< int startArgc, typename A > +template< S32 startArgc, typename A > struct _EngineConsoleThunk< startArgc, void( A ) > { typedef void ReturnType; - static const int NUM_ARGS = 1 + startArgc; + static const S32 NUM_ARGS = 1 + startArgc; static void thunk( S32 argc, const char** argv, void ( *fn )( A ), const _EngineFunctionDefaultArguments< void( A ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1452,11 +1453,11 @@ struct _EngineConsoleThunk< startArgc, void( A ) > } }; -template< int startArgc, typename R, typename A, typename B > +template< S32 startArgc, typename R, typename A, typename B > struct _EngineConsoleThunk< startArgc, R( A, B ) > { typedef typename _EngineConsoleThunkType< R >::ReturnType ReturnType; - static const int NUM_ARGS = 2 + startArgc; + static const S32 NUM_ARGS = 2 + startArgc; static ReturnType thunk( S32 argc, const char** argv, R ( *fn )( A, B ), const _EngineFunctionDefaultArguments< void( A, B ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1471,11 +1472,11 @@ struct _EngineConsoleThunk< startArgc, R( A, B ) > return _EngineConsoleThunkReturnValue( ( frame->*fn )( a, b ) ); } }; -template< int startArgc, typename A, typename B > +template< S32 startArgc, typename A, typename B > struct _EngineConsoleThunk< startArgc, void( A, B ) > { typedef void ReturnType; - static const int NUM_ARGS = 2 + startArgc; + static const S32 NUM_ARGS = 2 + startArgc; static void thunk( S32 argc, const char** argv, void ( *fn )( A, B ), const _EngineFunctionDefaultArguments< void( A, B ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1491,11 +1492,11 @@ struct _EngineConsoleThunk< startArgc, void( A, B ) > } }; -template< int startArgc, typename R, typename A, typename B, typename C > +template< S32 startArgc, typename R, typename A, typename B, typename C > struct _EngineConsoleThunk< startArgc, R( A, B, C ) > { typedef typename _EngineConsoleThunkType< R >::ReturnType ReturnType; - static const int NUM_ARGS = 3 + startArgc; + static const S32 NUM_ARGS = 3 + startArgc; static ReturnType thunk( S32 argc, const char** argv, R ( *fn )( A, B, C ), const _EngineFunctionDefaultArguments< void( A, B, C ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1512,11 +1513,11 @@ struct _EngineConsoleThunk< startArgc, R( A, B, C ) > return _EngineConsoleThunkReturnValue( ( frame->*fn )( a, b, c ) ); } }; -template< int startArgc, typename A, typename B, typename C > +template< S32 startArgc, typename A, typename B, typename C > struct _EngineConsoleThunk< startArgc, void( A, B, C ) > { typedef void ReturnType; - static const int NUM_ARGS = 3 + startArgc; + static const S32 NUM_ARGS = 3 + startArgc; static void thunk( S32 argc, const char** argv, void ( *fn )( A, B, C ), const _EngineFunctionDefaultArguments< void( A, B, C ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1534,11 +1535,11 @@ struct _EngineConsoleThunk< startArgc, void( A, B, C ) > } }; -template< int startArgc, typename R, typename A, typename B, typename C, typename D > +template< S32 startArgc, typename R, typename A, typename B, typename C, typename D > struct _EngineConsoleThunk< startArgc, R( A, B, C, D ) > { typedef typename _EngineConsoleThunkType< R >::ReturnType ReturnType; - static const int NUM_ARGS = 4 + startArgc; + static const S32 NUM_ARGS = 4 + startArgc; static ReturnType thunk( S32 argc, const char** argv, R ( *fn )( A, B, C, D ), const _EngineFunctionDefaultArguments< void( A, B, C, D ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1557,11 +1558,11 @@ struct _EngineConsoleThunk< startArgc, R( A, B, C, D ) > return _EngineConsoleThunkReturnValue( ( frame->*fn )( a, b, c, d ) ); } }; -template< int startArgc, typename A, typename B, typename C, typename D > +template< S32 startArgc, typename A, typename B, typename C, typename D > struct _EngineConsoleThunk< startArgc, void( A, B, C, D ) > { typedef void ReturnType; - static const int NUM_ARGS = 4 + startArgc; + static const S32 NUM_ARGS = 4 + startArgc; static void thunk( S32 argc, const char** argv, void ( *fn )( A, B, C, D ), const _EngineFunctionDefaultArguments< void( A, B, C, D ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1581,11 +1582,11 @@ struct _EngineConsoleThunk< startArgc, void( A, B, C, D ) > } }; -template< int startArgc, typename R, typename A, typename B, typename C, typename D, typename E > +template< S32 startArgc, typename R, typename A, typename B, typename C, typename D, typename E > struct _EngineConsoleThunk< startArgc, R( A, B, C, D, E ) > { typedef typename _EngineConsoleThunkType< R >::ReturnType ReturnType; - static const int NUM_ARGS = 5 + startArgc; + static const S32 NUM_ARGS = 5 + startArgc; static ReturnType thunk( S32 argc, const char** argv, R ( *fn )( A, B, C, D, E ), const _EngineFunctionDefaultArguments< void( A, B, C, D, E ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1606,11 +1607,11 @@ struct _EngineConsoleThunk< startArgc, R( A, B, C, D, E ) > return _EngineConsoleThunkReturnValue( ( frame->*fn )( a, b, c, d, e ) ); } }; -template< int startArgc, typename A, typename B, typename C, typename D, typename E > +template< S32 startArgc, typename A, typename B, typename C, typename D, typename E > struct _EngineConsoleThunk< startArgc, void( A, B, C, D, E ) > { typedef void ReturnType; - static const int NUM_ARGS = 5 + startArgc; + static const S32 NUM_ARGS = 5 + startArgc; static void thunk( S32 argc, const char** argv, void ( *fn )( A, B, C, D, E ), const _EngineFunctionDefaultArguments< void( A, B, C, D, E ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1632,11 +1633,11 @@ struct _EngineConsoleThunk< startArgc, void( A, B, C, D, E ) > } }; -template< int startArgc, typename R, typename A, typename B, typename C, typename D, typename E, typename F > +template< S32 startArgc, typename R, typename A, typename B, typename C, typename D, typename E, typename F > struct _EngineConsoleThunk< startArgc, R( A, B, C, D, E, F ) > { typedef typename _EngineConsoleThunkType< R >::ReturnType ReturnType; - static const int NUM_ARGS = 6 + startArgc; + static const S32 NUM_ARGS = 6 + startArgc; static ReturnType thunk( S32 argc, const char** argv, R ( *fn )( A, B, C, D, E, F ), const _EngineFunctionDefaultArguments< void( A, B, C, D, E, F ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1659,11 +1660,11 @@ struct _EngineConsoleThunk< startArgc, R( A, B, C, D, E, F ) > return _EngineConsoleThunkReturnValue( ( frame->*fn )( a, b, c, d, e, f ) ); } }; -template< int startArgc, typename A, typename B, typename C, typename D, typename E, typename F > +template< S32 startArgc, typename A, typename B, typename C, typename D, typename E, typename F > struct _EngineConsoleThunk< startArgc, void( A, B, C, D, E, F ) > { typedef void ReturnType; - static const int NUM_ARGS = 6 + startArgc; + static const S32 NUM_ARGS = 6 + startArgc; static void thunk( S32 argc, const char** argv, void ( *fn )( A, B, C, D, E, F ), const _EngineFunctionDefaultArguments< void( A, B, C, D, E, F ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1687,11 +1688,11 @@ struct _EngineConsoleThunk< startArgc, void( A, B, C, D, E, F ) > } }; -template< int startArgc, typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G > +template< S32 startArgc, typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G > struct _EngineConsoleThunk< startArgc, R( A, B, C, D, E, F, G ) > { typedef typename _EngineConsoleThunkType< R >::ReturnType ReturnType; - static const int NUM_ARGS = 7 + startArgc; + static const S32 NUM_ARGS = 7 + startArgc; static ReturnType thunk( S32 argc, const char** argv, R ( *fn )( A, B, C, D, E, F, G ), const _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1716,11 +1717,11 @@ struct _EngineConsoleThunk< startArgc, R( A, B, C, D, E, F, G ) > return _EngineConsoleThunkReturnValue( ( frame->*fn )( a, b, c, d, e, f, g ) ); } }; -template< int startArgc, typename A, typename B, typename C, typename D, typename E, typename F, typename G > +template< S32 startArgc, typename A, typename B, typename C, typename D, typename E, typename F, typename G > struct _EngineConsoleThunk< startArgc, void( A, B, C, D, E, F, G ) > { typedef void ReturnType; - static const int NUM_ARGS = 7 + startArgc; + static const S32 NUM_ARGS = 7 + startArgc; static void thunk( S32 argc, const char** argv, void ( *fn )( A, B, C, D, E, F, G ), const _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1746,11 +1747,11 @@ struct _EngineConsoleThunk< startArgc, void( A, B, C, D, E, F, G ) > } }; -template< int startArgc, typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H > +template< S32 startArgc, typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H > struct _EngineConsoleThunk< startArgc, R( A, B, C, D, E, F, G, H ) > { typedef typename _EngineConsoleThunkType< R >::ReturnType ReturnType; - static const int NUM_ARGS = 8 + startArgc; + static const S32 NUM_ARGS = 8 + startArgc; static ReturnType thunk( S32 argc, const char** argv, R ( *fn )( A, B, C, D, E, F, G, H ), const _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G, H ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1777,11 +1778,11 @@ struct _EngineConsoleThunk< startArgc, R( A, B, C, D, E, F, G, H ) > return _EngineConsoleThunkReturnValue( ( frame->*fn )( a, b, c, d, e, f, g, h ) ); } }; -template< int startArgc, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H > +template< S32 startArgc, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H > struct _EngineConsoleThunk< startArgc, void( A, B, C, D, E, F, G, H ) > { typedef void ReturnType; - static const int NUM_ARGS = 8 + startArgc; + static const S32 NUM_ARGS = 8 + startArgc; static void thunk( S32 argc, const char** argv, void ( *fn )( A, B, C, D, E, F, G, H ), const _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G, H ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1809,11 +1810,11 @@ struct _EngineConsoleThunk< startArgc, void( A, B, C, D, E, F, G, H ) > } }; -template< int startArgc, typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I > +template< S32 startArgc, typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I > struct _EngineConsoleThunk< startArgc, R( A, B, C, D, E, F, G, H, I ) > { typedef typename _EngineConsoleThunkType< R >::ReturnType ReturnType; - static const int NUM_ARGS = 9 + startArgc; + static const S32 NUM_ARGS = 9 + startArgc; static ReturnType thunk( S32 argc, const char** argv, R ( *fn )( A, B, C, D, E, F, G, H, I ), const _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G, H, I ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1842,11 +1843,11 @@ struct _EngineConsoleThunk< startArgc, R( A, B, C, D, E, F, G, H, I ) > return _EngineConsoleThunkReturnValue( ( frame->*fn )( a, b, c, d, e, f, g, h, i ) ); } }; -template< int startArgc, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I > +template< S32 startArgc, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I > struct _EngineConsoleThunk< startArgc, void( A, B, C, D, E, F, G, H, I ) > { typedef void ReturnType; - static const int NUM_ARGS = 9 + startArgc; + static const S32 NUM_ARGS = 9 + startArgc; static void thunk( S32 argc, const char** argv, void ( *fn )( A, B, C, D, E, F, G, H, I ), const _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G, H, I ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1876,11 +1877,11 @@ struct _EngineConsoleThunk< startArgc, void( A, B, C, D, E, F, G, H, I ) > } }; -template< int startArgc, typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J > +template< S32 startArgc, typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J > struct _EngineConsoleThunk< startArgc, R( A, B, C, D, E, F, G, H, I, J ) > { typedef typename _EngineConsoleThunkType< R >::ReturnType ReturnType; - static const int NUM_ARGS = 10 + startArgc; + static const S32 NUM_ARGS = 10 + startArgc; static ReturnType thunk( S32 argc, const char** argv, R ( *fn )( A, B, C, D, E, F, G, H, I, J ), const _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G, H, I, J ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1911,11 +1912,11 @@ struct _EngineConsoleThunk< startArgc, R( A, B, C, D, E, F, G, H, I, J ) > return _EngineConsoleThunkReturnValue( ( frame->*fn )( a, b, c, d, e, f, g, h, i, j ) ); } }; -template< int startArgc, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J > +template< S32 startArgc, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J > struct _EngineConsoleThunk< startArgc, void( A, B, C, D, E, F, G, H, I, J ) > { typedef void ReturnType; - static const int NUM_ARGS = 10 + startArgc; + static const S32 NUM_ARGS = 10 + startArgc; static void thunk( S32 argc, const char** argv, void ( *fn )( A, B, C, D, E, F, G, H, I, J ), const _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G, H, I, J ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1946,11 +1947,11 @@ struct _EngineConsoleThunk< startArgc, void( A, B, C, D, E, F, G, H, I, J ) > ( frame->*fn )( a, b, c, d, e, f, g, h, i, j ); } }; -template< int startArgc, typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K > +template< S32 startArgc, typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K > struct _EngineConsoleThunk< startArgc, R( A, B, C, D, E, F, G, H, I, J, K ) > { typedef typename _EngineConsoleThunkType< R >::ReturnType ReturnType; - static const int NUM_ARGS = 11 + startArgc; + static const S32 NUM_ARGS = 11 + startArgc; static ReturnType thunk( S32 argc, const char** argv, R ( *fn )( A, B, C, D, E, F, G, H, I, J, K ), const _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G, H, I, J, K ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -1983,11 +1984,11 @@ struct _EngineConsoleThunk< startArgc, R( A, B, C, D, E, F, G, H, I, J, K ) > return _EngineConsoleThunkReturnValue( ( frame->*fn )( a, b, c, d, e, f, g, h, i, j, k ) ); } }; -template< int startArgc, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K > +template< S32 startArgc, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K > struct _EngineConsoleThunk< startArgc, void( A, B, C, D, E, F, G, H, I, J, K ) > { typedef void ReturnType; - static const int NUM_ARGS = 11 + startArgc; + static const S32 NUM_ARGS = 11 + startArgc; static void thunk( S32 argc, const char** argv, void ( *fn )( A, B, C, D, E, F, G, H, I, J, K ), const _EngineFunctionDefaultArguments< void( A, B, C, D, E, F, G, H, I, J, K ) >& defaultArgs ) { A a = ( startArgc < argc ? EngineUnmarshallData< A >()( argv[ startArgc ] ) : A( defaultArgs.a ) ); @@ -2532,79 +2533,79 @@ struct _EngineCallbackHelper R call() const { typedef R( FunctionType )( EngineObject* ); - return R( reinterpret_cast< FunctionType* >( mFn )( mThis ) ); + return R( reinterpret_cast< FunctionType* >( const_cast(mFn) )( mThis ) ); } template< typename R, typename A > R call( A a ) const { typedef R( FunctionType )( EngineObject*, A ); - return R( reinterpret_cast< FunctionType* >( mFn )( mThis, a ) ); + return R( reinterpret_cast< FunctionType* >( const_cast(mFn) )( mThis, a ) ); } template< typename R, typename A, typename B > R call( A a, B b ) const { typedef R( FunctionType )( EngineObject*, A, B ); - return R( reinterpret_cast< FunctionType* >( mFn )( mThis, a, b ) ); + return R( reinterpret_cast< FunctionType* >( const_cast(mFn) )( mThis, a, b ) ); } template< typename R, typename A, typename B, typename C > R call( A a, B b, C c ) const { typedef R( FunctionType )( EngineObject*, A, B, C ); - return R( reinterpret_cast< FunctionType* >( mFn )( mThis, a, b, c ) ); + return R( reinterpret_cast< FunctionType* >( const_cast(mFn) )( mThis, a, b, c ) ); } template< typename R, typename A, typename B, typename C, typename D > R call( A a, B b, C c, D d ) const { typedef R( FunctionType )( EngineObject*, A, B, C, D ); - return R( reinterpret_cast< FunctionType* >( mFn )( mThis, a, b, c, d ) ); + return R( reinterpret_cast< FunctionType* >( const_cast(mFn) )( mThis, a, b, c, d ) ); } template< typename R, typename A, typename B, typename C, typename D, typename E > R call( A a, B b, C c, D d, E e ) const { typedef R( FunctionType )( EngineObject*, A, B, C, D, E ); - return R( reinterpret_cast< FunctionType* >( mFn )( mThis, a, b, c, d, e ) ); + return R( reinterpret_cast< FunctionType* >( const_cast(mFn) )( mThis, a, b, c, d, e ) ); } template< typename R, typename A, typename B, typename C, typename D, typename E, typename F > R call( A a, B b, C c, D d, E e, F f ) const { typedef R( FunctionType )( EngineObject*, A, B, C, D, E, F ); - return R( reinterpret_cast< FunctionType* >( mFn )( mThis, a, b, c, d, e, f ) ); + return R( reinterpret_cast< FunctionType* >( const_cast(mFn) )( mThis, a, b, c, d, e, f ) ); } template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G > R call( A a, B b, C c, D d, E e, F f, G g ) const { typedef R( FunctionType )( EngineObject*, A, B, C, D, E, F, G ); - return R( reinterpret_cast< FunctionType* >( mFn )( mThis, a, b, c, d, e, f, g ) ); + return R( reinterpret_cast< FunctionType* >( const_cast(mFn) )( mThis, a, b, c, d, e, f, g ) ); } template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H > R call( A a, B b, C c, D d, E e, F f, G g, H h ) const { typedef R( FunctionType )( EngineObject*, A, B, C, D, E, F, G, H ); - return R( reinterpret_cast< FunctionType* >( mFn )( mThis, a, b, c, d, e, f, g, h ) ); + return R( reinterpret_cast< FunctionType* >( const_cast(mFn) )( mThis, a, b, c, d, e, f, g, h ) ); } template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I > R call( A a, B b, C c, D d, E e, F f, G g, H h, I i ) const { typedef R( FunctionType )( EngineObject*, A, B, C, D, E, F, G, H, I ); - return R( reinterpret_cast< FunctionType* >( mFn )( mThis, a, b, c, d, e, f, g, h, i ) ); + return R( reinterpret_cast< FunctionType* >( const_cast(mFn) )( mThis, a, b, c, d, e, f, g, h, i ) ); } template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J > R call( A a, B b, C c, D d, E e, F f, G g, H h, I i, J j ) const { typedef R( FunctionType )( EngineObject*, A, B, C, D, E, F, G, H, I, J ); - return R( reinterpret_cast< FunctionType* >( mFn )( mThis, a, b, c, d, e, f, g, h, i, j ) ); + return R( reinterpret_cast< FunctionType* >( const_cast(mFn) )( mThis, a, b, c, d, e, f, g, h, i, j ) ); } template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K > R call( A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k ) const { typedef R( FunctionType )( EngineObject*, A, B, C, D, E, F, G, H, I, J, K ); - return R( reinterpret_cast< FunctionType* >( mFn )( mThis, a, b, c, d, e, f, g, h, i, j, k ) ); + return R( reinterpret_cast< FunctionType* >( const_cast(mFn) )( mThis, a, b, c, d, e, f, g, h, i, j, k ) ); } template< typename R, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L > R call( A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l ) const { typedef R( FunctionType )( EngineObject*, A, B, C, D, E, F, G, H, I, J, K, L l ); - return R( reinterpret_cast< FunctionType* >( mFn )( mThis, a, b, c, d, e, f, g, h, i, j, k, l ) ); + return R( reinterpret_cast< FunctionType* >( const_cast(mFn) )( mThis, a, b, c, d, e, f, g, h, i, j, k, l ) ); } }; @@ -2788,7 +2789,6 @@ struct _EngineConsoleCallbackHelper // Re-enable some VC warnings we disabled for this file. -#pragma warning( default : 4510 ) -#pragma warning( default : 4610 ) +#pragma warning( pop ) // 4510 and 4610 #endif // !_ENGINEAPI_H_ diff --git a/Engine/source/console/engineDoc.cpp b/Engine/source/console/engineDoc.cpp index f049b6cc3..2bc03cbe3 100644 --- a/Engine/source/console/engineDoc.cpp +++ b/Engine/source/console/engineDoc.cpp @@ -307,7 +307,7 @@ static void dumpNamespaceEntries( Stream &stream, Namespace *g, bool callbacks = // Go through all the entries in the namespace. for ( Namespace::Entry *ewalk = g->mEntryList; ewalk; ewalk = ewalk->mNext ) { - int eType = ewalk->mType; + S32 eType = ewalk->mType; // We do not dump script defined functions... only engine exports. if( eType == Namespace::Entry::ConsoleFunctionType diff --git a/Engine/source/console/fileSystemFunctions.cpp b/Engine/source/console/fileSystemFunctions.cpp index d6e29ecaa..75b1ba9f7 100644 --- a/Engine/source/console/fileSystemFunctions.cpp +++ b/Engine/source/console/fileSystemFunctions.cpp @@ -599,10 +599,10 @@ DefineEngineFunction(fileExt, String, ( const char* fileName ),, } DefineEngineFunction(fileBase, String, ( const char* fileName ),, - "@brief Get the base of a file name (removes extension)\n\n" + "@brief Get the base of a file name (removes extension and path)\n\n" "@param fileName Name and path of file to check\n" - "@return String containing the file name, minus extension\n" + "@return String containing the file name, minus extension and path\n" "@ingroup FileSystem") { @@ -626,10 +626,10 @@ DefineEngineFunction(fileBase, String, ( const char* fileName ),, } DefineEngineFunction(fileName, String, ( const char* fileName ),, - "@brief Get the file name of a file (removes extension and path)\n\n" + "@brief Get only the file name of a path and file name string (removes path)\n\n" "@param fileName Name and path of file to check\n" - "@return String containing the file name, minus extension and path\n" + "@return String containing the file name, minus the path\n" "@ingroup FileSystem") { S32 pathLen = dStrlen( fileName ); @@ -695,8 +695,9 @@ DefineEngineFunction(makeFullPath, String, ( const char* path, const char* cwd ) "@return String containing non-relative directory of path\n" "@ingroup FileSystem") { - char *buf = Con::getReturnBuffer(512); - Platform::makeFullPathName(path, buf, 512, dStrlen(cwd) > 1 ? cwd : NULL); + static const U32 bufSize = 512; + char *buf = Con::getReturnBuffer(buf); + Platform::makeFullPathName(path, buf, bufSize, dStrlen(cwd) > 1 ? cwd : NULL); return buf; } @@ -721,8 +722,9 @@ DefineEngineFunction(pathConcat, String, ( const char* path, const char* file),, "@return String containing concatenated file name and path\n" "@ingroup FileSystem") { - char *buf = Con::getReturnBuffer(1024); - Platform::makeFullPathName(file, buf, 1024, path); + static const U32 bufSize = 1024; + char *buf = Con::getReturnBuffer(buf); + Platform::makeFullPathName(file, buf, bufSize, path); return buf; } diff --git a/Engine/source/console/scriptFilename.cpp b/Engine/source/console/scriptFilename.cpp index 35631e60b..649e109eb 100644 --- a/Engine/source/console/scriptFilename.cpp +++ b/Engine/source/console/scriptFilename.cpp @@ -344,8 +344,9 @@ ConsoleFunction(expandFilename, const char*, 2, 2, "(string filename)" "@ingroup FileSystem") { TORQUE_UNUSED(argc); - char* ret = Con::getReturnBuffer( 1024 ); - Con::expandScriptFilename(ret, 1024, argv[1]); + static const U32 bufSize = 1024; + char* ret = Con::getReturnBuffer( bufSize ); + Con::expandScriptFilename(ret, bufSize, argv[1]); return ret; } @@ -355,8 +356,9 @@ ConsoleFunction(expandOldFilename, const char*, 2, 2, "(string filename)" "@ingroup FileSystem") { TORQUE_UNUSED(argc); - char* ret = Con::getReturnBuffer( 1024 ); - Con::expandOldScriptFilename(ret, 1024, argv[1]); + static const U32 bufSize = 1024; + char* ret = Con::getReturnBuffer( bufSize ); + Con::expandOldScriptFilename(ret, bufSize, argv[1]); return ret; } @@ -368,8 +370,9 @@ ConsoleToolFunction(collapseFilename, const char*, 2, 2, "(string filename)" "@internal Editor use only") { TORQUE_UNUSED(argc); - char* ret = Con::getReturnBuffer( 1024 ); - Con::collapseScriptFilename(ret, 1024, argv[1]); + static const U32 bufSize = 1024; + char* ret = Con::getReturnBuffer( bufSize ); + Con::collapseScriptFilename(ret, bufSize, argv[1]); return ret; } diff --git a/Engine/source/console/simDictionary.cpp b/Engine/source/console/simDictionary.cpp index 5065d0a08..dac603517 100644 --- a/Engine/source/console/simDictionary.cpp +++ b/Engine/source/console/simDictionary.cpp @@ -25,7 +25,7 @@ //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- -extern S32 HashPointer(StringTableEntry e); +extern U32 HashPointer(StringTableEntry e); SimNameDictionary::SimNameDictionary() { diff --git a/Engine/source/console/simObject.cpp b/Engine/source/console/simObject.cpp index 3385f3a91..629542531 100644 --- a/Engine/source/console/simObject.cpp +++ b/Engine/source/console/simObject.cpp @@ -2663,7 +2663,7 @@ DefineConsoleMethod( SimObject, getDynamicFieldCount, S32, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, getDynamicField, const char*, ( int index ),, +DefineConsoleMethod( SimObject, getDynamicField, const char*, ( S32 index ),, "Get a value of a dynamic field by index.\n" "@param index The index of the dynamic field.\n" "@return The value of the dynamic field at the given index or \"\"." ) @@ -2680,11 +2680,12 @@ DefineConsoleMethod( SimObject, getDynamicField, const char*, ( int index ),, ++itr; } - char* buffer = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char* buffer = Con::getReturnBuffer(bufSize); if (*itr) { SimFieldDictionary::Entry* entry = *itr; - dSprintf(buffer, 256, "%s\t%s", entry->slotName, entry->value); + dSprintf(buffer, bufSize, "%s\t%s", entry->slotName, entry->value); return buffer; } @@ -2702,7 +2703,7 @@ DefineConsoleMethod( SimObject, getFieldCount, S32, (),, const AbstractClassRep::Field* f; U32 numDummyEntries = 0; - for(int i = 0; i < list.size(); i++) + for(S32 i = 0; i < list.size(); i++) { f = &list[i]; @@ -2716,7 +2717,7 @@ DefineConsoleMethod( SimObject, getFieldCount, S32, (),, //----------------------------------------------------------------------------- -DefineConsoleMethod( SimObject, getField, const char*, ( int index ),, +DefineConsoleMethod( SimObject, getField, const char*, ( S32 index ),, "Retrieve the value of a static field by index.\n" "@param index The index of the static field.\n" "@return The value of the static field with the given index or \"\"." ) diff --git a/Engine/source/console/simObject.h b/Engine/source/console/simObject.h index 541c15bbc..f7f5f550f 100644 --- a/Engine/source/console/simObject.h +++ b/Engine/source/console/simObject.h @@ -781,7 +781,7 @@ class SimObject: public ConsoleObject void setCanSaveDynamicFields( bool bCanSave ) { mCanSaveFieldDictionary = bCanSave; } /// Get whether fields created at runtime should be saved. Default is true. - bool getCanSaveDynamicFields( bool bCanSave ) { return mCanSaveFieldDictionary;} + bool getCanSaveDynamicFields( ) { return mCanSaveFieldDictionary;} /// Return the object that this object is copying fields from. SimObject* getCopySource() const { return mCopySource; } diff --git a/Engine/source/console/telnetDebugger.h b/Engine/source/console/telnetDebugger.h index 6916ae935..5a30c9cf7 100644 --- a/Engine/source/console/telnetDebugger.h +++ b/Engine/source/console/telnetDebugger.h @@ -127,7 +127,7 @@ public: void breakProcess(); - virtual void executionStopped(CodeBlock *code, U32 lineNumber); + void executionStopped(CodeBlock *code, U32 lineNumber); void send(const char *s); void setDebugParameters(S32 port, const char *password, bool waitForClient); void processConsoleLine(const char *consoleLine); diff --git a/Engine/source/console/test/runtimeClassRepTest.cpp b/Engine/source/console/test/runtimeClassRepTest.cpp new file mode 100644 index 000000000..0787e4af5 --- /dev/null +++ b/Engine/source/console/test/runtimeClassRepTest.cpp @@ -0,0 +1,108 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "platform/platform.h" +#include "console/simBase.h" +#include "console/consoleTypes.h" +#include "console/runtimeClassRep.h" + +class RuntimeRegisteredSimObject : public SimObject +{ + typedef SimObject Parent; + +protected: + bool mFoo; + +public: + RuntimeRegisteredSimObject() : mFoo(false) {}; + + DECLARE_RUNTIME_CONOBJECT(RuntimeRegisteredSimObject); + + static void initPersistFields(); +}; + +IMPLEMENT_RUNTIME_CONOBJECT(RuntimeRegisteredSimObject); + +void RuntimeRegisteredSimObject::initPersistFields() +{ + addField("fooField", TypeBool, Offset(mFoo, RuntimeRegisteredSimObject)); +} + +TEST(Console, RuntimeClassRep) +{ + // First test to make sure that the test class is not registered (don't + // know how it could be, but that's programming for you). Stop the test if + // it is. + ASSERT_TRUE(!RuntimeRegisteredSimObject::dynRTClassRep.isRegistered()) + << "RuntimeRegisteredSimObject class was already registered with the console"; + + // This should not be able to find the class, and return null (this may + // AssertWarn as well). + ConsoleObject *conobj = ConsoleObject::create("RuntimeRegisteredSimObject"); + EXPECT_TRUE(conobj == NULL) + << "Unregistered AbstractClassRep returned non-NULL value! That is really bad!"; + + // Register with console system. + RuntimeRegisteredSimObject::dynRTClassRep.consoleRegister(); + + // Make sure that the object knows it's registered. + EXPECT_TRUE(RuntimeRegisteredSimObject::dynRTClassRep.isRegistered()) + << "RuntimeRegisteredSimObject class failed console registration"; + + // Now try again to create the instance. + conobj = ConsoleObject::create("RuntimeRegisteredSimObject"); + EXPECT_TRUE(conobj != NULL) + << "AbstractClassRep::create method failed!"; + + // Cast the instance, and test it. + RuntimeRegisteredSimObject *rtinst = + dynamic_cast(conobj); + EXPECT_TRUE(rtinst != NULL) + << "Casting failed for some reason"; + + // Register it with a name. + rtinst->registerObject("_utRRTestObject"); + EXPECT_TRUE(rtinst->isProperlyAdded()) + << "registerObject failed on test object"; + + // Now execute some script on it. + Con::evaluate("_utRRTestObject.fooField = true;"); + + // Test to make sure field worked. + EXPECT_TRUE(dAtob(rtinst->getDataField(StringTable->insert("fooField"), NULL))) + << "Set property failed on instance."; + + // BALETED + rtinst->deleteObject(); + + // Unregister the type. + RuntimeRegisteredSimObject::dynRTClassRep.consoleUnRegister(); + + // And make sure we can't create another one. + conobj = ConsoleObject::create("RuntimeRegisteredSimObject"); + EXPECT_TRUE(conobj == NULL) + << "Unregistration of type failed"; +} + +#endif \ No newline at end of file diff --git a/Engine/source/core/bitRender.cpp b/Engine/source/core/bitRender.cpp index 39bbe127f..0365e6ac2 100644 --- a/Engine/source/core/bitRender.cpp +++ b/Engine/source/core/bitRender.cpp @@ -799,7 +799,7 @@ void BitRender::bitTo8Bit_3(U32 * bits, U32 * eightBits, S32 dim) #if defined(TORQUE_BIG_ENDIAN) #define MAX_SHADOW_TEXELS (256 + 4) //256 seems big enough, +4 so we can run off end of buffer. // slow fake gaussian - int i, j, c; + S32 i, j, c; U8 tmpLine[3][MAX_SHADOW_TEXELS]; U8 *src0, *src1, *src2; U8 *s0, *s1, *s2; @@ -809,7 +809,7 @@ void BitRender::bitTo8Bit_3(U32 * bits, U32 * eightBits, S32 dim) U32 currVal; U32 sampleVal; U8 c00, c01, c02, c10, c11, c12, c20, c21, c22; - int openBuf; + S32 openBuf; src0 = tmpLine[0]; src1 = tmpLine[1]; @@ -902,9 +902,9 @@ void BitRender::bitTo8Bit_3(U32 * bits, U32 * eightBits, S32 dim) sampleVal = 0; //c12; // take end. else // inner pixel { - const int wXP = 3; // corners - const int wPP = 4; // plus/NSEW - const int wCP = 4; // center + const S32 wXP = 3; // corners + const S32 wPP = 4; // plus/NSEW + const S32 wCP = 4; // center sampleVal = (c00+c02+c20+c22)*wXP + (c01+c10+c12+c21)*wPP + c11*wCP; sampleVal >>= 5; // div by 32 subsamples } diff --git a/Engine/source/core/color.cpp b/Engine/source/core/color.cpp index 17df1cb44..a28ef430f 100644 --- a/Engine/source/core/color.cpp +++ b/Engine/source/core/color.cpp @@ -38,3 +38,507 @@ const ColorI ColorI::BLACK( 0, 0, 0 ); const ColorI ColorI::RED( 255, 0, 0 ); const ColorI ColorI::GREEN( 0, 255, 0 ); const ColorI ColorI::BLUE( 0, 0, 255 ); + +#include "console/console.h" +#include "console/consoleTypes.h" + +#ifndef _STRINGUNIT_H_ +#include "core/strings/stringUnit.h" +#endif + +#ifndef _TDICTIONARY_H_ +#include "core/util/tDictionary.h" +#endif + +#include "console/consoleInternal.h" + +//----------------------------------------------------------------------------- + +typedef HashTable typeNameToColorFHash; +typedef HashTable typeNameToColorIHash; +typedef HashTable typeColorFToNameHash; +typedef HashTable typeColorIToNameHash; + +static typeNameToColorFHash mNameToColorF; +static typeNameToColorIHash mNameToColorI; +static typeColorFToNameHash mColorFToName; +static typeColorIToNameHash mColorIToName; + +#define DEFAULT_UNKNOWN_STOCK_COLOR_NAME "White" + +MODULE_BEGIN( StockColors ) + + MODULE_INIT_AFTER( GFX ) + + MODULE_INIT + { + // Create the stock colors. + StockColor::create(); + } + + MODULE_SHUTDOWN + { + // Destroy the stock colors. + StockColor::destroy(); + } + +MODULE_END; + +//----------------------------------------------------------------------------- + +StockColorItem StockColorTable[] = +{ + StockColorItem( "InvisibleBlack", 0, 0, 0, 0 ), + StockColorItem( "TransparentWhite", 255, 255, 255, 0 ), + StockColorItem( "AliceBlue", 240, 248, 255 ), + StockColorItem( "AntiqueWhite", 250, 235, 215 ), + StockColorItem( "Aqua", 0, 255, 255 ), + StockColorItem( "Aquamarine", 127, 255, 212 ), + StockColorItem( "Azure", 240, 255, 255 ), + StockColorItem( "Beige", 245, 245, 220 ), + StockColorItem( "Bisque", 255, 228, 196 ), + StockColorItem( "Black", 0, 0, 0, 255 ), + StockColorItem( "BlanchedAlmond", 255, 235, 205, 255 ), + StockColorItem( "Blue", 0, 0, 255 ), + StockColorItem( "BlueViolet", 138, 43, 226 ), + StockColorItem( "Brown", 165, 42, 42, 255 ), + StockColorItem( "BurlyWood", 222, 184, 135 ), + StockColorItem( "CadetBlue", 95, 158, 160 ), + StockColorItem( "Chartreuse", 127, 255, 0 ), + StockColorItem( "Chocolate", 210, 105, 30 ), + StockColorItem( "Coral", 255, 127, 80 ), + StockColorItem( "CornflowerBlue", 100, 149, 237 ), + StockColorItem( "Cornsilk", 255, 248, 220 ), + StockColorItem( "Crimson", 220, 20, 60 ), + StockColorItem( "Cyan", 0, 255, 255 ), + StockColorItem( "DarkBlue", 0, 0, 139 ), + StockColorItem( "DarkCyan", 0, 139, 139 ), + StockColorItem( "DarkGoldenrod", 184, 134, 11 ), + StockColorItem( "DarkGray", 169, 169, 169), + StockColorItem( "DarkGreen", 0, 100, 0 ), + StockColorItem( "DarkKhaki", 189, 183, 107 ), + StockColorItem( "DarkMagenta", 139, 0, 139 ), + StockColorItem( "DarkOliveGreen", 85, 107, 47 ), + StockColorItem( "DarkOrange", 255, 140, 0 ), + StockColorItem( "DarkOrchid", 153, 50, 204 ), + StockColorItem( "DarkRed", 139, 0, 0 ), + StockColorItem( "DarkSalmon", 233, 150, 122 ), + StockColorItem( "DarkSeaGreen", 143, 188, 139 ), + StockColorItem( "DarkSlateBlue", 72, 61, 139 ), + StockColorItem( "DarkSlateGray", 47, 79, 79 ), + StockColorItem( "DarkTurquoise", 0, 206, 209 ), + StockColorItem( "DarkViolet", 148, 0, 211 ), + StockColorItem( "DeepPink", 255, 20, 147 ), + StockColorItem( "DeepSkyBlue", 0, 191, 255 ), + StockColorItem( "DimGray", 105, 105, 105 ), + StockColorItem( "DodgerBlue", 30, 144, 255 ), + StockColorItem( "Firebrick", 178, 34, 34 ), + StockColorItem( "FloralWhite", 255, 250, 240 ), + StockColorItem( "ForestGreen", 34, 139, 34 ), + StockColorItem( "Fuchsia", 255, 0, 255 ), + StockColorItem( "Gainsboro", 220, 220, 220 ), + StockColorItem( "GhostWhite", 248, 248, 255 ), + StockColorItem( "Gold", 255, 215, 0 ), + StockColorItem( "Goldenrod", 218, 165, 32 ), + StockColorItem( "Gray", 128, 128, 128 ), + StockColorItem( "Green", 0, 128, 0 ), + StockColorItem( "GreenYellow", 173, 255, 47 ), + StockColorItem( "Honeydew", 240, 255, 24 ), + StockColorItem( "HotPink", 255, 105, 180 ), + StockColorItem( "IndianRed", 205, 92, 92 ), + StockColorItem( "Indigo", 75, 0, 130 ), + StockColorItem( "Ivory", 255, 255, 240 ), + StockColorItem( "Khaki", 240, 230, 140 ), + StockColorItem( "Lavender", 230, 230, 250 ), + StockColorItem( "LavenderBlush", 255, 240, 245 ), + StockColorItem( "LawnGreen", 124, 252, 0 ), + StockColorItem( "LemonChiffon", 255, 250, 205 ), + StockColorItem( "LightBlue", 173, 216, 230 ), + StockColorItem( "LightCoral", 240, 128, 128 ), + StockColorItem( "LightCyan", 224, 255, 255), + StockColorItem( "LightGoldenrodYellow", 250, 250, 210 ), + StockColorItem( "LightGray", 211, 211, 211), + StockColorItem( "LightGreen", 144, 238, 144 ), + StockColorItem( "LightPink", 255, 182, 193 ), + StockColorItem( "LightSalmon", 255, 160, 122 ), + StockColorItem( "LightSeaGreen", 32, 178, 170 ), + StockColorItem( "LightSkyBlue",135, 206, 250 ), + StockColorItem( "LightSlateGray", 119, 136, 153 ), + StockColorItem( "LightSteelBlue", 176, 196, 222 ), + StockColorItem( "LightYellow", 255, 255, 224 ), + StockColorItem( "Lime", 0, 255, 0 ), + StockColorItem( "LimeGreen", 50, 205, 50 ), + StockColorItem( "Linen", 250, 240, 230 ), + StockColorItem( "Magenta", 255, 0, 255 ), + StockColorItem( "Maroon", 128, 0, 0 ), + StockColorItem( "MediumAquamarine", 102, 205, 170 ), + StockColorItem( "MediumBlue", 0, 0, 205 ), + StockColorItem( "MediumOrchid", 186, 85, 211 ), + StockColorItem( "MediumPurple", 147, 112, 219 ), + StockColorItem( "MediumSeaGreen", 60, 179, 113 ), + StockColorItem( "MediumSlateBlue", 123, 104, 238 ), + StockColorItem( "MediumSpringGreen", 0, 250, 154 ), + StockColorItem( "MediumTurquoise", 72, 209, 204 ), + StockColorItem( "MediumVioletRed", 199, 21, 133 ), + StockColorItem( "MidnightBlue", 25, 25, 112 ), + StockColorItem( "MintCream", 245, 255, 250 ), + StockColorItem( "MistyRose", 255, 228, 225 ), + StockColorItem( "Moccasin", 255, 228, 181 ), + StockColorItem( "NavajoWhite", 255, 222, 173 ), + StockColorItem( "Navy", 0, 0, 128 ), + StockColorItem( "OldLace", 253, 245, 230 ), + StockColorItem( "Olive", 128, 128, 0 ), + StockColorItem( "OliveDrab", 107, 142, 35 ), + StockColorItem( "Orange", 255, 165, 0 ), + StockColorItem( "OrangeRed", 255, 69, 0 ), + StockColorItem( "Orchid", 218, 112, 214 ), + StockColorItem( "PaleGoldenrod", 238, 232, 170 ), + StockColorItem( "PaleGreen", 152, 251, 152 ), + StockColorItem( "PaleTurquoise", 175, 238, 238 ), + StockColorItem( "PaleVioletRed", 219, 112, 147 ), + StockColorItem( "PapayaWhip", 255, 239, 213 ), + StockColorItem( "PeachPuff", 255, 218, 185 ), + StockColorItem( "Peru", 205, 133, 63 ), + StockColorItem( "Pink", 55, 192, 203 ), + StockColorItem( "Plum", 221, 160, 221 ), + StockColorItem( "PowderBlue", 176, 224, 230 ), + StockColorItem( "Purple", 128, 0, 128 ), + StockColorItem( "Red", 255, 0, 0 ), + StockColorItem( "RosyBrown", 188, 143, 143 ), + StockColorItem( "RoyalBlue", 65, 105, 225 ), + StockColorItem( "SaddleBrown", 139, 69, 19 ), + StockColorItem( "Salmon", 250, 128, 114 ), + StockColorItem( "SandyBrown", 244, 164, 96 ), + StockColorItem( "SeaGreen", 46, 139, 87 ), + StockColorItem( "SeaShell", 255, 245, 238 ), + StockColorItem( "Sienna", 160, 82, 45 ), + StockColorItem( "Silver", 192, 192, 192 ), + StockColorItem( "SkyBlue", 135, 206, 235 ), + StockColorItem( "SlateBlue", 106, 90, 205 ), + StockColorItem( "SlateGray", 112, 128, 144 ), + StockColorItem( "Snow", 255, 250, 250 ), + StockColorItem( "SpringGreen", 0, 255, 127 ), + StockColorItem( "SteelBlue", 70, 130, 180 ), + StockColorItem( "Tan", 210, 180, 140 ), + StockColorItem( "Teal", 0, 128, 128 ), + StockColorItem( "Thistle", 216, 191, 216 ), + StockColorItem( "Tomato", 255, 99, 71 ), + StockColorItem( "Turquoise", 64, 224, 208 ), + StockColorItem( "Violet", 238, 130, 238 ), + StockColorItem( "Wheat", 245, 222, 179 ), + StockColorItem( "White", 255, 255, 255 ), + StockColorItem( "WhiteSmoke", 245, 245, 245 ), + StockColorItem( "Yellow", 255, 255, 0 ), + StockColorItem( "YellowGreen", 154, 205, 50 ) +}; + +//----------------------------------------------------------------------------- + +static bool stockColorsCreated = false; + +void StockColor::create( void ) +{ + // Finish if already created. + if ( stockColorsCreated ) + return; + + // Fetch stock color count. + const S32 stockColorCount = sizeof(StockColorTable) / sizeof(StockColorItem); + + // Insert all stock colors. + for( S32 index = 0; index < stockColorCount; ++index ) + { + // Fetch stock color item. + StockColorItem& stockColor = StockColorTable[index]; + + // Fetch stock color item. + StringTableEntry colorName = StringTable->insert( stockColor.mColorName ); + + // Insert stock color mappings. + mNameToColorF.insertUnique(colorName, stockColor.mColorF); + mNameToColorI.insertUnique(colorName, stockColor.mColorI); + mColorFToName.insertUnique(stockColor.mColorF, colorName); + mColorIToName.insertUnique(stockColor.mColorI, colorName); + } + + // Flag as created. + stockColorsCreated = true; +} + +//----------------------------------------------------------------------------- + +void StockColor::destroy( void ) +{ + // Finish if not created. + if ( !stockColorsCreated ) + return; + + // Clear stock color mappings. + mNameToColorF.clear(); + mNameToColorI.clear(); + mColorFToName.clear(); + mColorIToName.clear(); + + // Flag as not created. + stockColorsCreated = false; +} + +//----------------------------------------------------------------------------- + +bool StockColor::isColor( const char* pStockColorName ) +{ + // Sanity! + AssertFatal( pStockColorName != NULL, "Cannot fetch a NULL stock color name." ); + + // Fetch color name. + StringTableEntry colorName = StringTable->insert( pStockColorName ); + + // Find if color name exists or not. + return mNameToColorF.find( colorName ) != mNameToColorF.end(); +} + +//----------------------------------------------------------------------------- + +const ColorF& StockColor::colorF( const char* pStockColorName ) +{ + // Sanity! + AssertFatal( pStockColorName != NULL, "Cannot fetch a NULL stock color name." ); + + // Fetch color name. + StringTableEntry colorName = StringTable->insert( pStockColorName ); + + // Find stock color. + typeNameToColorFHash::Iterator colorItr = mNameToColorF.find( colorName ); + + // Return color if found. + if ( colorItr != mNameToColorF.end() ) + return colorItr->value; + + // Warn. + Con::warnf( "Could not find stock color name '%s'.", pStockColorName ); + + // Return default stock color. + return mNameToColorF.find( DEFAULT_UNKNOWN_STOCK_COLOR_NAME )->value; +} + +//----------------------------------------------------------------------------- + +const ColorI& StockColor::colorI( const char* pStockColorName ) +{ + // Sanity! + AssertFatal( pStockColorName != NULL, "Cannot fetch a NULL stock color name." ); + + // Fetch color name. + StringTableEntry colorName = StringTable->insert( pStockColorName ); + + // Find stock color. + typeNameToColorIHash::Iterator colorItr = mNameToColorI.find( colorName ); + + // Return color if found. + if ( colorItr != mNameToColorI.end() ) + return colorItr->value; + + // Warn. + Con::warnf( "Could not find stock color name '%s'.", colorName ); + + // Return default stock color. + return mNameToColorI.find( DEFAULT_UNKNOWN_STOCK_COLOR_NAME )->value; +} + +//----------------------------------------------------------------------------- + +StringTableEntry StockColor::name( const ColorF& color ) +{ + // Find stock color name. + typeColorFToNameHash::Iterator colorNameItr = mColorFToName.find( color ); + + // Return name if found. + if ( colorNameItr != mColorFToName.end() ) + return colorNameItr->value; + + // Return empty string. + return StringTable->EmptyString(); +} + +//----------------------------------------------------------------------------- + +StringTableEntry StockColor::name( const ColorI& color ) +{ + // Find stock color name. + typeColorIToNameHash::Iterator colorNameItr = mColorIToName.find( color ); + + // Return name if found. + if ( colorNameItr != mColorIToName.end() ) + return colorNameItr->value; + + // Return empty string. + return StringTable->EmptyString(); +} + +//----------------------------------------------------------------------------- + +S32 StockColor::getCount( void ) +{ + return sizeof(StockColorTable) / sizeof(StockColorItem); +} + +//----------------------------------------------------------------------------- + +const StockColorItem* StockColor::getColorItem( const S32 index ) +{ + // Fetch stock color count. + const S32 stockColorCount = StockColor::getCount(); + + // Is the stock color index in range? + if ( index < 0 || index >= stockColorCount ) + { + // No, so warn. + Con::warnf("StockColor::getName() - Specified color index '%d' is out of range. Range is 0 to %d.", index, stockColorCount-1 ); + return NULL; + } + + // Return color name. + return &(StockColorTable[index]); +} + +//----------------------------------------------------------------------------- + +ColorF::ColorF( const char* pStockColorName ) +{ + // Set stock color. + *this = StockColor::colorF( pStockColorName ); +} + +//----------------------------------------------------------------------------- + +void ColorF::set( const char* pStockColorName ) +{ + // Set stock color. + *this = StockColor::colorF( pStockColorName ); +} + +//----------------------------------------------------------------------------- + +const ColorF& ColorF::StockColor( const char* pStockColorName ) +{ + return StockColor::colorF( pStockColorName ); +} + +//----------------------------------------------------------------------------- + +StringTableEntry ColorF::StockColor( void ) +{ + // Return stock color name. + return StockColor::name( *this ); +} + +//----------------------------------------------------------------------------- + +ColorI::ColorI( const char* pStockColorName ) +{ + // Set stock color. + *this = StockColor::colorI( pStockColorName ); +} + +//----------------------------------------------------------------------------- + +void ColorI::set( const char* pStockColorName ) +{ + // Set stock color. + *this = StockColor::colorI( pStockColorName ); +} + +//----------------------------------------------------------------------------- + +const ColorI& ColorI::StockColor( const char* pStockColorName ) +{ + return StockColor::colorI( pStockColorName ); +} + +//----------------------------------------------------------------------------- + +StringTableEntry ColorI::StockColor( void ) +{ + // Return stock color name. + return StockColor::name( *this ); +} + +//----------------------------------------------------------------------------- + +ConsoleFunction( getStockColorCount, S32, 1, 1, "() - Gets a count of available stock colors.\n" + "@return A count of available stock colors." ) +{ + return StockColor::getCount(); +} + +//----------------------------------------------------------------------------- + +ConsoleFunction( getStockColorName, const char*, 2, 2, "(stockColorIndex) - Gets the stock color name at the specified index.\n" + "@param stockColorIndex The zero-based index of the stock color name to retrieve.\n" + "@return The stock color name at the specified index or nothing if the string is invalid." ) +{ + // Fetch stock color index. + const S32 stockColorIndex = dAtoi(argv[1]); + + // Fetch the color item. + const StockColorItem* pColorItem = StockColor::getColorItem( stockColorIndex ); + + return pColorItem == NULL ? NULL : pColorItem->getColorName(); +} + +//----------------------------------------------------------------------------- + +ConsoleFunction( isStockColor, bool, 2, 2, "(stockColorName) - Gets whether the specified name is a stock color or not.\n" + "@param stockColorName - The stock color name to test for.\n" + "@return Whether the specified name is a stock color or not.\n" ) +{ + // Fetch stock color name. + const char* pStockColorName = argv[1]; + + // Return whether this is a stock color name or not. + return StockColor::isColor( pStockColorName ); +} + +//----------------------------------------------------------------------------- + +ConsoleFunction( getStockColorF, const char*, 2, 2, "(stockColorName) - Gets a floating-point-based stock color by name.\n" + "@param stockColorName - The stock color name to retrieve.\n" + "@return The stock color that matches the specified color name. Returns nothing if the color name is not found.\n" ) +{ + // Fetch stock color name. + const char* pStockColorName = argv[1]; + + // Return nothing if stock color name is invalid. + if ( !StockColor::isColor( pStockColorName ) ) + return StringTable->EmptyString(); + + // Fetch stock color. + const ColorF& color = StockColor::colorF( pStockColorName ); + + // Format stock color. + char* returnBuffer = Con::getReturnBuffer(256); + dSprintf(returnBuffer, 256, "%g %g %g %g", color.red, color.green, color.blue, color.alpha); + return(returnBuffer); +} + +//----------------------------------------------------------------------------- + +ConsoleFunction( getStockColorI, const char*, 2, 2, "(stockColorName) - Gets a byte-based stock color by name.\n" + "@param stockColorName - The stock color name to retrieve.\n" + "@return The stock color that matches the specified color name. Returns nothing if the color name is not found.\n" ) +{ + // Fetch stock color name. + const char* pStockColorName = argv[1]; + + // Return nothing if stock color name is invalid. + if ( !StockColor::isColor( pStockColorName ) ) + return StringTable->EmptyString(); + + // Fetch stock color. + const ColorI& color = StockColor::colorI( pStockColorName ); + + // Format stock color. + char* returnBuffer = Con::getReturnBuffer(256); + dSprintf(returnBuffer, 256, "%d %d %d %d", color.red, color.green, color.blue, color.alpha); + return(returnBuffer); +} \ No newline at end of file diff --git a/Engine/source/core/color.h b/Engine/source/core/color.h index 7a9206cd3..b0620fc4f 100644 --- a/Engine/source/core/color.h +++ b/Engine/source/core/color.h @@ -49,11 +49,18 @@ class ColorF const F32 in_b, const F32 in_a = 1.0f); + ColorF( const char* pStockColorName ); + void set(const F32 in_r, const F32 in_g, const F32 in_b, const F32 in_a = 1.0f); + void set( const char* pStockColorName ); + + static const ColorF& StockColor( const char* pStockColorName ); + StringTableEntry StockColor( void ); + ColorF& operator*=(const ColorF& in_mul); // Can be useful for lighting ColorF operator*(const ColorF& in_mul) const; ColorF& operator+=(const ColorF& in_rAdd); @@ -123,6 +130,8 @@ class ColorI const U8 in_a = U8(255)); ColorI(const ColorI& in_rCopy, const U8 in_a); + ColorI( const char* pStockColorName ); + void set(const U8 in_r, const U8 in_g, const U8 in_b, @@ -131,6 +140,11 @@ class ColorI void set(const ColorI& in_rCopy, const U8 in_a); + void set( const char* pStockColorName ); + + static const ColorI& StockColor( const char* pStockColorName ); + StringTableEntry StockColor( void ); + ColorI& operator*=(const F32 in_mul); ColorI operator*(const F32 in_mul) const; @@ -175,6 +189,53 @@ class ColorI static const ColorI BLUE; }; +//----------------------------------------------------------------------------- + +class StockColorItem +{ +private: + StockColorItem() {} + +public: + StockColorItem( const char* pName, const U8 red, const U8 green, const U8 blue, const U8 alpha = 255 ) + { + // Sanity! + AssertFatal( pName != NULL, "Stock color name cannot be NULL." ); + + // Set stock color. + // NOTE:- We'll use the char pointer here. We can yet use the string-table unfortunately. + mColorName = pName; + mColorI.set( red, green, blue, alpha ); + mColorF = mColorI; + } + + inline const char* getColorName( void ) const { return mColorName; } + inline const ColorF& getColorF( void ) const { return mColorF; } + inline const ColorI& getColorI( void ) const { return mColorI; } + + const char* mColorName; + ColorF mColorF; + ColorI mColorI; +}; + +//----------------------------------------------------------------------------- + +class StockColor +{ +public: + static bool isColor( const char* pStockColorName ); + static const ColorF& colorF( const char* pStockColorName ); + static const ColorI& colorI( const char* pStockColorName ); + static StringTableEntry name( const ColorF& color ); + static StringTableEntry name( const ColorI& color ); + + static S32 getCount( void ); + static const StockColorItem* getColorItem( const S32 index ); + + static void create( void ); + static void destroy( void ); +}; + //------------------------------------------------------------------------------ //-------------------------------------- INLINES (ColorF) // diff --git a/Engine/source/core/fileObject.cpp b/Engine/source/core/fileObject.cpp index 4234d583d..7ab38ae00 100644 --- a/Engine/source/core/fileObject.cpp +++ b/Engine/source/core/fileObject.cpp @@ -343,8 +343,9 @@ DefineEngineMethod( FileObject, peekLine, const char*, (),, "@return String containing the line of data that was just peeked\n") { - char *line = Con::getReturnBuffer( 512 ); - object->peekLine( (U8*)line, 512 ); + static const U32 bufSize = 512; + char *line = Con::getReturnBuffer( bufSize ); + object->peekLine( (U8*)line, bufSize ); return line; } diff --git a/Engine/source/core/fileio.h b/Engine/source/core/fileio.h index 31b367033..a7deb1078 100644 --- a/Engine/source/core/fileio.h +++ b/Engine/source/core/fileio.h @@ -31,7 +31,7 @@ class File { public: /// What is the status of our file handle? - enum Status + enum FileStatus { Ok = 0, ///< Ok! IOError, ///< Read or Write error @@ -59,7 +59,7 @@ public: private: void *handle; ///< Pointer to the file handle. - Status currentStatus; ///< Current status of the file (Ok, IOError, etc.). + FileStatus currentStatus; ///< Current status of the file (Ok, IOError, etc.). U32 capability; ///< Keeps track of file capabilities. File(const File&); ///< This is here to disable the copy constructor. @@ -72,7 +72,7 @@ public: /// Opens a file for access using the specified AccessMode /// /// @returns The status of the file - Status open(const char *filename, const AccessMode openMode); + FileStatus open(const char *filename, const AccessMode openMode); /// Gets the current position in the file /// @@ -99,7 +99,7 @@ public: /// @endcode /// /// @returns The status of the file - Status setPosition(S32 position, bool absolutePos = true); + FileStatus setPosition(S32 position, bool absolutePos = true); /// Returns the size of the file U32 getSize() const; @@ -107,25 +107,25 @@ public: /// Make sure everything that's supposed to be written to the file gets written. /// /// @returns The status of the file. - Status flush(); + FileStatus flush(); /// Closes the file /// /// @returns The status of the file. - Status close(); + FileStatus close(); /// Gets the status of the file - Status getStatus() const; + FileStatus getStatus() const; /// Reads "size" bytes from the file, and dumps data into "dst". /// The number of actual bytes read is returned in bytesRead /// @returns The status of the file - Status read(U32 size, char *dst, U32 *bytesRead = NULL); + FileStatus read(U32 size, char *dst, U32 *bytesRead = NULL); /// Writes "size" bytes into the file from the pointer "src". /// The number of actual bytes written is returned in bytesWritten /// @returns The status of the file - Status write(U32 size, const char *src, U32 *bytesWritten = NULL); + FileStatus write(U32 size, const char *src, U32 *bytesWritten = NULL); /// Returns whether or not this file is capable of the given function. bool hasCapability(Capability cap) const; @@ -133,8 +133,8 @@ public: const void* getHandle() { return handle; } protected: - Status setStatus(); ///< Called after error encountered. - Status setStatus(Status status); ///< Setter for the current status. + FileStatus setStatus(); ///< Called after error encountered. + FileStatus setStatus(FileStatus status); ///< Setter for the current status. }; #endif // _FILE_IO_H_ diff --git a/Engine/source/core/frameAllocator.h b/Engine/source/core/frameAllocator.h index 6abdd13cf..86884085c 100644 --- a/Engine/source/core/frameAllocator.h +++ b/Engine/source/core/frameAllocator.h @@ -234,7 +234,7 @@ public: mWaterMark = FrameAllocator::getWaterMark(); mMemory = reinterpret_cast( FrameAllocator::alloc( sizeof( T ) * count ) ); - for( int i = 0; i < mNumObjectsInMemory; i++ ) + for( S32 i = 0; i < mNumObjectsInMemory; i++ ) constructInPlace( &mMemory[i] ); } @@ -242,7 +242,7 @@ public: ~FrameTemp() { // Call destructor - for( int i = 0; i < mNumObjectsInMemory; i++ ) + for( S32 i = 0; i < mNumObjectsInMemory; i++ ) destructInPlace( &mMemory[i] ); FrameAllocator::setWaterMark( mWaterMark ); diff --git a/Engine/source/core/memVolume.cpp b/Engine/source/core/memVolume.cpp index 284e753fb..56d53174f 100644 --- a/Engine/source/core/memVolume.cpp +++ b/Engine/source/core/memVolume.cpp @@ -324,7 +324,7 @@ namespace Torque return mFileData->mPath; } - FileNode::Status MemFile::getStatus() const + FileNode::NodeStatus MemFile::getStatus() const { return mStatus; } @@ -502,7 +502,7 @@ namespace Torque return mDirectoryData->getAttributes(attr); } - FileNode::Status MemDirectory::getStatus() const + FileNode::NodeStatus MemDirectory::getStatus() const { return mStatus; } diff --git a/Engine/source/core/memVolume.h b/Engine/source/core/memVolume.h index 18e4641fb..0a20fa84f 100644 --- a/Engine/source/core/memVolume.h +++ b/Engine/source/core/memVolume.h @@ -74,7 +74,7 @@ namespace Torque virtual ~MemFile(); Path getName() const; - Status getStatus() const; + NodeStatus getStatus() const; bool getAttributes(Attributes*); U32 getPosition(); @@ -91,7 +91,7 @@ namespace Torque MemFileSystem* mFileSystem; MemFileData* mFileData; - Status mStatus; + NodeStatus mStatus; U32 mCurrentPos; bool _updateInfo(); @@ -108,7 +108,7 @@ namespace Torque ~MemDirectory(); Path getName() const; - Status getStatus() const; + NodeStatus getStatus() const; bool getAttributes(Attributes*); bool open(); @@ -122,7 +122,7 @@ namespace Torque U32 calculateChecksum(); - Status mStatus; + NodeStatus mStatus; U32 mSearchIndex; }; diff --git a/Engine/source/core/ogg/oggInputStream.cpp b/Engine/source/core/ogg/oggInputStream.cpp index 7704f3152..e0777e6ad 100644 --- a/Engine/source/core/ogg/oggInputStream.cpp +++ b/Engine/source/core/ogg/oggInputStream.cpp @@ -55,7 +55,7 @@ bool OggDecoder::_readNextPacket( ogg_packet* packet ) while( 1 ) { - int result = ogg_stream_packetout( &mOggStreamState, packet ); + S32 result = ogg_stream_packetout( &mOggStreamState, packet ); if( result == 0 ) { if( !mOggStream->_requestData() ) diff --git a/Engine/source/core/ogg/oggTheoraDecoder.cpp b/Engine/source/core/ogg/oggTheoraDecoder.cpp index b0c62ea5f..1259c3afb 100644 --- a/Engine/source/core/ogg/oggTheoraDecoder.cpp +++ b/Engine/source/core/ogg/oggTheoraDecoder.cpp @@ -169,7 +169,7 @@ bool OggTheoraDecoder::_init() break; } - int result = th_decode_headerin( &mTheoraInfo, &mTheoraComment, &mTheoraSetup, &nextPacket ); + S32 result = th_decode_headerin( &mTheoraInfo, &mTheoraComment, &mTheoraSetup, &nextPacket ); if( result < 0 ) { haveTheoraHeader = false; diff --git a/Engine/source/core/ogg/oggVorbisDecoder.cpp b/Engine/source/core/ogg/oggVorbisDecoder.cpp index 3df624df3..885c3fd53 100644 --- a/Engine/source/core/ogg/oggVorbisDecoder.cpp +++ b/Engine/source/core/ogg/oggVorbisDecoder.cpp @@ -89,7 +89,7 @@ bool OggVorbisDecoder::_init() break; } - int result = vorbis_synthesis_headerin( &mVorbisInfo, &mVorbisComment, &nextPacket ); + S32 result = vorbis_synthesis_headerin( &mVorbisInfo, &mVorbisComment, &nextPacket ); if( result != 0 ) { haveVorbisHeader = false; diff --git a/Engine/source/core/stream/stream.cpp b/Engine/source/core/stream/stream.cpp index a11d40010..873bdeba6 100644 --- a/Engine/source/core/stream/stream.cpp +++ b/Engine/source/core/stream/stream.cpp @@ -91,7 +91,7 @@ Stream::Stream() { } -const char* Stream::getStatusString(const Status in_status) +const char* Stream::getStatusString(const StreamStatus in_status) { switch (in_status) { case Ok: diff --git a/Engine/source/core/stream/stream.h b/Engine/source/core/stream/stream.h index c4d17a791..c50acb659 100644 --- a/Engine/source/core/stream/stream.h +++ b/Engine/source/core/stream/stream.h @@ -57,7 +57,7 @@ class Stream // Public structs and enumerations... public: /// Status constants for the stream - enum Status { + enum StreamStatus { Ok = 0, ///< Ok! IOError, ///< Read or Write error EOS, ///< End of Stream reached (mostly for reads) @@ -74,20 +74,20 @@ public: // Accessible only through inline accessors private: - Status m_streamStatus; + StreamStatus m_streamStatus; // Derived accessible data modifiers... protected: - void setStatus(const Status in_newStatus) { m_streamStatus = in_newStatus; } + void setStatus(const StreamStatus in_newStatus) { m_streamStatus = in_newStatus; } public: Stream(); virtual ~Stream() {} /// Gets the status of the stream - Stream::Status getStatus() const { return m_streamStatus; } + Stream::StreamStatus getStatus() const { return m_streamStatus; } /// Gets a printable string form of the status - static const char* getStatusString(const Status in_status); + static const char* getStatusString(const StreamStatus in_status); // Derived classes must override these... protected: diff --git a/Engine/source/core/stream/streamObject.cpp b/Engine/source/core/stream/streamObject.cpp index bf684cf08..924df4bcd 100644 --- a/Engine/source/core/stream/streamObject.cpp +++ b/Engine/source/core/stream/streamObject.cpp @@ -113,8 +113,9 @@ const char * StreamObject::readLine() if(mStream == NULL) return NULL; - char *buffer = Con::getReturnBuffer(256); - mStream->readLine((U8 *)buffer, 256); + static const U32 bufSize = 256; + char *buffer = Con::getReturnBuffer(bufSize); + mStream->readLine((U8 *)buffer, bufSize); return buffer; } diff --git a/Engine/source/core/stringBuffer.cpp b/Engine/source/core/stringBuffer.cpp index be2840153..fd16d159b 100644 --- a/Engine/source/core/stringBuffer.cpp +++ b/Engine/source/core/stringBuffer.cpp @@ -438,7 +438,7 @@ void StringBufferManager::updateStats() request8 = 0; request16 = 0; U32 nstrings = strings.size(); - for(int i=0; i < nstrings; i++) + for(S32 i=0; i < nstrings; i++) { request8 += strings[i]->rc->requestCount8; request16 += strings[i]->rc->requestCount16; @@ -459,7 +459,7 @@ void StringBufferManager::dumpAllStrings() U32 nstrings = strings.size(); Con::printf("===== String Manager: All Strings ====="); Con::printf(" utf8 | utf16 | string"); - for(int i=0; i < nstrings; i++) + for(S32 i=0; i < nstrings; i++) { UTF8* tmp = strings[i]->createCopy8(); strings[i]->rc->requestCount8--; diff --git a/Engine/source/core/stringTable.cpp b/Engine/source/core/stringTable.cpp index 3c2ff86f8..2340fd5af 100644 --- a/Engine/source/core/stringTable.cpp +++ b/Engine/source/core/stringTable.cpp @@ -59,7 +59,7 @@ U32 _StringTable::hashString(const char* str) char c; while((c = *str++) != 0) { ret <<= 1; - ret ^= sgHashTable[static_cast(c)]; + ret ^= sgHashTable[static_cast(c)]; } return ret; } @@ -73,7 +73,7 @@ U32 _StringTable::hashStringn(const char* str, S32 len) char c; while((c = *str++) != 0 && len--) { ret <<= 1; - ret ^= sgHashTable[static_cast(c)]; + ret ^= sgHashTable[static_cast(c)]; } return ret; } @@ -195,8 +195,11 @@ StringTableEntry _StringTable::lookupn(const char* val, S32 len, const bool cas } //-------------------------------------- -void _StringTable::resize(const U32 newSize) +void _StringTable::resize(const U32 _newSize) { + /// avoid a possible 0 division + const U32 newSize = _newSize ? _newSize : 1; + Node *head = NULL, *walk, *temp; U32 i; // reverse individual bucket lists diff --git a/Engine/source/core/strings/findMatch.cpp b/Engine/source/core/strings/findMatch.cpp index c41dd9230..1bb35128e 100644 --- a/Engine/source/core/strings/findMatch.cpp +++ b/Engine/source/core/strings/findMatch.cpp @@ -140,7 +140,7 @@ bool FindMatch::isMatch( const char *exp, const char *str, bool caseSensitive ) bool FindMatch::isMatchMultipleExprs( const char *exps, const char *str, bool caseSensitive ) { char *tok = 0; - int len = dStrlen(exps); + S32 len = dStrlen(exps); char *e = new char[len+1]; dStrcpy(e,exps); diff --git a/Engine/source/core/strings/stringFunctions.cpp b/Engine/source/core/strings/stringFunctions.cpp index 25c7e22b1..476edf71b 100644 --- a/Engine/source/core/strings/stringFunctions.cpp +++ b/Engine/source/core/strings/stringFunctions.cpp @@ -27,7 +27,7 @@ #include "platform/platform.h" -#if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) +#if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) // This standard function is not defined when compiling with VC7... #define vsnprintf _vsnprintf #endif @@ -97,10 +97,10 @@ nat_toupper( nat_char a ) -static int +static S32 compare_right(const nat_char* a, const nat_char* b) { - int bias = 0; + S32 bias = 0; /* The longest run of digits wins. That aside, the greatest value wins, but we can't know that it will until we've scanned @@ -108,7 +108,7 @@ compare_right(const nat_char* a, const nat_char* b) remember it in BIAS. */ for (;; a++, b++) { if (!nat_isdigit(*a) && !nat_isdigit(*b)) - return bias; + break; else if (!nat_isdigit(*a)) return -1; else if (!nat_isdigit(*b)) @@ -123,7 +123,7 @@ compare_right(const nat_char* a, const nat_char* b) return bias; } - return 0; + return bias; } @@ -134,7 +134,7 @@ compare_left(const nat_char* a, const nat_char* b) different value wins. */ for (;; a++, b++) { if (!nat_isdigit(*a) && !nat_isdigit(*b)) - return 0; + break; else if (!nat_isdigit(*a)) return -1; else if (!nat_isdigit(*b)) @@ -149,11 +149,11 @@ compare_left(const nat_char* a, const nat_char* b) } -static int strnatcmp0(const nat_char* a, const nat_char* b, int fold_case) +static S32 strnatcmp0(const nat_char* a, const nat_char* b, S32 fold_case) { - int ai, bi; + S32 ai, bi; nat_char ca, cb; - int fractional, result; + S32 fractional, result; ai = bi = 0; while (1) { @@ -200,13 +200,13 @@ static int strnatcmp0(const nat_char* a, const nat_char* b, int fold_case) } -int dStrnatcmp(const nat_char* a, const nat_char* b) { +S32 dStrnatcmp(const nat_char* a, const nat_char* b) { return strnatcmp0(a, b, 0); } /* Compare, recognizing numeric string and ignoring case. */ -int dStrnatcasecmp(const nat_char* a, const nat_char* b) { +S32 dStrnatcasecmp(const nat_char* a, const nat_char* b) { return strnatcmp0(a, b, 1); } @@ -328,12 +328,12 @@ char* dStrcpyl(char *dst, dsize_t dstSize, ...) } -int dStrcmp( const UTF16 *str1, const UTF16 *str2) +S32 dStrcmp( const UTF16 *str1, const UTF16 *str2) { -#if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) +#if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) return wcscmp( reinterpret_cast( str1 ), reinterpret_cast( str2 ) ); #else - int ret; + S32 ret; const UTF16 *a, *b; a = str1; b = str2; @@ -347,7 +347,7 @@ int dStrcmp( const UTF16 *str1, const UTF16 *str2) char* dStrupr(char *str) { -#if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) +#if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) return _strupr(str); #else if (str == NULL) @@ -365,7 +365,7 @@ char* dStrupr(char *str) char* dStrlwr(char *str) { -#if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) +#if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) return _strlwr(str); #else if (str == NULL) @@ -421,7 +421,7 @@ S32 dVsprintf(char *buffer, U32 bufferSize, const char *format, void *arglist) S32 dSscanf(const char *buffer, const char *format, ...) { -#if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) +#if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) va_list args; va_start(args, format); @@ -532,3 +532,32 @@ const char* dStristr( const char* str1, const char* str2 ) { return dStristr( const_cast< char* >( str1 ), str2 ); } + +int dStrrev(char* str) +{ + int l=dStrlen(str)-1; //get the string length + for(int x=0;x < l;x++,l--) + { + str[x]^=str[l]; //triple XOR Trick + str[l]^=str[x]; //for not using a temp + str[x]^=str[l]; + } + return l; +} + +int dItoa(int n, char s[]) +{ + int i, sign; + + if ((sign = n) < 0) /* record sign */ + n = -n; /* make n positive */ + i = 0; + do { /* generate digits in reverse order */ + s[i++] = n % 10 + '0'; /* get next digit */ + } while ((n /= 10) > 0); /* delete it */ + if (sign < 0) + s[i++] = '-'; + s[i] = '\0'; + dStrrev(s); + return dStrlen(s); +} diff --git a/Engine/source/core/strings/stringFunctions.h b/Engine/source/core/strings/stringFunctions.h index 34af03b9b..92602fd21 100644 --- a/Engine/source/core/strings/stringFunctions.h +++ b/Engine/source/core/strings/stringFunctions.h @@ -31,10 +31,12 @@ #include "platform/types.h" #endif -#if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) +#if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) // These standard functions are not defined on Win32 and other Microsoft platforms... #define strcasecmp _stricmp #define strncasecmp _strnicmp +#endif +#if (_MSC_VER < 1800) && (defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON)) #define strtof (float)strtod #endif @@ -52,22 +54,22 @@ inline char *dStrncat(char *dst, const char *src, dsize_t len) return strncat(dst,src,len); } -inline int dStrcmp(const char *str1, const char *str2) +inline S32 dStrcmp(const char *str1, const char *str2) { return strcmp(str1, str2); } -inline int dStrncmp(const char *str1, const char *str2, dsize_t len) +inline S32 dStrncmp(const char *str1, const char *str2, dsize_t len) { return strncmp(str1, str2, len); } -inline int dStricmp(const char *str1, const char *str2) +inline S32 dStricmp(const char *str1, const char *str2) { return strcasecmp( str1, str2 ); } -inline int dStrnicmp(const char *str1, const char *str2, dsize_t len) +inline S32 dStrnicmp(const char *str1, const char *str2, dsize_t len) { return strncasecmp( str1, str2, len ); } @@ -87,22 +89,22 @@ inline dsize_t dStrlen(const char *str) return strlen(str); } -inline char *dStrchr(char *str, int c) +inline char *dStrchr(char *str, S32 c) { return strchr(str,c); } -inline const char *dStrchr(const char *str, int c) +inline const char *dStrchr(const char *str, S32 c) { return strchr(str,c); } -inline char *dStrrchr(char *str, int c) +inline char *dStrrchr(char *str, S32 c) { return strrchr(str,c); } -inline const char *dStrrchr(const char *str, int c) +inline const char *dStrrchr(const char *str, S32 c) { return strrchr(str,c); } @@ -198,9 +200,9 @@ extern char *dStrlwr(char *str); extern char* dStrichr( char* str, char ch ); extern const char* dStrichr( const char* str, char ch ); -extern int dStrcmp(const UTF16 *str1, const UTF16 *str2); -extern int dStrnatcmp( const char* str1, const char* str2 ); -extern int dStrnatcasecmp( const char* str1, const char* str2 ); +extern S32 dStrcmp(const UTF16 *str1, const UTF16 *str2); +extern S32 dStrnatcmp( const char* str1, const char* str2 ); +extern S32 dStrnatcasecmp( const char* str1, const char* str2 ); inline bool dAtob(const char *str) { @@ -215,13 +217,16 @@ bool dStrEndsWith(const char* str1, const char* str2); char* dStripPath(const char* filename); +int dStrrev(char* str); +int dItoa(int n, char s[]); + //------------------------------------------------------------------------------ // standard I/O functions [defined in platformString.cpp] extern void dPrintf(const char *format, ...); -extern int dVprintf(const char *format, void *arglist); -extern int dSprintf(char *buffer, U32 bufferSize, const char *format, ...); -extern int dVsprintf(char *buffer, U32 bufferSize, const char *format, void *arglist); -extern int dSscanf(const char *buffer, const char *format, ...); +extern S32 dVprintf(const char *format, void *arglist); +extern S32 dSprintf(char *buffer, U32 bufferSize, const char *format, ...); +extern S32 dVsprintf(char *buffer, U32 bufferSize, const char *format, void *arglist); +extern S32 dSscanf(const char *buffer, const char *format, ...); #endif diff --git a/Engine/source/core/strings/unicode.cpp b/Engine/source/core/strings/unicode.cpp index 2edea59e8..b6c915e05 100644 --- a/Engine/source/core/strings/unicode.cpp +++ b/Engine/source/core/strings/unicode.cpp @@ -311,7 +311,7 @@ UTF32 oneUTF8toUTF32( const UTF8* codepoint, U32 *unitsWalked) U8 codeunit; // check the first byte ( a.k.a. codeunit ) . - unsigned char c = codepoint[0]; + U8 c = codepoint[0]; c = c >> 1; expectedByteCount = sgFirstByteLUT[c]; if(expectedByteCount > 0) // 0 or negative is illegal to start with @@ -469,7 +469,7 @@ U32 oneUTF32toUTF8(const UTF32 codepoint, UTF8 *threeByteCodeunitBuf) U8 marker = ( ~mask << 1); // 1000 0000 // Process the low order bytes, shifting the codepoint down 6 each pass. - for( int i = bytecount-1; i > 0; i--) + for( S32 i = bytecount-1; i > 0; i--) { threeByteCodeunitBuf[i] = marker | (working & mask); working >>= 6; diff --git a/Engine/source/core/tagDictionary.cpp b/Engine/source/core/tagDictionary.cpp index e31bb5e29..a25ed4f5b 100644 --- a/Engine/source/core/tagDictionary.cpp +++ b/Engine/source/core/tagDictionary.cpp @@ -308,7 +308,7 @@ bool TagDictionary::match(const char* pattern, const char* str) //------------------------------------------------------------------------------ -static int QSORT_CALLBACK idCompare(const void *in_p1, const void *in_p2) +static S32 QSORT_CALLBACK idCompare(const void *in_p1, const void *in_p2) { return *((S32 *) in_p1) - *((S32 *) in_p2); } diff --git a/Engine/source/core/threadStatic.cpp b/Engine/source/core/threadStatic.cpp index 511db4259..aff06730f 100644 --- a/Engine/source/core/threadStatic.cpp +++ b/Engine/source/core/threadStatic.cpp @@ -103,7 +103,7 @@ TorqueThreadStaticListHandle _TorqueThreadStaticReg::spawnThreadStaticsInstance( // Copy mThreadStaticInstances[0] (master copy) into new memory, and // pass it back. - for( int i = 0; i < getThreadStaticListVector()[0].size(); i++ ) + for( S32 i = 0; i < getThreadStaticListVector()[0].size(); i++ ) { getThreadStaticListVector().last().push_back( getThreadStaticListVector()[0][i]->_createInstance() ); } diff --git a/Engine/source/core/threadStatic.h b/Engine/source/core/threadStatic.h index 716d590b9..830ba260c 100644 --- a/Engine/source/core/threadStatic.h +++ b/Engine/source/core/threadStatic.h @@ -47,10 +47,12 @@ public: : mHitCount( 0 ) #endif { }; + virtual ~_TorqueThreadStatic() { } static const U32 getListIndex(){ return mListIndex; } virtual void *getMemInstPtr() = 0; + virtual const void *getConstMemInstPtr() const = 0; virtual const dsize_t getMemInstSize() const = 0; #ifdef TORQUE_ENABLE_THREAD_STATIC_METRICS @@ -142,6 +144,7 @@ private: public: TorqueThreadStatic( T instanceVal ) : mInstance( instanceVal ) {} virtual void *getMemInstPtr() { return &mInstance; } + virtual const void *getConstMemInstPtr() const { return &mInstance; } // I am not sure these are needed, and I don't want to create confusing-to-debug code #if 0 @@ -180,7 +183,7 @@ public: \ _##name##TorqueThreadStatic() : TorqueThreadStatic( initalvalue ) {} \ virtual const dsize_t getMemInstSize() const { return sizeof( type ); } \ type &_cast() { return *reinterpret_cast( getMemInstPtr() ); } \ - const type &_const_cast() const { return *reinterpret_cast( getMemInstPtr() ); } \ + const type &_const_cast() const { return *reinterpret_cast( getConstMemInstPtr() ); } \ }; \ static _##name##TorqueThreadStatic name##TorqueThreadStatic; \ static _TorqueThreadStaticReg _##name##TTSReg( reinterpret_cast<_TorqueThreadStatic *>( & name##TorqueThreadStatic ) ) diff --git a/Engine/source/core/util/FastDelegate.h b/Engine/source/core/util/FastDelegate.h index b977a6a12..f2494d475 100644 --- a/Engine/source/core/util/FastDelegate.h +++ b/Engine/source/core/util/FastDelegate.h @@ -174,7 +174,7 @@ inline OutputClass horrible_cast(const InputClass input){ // Cause a compile-time error if in, out and u are not the same size. // If the compile fails here, it means the compiler has peculiar // unions which would prevent the cast from working. - typedef int ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u) + typedef S32 ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u) && sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1]; u.in = input; return u.out; @@ -270,7 +270,7 @@ struct VoidToDefaultVoid { typedef DefaultVoid type; }; #endif // The size of a single inheritance member function pointer. -const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)()); +const S32 SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)()); // SimplifyMemFunc< >::Convert() // @@ -284,7 +284,7 @@ const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)()); // template specialisation, I use full specialisation of a wrapper struct. // general case -- don't know how to convert it. Force a compile failure -template +template struct SimplifyMemFunc { template inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, @@ -344,11 +344,11 @@ struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) > { XFuncType func; struct { GenericMemFuncType funcaddress; // points to the actual member function - int delta; // #BYTES to be added to the 'this' pointer + S32 delta; // #BYTES to be added to the 'this' pointer }s; } u; // Check that the horrible_cast will work - typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)? 1 : -1]; + typedef S32 ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)? 1 : -1]; u.func = function_to_bind; bound_func = u.s.funcaddress; return reinterpret_cast(reinterpret_cast(pthis) + u.s.delta); @@ -367,8 +367,8 @@ struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) > { // is internally defined as: struct MicrosoftVirtualMFP { void (GenericClass::*codeptr)(); // points to the actual member function - int delta; // #bytes to be added to the 'this' pointer - int vtable_index; // or 0 if no virtual inheritance + S32 delta; // #bytes to be added to the 'this' pointer + S32 vtable_index; // or 0 if no virtual inheritance }; // The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the // m_codeptr member is *always* called, regardless of the values of the other @@ -405,7 +405,7 @@ struct SimplifyMemFunc MicrosoftVirtualMFP s; } u2; // Check that the horrible_cast<>s will work - typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s) + typedef S32 ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s) && sizeof(function_to_bind)==sizeof(u.ProbeFunc) && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1]; // Unfortunately, taking the address of a MF prevents it from being inlined, so @@ -477,24 +477,24 @@ struct SimplifyMemFunc // is internally defined as: struct { GenericMemFuncType m_funcaddress; // points to the actual member function - int delta; // #bytes to be added to the 'this' pointer - int vtordisp; // #bytes to add to 'this' to find the vtable - int vtable_index; // or 0 if no virtual inheritance + S32 delta; // #bytes to be added to the 'this' pointer + S32 vtordisp; // #bytes to add to 'this' to find the vtable + S32 vtable_index; // or 0 if no virtual inheritance } s; } u; // Check that the horrible_cast will work - typedef int ERROR_CantUsehorrible_cast[sizeof(XFuncType)==sizeof(u.s)? 1 : -1]; + typedef S32 ERROR_CantUsehorrible_cast[sizeof(XFuncType)==sizeof(u.s)? 1 : -1]; u.func = function_to_bind; bound_func = u.s.funcaddress; - int virtual_delta = 0; + S32 virtual_delta = 0; if (u.s.vtable_index) { // Virtual inheritance is used // First, get to the vtable. // It is 'vtordisp' bytes from the start of the class. - const int * vtable = *reinterpret_cast( + const S32 * vtable = *reinterpret_cast( reinterpret_cast(pthis) + u.s.vtordisp ); // 'vtable_index' tells us where in the table we should be looking. - virtual_delta = u.s.vtordisp + *reinterpret_cast( + virtual_delta = u.s.vtordisp + *reinterpret_cast( reinterpret_cast(vtable) + u.s.vtable_index); } // The int at 'virtual_delta' gives us the amount to add to 'this'. @@ -777,7 +777,7 @@ public: // Ensure that there's a compilation failure if function pointers // and data pointers have different sizes. // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. - typedef int ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1]; + typedef S32 ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1]; m_pthis = horrible_cast(function_to_bind); // MSVC, SunC++ and DMC accept the following (non-standard) code: // m_pthis = static_cast(static_cast(function_to_bind)); @@ -792,7 +792,7 @@ public: // Ensure that there's a compilation failure if function pointers // and data pointers have different sizes. // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. - typedef int ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1]; + typedef S32 ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1]; return horrible_cast(this); } #endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) @@ -906,7 +906,7 @@ public: // Implicit conversion to "bool" using the safe_bool idiom private: typedef struct SafeBoolStruct { - int a_data_pointer_to_this_is_0_on_buggy_compilers; + S32 a_data_pointer_to_this_is_0_on_buggy_compilers; StaticFunctionPtr m_nonzero; } UselessTypedef; typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; @@ -991,7 +991,7 @@ public: // Implicit conversion to "bool" using the safe_bool idiom private: typedef struct SafeBoolStruct { - int a_data_pointer_to_this_is_0_on_buggy_compilers; + S32 a_data_pointer_to_this_is_0_on_buggy_compilers; StaticFunctionPtr m_nonzero; } UselessTypedef; typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; @@ -1076,7 +1076,7 @@ public: // Implicit conversion to "bool" using the safe_bool idiom private: typedef struct SafeBoolStruct { - int a_data_pointer_to_this_is_0_on_buggy_compilers; + S32 a_data_pointer_to_this_is_0_on_buggy_compilers; StaticFunctionPtr m_nonzero; } UselessTypedef; typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; @@ -1161,7 +1161,7 @@ public: // Implicit conversion to "bool" using the safe_bool idiom private: typedef struct SafeBoolStruct { - int a_data_pointer_to_this_is_0_on_buggy_compilers; + S32 a_data_pointer_to_this_is_0_on_buggy_compilers; StaticFunctionPtr m_nonzero; } UselessTypedef; typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; @@ -1246,7 +1246,7 @@ public: // Implicit conversion to "bool" using the safe_bool idiom private: typedef struct SafeBoolStruct { - int a_data_pointer_to_this_is_0_on_buggy_compilers; + S32 a_data_pointer_to_this_is_0_on_buggy_compilers; StaticFunctionPtr m_nonzero; } UselessTypedef; typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; @@ -1331,7 +1331,7 @@ public: // Implicit conversion to "bool" using the safe_bool idiom private: typedef struct SafeBoolStruct { - int a_data_pointer_to_this_is_0_on_buggy_compilers; + S32 a_data_pointer_to_this_is_0_on_buggy_compilers; StaticFunctionPtr m_nonzero; } UselessTypedef; typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; @@ -1416,7 +1416,7 @@ public: // Implicit conversion to "bool" using the safe_bool idiom private: typedef struct SafeBoolStruct { - int a_data_pointer_to_this_is_0_on_buggy_compilers; + S32 a_data_pointer_to_this_is_0_on_buggy_compilers; StaticFunctionPtr m_nonzero; } UselessTypedef; typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; @@ -1501,7 +1501,7 @@ public: // Implicit conversion to "bool" using the safe_bool idiom private: typedef struct SafeBoolStruct { - int a_data_pointer_to_this_is_0_on_buggy_compilers; + S32 a_data_pointer_to_this_is_0_on_buggy_compilers; StaticFunctionPtr m_nonzero; } UselessTypedef; typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; @@ -1586,7 +1586,7 @@ public: // Implicit conversion to "bool" using the safe_bool idiom private: typedef struct SafeBoolStruct { - int a_data_pointer_to_this_is_0_on_buggy_compilers; + S32 a_data_pointer_to_this_is_0_on_buggy_compilers; StaticFunctionPtr m_nonzero; } UselessTypedef; typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; @@ -1671,7 +1671,7 @@ public: // Implicit conversion to "bool" using the safe_bool idiom private: typedef struct SafeBoolStruct { - int a_data_pointer_to_this_is_0_on_buggy_compilers; + S32 a_data_pointer_to_this_is_0_on_buggy_compilers; StaticFunctionPtr m_nonzero; } UselessTypedef; typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; @@ -1756,7 +1756,7 @@ public: // Implicit conversion to "bool" using the safe_bool idiom private: typedef struct SafeBoolStruct { - int a_data_pointer_to_this_is_0_on_buggy_compilers; + S32 a_data_pointer_to_this_is_0_on_buggy_compilers; StaticFunctionPtr m_nonzero; } UselessTypedef; typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; @@ -1841,7 +1841,7 @@ public: // Implicit conversion to "bool" using the safe_bool idiom private: typedef struct SafeBoolStruct { - int a_data_pointer_to_this_is_0_on_buggy_compilers; + S32 a_data_pointer_to_this_is_0_on_buggy_compilers; StaticFunctionPtr m_nonzero; } UselessTypedef; typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; diff --git a/Engine/source/core/util/delegate.h b/Engine/source/core/util/delegate.h index 6dbf1f668..0b1e51ec5 100644 --- a/Engine/source/core/util/delegate.h +++ b/Engine/source/core/util/delegate.h @@ -55,7 +55,7 @@ public: } protected: - int mOffset; + S32 mOffset; }; #endif // _UTIL_DELEGATE_H_ \ No newline at end of file diff --git a/Engine/source/core/util/dxt5nmSwizzle.h b/Engine/source/core/util/dxt5nmSwizzle.h index 555a21eee..58acbac66 100644 --- a/Engine/source/core/util/dxt5nmSwizzle.h +++ b/Engine/source/core/util/dxt5nmSwizzle.h @@ -37,7 +37,7 @@ public: volatile U8 *u8Mem = reinterpret_cast( memory ); - for( int i = 0; i < size >> 2; i++ ) + for( S32 i = 0; i < size >> 2; i++ ) { // g = garbage byte // Input: [X|Y|Z|g] (rgba) @@ -57,7 +57,7 @@ public: volatile const U8 *srcU8 = reinterpret_cast( source ); volatile U8 *dstU8 = reinterpret_cast( destination ); - for( int i = 0; i < size >> 2; i++ ) + for( S32 i = 0; i < size >> 2; i++ ) { // g = garbage byte // Input: [X|Y|Z|g] (rgba) @@ -85,13 +85,13 @@ public: virtual void ToBuffer( void *destination, const void *source, const dsize_t size ) const { AssertFatal( size % 3 == 0, "Bad buffer size for DXT5nm Swizzle" ); - const int pixels = size / 3; + const S32 pixels = size / 3; volatile const U8 *srcU8 = reinterpret_cast( source ); volatile U8 *dstU8 = reinterpret_cast( destination ); // destination better damn well be the right size - for( int i = 0; i < pixels; i++ ) + for( S32 i = 0; i < pixels; i++ ) { // g = garbage byte // Input: [X|Y|Z|g] (rgba) diff --git a/Engine/source/core/util/journal/process.h b/Engine/source/core/util/journal/process.h index 19040e747..4d21898d9 100644 --- a/Engine/source/core/util/journal/process.h +++ b/Engine/source/core/util/journal/process.h @@ -96,6 +96,11 @@ public: get()._signalProcess.notify(del,order); } + static void notify(SignalSlot &slot, F32 order = PROCESS_DEFAULT_ORDER) + { + get()._signalProcess.notify(slot,order); + } + template static void notify(T func, F32 order = PROCESS_DEFAULT_ORDER) { diff --git a/Engine/source/core/util/journal/test/journalTest.cpp b/Engine/source/core/util/journal/test/journalTest.cpp new file mode 100644 index 000000000..fc638f11c --- /dev/null +++ b/Engine/source/core/util/journal/test/journalTest.cpp @@ -0,0 +1,189 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "core/util/journal/journaledSignal.h" +#include "core/util/safeDelete.h" + +FIXTURE(Journal) +{ +public: + // Used for basic API test. + struct receiver + { + U16 lastTriggerValue; + void trigger(U16 msg) + { + lastTriggerValue = msg; + } + }; + + // Used for non-basic test. + typedef JournaledSignal EventA; + typedef JournaledSignal EventB; + typedef JournaledSignal EventC; + + // Root, non-dynamic signal receiver. + struct multiReceiver { + U32 recvA, recvB, recvC; + + EventA *dynamicA; + EventB *dynamicB; + EventC *dynamicC; + + void receiverRoot(U8 msg) + { + if(msg==1) + { + dynamicA = new EventA(); + dynamicA->notify(this, &multiReceiver::receiverA); + } + + if(msg==2) + { + dynamicB = new EventB(); + dynamicB->notify(this, &multiReceiver::receiverB); + } + + if(msg==3) + { + dynamicC = new EventC(); + dynamicC->notify(this, &multiReceiver::receiverC); + } + } + + void receiverA(U32, U16 d) + { + recvA += d; + } + + void receiverB(U8, S8 d) + { + recvB += d; + } + + void receiverC(U32, S32 d) + { + recvC += d; + } + }; +}; + +TEST_FIX(Journal, BasicAPI) +{ + receiver rec; + rec.lastTriggerValue = 0; + + // Set up a journaled signal to test with. + JournaledSignal testEvent; + testEvent.notify(&rec, &receiver::trigger); + + // Initialize journal recording and fire off some events... + Journal::Record("test.jrn"); + ASSERT_TRUE(Journal::IsRecording()); + + testEvent.trigger(16); + testEvent.trigger(17); + testEvent.trigger(18); + + EXPECT_EQ(rec.lastTriggerValue, 18) + << "Should encounter last triggered value (18)."; + + Journal::Stop(); + ASSERT_FALSE(Journal::IsRecording()); + + // Clear it... + rec.lastTriggerValue = 0; + + // and play back - should get same thing. + Journal::Play("test.jrn"); + + // Since we fired 3 events, it should take three loops. + EXPECT_TRUE(Journal::PlayNext()) << "Should be two more events."; + EXPECT_TRUE(Journal::PlayNext()) << "Should be one more event."; + EXPECT_FALSE(Journal::PlayNext()) << "Should be no more events."; + + EXPECT_EQ(rec.lastTriggerValue, 18) + << "Should encounter last journaled value (18)."; +} + +TEST_FIX(Journal, DynamicSignals) +{ + multiReceiver rec; + + // Reset our state values. + rec.recvA = rec.recvB = rec.recvC = 0; + + // Set up a signal to start with. + JournaledSignal testEvent; + testEvent.notify(&rec, &multiReceiver::receiverRoot); + + // Initialize journal recording and fire off some events... + Journal::Record("test.jrn"); + ASSERT_TRUE(Journal::IsRecording()); + + testEvent.trigger(1); + rec.dynamicA->trigger(8, 100); + testEvent.trigger(2); + rec.dynamicA->trigger(8, 8); + rec.dynamicB->trigger(9, 'a'); + testEvent.trigger(3); + SAFE_DELETE(rec.dynamicB); // Test a deletion. + rec.dynamicC->trigger(8, 1); + rec.dynamicC->trigger(8, 1); + + // Did we end up with expected values? Check before clearing. + EXPECT_EQ(rec.recvA, 108) << "recvA wasn't 108 - something broken in signals?"; + EXPECT_EQ(rec.recvB, 'a') << "recvB wasn't 'a' - something broken in signals?"; + EXPECT_EQ(rec.recvC, 2) << "recvC wasn't 2 - something broken in signals?"; + + // Reset our state values. + rec.recvA = rec.recvB = rec.recvC = 0; + + // And kill the journal... + Journal::Stop(); + + // Also kill our remaining dynamic signals. + SAFE_DELETE(rec.dynamicA); + SAFE_DELETE(rec.dynamicB); + SAFE_DELETE(rec.dynamicC); + + // Play back - should get same thing. + Journal::Play("test.jrn"); + + // Since we fired 8 events, it should take 7+1=8 loops. + for(S32 i = 0; i < 7; i++) + { + EXPECT_TRUE(Journal::PlayNext()) + << "Should be more events."; + } + + EXPECT_FALSE(Journal::PlayNext()) + << "Should be no more events."; + + EXPECT_EQ(rec.recvA, 108) << "recvA wasn't 108 - something broken in journal?"; + EXPECT_EQ(rec.recvB, 'a') << "recvB wasn't 'a' - something broken in journal?"; + EXPECT_EQ(rec.recvC, 2) << "recvC wasn't 2 - something broken in journal?"; +} + +#endif diff --git a/Engine/source/core/util/journal/test/testProcess.cpp b/Engine/source/core/util/journal/test/processTest.cpp similarity index 62% rename from Engine/source/core/util/journal/test/testProcess.cpp rename to Engine/source/core/util/journal/test/processTest.cpp index 1dc847b34..1b011a397 100644 --- a/Engine/source/core/util/journal/test/testProcess.cpp +++ b/Engine/source/core/util/journal/test/processTest.cpp @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC +// Copyright (c) 2014 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to @@ -20,37 +20,41 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "unit/test.h" +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" #include "core/util/journal/process.h" -#include "core/util/safeDelete.h" -using namespace UnitTesting; - -CreateUnitTest(TestingProcess, "Journal/Process") +FIXTURE(Process) { - // How many ticks remaining? - U32 _remainingTicks; - - // Callback for process list. - void process() +public: + U32 remainingTicks; + void notification() { - if(_remainingTicks==0) + if(remainingTicks == 0) Process::requestShutdown(); - - _remainingTicks--; + remainingTicks--; } +}; - void run() +TEST_FIX(Process, BasicAPI) +{ + // We'll run 30 ticks, then quit. + remainingTicks = 30; + + // Register with the process list. + Process::notify(this, &ProcessFixture::notification); + + // And do 30 notifies, making sure we end on the 30th. + for(S32 i = 0; i < 30; i++) { - // We'll run 30 ticks, then quit. - _remainingTicks = 30; - - // Register with the process list. - Process::notify(this, &TestingProcess::process); - - // And do 30 notifies, making sure we end on the 30th. - for(S32 i=0; i<30; i++) - test(Process::processEvents(), "Should quit after 30 ProcessEvents() calls - not before!"); - test(!Process::processEvents(), "Should quit after the 30th ProcessEvent() call!"); + EXPECT_TRUE(Process::processEvents()) + << "Should quit after 30 ProcessEvents() calls - not before!"; } -}; \ No newline at end of file + + EXPECT_FALSE(Process::processEvents()) + << "Should quit after the 30th ProcessEvent() call!"; + + Process::remove(this, &ProcessFixture::notification); +}; + +#endif \ No newline at end of file diff --git a/Engine/source/core/util/journal/test/testJournal.cpp b/Engine/source/core/util/journal/test/testJournal.cpp deleted file mode 100644 index 404f7637e..000000000 --- a/Engine/source/core/util/journal/test/testJournal.cpp +++ /dev/null @@ -1,173 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "unit/test.h" -#include "core/util/journal/journaledSignal.h" -#include "core/util/safeDelete.h" - -using namespace UnitTesting; - -CreateUnitTest(TestsJournalRecordAndPlayback, "Journal/Basic") -{ - U32 _lastTriggerValue; - - void triggerReceiver(U16 msg) - { - _lastTriggerValue = msg; - } - - void run() - { - // Reset the last trigger value just in case... - _lastTriggerValue = 0; - - // Set up a journaled signal to test with. - JournaledSignal testEvent; - - testEvent.notify(this, &TestsJournalRecordAndPlayback::triggerReceiver); - - // Initialize journal recording and fire off some events... - Journal::Record("test.jrn"); - - testEvent.trigger(16); - testEvent.trigger(17); - testEvent.trigger(18); - - test(_lastTriggerValue == 18, "Should encounter last triggered value (18)."); - - Journal::Stop(); - - // Clear it... - _lastTriggerValue = 0; - - // and play back - should get same thing. - Journal::Play("test.jrn"); - - // Since we fired 3 events, it should take three loops. - test(Journal::PlayNext(), "Should be two more events."); - test(Journal::PlayNext(), "Should be one more event."); - test(!Journal::PlayNext(), "Should be no more events."); - - test(_lastTriggerValue == 18, "Should encounter last journaled value (18)."); - } -}; - -CreateUnitTest(TestsJournalDynamicSignals, "Journal/DynamicSignals") -{ - typedef JournaledSignal EventA; - typedef JournaledSignal EventB; - typedef JournaledSignal EventC; - - EventA *dynamicA; - EventB *dynamicB; - EventC *dynamicC; - - // Root, non-dynamic signal receiver. - void receiverRoot(U8 msg) - { - if(msg==1) - { - dynamicA = new EventA(); - dynamicA->notify(this, &TestsJournalDynamicSignals::receiverA); - } - - if(msg==2) - { - dynamicB = new EventB(); - dynamicB->notify(this, &TestsJournalDynamicSignals::receiverB); - } - - if(msg==3) - { - dynamicC = new EventC(); - dynamicC->notify(this, &TestsJournalDynamicSignals::receiverC); - } - } - - U32 recvA, recvB, recvC; - - void receiverA(U32, U16 d) - { - recvA += d; - } - - void receiverB(U8, S8 d) - { - recvB += d; - } - - void receiverC(U32, S32 d) - { - recvC += d; - } - - void run() - { - // Reset our state values. - recvA = recvB = recvC = 0; - - // Set up a signal to start with. - JournaledSignal testEvent; - testEvent.notify(this, &TestsJournalDynamicSignals::receiverRoot); - - // Initialize journal recording and fire off some events... - Journal::Record("test.jrn"); - - testEvent.trigger(1); - dynamicA->trigger(8, 100); - testEvent.trigger(2); - dynamicA->trigger(8, 8); - dynamicB->trigger(9, 'a'); - testEvent.trigger(3); - SAFE_DELETE(dynamicB); // Test a deletion. - dynamicC->trigger(8, 1); - dynamicC->trigger(8, 1); - - // Did we end up with expected values? Check before clearing. - test(recvA == 108, "recvA wasn't 108 - something broken in signals?"); - test(recvB == 'a', "recvB wasn't 'a' - something broken in signals?"); - test(recvC == 2, "recvC wasn't 2 - something broken in signals?"); - - // Reset our state values. - recvA = recvB = recvC = 0; - - // And kill the journal... - Journal::Stop(); - - // Also kill our remaining dynamic signals. - SAFE_DELETE(dynamicA); - SAFE_DELETE(dynamicB); - SAFE_DELETE(dynamicC); - - // Play back - should get same thing. - Journal::Play("test.jrn"); - - // Since we fired 8 events, it should take 7+1=8 loops. - for(S32 i=0; i<7; i++) - test(Journal::PlayNext(), "Should be more events."); - test(!Journal::PlayNext(), "Should be no more events."); - - test(recvA == 108, "recvA wasn't 108 - something broken in journal?"); - test(recvB == 'a', "recvB wasn't 'a' - something broken in journal?"); - test(recvC == 2, "recvC wasn't 2 - something broken in journal?"); - } -}; diff --git a/Engine/source/core/util/md5.cpp b/Engine/source/core/util/md5.cpp index 8358d7655..41503cb86 100644 --- a/Engine/source/core/util/md5.cpp +++ b/Engine/source/core/util/md5.cpp @@ -154,7 +154,7 @@ void MD5Final( unsigned char digest[16], MD5Context* ctx) MD5Transform(ctx->buf, (int *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); memcpy(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ + memset(ctx, 0, sizeof(MD5Context)); /* In case it's sensitive */ } diff --git a/Engine/source/core/util/path.cpp b/Engine/source/core/util/path.cpp index 5bcea08fb..f188b5342 100644 --- a/Engine/source/core/util/path.cpp +++ b/Engine/source/core/util/path.cpp @@ -56,7 +56,7 @@ void Path::_split(String name) idx = name.find('/', 0, String::Right); if (idx >= pos) { - int len = idx - pos; + S32 len = idx - pos; mPath = name.substr(pos,len? len: 1); mPath = Path::CleanSeparators(mPath); pos = idx + 1; @@ -408,7 +408,7 @@ String Path::getDirectory(U32 count) const U32 end = offset; - while (mPath[end] != '/' && end < mPath.length()) + while (end < mPath.length() && mPath[end] != '/') end++; return mPath.substr(offset,end - offset); diff --git a/Engine/source/core/util/path.h b/Engine/source/core/util/path.h index 604b48f76..73cc5af13 100644 --- a/Engine/source/core/util/path.h +++ b/Engine/source/core/util/path.h @@ -40,7 +40,7 @@ class Path public: enum Separator { -#if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XENON) +#if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XENON) OsSeparator = '\\' #else OsSeparator = '/' diff --git a/Engine/source/core/util/str.cpp b/Engine/source/core/util/str.cpp index 9a89ef2a1..36b0637de 100644 --- a/Engine/source/core/util/str.cpp +++ b/Engine/source/core/util/str.cpp @@ -760,7 +760,7 @@ String& String::operator=(const String &src) String& String::operator+=(const StringChar *src) { - if( src == NULL && !*src ) + if( src == NULL || !*src ) return *this; // Append the given string into a new string @@ -1419,7 +1419,7 @@ void String::copy(StringChar* dst, const StringChar *src, U32 len) //----------------------------------------------------------------------------- -#if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) +#if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) // This standard function is not defined when compiling with VC7... #define vsnprintf _vsnprintf #endif diff --git a/Engine/source/core/util/swizzle.h b/Engine/source/core/util/swizzle.h index 4cf929fce..abbff288f 100644 --- a/Engine/source/core/util/swizzle.h +++ b/Engine/source/core/util/swizzle.h @@ -126,11 +126,11 @@ inline void Swizzle::ToBuffer( void *destination, const void *sour T *dest = reinterpret_cast( destination ); const T *src = reinterpret_cast( source ); - for( int i = 0; i < size / ( mapLength * sizeof( T ) ); i++ ) + for( S32 i = 0; i < size / ( mapLength * sizeof( T ) ); i++ ) { dMemcpy( dest, src, mapLength * sizeof( T ) ); - for( int j = 0; j < mapLength; j++ ) + for( S32 j = 0; j < mapLength; j++ ) *dest++ = src[mMap[j]]; src += mapLength; diff --git a/Engine/source/core/util/swizzleSpec.h b/Engine/source/core/util/swizzleSpec.h index d45273498..ee0259ac4 100644 --- a/Engine/source/core/util/swizzleSpec.h +++ b/Engine/source/core/util/swizzleSpec.h @@ -37,7 +37,7 @@ inline void Swizzle::InPlace( void *memory, const dsize_t size ) const U8 *src = reinterpret_cast( memory ); // Fast divide by 4 since we are assured a proper size - for( int i = 0; i < size >> 2; i++ ) + for( S32 i = 0; i < size >> 2; i++ ) { BYTESWAP( *dest++, src[mMap[0]] ); BYTESWAP( *dest++, src[mMap[1]] ); @@ -57,7 +57,7 @@ inline void Swizzle::ToBuffer( void *destination, const void *source, con const U8 *src = reinterpret_cast( source ); // Fast divide by 4 since we are assured a proper size - for( int i = 0; i < size >> 2; i++ ) + for( S32 i = 0; i < size >> 2; i++ ) { *dest++ = src[mMap[0]]; *dest++ = src[mMap[1]]; @@ -80,7 +80,7 @@ inline void Swizzle::InPlace( void *memory, const dsize_t size ) const U8 *dest = reinterpret_cast( memory ); U8 *src = reinterpret_cast( memory ); - for( int i = 0; i < size /3; i++ ) + for( S32 i = 0; i < size /3; i++ ) { BYTESWAP( *dest++, src[mMap[0]] ); BYTESWAP( *dest++, src[mMap[1]] ); @@ -98,7 +98,7 @@ inline void Swizzle::ToBuffer( void *destination, const void *source, con U8 *dest = reinterpret_cast( destination ); const U8 *src = reinterpret_cast( source ); - for( int i = 0; i < size / 3; i++ ) + for( S32 i = 0; i < size / 3; i++ ) { *dest++ = src[mMap[0]]; *dest++ = src[mMap[1]]; diff --git a/Engine/source/core/util/tFixedSizeVector.h b/Engine/source/core/util/tFixedSizeVector.h index cab8a2186..fedd12587 100644 --- a/Engine/source/core/util/tFixedSizeVector.h +++ b/Engine/source/core/util/tFixedSizeVector.h @@ -25,7 +25,7 @@ /// A vector with a compile-time constant size. -template< typename T, int SIZE > +template< typename T, S32 SIZE > class FixedSizeVector { protected: @@ -46,19 +46,19 @@ class FixedSizeVector FixedSizeVector( const T& a, const T& b, const T& c, const T& d, const T& e, const T& f ) { mArray[ 0 ] = a; mArray[ 1 ] = b; mArray[ 2 ] = c; mArray[ 3 ] = d; mArray[ 4 ] = e; mArray[ 5 ] = f; } FixedSizeVector( const T& a, const T& b, const T& c, const T& d, const T& e, const T& f, const T& g ) - { mArray[ 0 ] = a; mArray[ 1 ] = b; mArray[ 2 ] = c; mArray[ 3 ] = d; mArray[ 4 ] = e; mArray[ 5 ] = f; mArray[ 6 ]; } + { mArray[ 0 ] = a; mArray[ 1 ] = b; mArray[ 2 ] = c; mArray[ 3 ] = d; mArray[ 4 ] = e; mArray[ 5 ] = f; mArray[ 6 ] = g; } FixedSizeVector( const T& a, const T& b, const T& c, const T& d, const T& e, const T& f, const T& g, const T& h ) - { mArray[ 0 ] = a; mArray[ 1 ] = b; mArray[ 2 ] = c; mArray[ 3 ] = d; mArray[ 4 ] = e; mArray[ 5 ] = f; mArray[ 6 ]; mArray[ 7 ] = h; } + { mArray[ 0 ] = a; mArray[ 1 ] = b; mArray[ 2 ] = c; mArray[ 3 ] = d; mArray[ 4 ] = e; mArray[ 5 ] = f; mArray[ 6 ] = g; mArray[ 7 ] = h; } FixedSizeVector( const T& a, const T& b, const T& c, const T& d, const T& e, const T& f, const T& g, const T& h, const T& i ) - { mArray[ 0 ] = a; mArray[ 1 ] = b; mArray[ 2 ] = c; mArray[ 3 ] = d; mArray[ 4 ] = e; mArray[ 5 ] = f; mArray[ 6 ]; mArray[ 7 ] = h; mArray[ 8 ] = i; } + { mArray[ 0 ] = a; mArray[ 1 ] = b; mArray[ 2 ] = c; mArray[ 3 ] = d; mArray[ 4 ] = e; mArray[ 5 ] = f; mArray[ 6 ] = g; mArray[ 7 ] = h; mArray[ 8 ] = i; } FixedSizeVector( const T& a, const T& b, const T& c, const T& d, const T& e, const T& f, const T& g, const T& h, const T& i, const T& j ) - { mArray[ 0 ] = a; mArray[ 1 ] = b; mArray[ 2 ] = c; mArray[ 3 ] = d; mArray[ 4 ] = e; mArray[ 5 ] = f; mArray[ 6 ]; mArray[ 7 ] = h; mArray[ 8 ] = i; mArray[ 9 ] = j; } + { mArray[ 0 ] = a; mArray[ 1 ] = b; mArray[ 2 ] = c; mArray[ 3 ] = d; mArray[ 4 ] = e; mArray[ 5 ] = f; mArray[ 6 ] = g; mArray[ 7 ] = h; mArray[ 8 ] = i; mArray[ 9 ] = j; } FixedSizeVector( const T& a, const T& b, const T& c, const T& d, const T& e, const T& f, const T& g, const T& h, const T& i, const T& j, const T& k ) - { mArray[ 0 ] = a; mArray[ 1 ] = b; mArray[ 2 ] = c; mArray[ 3 ] = d; mArray[ 4 ] = e; mArray[ 5 ] = f; mArray[ 6 ]; mArray[ 7 ] = h; mArray[ 8 ] = i; mArray[ 9 ] = j; mArray[ 10 ] = k; } + { mArray[ 0 ] = a; mArray[ 1 ] = b; mArray[ 2 ] = c; mArray[ 3 ] = d; mArray[ 4 ] = e; mArray[ 5 ] = f; mArray[ 6 ] = g; mArray[ 7 ] = h; mArray[ 8 ] = i; mArray[ 9 ] = j; mArray[ 10 ] = k; } FixedSizeVector( const T& a, const T& b, const T& c, const T& d, const T& e, const T& f, const T& g, const T& h, const T& i, const T& j, const T& k, const T& l ) - { mArray[ 0 ] = a; mArray[ 1 ] = b; mArray[ 2 ] = c; mArray[ 3 ] = d; mArray[ 4 ] = e; mArray[ 5 ] = f; mArray[ 6 ]; mArray[ 7 ] = h; mArray[ 8 ] = i; mArray[ 9 ] = j; mArray[ 10 ] = k; mArray[ 11 ] = l; } + { mArray[ 0 ] = a; mArray[ 1 ] = b; mArray[ 2 ] = c; mArray[ 3 ] = d; mArray[ 4 ] = e; mArray[ 5 ] = f; mArray[ 6 ] = g; mArray[ 7 ] = h; mArray[ 8 ] = i; mArray[ 9 ] = j; mArray[ 10 ] = k; mArray[ 11 ] = l; } FixedSizeVector( const T& a, const T& b, const T& c, const T& d, const T& e, const T& f, const T& g, const T& h, const T& i, const T& j, const T& k, const T& l, const T& m ) - { mArray[ 0 ] = a; mArray[ 1 ] = b; mArray[ 2 ] = c; mArray[ 3 ] = d; mArray[ 4 ] = e; mArray[ 5 ] = f; mArray[ 6 ]; mArray[ 7 ] = h; mArray[ 8 ] = i; mArray[ 9 ] = j; mArray[ 10 ] = k; mArray[ 11 ] = l; mArray[ 12 ] =m; } + { mArray[ 0 ] = a; mArray[ 1 ] = b; mArray[ 2 ] = c; mArray[ 3 ] = d; mArray[ 4 ] = e; mArray[ 5 ] = f; mArray[ 6 ] = g; mArray[ 7 ] = h; mArray[ 8 ] = i; mArray[ 9 ] = j; mArray[ 10 ] = k; mArray[ 11 ] = l; mArray[ 12 ] =m; } U32 size() const { return SIZE; } bool empty() const { return ( SIZE == 0 ); } diff --git a/Engine/source/core/util/tSignal.cpp b/Engine/source/core/util/tSignal.cpp index 8bc5e8164..30980a715 100644 --- a/Engine/source/core/util/tSignal.cpp +++ b/Engine/source/core/util/tSignal.cpp @@ -24,7 +24,7 @@ #include "core/util/tSignal.h" -void SignalBase::DelegateLink::insert(DelegateLink* node, float order) +void SignalBase::DelegateLink::insert(DelegateLink* node, F32 order) { // Note: can only legitimately be called on list head DelegateLink * walk = next; diff --git a/Engine/source/core/util/tSignal.h b/Engine/source/core/util/tSignal.h index ea2e67954..206533458 100644 --- a/Engine/source/core/util/tSignal.h +++ b/Engine/source/core/util/tSignal.h @@ -54,7 +54,6 @@ public: { mList.next = mList.prev = &mList; mList.order = 0.5f; - mTriggerNext = NULL; } ~SignalBase(); @@ -77,6 +76,8 @@ protected: void insert(DelegateLink* node, F32 order); void unlink(); + + virtual ~DelegateLink() {} }; DelegateLink mList; @@ -92,6 +93,78 @@ protected: Vector mTriggerNext; }; +template class SignalBaseT; + +/// Class for handle automatic diconnect form Signal when destroyed +template< typename Signature > +class SignalSlot +{ +public: + typedef Delegate< Signature > DelegateSig; + typedef SignalBaseT< Signature > SignalSig; + + SignalSlot() : mSignal(NULL) + { + + } + + ~SignalSlot() + { + disconnect(); + } + + const DelegateSig& getDelegate() { return mDlg; } + + /// setDelegate disconect form Signal old delegate and connect new delegate + template + void setDelegate( const X &fn ) { setDelegate( DelegateSig( fn ) ); } + + template + void setDelegate( const X &ptr, const Y &fn ) { setDelegate( DelegateSig( ptr, fn ) ); } + + void setDelegate( const DelegateSig &dlg) + { + SignalSig* signal = mSignal; + if( isConnected() ) + disconnect(); + + mDlg = dlg; + if( signal && mDlg ) + signal->notify( mDlg ); + } + + /// is connected to Signal + bool isConnected() const { return mSignal; } + + /// disconnect from Signal + void disconnect() + { + if( mSignal ) + { + SignalSig *oldSignal = mSignal; + mSignal = NULL; + oldSignal->remove( mDlg ); + } + } + +protected: + friend class SignalBaseT< Signature >; + + void _setSignal(SignalSig *sig) + { + mSignal = sig; + } + + SignalSig* _getSignal() const { return mSignal; } + + DelegateSig mDlg; + SignalSig *mSignal; + +private: + SignalSlot( const SignalSlot&) {} + SignalSlot& operator=( const SignalSlot&) {} +}; + template class SignalBaseT : public SignalBase { public: @@ -135,7 +208,7 @@ public: { if( del->mDelegate == dlg ) { - for ( int i = 0; i < mTriggerNext.size(); i++ ) + for ( S32 i = 0; i < mTriggerNext.size(); i++ ) { if( mTriggerNext[i] == ptr ) mTriggerNext[i] = ptr->next; @@ -163,6 +236,18 @@ public: notify(dlg, order); } + void notify( SignalSlot &slot, F32 order = 0.5f) + { + if( !slot.getDelegate() ) + return; + + if( slot.isConnected() ) + slot.disconnect(); + + slot._setSignal( this ); + mList.insert( new SlotLinkImpl(slot), order ); + } + template void remove(T obj,U func) { @@ -198,6 +283,23 @@ protected: DelegateLinkImpl(DelegateSig dlg) : mDelegate(dlg) {} }; + struct SlotLinkImpl : public DelegateLinkImpl + { + SlotLinkImpl(SignalSlot& slot) : mSlot( &slot ), DelegateLinkImpl( slot.getDelegate() ) + { + + } + + ~SlotLinkImpl() + { + if( mSlot ) + mSlot->_setSignal( NULL ); + } + + protected: + SignalSlot *mSlot; + }; + DelegateSig & getDelegate(SignalBase::DelegateLink * link) { return ((DelegateLinkImpl*)link)->mDelegate; diff --git a/Engine/source/core/util/tVector.h b/Engine/source/core/util/tVector.h index 457ac5245..5042c4ba8 100644 --- a/Engine/source/core/util/tVector.h +++ b/Engine/source/core/util/tVector.h @@ -28,6 +28,7 @@ #ifndef _PLATFORM_H_ #include "platform/platform.h" #endif +#include //----------------------------------------------------------------------------- // Helper definitions for the vector class. @@ -181,6 +182,9 @@ class Vector /// void merge( const T *addr, U32 count ); + // Reverses the order of elements. + void reverse(); + /// @} }; @@ -504,7 +508,7 @@ template inline void Vector::compact() resize(mElementCount); } -typedef int (QSORT_CALLBACK *qsort_compare_func)(const void *, const void *); +typedef S32 (QSORT_CALLBACK *qsort_compare_func)(const void *, const void *); template inline void Vector::sort(compare_func f) { @@ -760,6 +764,12 @@ template inline void Vector::merge( const T *addr, U32 count ) mElementCount = newSize; } +template inline void Vector::reverse() +{ + for (U32 i = 0, j = size(); (i != j) && (i != --j); ++i) + std::swap( mArray[ i ], mArray[ j ] ); +} + //----------------------------------------------------------------------------- /// Template for vectors of pointers. template @@ -790,7 +800,7 @@ class VectorPtr : public Vector const_iterator end() const; void insert(iterator,const T&); - void insert(int idx) { Parent::insert(idx); } + void insert(S32 idx) { Parent::insert(idx); } void erase(iterator); T& front(); diff --git a/Engine/source/core/util/test/pathTest.cpp b/Engine/source/core/util/test/pathTest.cpp new file mode 100644 index 000000000..67009da6a --- /dev/null +++ b/Engine/source/core/util/test/pathTest.cpp @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "core/util/path.h" + +TEST(MakeRelativePath, MakeRelativePath) +{ + EXPECT_EQ(Torque::Path::MakeRelativePath("art/interiors/burg/file.png", "art/interiors/"), "burg/file.png"); + EXPECT_EQ(Torque::Path::MakeRelativePath("art/interiors/file.png", "art/interiors/burg/"), "../file.png"); + EXPECT_EQ(Torque::Path::MakeRelativePath("art/file.png", "art/interiors/burg/"), "../../file.png"); + EXPECT_EQ(Torque::Path::MakeRelativePath("file.png", "art/interiors/burg/"), "../../../file.png"); + EXPECT_EQ(Torque::Path::MakeRelativePath("art/interiors/burg/file.png", "art/interiors/burg/"), "file.png"); + EXPECT_EQ(Torque::Path::MakeRelativePath("art/interiors/camp/file.png", "art/interiors/burg/"), "../camp/file.png"); + EXPECT_EQ(Torque::Path::MakeRelativePath("art/interiors/burg/file.png", "art/shapes/"), "../interiors/burg/file.png"); + EXPECT_EQ(Torque::Path::MakeRelativePath("levels/den/file.png", "art/interiors/burg/"), "../../../levels/den/file.png"); + EXPECT_EQ(Torque::Path::MakeRelativePath("art/interiors/burg/file.png", "art/dts/burg/"), "../../interiors/burg/file.png"); +}; + +#endif \ No newline at end of file diff --git a/Engine/source/core/util/test/strTest.cpp b/Engine/source/core/util/test/strTest.cpp new file mode 100644 index 000000000..3bb381d56 --- /dev/null +++ b/Engine/source/core/util/test/strTest.cpp @@ -0,0 +1,332 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "core/util/str.h" +#include "core/util/tVector.h" +#include "core/strings/stringFunctions.h" +#include "core/strings/unicode.h" + +/// This is called Str, not String, because googletest doesn't let you use both +/// TEST(x) and TEST_FIX(x). So this fixture is called Str, to match the StrTest +/// struct, and the remaining fixture-les tests are named String. +FIXTURE(Str) +{ +protected: + struct StrTest + { + const UTF8* mData; + const UTF16* mUTF16; + U32 mLength; + + StrTest() : mData( 0 ), mUTF16( 0 ) {} + StrTest( const char* str ) + : mData( str ), mLength( str ? dStrlen( str ) : 0 ), mUTF16( NULL ) + { + if( str ) + mUTF16 = convertUTF8toUTF16( mData ); + } + ~StrTest() + { + if( mUTF16 ) + delete [] mUTF16; + } + }; + + Vector< StrTest* > mStrings; + + virtual void SetUp() + { + mStrings.push_back( new StrTest( NULL ) ); + mStrings.push_back( new StrTest( "" ) ); + mStrings.push_back( new StrTest( "Torque" ) ); + mStrings.push_back( new StrTest( "TGEA" ) ); + mStrings.push_back( new StrTest( "GarageGames" ) ); + mStrings.push_back( new StrTest( "TGB" ) ); + mStrings.push_back( new StrTest( "games" ) ); + mStrings.push_back( new StrTest( "engine" ) ); + mStrings.push_back( new StrTest( "rocks" ) ); + mStrings.push_back( new StrTest( "technology" ) ); + mStrings.push_back( new StrTest( "Torque 3D" ) ); + mStrings.push_back( new StrTest( "Torque 2D" ) ); + } + + virtual void TearDown() + { + for( U32 i = 0; i < mStrings.size(); ++ i ) + delete mStrings[ i ]; + mStrings.clear(); + } +}; + +#define EACH_STRING(i) \ + for( U32 i = 0; i < mStrings.size(); ++ i ) +#define EACH_PAIR(i, j) \ + for( U32 i = 0; i < mStrings.size(); ++ i ) \ + for( U32 j = 0; j < mStrings.size(); ++ j ) + +TEST_FIX(Str, Test1) +{ + EACH_STRING(i) + { + StrTest& data = *mStrings[i]; + String str( data.mData ); + String str16( data.mUTF16 ); + + EXPECT_TRUE( str.length() == data.mLength ); + EXPECT_TRUE( str.size() == data.mLength + 1 ); + EXPECT_TRUE( str.isEmpty() || str.length() > 0 ); + EXPECT_TRUE( str.length() == str16.length() ); + EXPECT_TRUE( str.size() == str16.size() ); + + EXPECT_TRUE( dMemcmp( str.utf16(), str16.utf16(), str.length() * sizeof( UTF16 ) ) == 0 ); + EXPECT_TRUE( !data.mData || dMemcmp( str.utf16(), data.mUTF16, str.length() * sizeof( UTF16 ) ) == 0 ); + EXPECT_TRUE( !data.mData || dMemcmp( str16.utf8(), data.mData, str.length() ) == 0 ); + + EXPECT_TRUE( !data.mData || dStrcmp( str.utf8(), data.mData ) == 0 ); + EXPECT_TRUE( !data.mData || dStrcmp( str.utf16(), data.mUTF16 ) == 0 ); + } +} + +TEST_FIX(Str, Test2) +{ + EACH_STRING(i) + { + StrTest& data = *mStrings[i]; + String str( data.mData ); + + EXPECT_TRUE( str == str ); + EXPECT_FALSE( str != str ); + EXPECT_FALSE( str < str ); + EXPECT_FALSE( str > str ); + EXPECT_TRUE( str.equal( str ) ); + EXPECT_TRUE( str.equal( str, String::NoCase ) ); + } +} + +TEST_FIX(Str, Test3) +{ + EACH_PAIR(i, j) + { + StrTest& d1 = *mStrings[i]; + StrTest& d2 = *mStrings[j]; + + if( &d1 != &d2 ) + EXPECT_TRUE( String( d1.mData ) != String( d2.mData ) + || ( String( d1.mData ).isEmpty() && String( d2.mData ).isEmpty() ) ); + else + EXPECT_TRUE( String( d1.mData ) == String( d2.mData ) ); + } +} + +TEST(String, Empty) +{ + EXPECT_TRUE( String().length() == 0 ); + EXPECT_TRUE( String( "" ).length() == 0 ); + EXPECT_TRUE( String().size() == 1 ); + EXPECT_TRUE( String( "" ).size() == 1 ); + EXPECT_TRUE( String().isEmpty() ); + EXPECT_TRUE( String( "" ).isEmpty() ); +} + +TEST(String, Trim) +{ + EXPECT_TRUE( String( " Foobar Barfoo \n\t " ).trim() == String( "Foobar Barfoo" ) ); + EXPECT_TRUE( String( "Foobar" ).trim() == String( "Foobar" ) ); + EXPECT_TRUE( String( " " ).trim().isEmpty() ); +} + +TEST(String, Compare) +{ + String str( "Foobar" ); + + EXPECT_TRUE( str.compare( "Foo", 3 ) == 0 ); + EXPECT_TRUE( str.compare( "bar", 3, String::NoCase | String::Right ) == 0 ); + EXPECT_TRUE( str.compare( "foo", 3, String::NoCase ) == 0 ); + EXPECT_TRUE( str.compare( "BAR", 3, String::NoCase | String::Right ) == 0 ); + EXPECT_TRUE( str.compare( "Foobar" ) == 0 ); + EXPECT_TRUE( str.compare( "Foo" ) != 0 ); + EXPECT_TRUE( str.compare( "foobar", 0, String::NoCase ) == 0 ); + EXPECT_TRUE( str.compare( "FOOBAR", 0, String::NoCase ) == 0 ); + EXPECT_TRUE( str.compare( "Foobar", 0, String::Right ) == 0 ); + EXPECT_TRUE( str.compare( "foobar", 0, String::NoCase | String::Right ) == 0 ); +} + +TEST(String, Order) +{ + Vector< String > strs; + + strs.push_back( "a" ); + strs.push_back( "a0" ); + strs.push_back( "a1" ); + strs.push_back( "a1a" ); + strs.push_back( "a1b" ); + strs.push_back( "a2" ); + strs.push_back( "a10" ); + strs.push_back( "a20" ); + + for( U32 i = 0; i < strs.size(); ++ i ) + { + for( U32 j = 0; j < i; ++ j ) + { + EXPECT_TRUE( strs[ j ] < strs[ i ] ); + EXPECT_TRUE( strs[ i ] > strs[ j ] ); + + EXPECT_TRUE( !( strs[ j ] > strs[ i ] ) ); + EXPECT_TRUE( !( strs[ i ] < strs[ i ] ) ); + + EXPECT_TRUE( strs[ j ] <= strs[ i ] ); + EXPECT_TRUE( strs[ i ] >= strs[ j ] ); + } + + EXPECT_TRUE( !( strs[ i ] < strs[ i ] ) ); + EXPECT_TRUE( !( strs[ i ] > strs[ i ] ) ); + EXPECT_TRUE( strs[ i ] <= strs[ i ] ); + EXPECT_TRUE( strs[ i ] >= strs[ i ] ); + + for( U32 j = i + 1; j < strs.size(); ++ j ) + { + EXPECT_TRUE( strs[ j ] > strs[ i ] ); + EXPECT_TRUE( strs[ i ] < strs[ j ] ); + + EXPECT_TRUE( !( strs[ j ] < strs[ i ] ) ); + EXPECT_TRUE( !( strs[ i ] > strs[ j ] ) ); + + EXPECT_TRUE( strs[ j ] >= strs[ i ] ); + EXPECT_TRUE( strs[ i ] <= strs[ j ] ); + } + } +} + +/// TODO +TEST(String, Find) +{ +} + +TEST(String, Insert) +{ + // String.insert( Pos, Char ) + EXPECT_TRUE( String( "aa" ).insert( 1, 'c' ) == String( "aca" ) ); + + // String.insert( Pos, String ) + EXPECT_TRUE( String( "aa" ).insert( 1, "cc" ) == String( "acca" ) ); + EXPECT_TRUE( String( "aa" ).insert( 1, String( "cc" ) ) == String( "acca" ) ); + + // String.insert( Pos, String, Len ) + EXPECT_TRUE( String( "aa" ).insert( 1, "ccdddd", 2 ) == String( "acca" ) ); +} + +TEST(String, Erase) +{ + EXPECT_TRUE( String( "abba" ).erase( 1, 2 ) == String( "aa" ) ); + EXPECT_TRUE( String( "abba" ).erase( 0, 4 ).isEmpty() ); +} + +TEST(String, Replace) +{ + // String.replace( Pos, Len, String ) + EXPECT_TRUE( String( "abba" ).replace( 1, 2, "ccc" ) == String( "accca" ) ); + EXPECT_TRUE( String( "abba" ).replace( 1, 2, String( "ccc" ) ) == String( "accca" ) ); + EXPECT_TRUE( String( "abba" ).replace( 0, 4, "" ).isEmpty() ); + EXPECT_TRUE( String( "abba" ).replace( 2, 2, "c" ) == String( "abc" ) ); + + // String.replace( Char, Char ) + EXPECT_TRUE( String().replace( 'a', 'b' ).isEmpty() ); + EXPECT_TRUE( String( "ababc" ).replace( 'a', 'b' ) == String( "bbbbc" ) ); + EXPECT_TRUE( String( "ababc" ).replace( 'd', 'e' ) == String( "ababc" ) ); + + // String.replace( String, String ) + EXPECT_TRUE( String().replace( "foo", "bar" ).isEmpty() ); + EXPECT_TRUE( String( "foobarfoo" ).replace( "foo", "bar" ) == String( "barbarbar" ) ); + EXPECT_TRUE( String( "foobar" ).replace( "xx", "yy" ) == String( "foobar" ) ); + EXPECT_TRUE( String( "foofoofoo" ).replace( "foo", "" ).isEmpty() ); +} + +TEST(String, SubStr) +{ + EXPECT_TRUE( String( "foobar" ).substr( 0, 3 ) == String( "foo" ) ); + EXPECT_TRUE( String( "foobar" ).substr( 3 ) == String( "bar" ) ); + EXPECT_TRUE( String( "foobar" ).substr( 2, 2 ) == String( "ob" ) ); + EXPECT_TRUE( String( "foobar" ).substr( 2, 0 ).isEmpty() ); + EXPECT_TRUE( String( "foobar" ).substr( 0, 6 ) == String( "foobar" ) ); +} + +TEST(String, ToString) +{ + EXPECT_TRUE( String::ToString( U32( 1 ) ) == String( "1" ) ); + EXPECT_TRUE( String::ToString( S32( -1 ) ) == String( "-1" ) ); + EXPECT_TRUE( String::ToString( F32( 1.01 ) ) == String( "1.01" ) ); + EXPECT_TRUE( String::ToString( "%s%i", "foo", 1 ) == String( "foo1" ) ); +} + +TEST(String, CaseConversion) +{ + EXPECT_TRUE( String::ToLower( "foobar123." ) == String( "foobar123." ) ); + EXPECT_TRUE( String::ToLower( "FOOBAR123." ) == String( "foobar123." ) ); + EXPECT_TRUE( String::ToUpper( "barfoo123." ) == String( "BARFOO123." ) ); + EXPECT_TRUE( String::ToUpper( "BARFOO123." ) == String( "BARFOO123." ) ); +} + +TEST(String, Concat) +{ + EXPECT_TRUE( String( "foo" ) + String( "bar" ) == String( "foobar" ) ); + EXPECT_TRUE( String() + String( "bar" ) == String( "bar" ) ); + EXPECT_TRUE( String( "foo" ) + String() == String( "foo" ) ); + EXPECT_TRUE( String() + String() == String() ); + EXPECT_TRUE( String( "fo" ) + 'o' == String( "foo" ) ); + EXPECT_TRUE( 'f' + String( "oo" ) == String( "foo" ) ); + EXPECT_TRUE( String( "foo" ) + "bar" == String( "foobar" ) ); + EXPECT_TRUE( "foo" + String( "bar" ) == String( "foobar" ) ); +} + +TEST(String, Hash) +{ + EXPECT_TRUE( String( "foo" ).getHashCaseSensitive() == String( "foo" ).getHashCaseSensitive() ); + EXPECT_TRUE( String( "foo" ).getHashCaseSensitive() != String( "bar" ).getHashCaseSensitive() ); + EXPECT_TRUE( String( "foo" ).getHashCaseInsensitive() == String( "FOO" ).getHashCaseInsensitive() ); +} + +TEST(String, Intern) +{ + EXPECT_TRUE( String( "foo" ).intern().isSame( String( "foo" ).intern() ) ); + EXPECT_TRUE( !String( "foo" ).intern().isSame( String( "bar" ).intern() ) ); + EXPECT_TRUE( !String( "foo" ).intern().isSame( String( "Foo" ).intern() ) ); + EXPECT_TRUE( String( "foo" ).intern() == String( "foo" ).intern() ); + EXPECT_TRUE( String( "foo" ).intern() != String( "bar" ).intern() ); + EXPECT_TRUE( String( "foo" ).intern().isInterned() ); +} + +TEST(StringBuilder, StringBuilder) +{ + StringBuilder str; + + str.append( 'f' ); + str.append( "oo" ); + str.append( String( "ba" ) ); + str.append( "rfajskfdj", 1 ); + str.format( "%s", "barfoo" ); + + EXPECT_TRUE( str.end() == String( "foobarbarfoo" ) ); +} + +#endif diff --git a/Engine/source/core/util/test/swizzleTest.cpp b/Engine/source/core/util/test/swizzleTest.cpp new file mode 100644 index 000000000..942150022 --- /dev/null +++ b/Engine/source/core/util/test/swizzleTest.cpp @@ -0,0 +1,129 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "platform/platform.h" +#include "testing/unitTesting.h" +#include "core/util/swizzle.h" +#include "math/mRandom.h" + +class TestStruct +{ +private: + static U32 smIdx; + U32 mIdx; + U32 mData; + +public: + TestStruct( const S32 data = -1 ) : mData( data ), mIdx( smIdx++ ) {}; + + dsize_t Idx() const { return mIdx; } + + U32 Data() const { return mData; } + void Data(U32 val) { mData = val; } +}; + +U32 TestStruct::smIdx = 0; + +TEST(Swizzle, Swizzle) +{ + //------------------------------------------------------------------------ + // Debugger-Observable Functionality Tests + //------------------------------------------------------------------------ + U8 simpleBuffer[] = { 0, 1, 2, 3 }; + U8 simpleTest[] = { 0, 1, 2, 3 }; + +#define RESET_SIMPLE() dMemcpy( simpleTest, simpleBuffer, sizeof( simpleBuffer ) ) + + //------------------------------------------------------------------------ + // No-switch test + dsize_t noSwzl4[] = { 0, 1, 2, 3 }; + Swizzle noSwizzle4( noSwzl4 ); + + noSwizzle4.InPlace( simpleTest, sizeof( simpleTest ) ); + EXPECT_EQ( dMemcmp( simpleTest, simpleBuffer, sizeof( simpleBuffer ) ), 0 ) + << "No-switch test failed!"; + RESET_SIMPLE(); + + //------------------------------------------------------------------------ + // No-brainer RGBA->BGRA test + dsize_t bgraSwzl[] = { 2, 1, 0, 3 }; + Swizzle bgraSwizzle( bgraSwzl ); + + U8 bgraTest[] = { 2, 1, 0, 3 }; + bgraSwizzle.InPlace( simpleTest, sizeof( simpleTest ) ); + EXPECT_EQ( dMemcmp( simpleTest, bgraTest, sizeof( bgraTest ) ), 0 ) + << "U8 RGBA->BGRA test failed"; + + //------------------------------------------------------------------------ + // Reverse test + bgraSwizzle.InPlace( simpleTest, sizeof( simpleTest ) ); + EXPECT_EQ( dMemcmp( simpleTest, simpleBuffer, sizeof( simpleBuffer ) ), 0 ) + << "U8 RGBA->BGRA reverse test failed"; + + RESET_SIMPLE(); + + //------------------------------------------------------------------------ + // Object support test + Swizzle bgraObjSwizzle( bgraSwzl ); + { + U32 objIdx[] = { 0, 1, 2, 3 }; + + FrameTemp objTest( sizeof( objIdx ) / sizeof( U32 ) ); + FrameTemp randData( sizeof( objIdx ) / sizeof( U32 ) ); + + bool same = true; + + for( U32 i = 0; i < sizeof( objIdx ) / sizeof( U32 ); i++ ) + { + // Make random data and assign it + randData[i] = gRandGen.randI(); + objTest[i].Data( randData[i] ); + + // Continue object sanity check + same &= ( objTest[i].Idx() == objIdx[i] ); + } + + EXPECT_TRUE( same ) + << "Test object failed to be competent"; + + bgraObjSwizzle.InPlace( ~objTest, sizeof( TestStruct ) * ( sizeof( objIdx ) / sizeof( U32 ) ) ); + same = true; + + for( U32 i = 0; i < sizeof( objIdx ) / sizeof( U32 ); i++ ) + same &= ( objTest[i].Idx() == bgraTest[i] ) && ( objTest[i].Data() == randData[ (U32)bgraTest[ i ] ] ); + + EXPECT_TRUE( same ) + << "Object RGBA->BGRA test failed."; + + bgraObjSwizzle.InPlace( ~objTest, sizeof( TestStruct ) * ( sizeof( objIdx ) / sizeof( U32 ) ) ); + same = true; + + for( U32 i = 0; i < sizeof( objIdx ) / sizeof( U32 ); i++ ) + same &= ( objTest[i].Idx() == objIdx[i] ) && ( objTest[i].Data() == randData[i] ); + + EXPECT_TRUE( same ) + << "Object RGBA->BGRA reverse test failed."; + } +}; + +#endif \ No newline at end of file diff --git a/Engine/source/unit/tests/testVector.cpp b/Engine/source/core/util/test/tFixedSizeDequeTest.cpp similarity index 63% rename from Engine/source/unit/tests/testVector.cpp rename to Engine/source/core/util/test/tFixedSizeDequeTest.cpp index c7e38d250..1fcc94e20 100644 --- a/Engine/source/unit/tests/testVector.cpp +++ b/Engine/source/core/util/test/tFixedSizeDequeTest.cpp @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC +// Copyright (c) 2014 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to @@ -20,34 +20,30 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "platform/platform.h" -#include "unit/test.h" -#include "unit/memoryTester.h" -#include "core/util/tVector.h" +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "core/util/tFixedSizeDeque.h" -using namespace UnitTesting; - -CreateUnitTest(TestVectorAllocate, "Types/Vector") +TEST(FixedSizeDeque, FixedSizeDeque) { - void run() - { - MemoryTester m; - m.mark(); + enum { DEQUE_SIZE = 3 }; + FixedSizeDeque< U32 > deque( DEQUE_SIZE ); - Vector *vector = new Vector; - for(S32 i=0; i<1000; i++) - vector->push_back(10000 + i); + EXPECT_EQ( deque.capacity(), DEQUE_SIZE ); + EXPECT_EQ( deque.size(), 0 ); - // Erase the first element, 500 times. - for(S32 i=0; i<500; i++) - vector->erase(U32(0)); + deque.pushFront( 1 ); + EXPECT_EQ( deque.capacity(), ( DEQUE_SIZE - 1 ) ); + EXPECT_EQ( deque.size(), 1 ); + EXPECT_FALSE( deque.isEmpty() ); - vector->compact(); + deque.pushBack( 2 ); + EXPECT_EQ( deque.capacity(), ( DEQUE_SIZE - 2 ) ); + EXPECT_EQ( deque.size(), 2 ); - test(vector->size() == 500, "Vector was unexpectedly short!"); + EXPECT_EQ( deque.popFront(), 1 ); + EXPECT_EQ( deque.popFront(), 2 ); + EXPECT_TRUE( deque.isEmpty() ); +}; - delete vector; - - test(m.check(), "Vector allocation test leaked memory!"); - } -}; \ No newline at end of file +#endif \ No newline at end of file diff --git a/Engine/source/core/util/test/tVectorTest.cpp b/Engine/source/core/util/test/tVectorTest.cpp new file mode 100644 index 000000000..3a3aeec13 --- /dev/null +++ b/Engine/source/core/util/test/tVectorTest.cpp @@ -0,0 +1,125 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "core/util/tVector.h" + +// Define some test data used below. +FIXTURE(Vector) +{ +public: + struct Dtor + { + bool* ptr; + Dtor() {} // Needed for vector increment. + Dtor(bool* ptr): ptr(ptr) {} + ~Dtor() + { + *ptr = true; + } + }; + + static const S32 ints[]; + static const U32 length; + static S32 QSORT_CALLBACK sortInts(const S32* a, const S32* b) + { + S32 av = *a; + S32 bv = *b; + + if (av < bv) + return -1; + else if (av > bv) + return 1; + else + return 0; + } +}; + +const S32 VectorFixture::ints[] = {0, 10, 2, 3, 14, 4, 12, 6, 16, 7, 8, 1, 11, 5, 13, 9, 15}; +const U32 VectorFixture::length = sizeof(VectorFixture::ints) / sizeof(S32); + +TEST_FIX(Vector, Allocation) +{ + Vector *vector = new Vector; + for (S32 i = 0; i < 1000; i++) + vector->push_back(10000 + i); + + // Erase the first element, 500 times. + for (S32 i = 0; i < 500; i++) + vector->erase(U32(0)); + + vector->compact(); + + EXPECT_EQ(vector->size(), 500) << "Vector was unexpectedly short!"; + + delete vector; +} + +TEST_FIX(Vector, Deallocation) +{ + bool dtorVals[10]; + Vector v; + + // Only add the first 9 entries; the last is populated below. + for (U32 i = 0; i < 9; i++) + v.push_back(Dtor(&dtorVals[i])); + + // Fill the values array with false so we can test for destruction. + for (U32 i = 0; i < 10; i++) + dtorVals[i] = false; + + v.decrement(); + EXPECT_TRUE(dtorVals[8]) << "Vector::decrement failed to call destructor"; + + v.decrement(2); + EXPECT_TRUE(dtorVals[7]) << "Vector::decrement failed to call destructor"; + EXPECT_TRUE(dtorVals[6]) << "Vector::decrement failed to call destructor"; + + v.pop_back(); + EXPECT_TRUE(dtorVals[5]) << "Vector::pop_back failed to call destructor"; + + v.increment(); + v.last() = Dtor(&dtorVals[9]); + v.clear(); + + // All elements should have been destructed. + for (U32 i = 0; i < 10; i++) + EXPECT_TRUE(dtorVals[i]) + << "Element " << i << "'s destructor was not called"; +} + +TEST_FIX(Vector, Sorting) +{ + Vector v; + + for(U32 i = 0; i < length; i++) + v.push_back(ints[i]); + + v.sort(sortInts); + + for(U32 i = 0; i < length - 1; i++) + EXPECT_TRUE(v[i] <= v[i + 1]) + << "Element " << i << " was not in sorted order"; +} + +#endif \ No newline at end of file diff --git a/Engine/source/core/util/test/testPath.cpp b/Engine/source/core/util/test/testPath.cpp deleted file mode 100644 index 94593185b..000000000 --- a/Engine/source/core/util/test/testPath.cpp +++ /dev/null @@ -1,44 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "unit/test.h" -#include "core/util/path.h" - -using namespace UnitTesting; - -#define TEST( x ) test( ( x ), "FAIL: " #x ) - -CreateUnitTest(TestPathMakeRelativePath, "Core/Util/Path/MakeRelativePath") -{ - void run() - { - TEST(Torque::Path::MakeRelativePath("art/interiors/burg/file.png", "art/interiors/") == "burg/file.png"); - TEST(Torque::Path::MakeRelativePath("art/interiors/file.png", "art/interiors/burg/") == "../file.png"); - TEST(Torque::Path::MakeRelativePath("art/file.png", "art/interiors/burg/") == "../../file.png"); - TEST(Torque::Path::MakeRelativePath("file.png", "art/interiors/burg/") == "../../../file.png"); - TEST(Torque::Path::MakeRelativePath("art/interiors/burg/file.png", "art/interiors/burg/") == "file.png"); - TEST(Torque::Path::MakeRelativePath("art/interiors/camp/file.png", "art/interiors/burg/") == "../camp/file.png"); - TEST(Torque::Path::MakeRelativePath("art/interiors/burg/file.png", "art/shapes/") == "../interiors/burg/file.png"); - TEST(Torque::Path::MakeRelativePath("levels/den/file.png", "art/interiors/burg/") == "../../../levels/den/file.png"); - TEST(Torque::Path::MakeRelativePath("art/interiors/burg/file.png", "art/dts/burg/") == "../../interiors/burg/file.png"); - } -}; diff --git a/Engine/source/core/util/test/testString.cpp b/Engine/source/core/util/test/testString.cpp deleted file mode 100644 index 33c6ea6d4..000000000 --- a/Engine/source/core/util/test/testString.cpp +++ /dev/null @@ -1,358 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "unit/test.h" -#include "core/util/str.h" -#include "core/util/tVector.h" -#include "core/strings/stringFunctions.h" -#include "core/strings/unicode.h" - - -#ifndef TORQUE_SHIPPING - -using namespace UnitTesting; - -#define TEST( x ) test( ( x ), "FAIL: " #x ) -#define XTEST( t, x ) t->test( ( x ), "FAIL: " #x ) - -CreateUnitTest( TestString, "Util/String" ) -{ - struct StrTest - { - const UTF8* mData; - const UTF16* mUTF16; - U32 mLength; - - StrTest() : mData( 0 ), mUTF16( 0 ) {} - StrTest( const char* str ) - : mData( str ), mLength( str ? dStrlen( str ) : 0 ), mUTF16( NULL ) - { - if( str ) - mUTF16 = convertUTF8toUTF16( mData ); - } - ~StrTest() - { - if( mUTF16 ) - delete [] mUTF16; - } - }; - - Vector< StrTest* > mStrings; - - template< class T > - void runTestOnStrings() - { - for( U32 i = 0; i < mStrings.size(); ++ i ) - T::run( this, *mStrings[ i ] ); - } - template< class T > - void runPairwiseTestOnStrings() - { - for( U32 i = 0; i < mStrings.size(); ++ i ) - for( U32 j = 0; j < mStrings.size(); ++ j ) - T::run( this, *mStrings[ i ], *mStrings[ j ] ); - } - - struct Test1 - { - static void run( TestString* test, StrTest& data ) - { - String str( data.mData ); - String str16( data.mUTF16 ); - - XTEST( test, str.length() == data.mLength ); - XTEST( test, str.size() == data.mLength + 1 ); - XTEST( test, str.isEmpty() || str.length() > 0 ); - XTEST( test, str.length() == str16.length() ); - XTEST( test, str.size() == str16.size() ); - - XTEST( test, dMemcmp( str.utf16(), str16.utf16(), str.length() * sizeof( UTF16 ) ) == 0 ); - XTEST( test, !data.mData || dMemcmp( str.utf16(), data.mUTF16, str.length() * sizeof( UTF16 ) ) == 0 ); - XTEST( test, !data.mData || dMemcmp( str16.utf8(), data.mData, str.length() ) == 0 ); - - XTEST( test, !data.mData || dStrcmp( str.utf8(), data.mData ) == 0 ); - XTEST( test, !data.mData || dStrcmp( str.utf16(), data.mUTF16 ) == 0 ); - } - }; - - struct Test2 - { - static void run( TestString* test, StrTest& data ) - { - String str( data.mData ); - - XTEST( test, str == str ); - XTEST( test, !( str != str ) ); - XTEST( test, !( str < str ) ); - XTEST( test, !( str > str ) ); - XTEST( test, str.equal( str ) ); - XTEST( test, str.equal( str, String::NoCase ) ); - } - }; - - struct Test3 - { - static void run( TestString* test, StrTest& d1, StrTest& d2 ) - { - if( &d1 != &d2 ) - XTEST( test, String( d1.mData ) != String( d2.mData ) - || ( String( d1.mData ).isEmpty() && String( d2.mData ).isEmpty() ) ); - else - XTEST( test, String( d1.mData ) == String( d2.mData ) ); - } - }; - - void testEmpty() - { - TEST( String().length() == 0 ); - TEST( String( "" ).length() == 0 ); - TEST( String().size() == 1 ); - TEST( String( "" ).size() == 1 ); - TEST( String().isEmpty() ); - TEST( String( "" ).isEmpty() ); - } - - void testTrim() - { - TEST( String( " Foobar Barfoo \n\t " ).trim() == String( "Foobar Barfoo" ) ); - TEST( String( "Foobar" ).trim() == String( "Foobar" ) ); - TEST( String( " " ).trim().isEmpty() ); - } - - void testCompare() - { - String str( "Foobar" ); - - TEST( str.compare( "Foo", 3 ) == 0 ); - TEST( str.compare( "bar", 3, String::NoCase | String::Right ) == 0 ); - TEST( str.compare( "foo", 3, String::NoCase ) == 0 ); - TEST( str.compare( "BAR", 3, String::NoCase | String::Right ) == 0 ); - TEST( str.compare( "Foobar" ) == 0 ); - TEST( str.compare( "Foo" ) != 0 ); - TEST( str.compare( "foobar", 0, String::NoCase ) == 0 ); - TEST( str.compare( "FOOBAR", 0, String::NoCase ) == 0 ); - TEST( str.compare( "Foobar", 0, String::Right ) == 0 ); - TEST( str.compare( "foobar", 0, String::NoCase | String::Right ) == 0 ); - } - - void testOrder() - { - Vector< String > strs; - - strs.push_back( "a" ); - strs.push_back( "a0" ); - strs.push_back( "a1" ); - strs.push_back( "a1a" ); - strs.push_back( "a1b" ); - strs.push_back( "a2" ); - strs.push_back( "a10" ); - strs.push_back( "a20" ); - - for( U32 i = 0; i < strs.size(); ++ i ) - { - for( U32 j = 0; j < i; ++ j ) - { - TEST( strs[ j ] < strs[ i ] ); - TEST( strs[ i ] > strs[ j ] ); - - TEST( !( strs[ j ] > strs[ i ] ) ); - TEST( !( strs[ i ] < strs[ i ] ) ); - - TEST( strs[ j ] <= strs[ i ] ); - TEST( strs[ i ] >= strs[ j ] ); - } - - TEST( !( strs[ i ] < strs[ i ] ) ); - TEST( !( strs[ i ] > strs[ i ] ) ); - TEST( strs[ i ] <= strs[ i ] ); - TEST( strs[ i ] >= strs[ i ] ); - - for( U32 j = i + 1; j < strs.size(); ++ j ) - { - TEST( strs[ j ] > strs[ i ] ); - TEST( strs[ i ] < strs[ j ] ); - - TEST( !( strs[ j ] < strs[ i ] ) ); - TEST( !( strs[ i ] > strs[ j ] ) ); - - TEST( strs[ j ] >= strs[ i ] ); - TEST( strs[ i ] <= strs[ j ] ); - } - } - } - - void testFind() - { - //TODO - } - - void testInsert() - { - // String.insert( Pos, Char ) - TEST( String( "aa" ).insert( 1, 'c' ) == String( "aca" ) ); - - // String.insert( Pos, String ) - TEST( String( "aa" ).insert( 1, "cc" ) == String( "acca" ) ); - TEST( String( "aa" ).insert( 1, String( "cc" ) ) == String( "acca" ) ); - - // String.insert( Pos, String, Len ) - TEST( String( "aa" ).insert( 1, "ccdddd", 2 ) == String( "acca" ) ); - } - - void testErase() - { - TEST( String( "abba" ).erase( 1, 2 ) == String( "aa" ) ); - TEST( String( "abba" ).erase( 0, 4 ).isEmpty() ); - } - - void testReplace() - { - // String.replace( Pos, Len, String ) - TEST( String( "abba" ).replace( 1, 2, "ccc" ) == String( "accca" ) ); - TEST( String( "abba" ).replace( 1, 2, String( "ccc" ) ) == String( "accca" ) ); - TEST( String( "abba" ).replace( 0, 4, "" ).isEmpty() ); - TEST( String( "abba" ).replace( 2, 2, "c" ) == String( "abc" ) ); - - // String.replace( Char, Char ) - TEST( String().replace( 'a', 'b' ).isEmpty() ); - TEST( String( "ababc" ).replace( 'a', 'b' ) == String( "bbbbc" ) ); - TEST( String( "ababc" ).replace( 'd', 'e' ) == String( "ababc" ) ); - - // String.replace( String, String ) - TEST( String().replace( "foo", "bar" ).isEmpty() ); - TEST( String( "foobarfoo" ).replace( "foo", "bar" ) == String( "barbarbar" ) ); - TEST( String( "foobar" ).replace( "xx", "yy" ) == String( "foobar" ) ); - TEST( String( "foofoofoo" ).replace( "foo", "" ).isEmpty() ); - } - - void testSubstr() - { - TEST( String( "foobar" ).substr( 0, 3 ) == String( "foo" ) ); - TEST( String( "foobar" ).substr( 3 ) == String( "bar" ) ); - TEST( String( "foobar" ).substr( 2, 2 ) == String( "ob" ) ); - TEST( String( "foobar" ).substr( 2, 0 ).isEmpty() ); - TEST( String( "foobar" ).substr( 0, 6 ) == String( "foobar" ) ); - } - - void testToString() - { - TEST( String::ToString( U32( 1 ) ) == String( "1" ) ); - TEST( String::ToString( S32( -1 ) ) == String( "-1" ) ); - TEST( String::ToString( F32( 1.01 ) ) == String( "1.01" ) ); - TEST( String::ToString( "%s%i", "foo", 1 ) == String( "foo1" ) ); - } - - void testCaseConversion() - { - TEST( String::ToLower( "foobar123." ) == String( "foobar123." ) ); - TEST( String::ToLower( "FOOBAR123." ) == String( "foobar123." ) ); - TEST( String::ToUpper( "barfoo123." ) == String( "BARFOO123." ) ); - TEST( String::ToUpper( "BARFOO123." ) == String( "BARFOO123." ) ); - } - - void testConcat() - { - TEST( String( "foo" ) + String( "bar" ) == String( "foobar" ) ); - TEST( String() + String( "bar" ) == String( "bar" ) ); - TEST( String( "foo" ) + String() == String( "foo" ) ); - TEST( String() + String() == String() ); - TEST( String( "fo" ) + 'o' == String( "foo" ) ); - TEST( 'f' + String( "oo" ) == String( "foo" ) ); - TEST( String( "foo" ) + "bar" == String( "foobar" ) ); - TEST( "foo" + String( "bar" ) == String( "foobar" ) ); - } - - void testHash() - { - TEST( String( "foo" ).getHashCaseSensitive() == String( "foo" ).getHashCaseSensitive() ); - TEST( String( "foo" ).getHashCaseSensitive() != String( "bar" ).getHashCaseSensitive() ); - TEST( String( "foo" ).getHashCaseInsensitive() == String( "FOO" ).getHashCaseInsensitive() ); - } - - void testIntern() - { - TEST( String( "foo" ).intern().isSame( String( "foo" ).intern() ) ); - TEST( !String( "foo" ).intern().isSame( String( "bar" ).intern() ) ); - TEST( !String( "foo" ).intern().isSame( String( "Foo" ).intern() ) ); - TEST( String( "foo" ).intern() == String( "foo" ).intern() ); - TEST( String( "foo" ).intern() != String( "bar" ).intern() ); - TEST( String( "foo" ).intern().isInterned() ); - } - - void run() - { - mStrings.push_back( new StrTest( NULL ) ); - mStrings.push_back( new StrTest( "" ) ); - mStrings.push_back( new StrTest( "Torque" ) ); - mStrings.push_back( new StrTest( "TGEA" ) ); - mStrings.push_back( new StrTest( "GarageGames" ) ); - mStrings.push_back( new StrTest( "TGB" ) ); - mStrings.push_back( new StrTest( "games" ) ); - mStrings.push_back( new StrTest( "engine" ) ); - mStrings.push_back( new StrTest( "rocks" ) ); - mStrings.push_back( new StrTest( "technology" ) ); - mStrings.push_back( new StrTest( "Torque 3D" ) ); - mStrings.push_back( new StrTest( "Torque 2D" ) ); - - runTestOnStrings< Test1 >(); - runTestOnStrings< Test2 >(); - - runPairwiseTestOnStrings< Test3 >(); - - testEmpty(); - testTrim(); - testCompare(); - testOrder(); - testFind(); - testInsert(); - testReplace(); - testErase(); - testSubstr(); - testToString(); - testCaseConversion(); - testConcat(); - testHash(); - testIntern(); - - for( U32 i = 0; i < mStrings.size(); ++ i ) - delete mStrings[ i ]; - mStrings.clear(); - } -}; - -CreateUnitTest( TestStringBuilder, "Util/StringBuilder" ) -{ - void run() - { - StringBuilder str; - - str.append( 'f' ); - str.append( "oo" ); - str.append( String( "ba" ) ); - str.append( "rfajskfdj", 1 ); - str.format( "%s", "barfoo" ); - - TEST( str.end() == String( "foobarbarfoo" ) ); - } -}; - -#endif // !TORQUE_SHIPPING diff --git a/Engine/source/core/util/test/testVector2.cpp b/Engine/source/core/util/test/testVector2.cpp deleted file mode 100644 index 7c0cf2189..000000000 --- a/Engine/source/core/util/test/testVector2.cpp +++ /dev/null @@ -1,138 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "unit/test.h" -#include "console/console.h" -#include "core/util/tVector.h" - - -#ifndef TORQUE_SHIPPING - -using namespace UnitTesting; - -#define TEST( x ) test( ( x ), "FAIL: " #x ) -#define XTEST( t, x ) t->test( ( x ), "FAIL: " #x ) - -CreateUnitTest( TestVector, "Util/Vector" ) -{ - bool dtorVals[ 10 ]; - struct Dtor - { - bool* ptr; - Dtor() {} - Dtor( bool* ptr ) - : ptr( ptr ) { *ptr = false; } - ~Dtor() - { - *ptr = true; - } - }; - void testDestruction() - { - Vector< Dtor > v; - - for( U32 i = 0; i < 9; ++ i ) - v.push_back( Dtor( &dtorVals[ i ] ) ); - - v.decrement(); - v.decrement( 2 ); - v.pop_back(); - v.increment(); - v.last() = Dtor( &dtorVals[ 9 ] ); - v.clear(); - - TEST( dtorVals[ 0 ] ); - TEST( dtorVals[ 1 ] ); - TEST( dtorVals[ 2 ] ); - TEST( dtorVals[ 3 ] ); - TEST( dtorVals[ 4 ] ); - TEST( dtorVals[ 5 ] ); - TEST( dtorVals[ 6 ] ); - TEST( dtorVals[ 7 ] ); - TEST( dtorVals[ 8 ] ); - TEST( dtorVals[ 9 ] ); - } - - static S32 QSORT_CALLBACK sortInts( const int* a, const int* b ) - { - int av = *a; - int bv = *b; - - if( av < bv ) - return -1; - else if( av > bv ) - return 1; - else - return 0; - } - - void testSort() - { - Vector< int > v; - - v.push_back( 0 ); - v.push_back( 10 ); - v.push_back( 2 ); - v.push_back( 3 ); - v.push_back( 14 ); - v.push_back( 4 ); - v.push_back( 12 ); - v.push_back( 6 ); - v.push_back( 16 ); - v.push_back( 7 ); - v.push_back( 8 ); - v.push_back( 1 ); - v.push_back( 11 ); - v.push_back( 5 ); - v.push_back( 13 ); - v.push_back( 9 ); - v.push_back( 15 ); - - v.sort( sortInts ); - - TEST( v[ 0 ] == 0 ); - TEST( v[ 1 ] == 1 ); - TEST( v[ 2 ] == 2 ); - TEST( v[ 3 ] == 3 ); - TEST( v[ 4 ] == 4 ); - TEST( v[ 5 ] == 5 ); - TEST( v[ 6 ] == 6 ); - TEST( v[ 7 ] == 7 ); - TEST( v[ 8 ] == 8 ); - TEST( v[ 9 ] == 9 ); - TEST( v[ 10 ] == 10 ); - TEST( v[ 11 ] == 11 ); - TEST( v[ 12 ] == 12 ); - TEST( v[ 13 ] == 13 ); - TEST( v[ 14 ] == 14 ); - TEST( v[ 15 ] == 15 ); - TEST( v[ 16 ] == 16 ); - } - - void run() - { - testSort(); - testDestruction(); - } -}; - -#endif diff --git a/Engine/source/core/util/zip/unitTests/zipTest.h b/Engine/source/core/util/zip/test/zipTest.h similarity index 100% rename from Engine/source/core/util/zip/unitTests/zipTest.h rename to Engine/source/core/util/zip/test/zipTest.h diff --git a/Engine/source/core/util/zip/unitTests/zipTestMisc.cpp b/Engine/source/core/util/zip/test/zipTestMisc.cpp similarity index 99% rename from Engine/source/core/util/zip/unitTests/zipTestMisc.cpp rename to Engine/source/core/util/zip/test/zipTestMisc.cpp index be5392c30..eda383e00 100644 --- a/Engine/source/core/util/zip/unitTests/zipTestMisc.cpp +++ b/Engine/source/core/util/zip/test/zipTestMisc.cpp @@ -19,7 +19,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- - +/* #include "core/crc.h" #include "core/strings/stringFunctions.h" #include "core/util/zip/zipArchive.h" @@ -194,3 +194,4 @@ private: return ret; } }; +*/ \ No newline at end of file diff --git a/Engine/source/core/util/zip/unitTests/zipTestRead.cpp b/Engine/source/core/util/zip/test/zipTestRead.cpp similarity index 99% rename from Engine/source/core/util/zip/unitTests/zipTestRead.cpp rename to Engine/source/core/util/zip/test/zipTestRead.cpp index 45be733d4..20df7c6b0 100644 --- a/Engine/source/core/util/zip/unitTests/zipTestRead.cpp +++ b/Engine/source/core/util/zip/test/zipTestRead.cpp @@ -19,7 +19,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- - +/* #include "platform/platform.h" #include "unit/test.h" @@ -250,3 +250,4 @@ private: return ret; } }; +*/ \ No newline at end of file diff --git a/Engine/source/core/util/zip/unitTests/zipTestWrite.cpp b/Engine/source/core/util/zip/test/zipTestWrite.cpp similarity index 99% rename from Engine/source/core/util/zip/unitTests/zipTestWrite.cpp rename to Engine/source/core/util/zip/test/zipTestWrite.cpp index cdfaa8778..889cf6948 100644 --- a/Engine/source/core/util/zip/unitTests/zipTestWrite.cpp +++ b/Engine/source/core/util/zip/test/zipTestWrite.cpp @@ -19,7 +19,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- - +/* #include "core/strings/stringFunctions.h" #include "core/util/zip/zipArchive.h" #include "core/util/zip/unitTests/zipTest.h" @@ -242,3 +242,4 @@ bail: return ret; } }; +*/ \ No newline at end of file diff --git a/Engine/source/core/util/zip/zipObject.cpp b/Engine/source/core/util/zip/zipObject.cpp index 60c05c183..419733350 100644 --- a/Engine/source/core/util/zip/zipObject.cpp +++ b/Engine/source/core/util/zip/zipObject.cpp @@ -216,7 +216,7 @@ String ZipObject::getFileEntry(S32 idx) const Zip::CentralDir &dir = (*mZipArchive)[idx]; char buffer[1024]; - int chars = dSprintf(buffer, sizeof(buffer), "%s\t%d\t%d\t%d\t%08x", + S32 chars = dSprintf(buffer, sizeof(buffer), "%s\t%d\t%d\t%d\t%08x", dir.mFilename.c_str(), dir.mUncompressedSize, dir.mCompressedSize, dir.mCompressMethod, dir.mCRC32); if (chars < sizeof(buffer)) diff --git a/Engine/source/core/util/zip/zipVolume.cpp b/Engine/source/core/util/zip/zipVolume.cpp index 16bad16dd..6982c70c0 100644 --- a/Engine/source/core/util/zip/zipVolume.cpp +++ b/Engine/source/core/util/zip/zipVolume.cpp @@ -55,7 +55,7 @@ public: } virtual Path getName() const { return mZipFilename; } - virtual Status getStatus() const + virtual NodeStatus getStatus() const { if (mZipStream) { @@ -182,7 +182,7 @@ public: Torque::Path getName() const { return mPath; } // getStatus() doesn't appear to be used for directories - Status getStatus() const + NodeStatus getStatus() const { return FileNode::Open; } @@ -274,7 +274,7 @@ public: Torque::Path getName() const { return mPath; } // getStatus() doesn't appear to be used for directories - Status getStatus() const + NodeStatus getStatus() const { return FileNode::Open; } diff --git a/Engine/source/core/volume.cpp b/Engine/source/core/volume.cpp index 1e0b6cda7..05a139eeb 100644 --- a/Engine/source/core/volume.cpp +++ b/Engine/source/core/volume.cpp @@ -651,7 +651,7 @@ bool MountSystem::unmount(FileSystemRef fs) // also check that fs is not null each time since its a strong ref // so it could be nulled during removal. bool unmounted = false; - for (int i = mMountList.size() - 1; !fs.isNull() && i >= 0; --i) + for (S32 i = mMountList.size() - 1; !fs.isNull() && i >= 0; --i) { if (mMountList[i].fileSystem.getPointer() == fs.getPointer()) { diff --git a/Engine/source/core/volume.h b/Engine/source/core/volume.h index db0d0e5e8..bd041fa42 100644 --- a/Engine/source/core/volume.h +++ b/Engine/source/core/volume.h @@ -79,7 +79,7 @@ public: class FileNode : public FileBase { public: - enum Status + enum NodeStatus { Open, ///< In an open state Closed, ///< In a closed state @@ -122,7 +122,7 @@ public: // Properties virtual Path getName() const = 0; - virtual Status getStatus() const = 0; + virtual NodeStatus getStatus() const = 0; virtual bool getAttributes(Attributes*) = 0; diff --git a/Engine/source/environment/editors/guiMeshRoadEditorCtrl.cpp b/Engine/source/environment/editors/guiMeshRoadEditorCtrl.cpp index ac4e4edc5..51fd2db7f 100644 --- a/Engine/source/environment/editors/guiMeshRoadEditorCtrl.cpp +++ b/Engine/source/environment/editors/guiMeshRoadEditorCtrl.cpp @@ -1223,9 +1223,10 @@ ConsoleMethod( GuiMeshRoadEditorCtrl, setNodeDepth, void, 3, 3, "" ) ConsoleMethod( GuiMeshRoadEditorCtrl, getNodePosition, const char*, 2, 2, "" ) { - char* returnBuffer = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer, 256, "%f %f %f", + dSprintf(returnBuffer, bufSize, "%f %f %f", object->getNodePosition().x, object->getNodePosition().y, object->getNodePosition().z); return returnBuffer; @@ -1249,9 +1250,10 @@ ConsoleMethod( GuiMeshRoadEditorCtrl, setNodePosition, void, 3, 3, "" ) ConsoleMethod( GuiMeshRoadEditorCtrl, getNodeNormal, const char*, 2, 2, "" ) { - char* returnBuffer = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer, 256, "%f %f %f", + dSprintf(returnBuffer, bufSize, "%f %f %f", object->getNodeNormal().x, object->getNodeNormal().y, object->getNodeNormal().z); return returnBuffer; diff --git a/Engine/source/environment/editors/guiRiverEditorCtrl.cpp b/Engine/source/environment/editors/guiRiverEditorCtrl.cpp index 18f49b0e6..ce7603643 100644 --- a/Engine/source/environment/editors/guiRiverEditorCtrl.cpp +++ b/Engine/source/environment/editors/guiRiverEditorCtrl.cpp @@ -1430,9 +1430,10 @@ ConsoleMethod( GuiRiverEditorCtrl, setNodeDepth, void, 3, 3, "" ) ConsoleMethod( GuiRiverEditorCtrl, getNodePosition, const char*, 2, 2, "" ) { - char* returnBuffer = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer, 256, "%f %f %f", + dSprintf(returnBuffer, bufSize, "%f %f %f", object->getNodePosition().x, object->getNodePosition().y, object->getNodePosition().z); return returnBuffer; @@ -1456,9 +1457,10 @@ ConsoleMethod( GuiRiverEditorCtrl, setNodePosition, void, 3, 3, "" ) ConsoleMethod( GuiRiverEditorCtrl, getNodeNormal, const char*, 2, 2, "" ) { - char* returnBuffer = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer, 256, "%f %f %f", + dSprintf(returnBuffer, bufSize, "%f %f %f", object->getNodeNormal().x, object->getNodeNormal().y, object->getNodeNormal().z); return returnBuffer; diff --git a/Engine/source/environment/editors/guiRoadEditorCtrl.cpp b/Engine/source/environment/editors/guiRoadEditorCtrl.cpp index a890c6ce2..c1f790de6 100644 --- a/Engine/source/environment/editors/guiRoadEditorCtrl.cpp +++ b/Engine/source/environment/editors/guiRoadEditorCtrl.cpp @@ -1064,9 +1064,10 @@ ConsoleMethod( GuiRoadEditorCtrl, setNodeWidth, void, 3, 3, "" ) ConsoleMethod( GuiRoadEditorCtrl, getNodePosition, const char*, 2, 2, "" ) { - char* returnBuffer = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer, 256, "%f %f %f", + dSprintf(returnBuffer, bufSize, "%f %f %f", object->getNodePosition().x, object->getNodePosition().y, object->getNodePosition().z); return returnBuffer; diff --git a/Engine/source/environment/meshRoad.cpp b/Engine/source/environment/meshRoad.cpp index fac154f72..6a5e3fbd1 100644 --- a/Engine/source/environment/meshRoad.cpp +++ b/Engine/source/environment/meshRoad.cpp @@ -1074,7 +1074,7 @@ void MeshRoad::unpackUpdate(NetConnection * con, BitStream * stream) stream->read( &mMaterialName[i] ); if ( !Sim::findObject( mMaterialName[i], pMat ) ) - Con::printf( "DecalRoad::unpackUpdate, failed to find Material of name &s!", mMaterialName[i].c_str() ); + Con::printf( "DecalRoad::unpackUpdate, failed to find Material of name %s", mMaterialName[i].c_str() ); else mMaterial[i] = pMat; } diff --git a/Engine/source/environment/scatterSky.cpp b/Engine/source/environment/scatterSky.cpp index 7fdf25296..ed5f8d3ad 100644 --- a/Engine/source/environment/scatterSky.cpp +++ b/Engine/source/environment/scatterSky.cpp @@ -1057,7 +1057,7 @@ void ScatterSky::_renderMoon( ObjectRenderInst *ri, SceneRenderState *state, Bas const MatrixF &camView = state->getCameraTransform(); // Finalize points - for(int i = 0; i < 4; i++) + for(S32 i = 0; i < 4; i++) { // align with camera camView.mulV(points[i]); @@ -1114,13 +1114,13 @@ void ScatterSky::_generateSkyPoints() F32 deltaSegAngle = ( 2.0f * M_PI_F / (F32)segments ); // Generate the group of rings for the sphere. - for( int ring = 0; ring < 2; ring++ ) + for( S32 ring = 0; ring < 2; ring++ ) { F32 r0 = mSin( ring * deltaRingAngle ); F32 y0 = mCos( ring * deltaRingAngle ); // Generate the group of segments for the current ring. - for( int seg = 0; seg < segments + 1 ; seg++ ) + for( S32 seg = 0; seg < segments + 1 ; seg++ ) { F32 x0 = r0 * sinf( seg * deltaSegAngle ); F32 z0 = r0 * cosf( seg * deltaSegAngle ); diff --git a/Engine/source/environment/scatterSky.h b/Engine/source/environment/scatterSky.h index 254756bc9..2ce581ad3 100644 --- a/Engine/source/environment/scatterSky.h +++ b/Engine/source/environment/scatterSky.h @@ -62,7 +62,7 @@ GFXDeclareVertexFormat( ScatterSkyVertex ) { Point3F point; VectorF normal; - ColorF color; + GFXVertexColor color; }; class ScatterSky : public SceneObject, public ISceneLight diff --git a/Engine/source/environment/skyBox.cpp b/Engine/source/environment/skyBox.cpp index a41b0a361..7d3e600f7 100644 --- a/Engine/source/environment/skyBox.cpp +++ b/Engine/source/environment/skyBox.cpp @@ -400,7 +400,11 @@ void SkyBox::_initRender() } GFXVertexPNTT *vertPtr = mVB.lock(); - if(!vertPtr) return; + if (!vertPtr) + { + delete[] tmpVerts; + return; + } dMemcpy( vertPtr, tmpVerts, sizeof ( GFXVertexPNTT ) * vertCount ); diff --git a/Engine/source/environment/sun.cpp b/Engine/source/environment/sun.cpp index ae42f2bbc..bd89d4cca 100644 --- a/Engine/source/environment/sun.cpp +++ b/Engine/source/environment/sun.cpp @@ -470,7 +470,7 @@ void Sun::_renderCorona( ObjectRenderInst *ri, SceneRenderState *state, BaseMatI const MatrixF &camView = state->getCameraTransform(); // Finalize points - for(int i = 0; i < 4; i++) + for(S32 i = 0; i < 4; i++) { // align with camera camView.mulV(points[i]); diff --git a/Engine/source/environment/waterObject.cpp b/Engine/source/environment/waterObject.cpp index 51e737717..3d55c6b02 100644 --- a/Engine/source/environment/waterObject.cpp +++ b/Engine/source/environment/waterObject.cpp @@ -91,6 +91,7 @@ void WaterMatParams::clear() mSpecularParamsSC = NULL; mDepthGradMaxSC = NULL; mReflectivitySC = NULL; + mDepthGradSamplerSC = NULL; } void WaterMatParams::init( BaseMatInstance* matInst ) @@ -132,6 +133,7 @@ void WaterMatParams::init( BaseMatInstance* matInst ) mSpecularParamsSC = matInst->getMaterialParameterHandle( "$specularParams" ); mDepthGradMaxSC = matInst->getMaterialParameterHandle( "$depthGradMax" ); mReflectivitySC = matInst->getMaterialParameterHandle( "$reflectivity" ); + mDepthGradSamplerSC = matInst->getMaterialParameterHandle( "$depthGradMap" ); } @@ -732,6 +734,11 @@ void WaterObject::renderObject( ObjectRenderInst *ri, SceneRenderState *state, B bool doQuery = ( !mPlaneReflector.mQueryPending && query && mReflectorDesc.useOcclusionQuery ); + // We need to call this for avoid a DX9 or Nvidia bug. + // At some resollutions read from render target, + // break current occlusion query. + REFLECTMGR->getRefractTex(); + if ( doQuery ) query->begin(); @@ -747,22 +754,20 @@ void WaterObject::renderObject( ObjectRenderInst *ri, SceneRenderState *state, B void WaterObject::setCustomTextures( S32 matIdx, U32 pass, const WaterMatParams ¶mHandles ) { - // TODO: Retrieve sampler numbers from parameter handles, see r22631. - // Always use the ripple texture. - GFX->setTexture( 0, mRippleTex ); + GFX->setTexture( paramHandles.mRippleSamplerSC->getSamplerRegister(pass), mRippleTex ); // Only above-water in advanced-lighting uses the foam texture. if ( matIdx == WaterMat ) { - GFX->setTexture( 5, mFoamTex ); - GFX->setTexture( 6, mDepthGradientTex ); + GFX->setTexture( paramHandles.mFoamSamplerSC->getSamplerRegister(pass), mFoamTex ); + GFX->setTexture( paramHandles.mDepthGradSamplerSC->getSamplerRegister(pass), mDepthGradientTex ); } if ( ( matIdx == WaterMat || matIdx == BasicWaterMat ) && mCubemap ) - GFX->setCubeTexture( 4, mCubemap->mCubemap ); - else - GFX->setCubeTexture( 4, NULL ); + GFX->setCubeTexture( paramHandles.mCubemapSamplerSC->getSamplerRegister(pass), mCubemap->mCubemap ); + else if(paramHandles.mCubemapSamplerSC->getSamplerRegister(pass) != -1 ) + GFX->setCubeTexture( paramHandles.mCubemapSamplerSC->getSamplerRegister(pass), NULL ); } void WaterObject::drawUnderwaterFilter( SceneRenderState *state ) diff --git a/Engine/source/environment/waterObject.h b/Engine/source/environment/waterObject.h index 06c5e7dd0..7eeb05703 100644 --- a/Engine/source/environment/waterObject.h +++ b/Engine/source/environment/waterObject.h @@ -97,6 +97,7 @@ struct WaterMatParams MaterialParameterHandle* mSpecularParamsSC; MaterialParameterHandle* mDepthGradMaxSC; MaterialParameterHandle* mReflectivitySC; + MaterialParameterHandle* mDepthGradSamplerSC; void clear(); void init(BaseMatInstance* matInst); diff --git a/Engine/source/environment/waterPlane.cpp b/Engine/source/environment/waterPlane.cpp index eab66a466..afa3dc254 100644 --- a/Engine/source/environment/waterPlane.cpp +++ b/Engine/source/environment/waterPlane.cpp @@ -163,7 +163,7 @@ void WaterPlane::unpackUpdate(NetConnection* con, BitStream* stream) if( stream->readFlag() ) // UpdateMask { - float posZ; + F32 posZ; stream->read( &posZ ); Point3F newPos = getPosition(); newPos.z = posZ; diff --git a/Engine/source/forest/editor/forestBrushTool.cpp b/Engine/source/forest/editor/forestBrushTool.cpp index a32e28ed7..4dd1734df 100644 --- a/Engine/source/forest/editor/forestBrushTool.cpp +++ b/Engine/source/forest/editor/forestBrushTool.cpp @@ -650,7 +650,7 @@ void ForestBrushTool::_collectElements() } } -bool ForestBrushTool::getGroundAt( const Point3F &worldPt, float *zValueOut, VectorF *normalOut ) +bool ForestBrushTool::getGroundAt( const Point3F &worldPt, F32 *zValueOut, VectorF *normalOut ) { const U32 mask = TerrainObjectType | StaticShapeObjectType; diff --git a/Engine/source/forest/editor/forestBrushTool.h b/Engine/source/forest/editor/forestBrushTool.h index 510146ff4..0debad616 100644 --- a/Engine/source/forest/editor/forestBrushTool.h +++ b/Engine/source/forest/editor/forestBrushTool.h @@ -82,7 +82,7 @@ public: void setPressure( F32 val ); void setHardness( F32 val ); void collectElements() { _collectElements(); } - bool getGroundAt( const Point3F &worldPt, float *zValueOut, VectorF *normalOut ); + bool getGroundAt( const Point3F &worldPt, F32 *zValueOut, VectorF *normalOut ); protected: diff --git a/Engine/source/forest/forestCollision.cpp b/Engine/source/forest/forestCollision.cpp index 8658f2474..ded08cd96 100644 --- a/Engine/source/forest/forestCollision.cpp +++ b/Engine/source/forest/forestCollision.cpp @@ -64,13 +64,14 @@ ScriptMethod( Forest, forestRayCast, const char*, 4, 4, "( Point3F start, Point3 dSscanf(argv[2], "%g %g %g", &start.x, &start.y, &start.z); dSscanf(argv[3], "%g %g %g", &end.x, &end.y, &end.z); - char *returnBuffer = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char *returnBuffer = Con::getReturnBuffer(bufSize); returnBuffer[0] = '0'; returnBuffer[1] = '\0'; ForestRayInfo rinfo; if ( object->castRayI( start, end, &rinfo ) ) - dSprintf( returnBuffer, 256, "%d %d %g", rinfo.item->getData()->getId(), rinfo.key, rinfo.t ); + dSprintf( returnBuffer, bufSize, "%d %d %g", rinfo.item->getData()->getId(), rinfo.key, rinfo.t ); return returnBuffer; } diff --git a/Engine/source/forest/glsl/windDeformationGLSL.cpp b/Engine/source/forest/glsl/windDeformationGLSL.cpp index 00502caa9..ae32b51f7 100644 --- a/Engine/source/forest/glsl/windDeformationGLSL.cpp +++ b/Engine/source/forest/glsl/windDeformationGLSL.cpp @@ -40,6 +40,9 @@ static void _onRegisterFeatures( GFXAdapterType type ) { + if ( type != OpenGL ) + return; + FEATUREMGR->registerFeature( MFT_WindEffect, new WindDeformationGLSL ); } @@ -83,29 +86,14 @@ void WindDeformationGLSL::processVert( Vector &componentList, // save constant space and reduce the memory copied to the // card. // - // This in particular helps when we're instancing. - // // .x = bend scale // .y = branch amplitude // .z = detail amplitude // .w = detail frequency // - Var *windParams; - if ( fd.features[MFT_UseInstancing] ) - { - ShaderConnector *vertStruct = dynamic_cast( componentList[C_VERT_STRUCT] ); - windParams = vertStruct->getElement( RT_TEXCOORD ); - windParams->setName( "inst_windParams" ); - windParams->setType( "vec4" ); - - mInstancingFormat->addElement( "windParams", GFXDeclType_Float4, windParams->constNum ); - } - else - { - windParams = new Var( "windParams", "vec4" ); + Var *windParams = new Var( "windParams", "vec4" ); windParams->uniform = true; windParams->constSortPos = cspPotentialPrimitive; - } // If we're instancing then we need to instance the wind direction // and speed as its unique for each tree instance. @@ -114,6 +102,7 @@ void WindDeformationGLSL::processVert( Vector &componentList, { ShaderConnector *vertStruct = dynamic_cast( componentList[C_VERT_STRUCT] ); windDirAndSpeed = vertStruct->getElement( RT_TEXCOORD ); + windDirAndSpeed->setStructName( "IN" ); windDirAndSpeed->setName( "inst_windDirAndSpeed" ); windDirAndSpeed->setType( "vec3" ); @@ -143,16 +132,31 @@ void WindDeformationGLSL::processVert( Vector &componentList, if ( !inPosition ) inPosition = (Var*)LangElement::find( "position" ); + // Copy the input position to the output first as + // the wind effects are conditional. + Var *outPosition = (Var*)LangElement::find( "inPosition" ); + if ( !outPosition ) + { + outPosition = new Var; + outPosition->setType( "vec3" ); + outPosition->setName( "inPosition" ); + meta->addStatement( new GenOp(" @ = @.xyz;\r\n", new DecOp( outPosition ), inPosition ) ); + } + // Get the incoming color data Var *inColor = (Var*)LangElement::find( "diffuse" ); + // Do a dynamic branch based on wind force. + if ( GFX->getPixelShaderVersion() >= 3.0f ) + meta->addStatement( new GenOp(" if ( any( bvec3(@) ) ) {\r\n", windDirAndSpeed ) ); + // Do the branch and detail bending first so that // it can work in pure object space of the tree. LangElement *effect = new GenOp( "windBranchBending( " - "@.xyz, " // vPos - "normalize( normal ), " // vNormal + "@, " // vPos + "normalize( IN_normal ), " // vNormal "@, " // fTime "@.z, " // fWindSpeed @@ -161,13 +165,13 @@ void WindDeformationGLSL::processVert( Vector &componentList, "@.y, " // fBranchAmp "@.r, " // fBranchAtten - "dot( @[3], vec4( 1.0 ) ), " // fDetailPhase + "dot( @[3], vec4(1) ), " // fDetailPhase "@.z, " // fDetailAmp "@.w, " // fDetailFreq - + "@.b )", // fEdgeAtten - inPosition, // vPos + outPosition, // vPos // vNormal accumTime, // fTime @@ -183,22 +187,15 @@ void WindDeformationGLSL::processVert( Vector &componentList, inColor ); // fEdgeAtten - Var *outPosition = (Var*)LangElement::find( "inPosition" ); - if ( outPosition ) - meta->addStatement( new GenOp( " @.xyz = @;\r\n", outPosition, effect, inPosition ) ); - else - { - outPosition = new Var; - outPosition->setType( "vec3" ); - outPosition->setName( "inPosition" ); - meta->addStatement( new GenOp(" vec3 inPosition = @;\r\n", effect, inPosition ) ); - } + meta->addStatement( new GenOp( " @ = @;\r\n", outPosition, effect ) ); // Now do the trunk bending. - effect = new GenOp( "windTrunkBending( @, @.xy, @.z * @.x )", - outPosition, windDirAndSpeed, outPosition, windParams ); + meta->addStatement( new GenOp(" @ = windTrunkBending( @, @.xy, @.z * @.x );\r\n", + outPosition, outPosition, windDirAndSpeed, outPosition, windParams ) ); - meta->addStatement( new GenOp(" @ = @;\r\n", outPosition, effect ) ); + // End the dynamic branch. + if ( GFX->getPixelShaderVersion() >= 3.0f ) + meta->addStatement( new GenOp(" } // [branch]\r\n" ) ); } ShaderFeatureConstHandles* WindDeformationGLSL::createConstHandles( GFXShader *shader, SimObject *userObject ) diff --git a/Engine/source/gfx/D3D9/gfxD3D9CardProfiler.cpp b/Engine/source/gfx/D3D9/gfxD3D9CardProfiler.cpp index a2fd892fe..988e3a4e2 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9CardProfiler.cpp +++ b/Engine/source/gfx/D3D9/gfxD3D9CardProfiler.cpp @@ -25,7 +25,7 @@ #include "gfx/primBuilder.h" #include "gfx/D3D9/gfxD3D9CardProfiler.h" #include "gfx/D3D9/gfxD3D9EnumTranslate.h" -#ifdef TORQUE_OS_WIN32 +#ifdef TORQUE_OS_WIN #include "platformWin32/videoInfo/wmiVideoInfo.h" #endif diff --git a/Engine/source/gfx/D3D9/gfxD3D9EnumTranslate.h b/Engine/source/gfx/D3D9/gfxD3D9EnumTranslate.h index 00448bad0..b0ec97eae 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9EnumTranslate.h +++ b/Engine/source/gfx/D3D9/gfxD3D9EnumTranslate.h @@ -54,8 +54,8 @@ extern _D3DTEXTUREOP GFXD3D9TextureOp[GFXTOP_COUNT]; extern _D3DDECLTYPE GFXD3D9DeclType[GFXDeclType_COUNT]; #define GFXREVERSE_LOOKUP( tablearray, enumprefix, val ) \ - for( int i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \ - if( (int)tablearray##[i] == val ) \ + for( S32 i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \ + if( (S32)tablearray##[i] == val ) \ { \ val = i; \ break; \ diff --git a/Engine/source/gfx/D3D9/gfxD3D9OcclusionQuery.cpp b/Engine/source/gfx/D3D9/gfxD3D9OcclusionQuery.cpp index 142896f68..99e664652 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9OcclusionQuery.cpp +++ b/Engine/source/gfx/D3D9/gfxD3D9OcclusionQuery.cpp @@ -124,9 +124,16 @@ GFXD3D9OcclusionQuery::OcclusionQueryStatus GFXD3D9OcclusionQuery::getStatus( bo DWORD dwOccluded = 0; if ( block ) - { + { while( ( hRes = mQuery->GetData( &dwOccluded, sizeof(DWORD), D3DGETDATA_FLUSH ) ) == S_FALSE ) - ; + { + //If we're stalled out, proceed with worst-case scenario -BJR + if(GFX->mFrameTime->getElapsedMs()>4) + { + this->end(); + return NotOccluded; + } + } } else { diff --git a/Engine/source/gfx/D3D9/gfxD3D9Shader.cpp b/Engine/source/gfx/D3D9/gfxD3D9Shader.cpp index 34b9c47d2..a7ff68a78 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9Shader.cpp +++ b/Engine/source/gfx/D3D9/gfxD3D9Shader.cpp @@ -444,7 +444,7 @@ const String GFXD3D9ShaderConstBuffer::describeSelf() const GenericConstBufferLayout::ParamDesc pd; mVertexConstBufferLayoutF->getDesc(i, pd); - ret += String::ToString(" Constant name: %s", pd.name); + ret += String::ToString(" Constant name: %s", pd.name.c_str()); } return ret; diff --git a/Engine/source/gfx/D3D9/gfxD3D9TextureManager.cpp b/Engine/source/gfx/D3D9/gfxD3D9TextureManager.cpp index 417d7f803..41556630f 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9TextureManager.cpp +++ b/Engine/source/gfx/D3D9/gfxD3D9TextureManager.cpp @@ -236,7 +236,7 @@ void GFXD3D9TextureManager::_innerCreateTexture( GFXD3D9TextureObject *retTex, // If this is a render target, and it wants AA or wants to match the backbuffer (for example, to share the z) // Check the caps though, if we can't stretchrect between textures, use the old RT method. (Which hopefully means // that they can't force AA on us as well.) - if (retTex->mProfile->isRenderTarget() && mslevel != 0 && (mDeviceCaps.Caps2 && D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES)) + if (retTex->mProfile->isRenderTarget() && mslevel != 0 && (mDeviceCaps.Caps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES)) { D3D9Assert(mD3DDevice->CreateRenderTarget(width, height, d3dTextureFormat, mstype, mslevel, false, retTex->getSurfacePtr(), NULL), @@ -259,7 +259,7 @@ void GFXD3D9TextureManager::_innerCreateTexture( GFXD3D9TextureObject *retTex, retTex->mTextureSize.set(probeDesc.Width, probeDesc.Height, 0); - int fmt = probeDesc.Format; + S32 fmt = probeDesc.Format; #if !defined(TORQUE_OS_XENON) GFXREVERSE_LOOKUP( GFXD3D9TextureFormat, GFXFormat, fmt ); @@ -568,7 +568,7 @@ bool GFXD3D9TextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dd GFXD3D9TextureObject *texture = static_cast(aTexture); // Fill the texture... - for( int i = 0; i < aTexture->mMipLevels; i++ ) + for( S32 i = 0; i < aTexture->mMipLevels; i++ ) { PROFILE_SCOPE(GFXD3DTexMan_loadSurface); diff --git a/Engine/source/gfx/D3D9/gfxD3D9TextureObject.cpp b/Engine/source/gfx/D3D9/gfxD3D9TextureObject.cpp index be859b857..ff9c69096 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9TextureObject.cpp +++ b/Engine/source/gfx/D3D9/gfxD3D9TextureObject.cpp @@ -242,9 +242,9 @@ bool GFXD3D9TextureObject::copyToBmp(GBitmap* bmp) PROFILE_START(GFXD3D9TextureObject_copyToBmp_pixCopy); // copy data into bitmap - for (int row = 0; row < height; ++row) + for (S32 row = 0; row < height; ++row) { - for (int col = 0; col < width; ++col) + for (S32 col = 0; col < width; ++col) { destPtr[0] = srcPtr[2]; // red destPtr[1] = srcPtr[1]; // green diff --git a/Engine/source/gfx/D3D9/pc/gfxD3D9EnumTranslate.pc.cpp b/Engine/source/gfx/D3D9/pc/gfxD3D9EnumTranslate.pc.cpp index ae143cfc3..f4e4accff 100644 --- a/Engine/source/gfx/D3D9/pc/gfxD3D9EnumTranslate.pc.cpp +++ b/Engine/source/gfx/D3D9/pc/gfxD3D9EnumTranslate.pc.cpp @@ -46,14 +46,14 @@ _D3DDECLTYPE GFXD3D9DeclType[GFXDeclType_COUNT]; //------------------------------------------------------------------------------ #define INIT_LOOKUPTABLE( tablearray, enumprefix, type ) \ - for( int i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \ + for( S32 i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \ tablearray##[i] = (##type##)GFX_UNINIT_VAL; #define VALIDATE_LOOKUPTABLE( tablearray, enumprefix ) \ - for( int i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \ - if( (int)tablearray##[i] == GFX_UNINIT_VAL ) \ + for( S32 i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \ + if( (S32)tablearray##[i] == GFX_UNINIT_VAL ) \ Con::warnf( "GFXD3D9EnumTranslate: Unassigned value in " #tablearray ": %i", i ); \ - else if( (int)tablearray##[i] == GFX_UNSUPPORTED_VAL ) \ + else if( (S32)tablearray##[i] == GFX_UNSUPPORTED_VAL ) \ Con::warnf( "GFXD3D9EnumTranslate: Unsupported value in " #tablearray ": %i", i ); //------------------------------------------------------------------------------ diff --git a/Engine/source/gfx/D3D9/pc/gfxPCD3D9Target.cpp b/Engine/source/gfx/D3D9/pc/gfxPCD3D9Target.cpp index 194e304fd..0ac4114cf 100644 --- a/Engine/source/gfx/D3D9/pc/gfxPCD3D9Target.cpp +++ b/Engine/source/gfx/D3D9/pc/gfxPCD3D9Target.cpp @@ -330,7 +330,7 @@ void GFXPCD3D9TextureTarget::resolveTo( GFXTextureObject *tex ) void GFXPCD3D9TextureTarget::zombify() { - for(int i = 0; i < MaxRenderSlotId; i++) + for(S32 i = 0; i < MaxRenderSlotId; i++) attachTexture(RenderSlot(i), NULL); } diff --git a/Engine/source/gfx/bitmap/ddsLoader.cpp b/Engine/source/gfx/bitmap/ddsLoader.cpp index 3405547a9..4ad23ef39 100644 --- a/Engine/source/gfx/bitmap/ddsLoader.cpp +++ b/Engine/source/gfx/bitmap/ddsLoader.cpp @@ -883,7 +883,7 @@ DDSFile *DDSFile::createDDSFileFromGBitmap( const GBitmap *gbmp ) ret->mSurfaces.push_back( new SurfaceData() ); // Load the mips - for( int i = 0; i < ret->mMipMapCount; i++ ) + for( S32 i = 0; i < ret->mMipMapCount; i++ ) { const U32 mipSz = ret->getSurfaceSize(i); ret->mSurfaces.last()->mMips.push_back( new U8[mipSz] ); @@ -898,7 +898,7 @@ DDSFile *DDSFile::createDDSFileFromGBitmap( const GBitmap *gbmp ) // Assumption: AssertFatal( gbmp->getBytesPerPixel() + 1 == ret->mBytesPerPixel, "Assumption failed, not 24->32 bit straight convert." ); - for( int pxl = 0; pxl < gbmp->getWidth(i) * gbmp->getHeight(i); pxl++ ) + for( S32 pxl = 0; pxl < gbmp->getWidth(i) * gbmp->getHeight(i); pxl++ ) { U8 *dst = &mipMem[pxl * ret->mBytesPerPixel]; const U8 *src = &gbmp->getBits(i)[pxl * gbmp->getBytesPerPixel()]; diff --git a/Engine/source/gfx/bitmap/ddsUtils.cpp b/Engine/source/gfx/bitmap/ddsUtils.cpp index 42971bfdc..b5e5fa4a8 100644 --- a/Engine/source/gfx/bitmap/ddsUtils.cpp +++ b/Engine/source/gfx/bitmap/ddsUtils.cpp @@ -77,7 +77,7 @@ bool DDSUtil::squishDDS( DDSFile *srcDDS, const GFXFormat dxtFormat ) // are done, we can discard the old surface, and replace it with this one. DDSFile::SurfaceData *newSurface = new DDSFile::SurfaceData(); - for( int i = 0; i < srcDDS->mMipMapCount; i++ ) + for( S32 i = 0; i < srcDDS->mMipMapCount; i++ ) { const U8 *srcBits = srcSurface->mMips[i]; @@ -106,7 +106,7 @@ bool DDSUtil::squishDDS( DDSFile *srcDDS, const GFXFormat dxtFormat ) void DDSUtil::swizzleDDS( DDSFile *srcDDS, const Swizzle &swizzle ) { - for( int i = 0; i < srcDDS->mMipMapCount; i++ ) + for( S32 i = 0; i < srcDDS->mMipMapCount; i++ ) { swizzle.InPlace( srcDDS->mSurfaces.last()->mMips[i], srcDDS->getSurfaceSize( i ) ); } diff --git a/Engine/source/gfx/bitmap/gBitmap.cpp b/Engine/source/gfx/bitmap/gBitmap.cpp index f0e0ad11e..151a792ed 100644 --- a/Engine/source/gfx/bitmap/gBitmap.cpp +++ b/Engine/source/gfx/bitmap/gBitmap.cpp @@ -796,11 +796,11 @@ bool GBitmap::combine( const GBitmap *bitmapA, const GBitmap *bitmapB, const GFX const U8 *aBits = bitmapA->getBits(); const U8 *bBits = bitmapB->getBits(); - for( int y = 0; y < getHeight(); y++ ) + for( S32 y = 0; y < getHeight(); y++ ) { - for( int x = 0; x < getWidth(); x++ ) + for( S32 x = 0; x < getWidth(); x++ ) { - for( int _byte = 0; _byte < mBytesPerPixel; _byte++ ) + for( S32 _byte = 0; _byte < mBytesPerPixel; _byte++ ) { U8 pxA = 0; U8 pxB = 0; diff --git a/Engine/source/gfx/bitmap/loaders/bitmapBmp.cpp b/Engine/source/gfx/bitmap/loaders/bitmapBmp.cpp index 925d676dd..a54c3997e 100644 --- a/Engine/source/gfx/bitmap/loaders/bitmapBmp.cpp +++ b/Engine/source/gfx/bitmap/loaders/bitmapBmp.cpp @@ -152,7 +152,7 @@ static bool sReadBMP(Stream &stream, GBitmap *bitmap) if(bytesPerPixel == 3 && bi.biBitCount != 8) // do BGR swap { U8 *ptr = bitmap->getAddress(0,0); - for(int i = 0; i < width * height; i++) + for(S32 i = 0; i < width * height; i++) { U8 tmp = ptr[0]; ptr[0] = ptr[2]; diff --git a/Engine/source/gfx/bitmap/loaders/bitmapGif.cpp b/Engine/source/gfx/bitmap/loaders/bitmapGif.cpp index ef1bb783b..d4c031026 100644 --- a/Engine/source/gfx/bitmap/loaders/bitmapGif.cpp +++ b/Engine/source/gfx/bitmap/loaders/bitmapGif.cpp @@ -54,7 +54,7 @@ static struct _privateRegisterGIF //-------------------------------------- Replacement I/O for standard LIBjpeg // functions. we don't wanna use // FILE*'s... -static int gifReadDataFn(GifFileType *gifinfo, GifByteType *data, int length) +static S32 gifReadDataFn(GifFileType *gifinfo, GifByteType *data, S32 length) { Stream *stream = (Stream*)gifinfo->UserData; AssertFatal(stream != NULL, "gifReadDataFn::No stream."); @@ -72,7 +72,7 @@ static int gifReadDataFn(GifFileType *gifinfo, GifByteType *data, int length) //-------------------------------------- #if 0 // CodeReview - until we can write these, get rid of warning by disabling method. -static int gifWriteDataFn(GifFileType *gifinfo, GifByteType *data, int length) +static S32 gifWriteDataFn(GifFileType *gifinfo, GifByteType *data, S32 length) { Stream *stream = (Stream*)gifinfo->UserData; AssertFatal(stream != NULL, "gifWriteDataFn::No stream."); diff --git a/Engine/source/gfx/bitmap/loaders/bitmapJpeg.cpp b/Engine/source/gfx/bitmap/loaders/bitmapJpeg.cpp index 790369f32..8a647afda 100644 --- a/Engine/source/gfx/bitmap/loaders/bitmapJpeg.cpp +++ b/Engine/source/gfx/bitmap/loaders/bitmapJpeg.cpp @@ -50,11 +50,11 @@ static struct _privateRegisterJPG //-------------------------------------- Replacement I/O for standard LIBjpeg // functions. we don't wanna use // FILE*'s... -static int jpegReadDataFn(void *client_data, unsigned char *data, int length) +static S32 jpegReadDataFn(void *client_data, U8 *data, S32 length) { Stream *stream = (Stream*)client_data; AssertFatal(stream != NULL, "jpegReadDataFn::No stream."); - int pos = stream->getPosition(); + S32 pos = stream->getPosition(); if (stream->read(length, data)) return length; @@ -66,7 +66,7 @@ static int jpegReadDataFn(void *client_data, unsigned char *data, int length) //-------------------------------------- -static int jpegWriteDataFn(void *client_data, unsigned char *data, int length) +static S32 jpegWriteDataFn(void *client_data, U8 *data, S32 length) { Stream *stream = (Stream*)client_data; AssertFatal(stream != NULL, "jpegWriteDataFn::No stream."); @@ -78,7 +78,7 @@ static int jpegWriteDataFn(void *client_data, unsigned char *data, int length) //-------------------------------------- -static int jpegFlushDataFn(void *) +static S32 jpegFlushDataFn(void *) { // do nothing since we can't flush the stream object return 0; @@ -86,7 +86,7 @@ static int jpegFlushDataFn(void *) //-------------------------------------- -static int jpegErrorFn(void *client_data) +static S32 jpegErrorFn(void *client_data) { Stream *stream = (Stream*)client_data; AssertFatal(stream != NULL, "jpegErrorFn::No stream."); diff --git a/Engine/source/gfx/gFont.cpp b/Engine/source/gfx/gFont.cpp index ec8ce4205..7c838915d 100644 --- a/Engine/source/gfx/gFont.cpp +++ b/Engine/source/gfx/gFont.cpp @@ -42,7 +42,7 @@ GFX_ImplementTextureProfile(GFXFontTextureProfile, GFXTextureProfile::Static | GFXTextureProfile::KeepBitmap | GFXTextureProfile::NoMipmap, - GFXTextureProfile::None); + GFXTextureProfile::NONE); template<> void *Resource::create(const Torque::Path &path) { @@ -265,7 +265,7 @@ void GFont::dumpInfo() const if(mapCount) Con::printf(" - Codepoints range from 0x%x to 0x%x.", mapBegin, mapEnd); else - Con::printf(" - No mapped codepoints.", mapBegin, mapEnd); + Con::printf(" - No mapped codepoints."); Con::printf(" - Platform font is %s.", (mPlatformFont ? "present" : "not present") ); } diff --git a/Engine/source/gfx/gfxDevice.cpp b/Engine/source/gfx/gfxDevice.cpp index fbf1f3c4b..d5195d880 100644 --- a/Engine/source/gfx/gfxDevice.cpp +++ b/Engine/source/gfx/gfxDevice.cpp @@ -103,7 +103,7 @@ GFXDevice::GFXDevice() mViewMatrix.identity(); mProjectionMatrix.identity(); - for( int i = 0; i < WORLD_STACK_MAX; i++ ) + for( S32 i = 0; i < WORLD_STACK_MAX; i++ ) mWorldMatrix[i].identity(); AssertFatal(smGFXDevice == NULL, "Already a GFXDevice created! Bad!"); @@ -180,12 +180,12 @@ GFXDevice::GFXDevice() // Initialize our drawing utility. mDrawer = NULL; - + mFrameTime = PlatformTimer::create(); // Add a few system wide shader macros. GFXShader::addGlobalMacro( "TORQUE", "1" ); GFXShader::addGlobalMacro( "TORQUE_VERSION", String::ToString(getVersionNumber()) ); - #if defined TORQUE_OS_WIN32 - GFXShader::addGlobalMacro( "TORQUE_OS_WIN32" ); + #if defined TORQUE_OS_WIN + GFXShader::addGlobalMacro( "TORQUE_OS_WIN" ); #elif defined TORQUE_OS_MAC GFXShader::addGlobalMacro( "TORQUE_OS_MAC" ); #elif defined TORQUE_OS_LINUX @@ -451,7 +451,7 @@ void GFXDevice::updateStates(bool forceSetAll /*=false*/) if( mTextureMatrixCheckDirty ) { - for( int i = 0; i < getNumSamplers(); i++ ) + for( S32 i = 0; i < getNumSamplers(); i++ ) { if( mTextureMatrixDirty[i] ) { @@ -804,7 +804,7 @@ inline bool GFXDevice::beginScene() // Send the start of frame signal. getDeviceEventSignal().trigger( GFXDevice::deStartOfFrame ); - + mFrameTime->reset(); return beginSceneInternal(); } @@ -1279,7 +1279,7 @@ DefineEngineFunction( getPixelShaderVersion, F32, (),, return GFX->getPixelShaderVersion(); } -DefineEngineFunction( setPixelShaderVersion, void, ( float version ),, +DefineEngineFunction( setPixelShaderVersion, void, ( F32 version ),, "@brief Sets the pixel shader version for the active device.\n" "This can be used to force a lower pixel shader version than is supported by " "the device for testing or performance optimization.\n" diff --git a/Engine/source/gfx/gfxDevice.h b/Engine/source/gfx/gfxDevice.h index 44a889f66..13620755e 100644 --- a/Engine/source/gfx/gfxDevice.h +++ b/Engine/source/gfx/gfxDevice.h @@ -54,6 +54,9 @@ #include "math/util/frustum.h" #endif +#ifndef _PLATFORM_PLATFORMTIMER_H_ +#include "platform/platformTimer.h" +#endif class FontRenderBatcher; class GFont; @@ -743,6 +746,7 @@ public: virtual void endScene(); virtual void beginField(); virtual void endField(); + PlatformTimer *mFrameTime; virtual GFXTexHandle & getFrontBuffer(){ return mFrontBuffer[mCurrentFrontBufferIdx]; } diff --git a/Engine/source/gfx/gfxDrawUtil.cpp b/Engine/source/gfx/gfxDrawUtil.cpp index d7e4b921e..d21cdb88d 100644 --- a/Engine/source/gfx/gfxDrawUtil.cpp +++ b/Engine/source/gfx/gfxDrawUtil.cpp @@ -183,7 +183,7 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_ U32 i; UTF16 c; - for(i = 0, c = in_string[i]; in_string[i] && i < n; i++, c = in_string[i]) + for (i = 0, c = in_string[i]; i < n && in_string[i]; i++, c = in_string[i]) { switch(c) { @@ -445,7 +445,7 @@ void GFXDrawUtil::drawRect( const Point2F &upperLeft, const Point2F &lowerRight, // Into Triangle-Strip Outline // v0-----------v2 // | a x | - // | v1-----v3 | + // | v1-----v3 | // | | | | // | v7-----v5 | // | x b | @@ -474,7 +474,7 @@ void GFXDrawUtil::drawRect( const Point2F &upperLeft, const Point2F &lowerRight, verts[8].point.set( upperLeft.x + ulOffset + nw.x, upperLeft.y + ulOffset + nw.y, 0.0f ); // same as 0 verts[9].point.set( upperLeft.x + ulOffset - nw.x, upperLeft.y + ulOffset - nw.y, 0.0f ); // same as 1 - for (int i=0; i<10; i++) + for (S32 i=0; i<10; i++) verts[i].color = color; verts.unlock(); @@ -512,7 +512,7 @@ void GFXDrawUtil::drawRectFill( const Point2F &upperLeft, const Point2F &lowerRi // Into Quad // v0---------v1 // | a x | - // | | + // | | // | x b | // v2---------v3 // @@ -531,7 +531,7 @@ void GFXDrawUtil::drawRectFill( const Point2F &upperLeft, const Point2F &lowerRi verts[2].point.set( upperLeft.x-ne.x+ulOffset, lowerRight.y-ne.y, 0.0f ); verts[3].point.set( lowerRight.x-nw.x, lowerRight.y-nw.y, 0.0f ); - for (int i=0; i<4; i++) + for (S32 i=0; i<4; i++) verts[i].color = color; verts.unlock(); @@ -558,7 +558,12 @@ void GFXDrawUtil::draw2DSquare( const Point2F &screenPoint, F32 width, F32 spinA verts[0].color = verts[1].color = verts[2].color = verts[3].color = mBitmapModulation; - if(spinAngle != 0.f) + if (spinAngle == 0.0f) + { + for( S32 i = 0; i < 4; i++ ) + verts[i].point += offset; + } + else { MatrixF rotMatrix( EulerF( 0.0, 0.0, spinAngle ) ); @@ -828,11 +833,11 @@ void GFXDrawUtil::_drawWireCube( const GFXStateBlockDesc &desc, const Point3F &s // setup 6 line loops U32 vertexIndex = 0; - for(int i = 0; i < 6; i++) + for(S32 i = 0; i < 6; i++) { - for(int j = 0; j < 5; j++) + for(S32 j = 0; j < 5; j++) { - int idx = cubeFaces[i][j%4]; + S32 idx = cubeFaces[i][j%4]; verts[vertexIndex].point = cubePoints[idx] * halfSize; verts[vertexIndex].color = color; @@ -872,7 +877,7 @@ void GFXDrawUtil::_drawSolidCube( const GFXStateBlockDesc &desc, const Point3F & // setup 6 line loops U32 vertexIndex = 0; U32 idx; - for(int i = 0; i < 6; i++) + for(S32 i = 0; i < 6; i++) { idx = cubeFaces[i][0]; verts[vertexIndex].point = cubePoints[idx] * halfSize; diff --git a/Engine/source/gfx/gfxDrawUtil.h b/Engine/source/gfx/gfxDrawUtil.h index 906342428..7decad785 100644 --- a/Engine/source/gfx/gfxDrawUtil.h +++ b/Engine/source/gfx/gfxDrawUtil.h @@ -58,7 +58,7 @@ public: void drawRectFill( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color ); void drawRectFill( const RectI &rect, const ColorI &color ); - void draw2DSquare( const Point2F &screenPoint, F32 width, F32 spinAngle ); + void draw2DSquare( const Point2F &screenPoint, F32 width, F32 spinAngle = 0.0f ); //----------------------------------------------------------------------------- // Draw Lines diff --git a/Engine/source/gfx/gfxFormatUtils.cpp b/Engine/source/gfx/gfxFormatUtils.cpp index 1dc101d80..433d6b8a9 100644 --- a/Engine/source/gfx/gfxFormatUtils.cpp +++ b/Engine/source/gfx/gfxFormatUtils.cpp @@ -81,7 +81,7 @@ void GFXCopyPixels( GFXFormat fromFormat, U32 fromWidth, U32 fromHeight, U8* fr { if( fromFormat == toFormat && fromWidth == toWidth - && fromHeight == fromHeight ) + && fromHeight == toHeight ) dMemcpy( toData, fromData, fromWidth * fromHeight * GFXFormatInfo( fromFormat ).getBytesPerPixel() ); else { diff --git a/Engine/source/gfx/gfxShader.cpp b/Engine/source/gfx/gfxShader.cpp index 0bbcb4942..5e81d8a10 100644 --- a/Engine/source/gfx/gfxShader.cpp +++ b/Engine/source/gfx/gfxShader.cpp @@ -45,16 +45,29 @@ GFXShader::~GFXShader() Torque::FS::RemoveChangeNotification( mPixelFile, this, &GFXShader::_onFileChanged ); } +#ifndef TORQUE_OPENGL bool GFXShader::init( const Torque::Path &vertFile, const Torque::Path &pixFile, F32 pixVersion, const Vector ¯os ) +{ + Vector samplerNames; + return init( vertFile, pixFile, pixVersion, macros, samplerNames ); +} +#endif + +bool GFXShader::init( const Torque::Path &vertFile, + const Torque::Path &pixFile, + F32 pixVersion, + const Vector ¯os, + const Vector &samplerNames) { // Store the inputs for use in reloading. mVertexFile = vertFile; mPixelFile = pixFile; mPixVersion = pixVersion; mMacros = macros; + mSamplerNamesOrdered = samplerNames; // Before we compile the shader make sure the // conditioner features have been updated. diff --git a/Engine/source/gfx/gfxShader.h b/Engine/source/gfx/gfxShader.h index 8c77a5448..4b2c10f46 100644 --- a/Engine/source/gfx/gfxShader.h +++ b/Engine/source/gfx/gfxShader.h @@ -237,6 +237,13 @@ protected: /// The macros to be passed to the shader. Vector mMacros; + /// Ordered SamplerNames + /// We need to store a list of sampler for allow OpenGL to + /// assign correct location for each sampler. + /// GLSL 150 not allow explicit uniform location. + /// Only used on OpenGL + Vector mSamplerNamesOrdered; + /// The pixel version this is compiled for. F32 mPixVersion; @@ -292,10 +299,20 @@ public: virtual ~GFXShader(); /// + /// Deprecated. Remove on T3D 4.0 +#ifndef TORQUE_OPENGL bool init( const Torque::Path &vertFile, const Torque::Path &pixFile, F32 pixVersion, const Vector ¯os ); +#endif + + /// + bool init( const Torque::Path &vertFile, + const Torque::Path &pixFile, + F32 pixVersion, + const Vector ¯os, + const Vector &samplerNames); /// Reloads the shader from disk. bool reload(); diff --git a/Engine/source/gfx/gfxStringEnumTranslate.cpp b/Engine/source/gfx/gfxStringEnumTranslate.cpp index 108422aec..ff21e41ac 100644 --- a/Engine/source/gfx/gfxStringEnumTranslate.cpp +++ b/Engine/source/gfx/gfxStringEnumTranslate.cpp @@ -76,20 +76,20 @@ _STRING_VALUE_LOOKUP_FXN(GFXStringBlendOp); //------------------------------------------------------------------------------ #define INIT_LOOKUPTABLE( tablearray, enumprefix, type ) \ - for( int i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \ + for( S32 i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \ tablearray[i] = (type)GFX_UNINIT_VAL; #define INIT_LOOKUPTABLE_EX( tablearray, enumprefix, type, typeTable ) \ - for( int i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \ + for( S32 i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \ {\ tablearray[i] = (type)GFX_UNINIT_VAL;\ typeTable[i] = &defaultStringValueLookup;\ } #define VALIDATE_LOOKUPTABLE( tablearray, enumprefix ) \ - for( int i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \ - if( (int)tablearray[i] == GFX_UNINIT_VAL ) \ + for( S32 i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \ + if( (S32)tablearray[i] == GFX_UNINIT_VAL ) \ Con::warnf( "GFXStringEnumTranslate: Unassigned value in " #tablearray ": %i", i ); \ - else if( (int)tablearray[i] == GFX_UNSUPPORTED_VAL ) \ + else if( (S32)tablearray[i] == GFX_UNSUPPORTED_VAL ) \ Con::warnf( "GFXStringEnumTranslate: Unsupported value in " #tablearray ": %i", i ); //------------------------------------------------------------------------------ diff --git a/Engine/source/gfx/gfxStringEnumTranslate.h b/Engine/source/gfx/gfxStringEnumTranslate.h index 2184ab18f..37aab7590 100644 --- a/Engine/source/gfx/gfxStringEnumTranslate.h +++ b/Engine/source/gfx/gfxStringEnumTranslate.h @@ -71,8 +71,8 @@ extern StringValueLookupFn GFXStringSamplerStateValueLookup[GFXSAMP_COUNT]; extern StringValueLookupFn GFXStringTextureStageStateValueLookup[GFXTSS_COUNT]; #define GFXREVERSE_LOOKUP( tablearray, enumprefix, val ) \ - for( int i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \ - if( (int)tablearray##[i] == val ) \ + for( S32 i = enumprefix##_FIRST; i < enumprefix##_COUNT; i++ ) \ + if( (S32)tablearray##[i] == val ) \ { \ val = i; \ break; \ diff --git a/Engine/source/gfx/gfxTextureManager.cpp b/Engine/source/gfx/gfxTextureManager.cpp index 7978eb6da..c997d1d2b 100644 --- a/Engine/source/gfx/gfxTextureManager.cpp +++ b/Engine/source/gfx/gfxTextureManager.cpp @@ -1031,9 +1031,9 @@ void GFXTextureManager::_validateTexParams( const U32 width, const U32 height, // If the format is non-compressed, and the profile requests a compressed format // than change the format. GFXFormat testingFormat = inOutFormat; - if( profile->getCompression() != GFXTextureProfile::None ) + if( profile->getCompression() != GFXTextureProfile::NONE ) { - const int offset = profile->getCompression() - GFXTextureProfile::DXT1; + const S32 offset = profile->getCompression() - GFXTextureProfile::DXT1; testingFormat = GFXFormat( GFXFormatDXT1 + offset ); // No auto-gen mips on compressed textures diff --git a/Engine/source/gfx/gfxTextureObject.h b/Engine/source/gfx/gfxTextureObject.h index b9db600f1..bed37bdce 100644 --- a/Engine/source/gfx/gfxTextureObject.h +++ b/Engine/source/gfx/gfxTextureObject.h @@ -63,7 +63,7 @@ struct GFXLockedRect { /// Pitch of the lock. This is the spacing in bytes of the start /// of each row of the locked region. - int pitch; + S32 pitch; /// Pointer to the start of locked rectangle. U8* bits; diff --git a/Engine/source/gfx/gfxTextureProfile.cpp b/Engine/source/gfx/gfxTextureProfile.cpp index 1c75b11ef..0272d6b31 100644 --- a/Engine/source/gfx/gfxTextureProfile.cpp +++ b/Engine/source/gfx/gfxTextureProfile.cpp @@ -34,15 +34,15 @@ GFX_ImplementTextureProfile(GFXDefaultRenderTargetProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::PreserveSize | GFXTextureProfile::NoMipmap | GFXTextureProfile::RenderTarget, - GFXTextureProfile::None); + GFXTextureProfile::NONE); GFX_ImplementTextureProfile(GFXDefaultStaticDiffuseProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::Static, - GFXTextureProfile::None); + GFXTextureProfile::NONE); GFX_ImplementTextureProfile(GFXDefaultStaticNormalMapProfile, GFXTextureProfile::NormalMap, GFXTextureProfile::Static, - GFXTextureProfile::None); + GFXTextureProfile::NONE); GFX_ImplementTextureProfile(GFXDefaultStaticDXT5nmProfile, GFXTextureProfile::NormalMap, GFXTextureProfile::Static, @@ -50,15 +50,15 @@ GFX_ImplementTextureProfile(GFXDefaultStaticDXT5nmProfile, GFX_ImplementTextureProfile(GFXDefaultPersistentProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::PreserveSize | GFXTextureProfile::Static | GFXTextureProfile::KeepBitmap, - GFXTextureProfile::None); + GFXTextureProfile::NONE); GFX_ImplementTextureProfile(GFXSystemMemProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::PreserveSize | GFXTextureProfile::NoMipmap | GFXTextureProfile::SystemMemory, - GFXTextureProfile::None); + GFXTextureProfile::NONE); GFX_ImplementTextureProfile(GFXDefaultZTargetProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::PreserveSize | GFXTextureProfile::NoMipmap | GFXTextureProfile::ZTarget | GFXTextureProfile::NoDiscard, - GFXTextureProfile::None); + GFXTextureProfile::NONE); //----------------------------------------------------------------------------- diff --git a/Engine/source/gfx/gfxTextureProfile.h b/Engine/source/gfx/gfxTextureProfile.h index 9153256e3..e5abbc4da 100644 --- a/Engine/source/gfx/gfxTextureProfile.h +++ b/Engine/source/gfx/gfxTextureProfile.h @@ -106,7 +106,7 @@ public: enum Compression { - None, + NONE, DXT1, DXT2, DXT3, @@ -114,7 +114,7 @@ public: DXT5, }; - GFXTextureProfile(const String &name, Types type, U32 flags, Compression compression = None); + GFXTextureProfile(const String &name, Types type, U32 flags, Compression compression = NONE); // Accessors String getName() const { return mName; }; diff --git a/Engine/source/gfx/screenshot.h b/Engine/source/gfx/screenshot.h index 63de45280..9de224f06 100644 --- a/Engine/source/gfx/screenshot.h +++ b/Engine/source/gfx/screenshot.h @@ -74,6 +74,7 @@ public: /// Constructor. ScreenShot(); + virtual ~ScreenShot() { } /// Used to start the screenshot capture. void setPending( const char *filename, bool writeJPG, S32 tiles, F32 overlap ); diff --git a/Engine/source/gfx/test/stanfordBunny.cpp b/Engine/source/gfx/test/stanfordBunny.cpp deleted file mode 100644 index 90a79fae6..000000000 --- a/Engine/source/gfx/test/stanfordBunny.cpp +++ /dev/null @@ -1,13623 +0,0 @@ -/* - - File: stanfordbunny.c - - Abstract: See - - Version: 1.0 - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple - Computer, Inc. ("Apple") in consideration of your agreement to the - following terms, and your use, installation, modification or - redistribution of this Apple software constitutes acceptance of these - terms. If you do not agree with these terms, please do not use, - install, modify or redistribute this Apple software. - - In consideration of your agreement to abide by the following terms, and - subject to these terms, Apple grants you a personal, non-exclusive - license, under Apple's copyrights in this original Apple software (the - "Apple Software"), to use, reproduce, modify and redistribute the Apple - Software, with or without modifications, in source and/or binary forms; - provided that if you redistribute the Apple Software in its entirety and - without modifications, you must retain this notice and the following - text and disclaimers in all such redistributions of the Apple Software. - Neither the name, trademarks, service marks or logos of Apple Computer, - Inc. may be used to endorse or promote products derived from the Apple - Software without specific prior written permission from Apple. Except - as expressly stated in this notice, no other rights or licenses, express - or implied, are granted by Apple herein, including but not limited to - any patent rights that may be infringed by your derivative works or by - other works in which the Apple Software may be incorporated. - - The Apple Software is provided by Apple on an "AS IS" basis. APPLE - MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION - THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND - OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. - - IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL - OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, - MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED - AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), - STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - Copyright 2006 Apple Computer, Inc., All Rights Reserved - -*/ - -/* - stanfordbunny.c - - This file contains the data and associated APIs to create a display list - of a complex model, the "Stanford Bunny" a reconstructed 3D scan of a Bunny. - - It provides GenStanfordBunnyWireList() and GenStanfordBunnySolidList() - to construct a display list and return it's ID using 3 arrays of data: - face_indicies, vertices and normals that you see below. -*/ - - - -/* - Stanford Bunny Data (culled) - - See for original data -*/ - -#include "gfx/gfxDevice.h" -#include "gfx/gfxVertexBuffer.h" -#include "gfx/gfxStructs.h" - -// 8146 Verticies -// 8127 Normals -// 16301 Triangles - -short face_indicies[16301][6] = { -// surface - {1538,2410,1101 ,0,1,2 }, {713,6196,101 ,3,4,5 }, {696,704,101 ,6,7,5 }, - {1192,117,1113 ,8,9,10 }, {1260,173,1857 ,11,12,13 }, {540,1192,1113 ,14,8,10 }, - {704,696,398 ,7,6,15 }, {398,696,458 ,15,6,16 }, {1605,772,4540 ,17,18,19 }, - {1192,540,1857 ,8,14,13 }, {772,713,809 ,18,3,20 }, {713,173,1260 ,3,12,11 }, - {173,1192,1857 ,12,8,13 }, {809,713,1260 ,20,3,11 }, {804,4128,4120 ,21,22,23 }, - {1133,804,4120 ,24,21,23 }, {4128,4140,4531 ,22,25,26 }, {4140,1534,4136 ,25,27,28 }, - {4531,4140,4136 ,26,25,28 }, {4136,1534,1254 ,28,27,29 }, {4515,1609,4485 ,30,31,32 }, - {710,1396,889 ,33,34,35 }, {1245,3618,4204 ,36,37,38 }, {2046,1905,768 ,39,40,41 }, - {2453,5699,5698 ,42,43,44 }, {1254,2046,768 ,29,39,41 }, {768,1905,1393 ,41,40,45 }, - {1393,1490,4112 ,45,46,47 }, {5657,5658,5680 ,48,49,50 }, {1490,4281,839 ,46,51,52 }, - {4112,1490,839 ,47,46,52 }, {839,4281,1330 ,52,51,53 }, {6897,8079,3286 ,54,55,56 }, - {920,4291,1937 ,57,58,59 }, {321,1132,1222 ,60,61,62 }, {5338,4915,4914 ,63,64,65 }, - {1093,4537,840 ,66,67,68 }, {4537,1697,840 ,67,69,68 }, {705,659,4158 ,70,71,72 }, - {7248,7323,7322 ,73,74,75 }, {5413,5103,798 ,76,77,78 }, {5244,5289,5266 ,79,80,81 }, - {4197,4217,4258 ,82,83,84 }, {277,360,214 ,85,86,87 }, {4498,4536,4535 ,88,89,90 }, - {4497,4498,4535 ,91,88,90 }, {231,654,775 ,92,93,94 }, {4535,4536,792 ,90,89,95 }, - {8065,6577,8094 ,96,97,98 }, {1595,703,4145 ,99,100,101 }, {5203,1089,4369 ,102,103,104 }, - {2698,5203,4369 ,105,102,104 }, {1653,4491,226 ,106,107,108 }, - {2941,2940,2907 ,109,110,111 }, {6413,6414,3340 ,112,113,114 }, - {5231,3276,922 ,115,116,117 }, {1628,792,883 ,118,95,119 }, {4273,2042,542 ,120,121,122 }, - {4091,4126,4125 ,123,124,125 }, {4077,4091,4125 ,126,123,125 }, - {5618,103,2011 ,127,128,129 }, {2026,934,4251 ,130,131,132 }, - {4123,4173,4172 ,133,134,135 }, {3397,4123,4172 ,136,133,135 }, - {4122,4123,3397 ,137,133,136 }, {82,284,80 ,138,139,140 }, {5113,6120,5845 ,141,142,143 }, - {803,696,101 ,144,6,5 }, {139,1420,2137 ,145,146,147 }, {1348,1310,737 ,148,149,150 }, - {1423,196,396 ,151,152,153 }, {4403,4356,4432 ,154,155,156 }, - {143,781,142 ,157,158,159 }, {1148,1925,4132 ,160,161,162 }, - {1031,804,1133 ,163,21,24 }, {458,1031,1133 ,16,163,24 }, {1318,2137,1420 ,164,147,146 }, - {4255,4328,4301 ,165,166,167 }, {715,174,1652 ,168,169,170 }, - {5483,8116,5261 ,171,172,173 }, {1468,1451,542 ,174,175,122 }, - {2206,2219,4978 ,176,177,178 }, {804,4140,4128 ,21,25,22 }, {1222,1132,4521 ,62,61,179 }, - {4521,1318,606 ,179,164,180 }, {5162,5618,1443 ,181,127,182 }, - {3221,5261,8119 ,183,173,184 }, {4067,4077,4071 ,185,126,186 }, - {4526,1651,4515 ,187,188,30 }, {4526,891,1651 ,187,189,188 }, - {6320,6345,3533 ,190,191,192 }, {4140,779,1534 ,25,193,27 }, - {839,1330,1481 ,52,53,194 }, {1534,544,1254 ,27,195,29 }, {139,1318,1420 ,145,164,146 }, - {1842,940,1840 ,196,197,198 }, {5730,5729,3615 ,199,200,201 }, - {174,715,1147 ,169,168,202 }, {1345,1846,1093 ,203,204,66 }, - {4084,1178,4113 ,205,206,207 }, {3397,4172,1257 ,136,135,208 }, - {2042,1468,542 ,121,174,122 }, {787,4130,175 ,209,210,211 }, - {1461,1311,1310 ,212,213,149 }, {1311,457,1310 ,213,214,149 }, - {4211,321,885 ,215,60,216 }, {116,4211,885 ,217,215,216 }, {3761,4326,1463 ,218,219,220 }, - {544,1905,2046 ,195,40,39 }, {1254,544,2046 ,29,195,39 }, {1310,457,229 ,149,214,221 }, - {57,4160,735 ,222,223,224 }, {4029,4214,4019 ,225,226,227 }, - {4367,4421,4390 ,228,229,230 }, {4255,4301,4300 ,165,167,231 }, - {4411,962,1006 ,232,233,234 }, {2707,1335,4446 ,235,236,237 }, - {888,757,120 ,238,239,240 }, {4980,4547,2163 ,241,242,243 }, - {891,1461,200 ,189,212,244 }, {891,200,1651 ,189,244,188 }, {4838,311,24 ,245,246,247 }, - {169,105,1880 ,248,249,250 }, {1393,4179,1490 ,45,251,46 }, {1490,4179,4281 ,46,251,51 }, - {3263,8102,8089 ,252,253,254 }, {700,757,896 ,255,239,256 }, - {4465,4484,4514 ,257,258,259 }, {4202,700,464 ,260,255,261 }, - {3283,2968,1693 ,262,263,264 }, {1609,4514,4484 ,31,259,258 }, - {4485,1609,4484 ,32,31,258 }, {1609,714,4514 ,31,265,259 }, {606,1318,139 ,180,164,145 }, - {1747,979,970 ,266,267,268 }, {4136,1254,399 ,28,29,269 }, {4473,4451,4497 ,270,271,91 }, - {4057,2420,4263 ,272,273,274 }, {1396,770,889 ,34,275,35 }, {4421,4420,4390 ,229,276,230 }, - {1069,4138,1209 ,277,278,279 }, {3948,3670,1877 ,280,281,282 }, - {2707,5162,1335 ,235,181,236 }, {3484,863,1300 ,283,284,285 }, - {4978,5000,6414 ,178,286,113 }, {190,1161,1021 ,287,288,289 }, - {896,757,888 ,256,239,238 }, {1348,737,497 ,148,150,290 }, {639,1348,497 ,291,148,290 }, - {1112,4202,4194 ,292,260,293 }, {3958,3957,3903 ,294,295,296 }, - {64,613,11 ,297,298,299 }, {1344,456,795 ,300,301,302 }, {27,43,545 ,303,304,305 }, - {1033,888,30 ,306,238,307 }, {1023,4224,1033 ,308,309,306 }, - {4194,4202,464 ,293,260,261 }, {497,737,190 ,290,150,287 }, {737,356,190 ,150,310,287 }, - {2872,1245,4204 ,311,36,38 }, {4375,4531,4136 ,312,26,28 }, {1241,241,1389 ,313,314,315 }, - {4128,4531,4375 ,22,26,312 }, {4120,4128,4375 ,23,22,312 }, {709,1833,653 ,316,317,318 }, - {1793,4150,69 ,319,320,321 }, {69,1319,70 ,321,322,323 }, {1792,1375,24 ,324,325,247 }, - {6320,7500,6345 ,190,326,191 }, {1225,57,1245 ,327,222,36 }, - {1257,4172,4214 ,208,135,226 }, {997,190,1021 ,328,287,289 }, - {464,4224,1023 ,261,309,308 }, {3,464,1023 ,329,261,308 }, {714,639,950 ,265,291,330 }, - {714,950,4514 ,265,330,259 }, {7747,7746,7698 ,331,332,333 }, - {652,1296,1383 ,334,335,336 }, {1203,1204,1202 ,337,338,339 }, - {970,6018,1747 ,268,340,266 }, {4430,4451,4473 ,341,271,270 }, - {120,4362,4411 ,240,342,232 }, {7848,7874,7823 ,343,344,345 }, - {467,466,360 ,346,347,86 }, {1259,4095,4179 ,348,349,251 }, {5,413,315 ,350,351,352 }, - {4098,4057,4263 ,353,272,274 }, {1057,1596,1069 ,354,355,277 }, - {971,1057,1069 ,356,354,277 }, {44,412,1793 ,357,358,319 }, {4019,4255,4300 ,227,165,231 }, - {5378,5412,5377 ,359,360,361 }, {1259,4114,4059 ,348,362,363 }, - {4982,5000,4978 ,364,286,178 }, {4334,965,1419 ,365,366,367 }, - {1564,1085,1595 ,368,369,99 }, {4172,4215,4214 ,135,370,226 }, - {1225,2872,2428 ,327,311,371 }, {4110,1633,503 ,372,373,374 }, - {4328,4378,4354 ,166,375,376 }, {513,1343,376 ,377,378,379 }, - {3997,3998,4039 ,380,381,382 }, {8101,8122,8087 ,383,384,385 }, - {5000,6415,6414 ,286,386,113 }, {660,703,1625 ,387,100,388 }, - {805,2352,24 ,389,390,247 }, {1599,799,1194 ,391,392,393 }, {5850,4011,5784 ,394,395,396 }, - {3871,5850,5784 ,397,394,396 }, {2872,1225,1245 ,311,327,36 }, - {1633,513,376 ,373,377,379 }, {3871,5784,878 ,397,396,398 }, - {659,4171,802 ,71,399,400 }, {708,1222,365 ,401,62,402 }, {117,458,1133 ,9,16,24 }, - {4497,4535,4534 ,91,90,403 }, {1967,1966,1903 ,404,405,406 }, - {3259,4091,4068 ,407,123,408 }, {4185,3113,52 ,409,410,411 }, - {8090,8132,3006 ,412,413,414 }, {211,965,4334 ,415,366,365 }, - {4214,4254,4019 ,226,416,227 }, {1023,2045,211 ,308,417,415 }, - {1923,1023,211 ,418,308,415 }, {4043,2798,2956 ,419,420,399 }, - {4535,792,1628 ,90,95,118 }, {398,458,117 ,15,16,9 }, {139,2137,777 ,145,147,421 }, - {4534,4535,1628 ,403,90,118 }, {4411,4362,962 ,232,342,233 }, - {5199,5198,5177 ,422,423,424 }, {1838,4427,363 ,425,426,427 }, - {5213,5233,5212 ,428,429,430 }, {1419,799,1599 ,367,392,391 }, - {211,30,965 ,415,307,366 }, {347,102,2423 ,431,432,433 }, {138,3871,878 ,434,397,398 }, - {4182,4201,4051 ,435,436,437 }, {2313,1222,708 ,438,62,401 }, - {885,2313,708 ,216,438,401 }, {3327,3977,3513 ,439,440,441 }, - {3535,1345,840 ,442,203,68 }, {915,913,916 ,443,444,445 }, {678,634,682 ,446,447,448 }, - {634,346,682 ,447,449,448 }, {7254,6347,7860 ,450,451,452 }, - {8061,8082,8102 ,453,454,253 }, {1595,1085,703 ,99,369,100 }, - {2660,2753,2349 ,455,456,457 }, {2338,2680,4039 ,458,459,382 }, - {4040,2338,4039 ,460,458,382 }, {5307,5306,4393 ,461,462,463 }, - {4537,705,1697 ,67,70,69 }, {6563,8061,8063 ,464,453,465 }, {1305,4446,1300 ,466,237,285 }, - {4312,4311,490 ,467,468,469 }, {4301,4328,4354 ,167,166,376 }, - {467,503,466 ,346,374,347 }, {4051,1933,1695 ,437,470,471 }, - {6859,6860,6911 ,472,473,474 }, {2455,2212,5001 ,475,476,477 }, - {1197,6341,4983 ,478,479,480 }, {5240,5239,5218 ,481,482,483 }, - {705,1346,1697 ,70,484,69 }, {1731,1747,604 ,485,266,486 }, {491,586,678 ,487,488,446 }, - {833,491,678 ,489,487,446 }, {586,679,678 ,488,490,446 }, {679,86,634 ,490,491,447 }, - {678,679,634 ,446,490,447 }, {1485,346,634 ,492,449,447 }, {86,1485,634 ,491,492,447 }, - {1485,496,346 ,492,493,449 }, {591,638,346 ,494,495,449 }, {496,591,346 ,493,494,449 }, - {29,15,638 ,496,497,495 }, {591,29,638 ,494,496,495 }, {29,438,15 ,496,498,497 }, - {745,961,438 ,499,500,498 }, {745,446,961 ,499,501,500 }, {4187,1023,1923 ,502,308,418 }, - {189,1021,4187 ,503,289,502 }, {365,606,139 ,402,180,145 }, {883,792,146 ,119,95,504 }, - {174,1597,892 ,169,505,506 }, {826,1021,189 ,507,289,503 }, {5570,1350,5641 ,508,509,510 }, - {8072,530,3668 ,511,512,513 }, {5699,5727,5726 ,43,514,515 }, - {2927,2926,2882 ,516,517,518 }, {6912,6943,6942 ,519,520,521 }, - {6341,1197,2808 ,479,478,522 }, {536,1305,1300 ,523,466,285 }, - {5178,5199,5177 ,524,422,424 }, {4311,4383,490 ,468,399,469 }, - {174,1422,1597 ,169,525,505 }, {5642,5658,5657 ,526,49,48 }, - {586,86,679 ,488,491,490 }, {1921,446,745 ,527,501,499 }, {1199,39,446 ,528,529,501 }, - {1625,4222,4251 ,388,530,132 }, {1487,304,2680 ,531,532,459 }, - {304,1487,488 ,532,531,533 }, {2150,964,3084 ,534,535,536 }, - {5726,5727,5764 ,515,514,537 }, {803,4,696 ,144,538,6 }, {3511,4029,4019 ,539,225,227 }, - {4,1031,458 ,538,163,16 }, {696,4,458 ,6,538,16 }, {5727,5765,5764 ,514,540,537 }, - {4369,1089,4393 ,104,103,463 }, {4326,3341,3258 ,219,541,542 }, - {4158,659,802 ,72,71,400 }, {5834,5833,5816 ,543,544,545 }, {3008,7051,7029 ,546,547,548 }, - {965,888,799 ,366,238,392 }, {950,1652,4483 ,330,170,549 }, {4514,950,4483 ,259,330,549 }, - {1112,116,885 ,292,217,216 }, {3862,1973,7810 ,550,551,552 }, - {2093,2257,1749 ,553,554,555 }, {466,416,143 ,347,556,157 }, - {811,4954,812 ,557,558,559 }, {92,1921,745 ,560,527,499 }, {92,446,1921 ,560,501,527 }, - {317,344,93 ,561,562,563 }, {93,344,39 ,563,562,529 }, {1626,3253,349 ,564,565,566 }, - {4379,4431,4430 ,567,568,341 }, {4378,4379,4430 ,375,567,341 }, - {4503,779,4140 ,569,193,25 }, {5283,5284,5337 ,570,571,572 }, - {804,4503,4140 ,21,569,25 }, {2070,1367,1244 ,573,574,575 }, - {360,466,214 ,86,347,87 }, {229,116,1112 ,221,217,292 }, {4077,4109,4076 ,126,576,577 }, - {1023,1033,2045 ,308,306,417 }, {314,1419,1599 ,578,367,391 }, - {875,2155,1920 ,579,580,581 }, {4444,4482,4464 ,582,583,584 }, - {30,888,965 ,307,238,366 }, {4900,4545,5578 ,585,586,587 }, {1260,1461,891 ,11,212,189 }, - {809,1260,891 ,20,11,189 }, {1271,4548,2252 ,588,589,590 }, {2246,351,352 ,591,592,593 }, - {6946,6968,6916 ,594,595,596 }, {6555,2093,1749 ,597,553,555 }, - {235,1292,1517 ,598,599,600 }, {1292,1850,1517 ,599,601,600 }, - {1520,586,491 ,602,488,487 }, {251,1520,491 ,603,602,487 }, {1520,2225,586 ,602,604,488 }, - {63,86,586 ,605,491,488 }, {2225,63,586 ,604,605,488 }, {63,244,1485 ,605,606,492 }, - {86,63,1485 ,491,605,492 }, {1485,244,496 ,492,606,493 }, {244,590,591 ,606,607,494 }, - {496,244,591 ,493,606,494 }, {590,1198,29 ,607,608,496 }, {591,590,29 ,494,607,496 }, - {1198,441,438 ,608,609,498 }, {29,1198,438 ,496,608,498 }, {441,956,745 ,609,610,499 }, - {438,441,745 ,498,609,499 }, {745,956,92 ,499,610,560 }, {92,868,446 ,560,611,501 }, - {1247,1199,446 ,612,528,501 }, {868,1247,446 ,611,612,501 }, - {93,39,1199 ,563,529,528 }, {1247,93,1199 ,612,563,528 }, {2150,3084,832 ,534,536,613 }, - {488,2150,832 ,533,534,613 }, {6044,5933,5934 ,614,615,616 }, - {8076,1295,3040 ,617,618,619 }, {779,544,1534 ,193,195,27 }, - {2338,1487,2680 ,458,531,459 }, {1487,2150,488 ,531,534,533 }, - {1905,4179,1393 ,40,251,45 }, {681,683,302 ,620,621,622 }, {1260,1311,1461 ,11,213,212 }, - {5162,1443,1335 ,181,182,236 }, {4482,4525,4513 ,583,623,624 }, - {4334,1419,314 ,365,367,578 }, {950,715,1652 ,330,168,170 }, - {1305,2707,4446 ,466,235,237 }, {120,4411,1006 ,240,232,234 }, - {4545,3621,5578 ,586,625,587 }, {7264,7263,7222 ,626,627,628 }, - {6698,6699,6750 ,629,630,631 }, {1520,534,63 ,602,632,605 }, - {2225,1520,63 ,604,602,605 }, {63,534,244 ,605,632,606 }, {317,93,4539 ,561,563,633 }, - {3084,964,3094 ,536,535,634 }, {1294,874,169 ,635,636,248 }, - {2789,2832,2831 ,637,638,639 }, {4165,87,2477 ,640,641,642 }, - {832,3084,3094 ,613,536,634 }, {4430,4431,4451 ,341,568,271 }, - {348,249,268 ,643,644,645 }, {5618,5616,1443 ,127,646,182 }, - {715,497,1147 ,168,290,202 }, {4468,3673,3473 ,647,648,649 }, - {7746,7745,7697 ,332,650,651 }, {3749,5380,5304 ,652,653,654 }, - {888,120,1006 ,238,240,234 }, {2132,2131,2085 ,655,656,657 }, - {8107,3006,2731 ,658,414,659 }, {5812,5823,7073 ,660,661,662 }, - {153,1243,1292 ,663,664,599 }, {235,153,1292 ,598,663,599 }, - {1292,1243,1850 ,599,664,601 }, {112,251,1850 ,665,603,601 }, - {1243,112,1850 ,664,665,601 }, {1593,1520,251 ,666,602,603 }, - {112,1593,251 ,665,666,603 }, {1593,172,534 ,666,667,632 }, {1520,1593,534 ,602,666,632 }, - {727,726,627 ,668,669,670 }, {590,589,1198 ,607,671,608 }, {1198,357,441 ,608,672,609 }, - {442,310,956 ,673,674,610 }, {441,442,956 ,609,673,610 }, {310,60,92 ,674,675,560 }, - {956,310,92 ,610,674,560 }, {92,60,868 ,560,675,611 }, {60,1788,1247 ,675,676,612 }, - {868,60,1247 ,611,675,612 }, {1788,113,93 ,676,677,563 }, {1247,1788,93 ,612,676,563 }, - {1059,1294,169 ,678,635,248 }, {105,783,1066 ,249,679,680 }, - {141,4206,4186 ,681,682,683 }, {6860,6912,6911 ,473,519,474 }, - {5013,6484,5455 ,684,685,686 }, {964,1294,1059 ,535,635,678 }, - {3094,964,1059 ,634,535,678 }, {128,883,4594 ,687,119,688 }, - {883,128,76 ,119,687,689 }, {3750,1463,3681 ,690,220,691 }, {6094,3373,3300 ,692,693,694 }, - {4179,1490,4281 ,251,46,51 }, {1490,4310,4281 ,46,695,51 }, {1461,1310,1348 ,212,149,148 }, - {700,896,4224 ,255,256,309 }, {1021,1161,3 ,289,288,329 }, {1350,5642,5641 ,509,526,510 }, - {459,211,4334 ,696,415,365 }, {4237,4257,4275 ,697,698,699 }, - {5801,5817,5800 ,700,701,702 }, {4444,4464,4443 ,582,584,703 }, - {6350,6349,6321 ,704,705,706 }, {2045,1033,30 ,417,306,307 }, - {1742,7051,3008 ,707,547,546 }, {7052,3660,3454 ,708,709,710 }, - {6790,6809,6754 ,711,712,713 }, {1593,16,172 ,666,714,667 }, - {3399,4550,4447 ,715,716,717 }, {526,582,625 ,718,719,720 }, - {725,724,625 ,721,722,720 }, {8129,7693,8116 ,723,724,172 }, - {1195,4395,5194 ,725,726,727 }, {3008,3975,3944 ,546,728,729 }, - {129,128,695 ,730,687,731 }, {129,76,128 ,730,689,687 }, {6149,3701,3648 ,732,733,734 }, - {3495,3494,3434 ,735,736,737 }, {8116,7693,8071 ,172,724,738 }, - {195,4350,4098 ,739,740,353 }, {1150,38,110 ,741,742,743 }, {1311,540,457 ,213,14,214 }, - {497,190,997 ,290,287,328 }, {459,4334,4412 ,696,365,744 }, {1750,4894,1698 ,745,746,747 }, - {4412,4334,314 ,744,365,578 }, {4544,6353,6686 ,748,749,750 }, - {5521,8071,8125 ,751,738,752 }, {314,1599,4244 ,578,391,753 }, - {5536,5522,5557 ,754,755,756 }, {5850,3749,4011 ,394,652,395 }, - {1995,2049,2015 ,757,758,759 }, {6299,404,6417 ,760,761,762 }, - {172,16,1743 ,667,714,763 }, {582,583,625 ,719,764,720 }, {783,688,1066 ,679,765,680 }, - {169,874,105 ,248,636,249 }, {874,783,105 ,636,679,249 }, {615,4281,4310 ,766,51,695 }, - {226,1150,110 ,108,741,743 }, {774,1634,683 ,767,768,621 }, {4174,4217,4197 ,769,83,82 }, - {540,4211,116 ,14,215,217 }, {200,1461,1348 ,244,212,148 }, {464,700,4224 ,261,255,309 }, - {1147,497,997 ,202,290,328 }, {103,2030,2011 ,128,770,129 }, - {4429,1923,459 ,771,418,696 }, {1699,1751,1750 ,772,773,745 }, - {1698,1699,1750 ,747,772,745 }, {4587,4588,4589 ,774,775,776 }, - {1811,1885,1810 ,777,778,779 }, {6553,3252,3283 ,780,781,262 }, - {4482,4513,4464 ,583,624,584 }, {976,4964,4965 ,782,783,784 }, - {2050,2049,1995 ,785,758,757 }, {1950,2050,1995 ,786,785,757 }, - {2050,2075,2049 ,785,787,758 }, {2075,2096,2049 ,787,788,758 }, - {3661,2212,2455 ,789,476,475 }, {1331,1243,153 ,790,664,663 }, - {597,1331,153 ,791,790,663 }, {553,112,1243 ,792,665,664 }, {1331,553,1243 ,790,792,664 }, - {553,1727,1593 ,792,793,666 }, {112,553,1593 ,665,792,666 }, - {1727,1743,16 ,793,763,714 }, {1593,1727,16 ,666,793,714 }, {170,1290,1240 ,794,795,796 }, - {1184,999,1188 ,797,798,799 }, {526,527,582 ,718,800,719 }, {583,626,625 ,764,801,720 }, - {3598,3547,6598 ,802,803,804 }, {2680,304,2662 ,459,532,805 }, - {2853,3190,2416 ,806,807,808 }, {3300,5977,6094 ,694,809,692 }, - {60,145,1788 ,675,810,676 }, {310,2694,60 ,674,811,675 }, {8126,6891,3148 ,812,813,814 }, - {7924,7923,7873 ,815,816,817 }, {3007,4486,6070 ,818,819,820 }, - {1065,1340,1450 ,821,822,823 }, {688,1065,1066 ,765,821,680 }, - {3359,3325,3326 ,824,825,826 }, {5178,5177,4630 ,524,424,827 }, - {1980,2007,1979 ,828,829,830 }, {1984,1916,1917 ,831,832,833 }, - {277,214,1992 ,85,87,834 }, {1539,96,1587 ,835,836,837 }, {4335,4151,1833 ,838,839,317 }, - {768,1393,864 ,41,45,840 }, {457,540,116 ,214,14,217 }, {1652,892,4525 ,170,506,623 }, - {2030,3913,2011 ,770,841,129 }, {2014,1923,736 ,842,418,843 }, - {4392,2341,7051 ,844,845,547 }, {2097,2096,2075 ,846,788,787 }, - {2007,1978,1979 ,829,847,830 }, {1936,1333,2341 ,848,849,845 }, - {1411,1331,597 ,850,790,791 }, {5353,6836,144 ,851,852,853 }, - {1721,1778,1777 ,854,855,856 }, {392,170,1240 ,857,794,796 }, - {1475,1476,1547 ,858,859,860 }, {433,434,485 ,861,862,863 }, - {527,583,582 ,800,764,719 }, {385,386,433 ,864,865,861 }, {434,527,526 ,862,800,718 }, - {337,338,385 ,866,867,864 }, {238,338,237 ,868,867,869 }, {386,434,433 ,865,862,861 }, - {338,386,385 ,867,865,864 }, {338,337,237 ,867,866,869 }, {3382,3381,3356 ,870,871,872 }, - {2582,2474,2585 ,873,874,875 }, {5077,4549,1809 ,876,877,878 }, - {3305,3358,3324 ,879,880,881 }, {3383,3382,3357 ,882,870,883 }, - {3900,3478,3455 ,884,885,886 }, {1066,1065,1450 ,680,821,823 }, - {2036,2081,2035 ,887,888,889 }, {2081,2126,2068 ,888,890,891 }, - {2081,2068,2035 ,888,891,889 }, {2126,2125,2068 ,890,892,891 }, - {2274,1882,4980 ,893,894,241 }, {864,4112,839 ,840,47,52 }, {3341,863,3258 ,541,284,542 }, - {863,536,1300 ,284,523,285 }, {1393,4112,864 ,45,47,840 }, {4211,4212,321 ,215,895,60 }, - {1597,1422,18 ,505,525,896 }, {2014,4187,1923 ,842,502,418 }, - {1923,4429,736 ,418,771,843 }, {736,4429,459 ,843,771,696 }, - {358,189,4184 ,897,503,898 }, {1950,1929,1885 ,786,899,778 }, - {2050,2097,2075 ,785,846,787 }, {1780,1843,1842 ,900,901,196 }, - {1548,1549,1617 ,902,903,904 }, {8130,8120,8098 ,905,906,907 }, - {3080,1302,13 ,908,909,910 }, {1844,1845,1873 ,911,912,913 }, - {2035,2068,1978 ,889,891,847 }, {1059,169,652 ,678,248,334 }, - {485,434,526 ,863,862,718 }, {2650,3981,3054 ,914,915,916 }, - {3453,2650,3054 ,917,914,916 }, {2892,1305,536 ,918,466,523 }, - {7693,8129,3976 ,724,723,919 }, {443,171,444 ,920,921,922 }, - {2743,3687,1378 ,923,924,925 }, {3545,3595,3574 ,926,927,928 }, - {913,2892,536 ,444,918,523 }, {3432,3492,3462 ,929,930,931 }, - {3358,3383,3357 ,880,882,883 }, {5769,5768,5731 ,932,933,934 }, - {6045,6080,5453 ,935,936,937 }, {548,595,645 ,938,939,940 }, - {8070,3534,3668 ,941,942,513 }, {1586,1195,3315 ,943,725,944 }, - {399,1254,768 ,269,29,41 }, {4375,4136,399 ,312,28,269 }, {4212,294,321 ,895,945,60 }, - {356,4194,1161 ,310,293,288 }, {190,356,1161 ,287,310,288 }, - {1422,1147,997 ,525,202,328 }, {1652,174,892 ,170,169,506 }, - {1422,826,18 ,525,507,896 }, {4184,4187,2014 ,898,502,842 }, - {5977,3300,1936 ,809,694,848 }, {1752,1812,1811 ,946,947,777 }, - {1751,1752,1811 ,773,946,777 }, {1886,1885,1811 ,948,778,777 }, - {1812,1886,1811 ,947,948,777 }, {1951,1950,1885 ,949,786,778 }, - {1886,1951,1885 ,948,949,778 }, {1951,1996,1950 ,949,950,786 }, - {2051,2050,1950 ,951,785,786 }, {1996,2051,1950 ,950,951,786 }, - {2098,2097,2050 ,952,846,785 }, {2051,2098,2050 ,951,952,785 }, - {2098,2143,2097 ,952,953,846 }, {595,646,645 ,939,954,940 }, - {3492,3545,3491 ,930,926,955 }, {1045,1144,992 ,956,957,958 }, - {8128,8066,3277 ,959,960,961 }, {1874,1913,1912 ,962,963,964 }, - {386,435,434 ,865,965,862 }, {395,171,59 ,966,921,967 }, {59,171,443 ,967,921,920 }, - {3917,3916,3868 ,968,969,970 }, {3148,6891,3008 ,814,813,546 }, - {743,742,647 ,971,972,973 }, {1403,1404,1475 ,974,975,858 }, - {788,2558,600 ,976,977,978 }, {3542,3573,3541 ,979,980,981 }, - {3958,3959,3998 ,294,982,381 }, {938,4,803 ,983,538,144 }, {4,264,1031 ,538,984,163 }, - {264,4235,804 ,984,985,21 }, {4194,464,3 ,293,261,329 }, {505,5309,469 ,986,987,988 }, - {1635,1699,1442 ,989,772,990 }, {4443,4442,4391 ,703,991,992 }, - {4443,4464,4442 ,703,584,991 }, {4464,4463,4442 ,584,993,991 }, - {1328,1405,1327 ,994,995,996 }, {1838,363,1837 ,425,427,997 }, - {724,816,815 ,722,998,999 }, {1914,1983,1982 ,1000,1001,1002 }, - {1619,1686,1685 ,1003,1004,1005 }, {2124,2193,2123 ,1006,1007,1008 }, - {1681,1682,1739 ,1009,1010,1011 }, {291,336,335 ,1012,1013,1014 }, - {1663,1630,3081 ,1015,1016,1017 }, {726,725,626 ,669,721,801 }, - {627,726,626 ,670,669,801 }, {726,818,725 ,669,1018,721 }, {1476,1548,1547 ,859,902,860 }, - {906,817,818 ,1019,1020,1018 }, {3960,3959,3916 ,1021,982,969 }, - {3917,3960,3916 ,968,1021,969 }, {3960,4000,3999 ,1021,1022,1023 }, - {3959,3960,3999 ,982,1021,1023 }, {7115,7139,7129 ,1024,1025,1026 }, - {3189,3016,2150 ,1027,1028,534 }, {1031,264,804 ,163,984,21 }, - {804,4235,4503 ,21,985,569 }, {4503,4235,779 ,569,985,193 }, - {779,709,544 ,193,316,195 }, {173,704,398 ,12,7,15 }, {1161,4194,3 ,288,293,329 }, - {2352,1792,24 ,390,324,247 }, {4715,4716,4714 ,1029,1030,1031 }, - {6432,3265,1941 ,1032,1033,1034 }, {1603,1636,1635 ,1035,1036,989 }, - {1566,1603,1635 ,1037,1035,989 }, {1703,1752,1702 ,1038,946,1039 }, - {2143,2166,2165 ,953,1040,1041 }, {290,333,289 ,1042,1043,1044 }, - {1405,1404,1327 ,995,975,996 }, {1405,1477,1404 ,995,1045,975 }, - {7003,7002,6963 ,1046,1047,1048 }, {3303,3304,3323 ,1049,1050,1051 }, - {722,723,814 ,1052,1053,1054 }, {627,626,583 ,670,801,764 }, - {528,627,583 ,1055,670,764 }, {4426,6577,6837 ,1056,97,1057 }, - {1908,28,3636 ,1058,1059,1060 }, {3358,3357,3324 ,880,883,881 }, - {4042,2946,4041 ,1061,1062,1063 }, {2946,2571,3194 ,1062,1064,1065 }, - {3190,2555,2416 ,807,1066,808 }, {2558,19,600 ,977,1067,978 }, - {544,4454,1905 ,195,1068,40 }, {4454,4135,1905 ,1068,1069,40 }, - {117,1133,4213 ,9,24,1070 }, {1905,4135,4179 ,40,1069,251 }, - {1805,1490,4179 ,1071,46,251 }, {1805,4310,1490 ,1071,695,46 }, - {1805,615,4310 ,1071,766,695 }, {4521,1591,1318 ,179,1072,164 }, - {106,1207,5146 ,1073,1074,1075 }, {4421,4462,4420 ,229,1076,276 }, - {1338,4214,4029 ,1077,226,225 }, {7457,7515,7539 ,1078,1079,1080 }, - {1495,1567,1566 ,1081,1082,1037 }, {1494,1495,1566 ,1083,1081,1037 }, - {1567,1568,1603 ,1082,1084,1035 }, {1566,1567,1603 ,1037,1082,1035 }, - {1568,1637,1636 ,1084,1085,1036 }, {1603,1568,1636 ,1035,1084,1036 }, - {1637,1704,1703 ,1085,1086,1038 }, {1636,1637,1703 ,1036,1085,1038 }, - {1753,1752,1703 ,1087,946,1038 }, {1704,1753,1703 ,1086,1087,1038 }, - {1753,1795,1752 ,1087,1088,946 }, {1813,1812,1752 ,1089,947,946 }, - {1795,1813,1752 ,1088,1089,946 }, {1887,1886,1812 ,1090,948,947 }, - {1813,1887,1812 ,1089,1090,947 }, {1887,1952,1951 ,1090,1091,949 }, - {1886,1887,1951 ,948,1090,949 }, {1952,1996,1951 ,1091,950,949 }, - {2052,2051,1996 ,1092,951,950 }, {1952,2052,1996 ,1091,1092,950 }, - {2099,2098,2051 ,1093,952,951 }, {2052,2099,2051 ,1092,1093,951 }, - {2099,2143,2098 ,1093,953,952 }, {8080,8094,8069 ,1094,98,1095 }, - {3932,1059,652 ,1096,678,334 }, {6311,8122,1168 ,1097,384,1098 }, - {624,723,623 ,1099,1053,1100 }, {1979,1978,1911 ,830,847,1101 }, - {387,386,338 ,1102,865,867 }, {238,239,338 ,868,1103,867 }, {1687,1782,1781 ,1104,1105,1106 }, - {340,593,909 ,1107,1108,1109 }, {1918,908,1190 ,1110,1111,1112 }, - {5117,350,2291 ,1113,1114,1115 }, {2433,2400,2434 ,1116,1117,1118 }, - {865,776,867 ,1119,1120,1121 }, {4213,1133,4120 ,1070,24,23 }, - {321,294,1132 ,60,945,61 }, {101,173,713 ,5,12,3 }, {655,195,4056 ,1122,739,1123 }, - {195,4098,4056 ,739,353,1123 }, {660,118,67 ,387,1124,1125 }, - {1609,200,714 ,31,244,265 }, {1428,1495,1494 ,1126,1081,1083 }, - {1495,1568,1567 ,1081,1084,1082 }, {1753,1813,1795 ,1087,1089,1088 }, - {3194,2571,3016 ,1065,1064,1028 }, {2032,2123,2122 ,1127,1008,1128 }, - {647,549,2609 ,973,1129,1130 }, {2259,6314,6646 ,1131,1132,1133 }, - {1328,1329,1405 ,994,1134,995 }, {1406,1447,1446 ,1135,1136,1137 }, - {1777,1778,1839 ,856,855,1138 }, {8084,8110,8124 ,1139,1140,1141 }, - {436,435,386 ,1142,965,865 }, {339,387,338 ,1143,1102,867 }, - {486,528,434 ,1144,1055,862 }, {528,583,527 ,1055,764,800 }, - {3456,3566,3861 ,1145,1146,1147 }, {529,528,486 ,1148,1055,1144 }, - {437,486,436 ,1149,1144,1142 }, {1873,1874,1912 ,913,962,964 }, - {1616,1617,1683 ,1150,904,1151 }, {3462,3492,3461 ,931,930,1152 }, - {1880,105,2558 ,250,249,977 }, {3545,3544,3491 ,926,1153,955 }, - {2433,111,2400 ,1116,1154,1117 }, {101,704,173 ,5,7,12 }, {1132,1591,4521 ,61,1072,179 }, - {5765,5801,5764 ,540,700,537 }, {277,781,11 ,85,158,299 }, {613,277,11 ,298,85,299 }, - {879,4123,4122 ,1155,133,137 }, {3421,8113,3278 ,1156,1157,1158 }, - {911,2158,6684 ,1159,1160,1161 }, {1351,1428,8008 ,1162,1126,1163 }, - {1351,1395,1428 ,1162,1164,1126 }, {1567,1568,1495 ,1082,1084,1081 }, - {1814,1813,1753 ,1165,1089,1087 }, {1656,3227,3198 ,1166,1167,1168 }, - {449,547,546 ,1169,1170,1171 }, {3959,3999,3998 ,982,1023,381 }, - {448,449,546 ,1172,1169,1171 }, {647,691,743 ,973,1173,971 }, - {2191,2192,392 ,1174,1175,857 }, {547,644,546 ,1170,1176,1171 }, - {627,628,727 ,670,1177,668 }, {1234,1235,1328 ,1178,1179,994 }, - {1976,2032,2006 ,1180,1127,1181 }, {3323,3322,3303 ,1051,1182,1049 }, - {486,434,435 ,1144,862,965 }, {387,436,386 ,1102,1142,865 }, - {528,527,434 ,1055,800,862 }, {1405,1406,1446 ,995,1135,1137 }, - {304,488,3080 ,532,533,908 }, {3331,3364,3330 ,1183,1184,1185 }, - {1296,1880,2558 ,335,250,977 }, {7397,7453,7424 ,1186,1187,1188 }, - {1318,867,2137 ,164,1121,147 }, {3817,4756,4682 ,1189,1190,1191 }, - {5240,5264,5239 ,481,1192,482 }, {5616,5618,2011 ,646,127,129 }, - {5258,5282,5281 ,1193,1194,1195 }, {2026,1927,4234 ,130,1196,1197 }, - {2258,1263,5455 ,1198,1199,686 }, {3362,6350,6321 ,1200,704,706 }, - {2158,2272,6684 ,1160,1201,1161 }, {7151,3291,3290 ,1202,1203,1204 }, - {1353,1429,1428 ,1205,1206,1126 }, {1395,1353,1428 ,1164,1205,1126 }, - {1496,1495,1428 ,1207,1081,1126 }, {1429,1496,1428 ,1206,1207,1126 }, - {1569,1567,1495 ,1208,1082,1081 }, {1496,1569,1495 ,1207,1208,1081 }, - {1604,1568,1567 ,1209,1084,1082 }, {1569,1604,1567 ,1208,1209,1082 }, - {1638,1637,1568 ,1210,1085,1084 }, {1604,1638,1568 ,1209,1210,1084 }, - {1638,1705,1704 ,1210,1211,1086 }, {1637,1638,1704 ,1085,1210,1086 }, - {1754,1753,1704 ,1212,1087,1086 }, {1705,1754,1704 ,1211,1212,1086 }, - {1815,1814,1753 ,1213,1165,1087 }, {1754,1815,1753 ,1212,1213,1087 }, - {1862,1813,1814 ,1214,1089,1165 }, {1815,1862,1814 ,1213,1214,1165 }, - {1888,1887,1813 ,1215,1090,1089 }, {1862,1888,1813 ,1214,1215,1089 }, - {1953,1952,1887 ,1216,1091,1090 }, {1888,1953,1887 ,1215,1216,1090 }, - {2053,2052,1952 ,1217,1092,1091 }, {1953,2053,1952 ,1216,1217,1091 }, - {2100,2099,2052 ,1218,1093,1092 }, {2053,2100,2052 ,1217,1218,1092 }, - {828,827,741 ,1219,1220,1221 }, {385,433,432 ,864,861,1222 }, - {1842,1843,1910 ,196,901,1223 }, {2009,1188,862 ,1224,799,1225 }, - {1780,1803,1843 ,900,1226,901 }, {436,486,435 ,1142,1144,965 }, - {432,484,483 ,1222,1227,1228 }, {3987,3946,21 ,1229,1230,1231 }, - {1780,1781,1803 ,900,1106,1226 }, {1062,1014,929 ,1232,1233,1234 }, - {1182,1048,953 ,1235,1236,1237 }, {1183,1182,953 ,1238,1235,1237 }, - {2945,3900,3455 ,1239,884,886 }, {7115,7129,7102 ,1024,1026,1240 }, - {4173,4216,4215 ,134,1241,370 }, {4335,4280,642 ,838,1242,1243 }, - {1112,885,4202 ,292,216,260 }, {2026,4234,934 ,130,1197,131 }, - {3818,1907,2785 ,1244,1245,1246 }, {4328,4329,4378 ,166,1247,375 }, - {1207,106,3878 ,1074,1073,1248 }, {6203,322,803 ,1249,1250,144 }, - {4329,4379,4378 ,1247,567,375 }, {2376,6570,1263 ,1251,1252,1199 }, - {5059,1516,3177 ,1253,1254,1255 }, {5502,2208,5081 ,1256,1257,1258 }, - {3319,2245,2336 ,1259,1260,1261 }, {1352,1395,1351 ,1262,1164,1162 }, - {1569,1638,1604 ,1208,1210,1209 }, {2054,2053,1953 ,1263,1217,1216 }, - {3916,3959,3904 ,969,982,1264 }, {908,909,1190 ,1111,1109,1112 }, - {5117,2291,186 ,1113,1115,1265 }, {628,728,727 ,1177,1266,668 }, - {334,335,431 ,1267,1014,1268 }, {2123,2192,2191 ,1008,1175,1174 }, - {1290,1184,2009 ,795,797,1224 }, {1447,1407,1479 ,1136,1269,1270 }, - {3463,3494,3432 ,1271,736,929 }, {1857,540,1311 ,13,14,213 }, - {863,3484,3258 ,284,283,542 }, {4077,4076,4071 ,126,577,186 }, - {4255,4275,4328 ,165,699,166 }, {322,5,4 ,1250,350,538 }, {938,322,4 ,983,1250,538 }, - {5,315,264 ,350,352,984 }, {4,5,264 ,538,350,984 }, {4275,4329,4328 ,699,1247,166 }, - {6619,2245,1265 ,1272,1260,1273 }, {625,624,581 ,720,1099,1274 }, - {582,625,581 ,719,720,1274 }, {1781,1782,1803 ,1106,1105,1226 }, - {1779,1841,1840 ,1275,1276,198 }, {1918,2009,908 ,1110,1224,1111 }, - {2192,2193,170 ,1175,1007,794 }, {1145,1144,1045 ,1277,957,956 }, - {2122,2123,2191 ,1128,1008,1174 }, {524,525,580 ,1278,1279,1280 }, - {4518,1928,1879 ,1281,1282,1283 }, {926,1011,1010 ,1284,1285,1286 }, - {926,925,827 ,1284,1287,1220 }, {2068,2033,2034 ,891,1288,1289 }, - {6295,3283,8103 ,1290,262,1291 }, {3355,3354,3322 ,1292,1293,1182 }, - {1978,2068,2034 ,847,891,1289 }, {1233,1327,1232 ,1294,996,1295 }, - {221,2768,2541 ,1296,1297,1298 }, {264,315,4235 ,984,352,985 }, - {4235,4159,779 ,985,1299,193 }, {779,4159,709 ,193,1299,316 }, - {5056,5005,4950 ,1300,1301,1302 }, {3702,5520,1990 ,1303,1304,1305 }, - {6562,6299,4554 ,1306,760,1307 }, {1354,1430,1429 ,1308,1309,1206 }, - {1353,1354,1429 ,1205,1308,1206 }, {1430,1497,1496 ,1309,1310,1207 }, - {1429,1430,1496 ,1206,1309,1207 }, {1497,1570,1569 ,1310,1311,1208 }, - {1496,1497,1569 ,1207,1310,1208 }, {1570,1639,1638 ,1311,1312,1210 }, - {1569,1570,1638 ,1208,1311,1210 }, {1706,1705,1638 ,1313,1211,1210 }, - {1639,1706,1638 ,1312,1313,1210 }, {1706,1755,1754 ,1313,1314,1212 }, - {1705,1706,1754 ,1211,1313,1212 }, {1816,1815,1754 ,1315,1213,1212 }, - {1755,1816,1754 ,1314,1315,1212 }, {1863,1862,1815 ,1316,1214,1213 }, - {1816,1863,1815 ,1315,1316,1213 }, {1863,1889,1888 ,1316,1317,1215 }, - {1862,1863,1888 ,1214,1316,1215 }, {1889,1954,1953 ,1317,1318,1216 }, - {1888,1889,1953 ,1215,1317,1216 }, {2055,2054,1953 ,1319,1263,1216 }, - {1954,2055,1953 ,1318,1319,1216 }, {2076,2053,2054 ,1320,1217,1263 }, - {2055,2076,2054 ,1319,1320,1263 }, {2101,2100,2053 ,1321,1218,1217 }, - {2076,2101,2053 ,1320,1321,1217 }, {2168,2167,2100 ,1322,1323,1218 }, - {2101,2168,2100 ,1321,1322,1218 }, {2168,2090,2089 ,1322,1324,1325 }, - {2167,2168,2089 ,1323,1322,1325 }, {862,960,340 ,1225,1326,1107 }, - {908,340,909 ,1111,1107,1109 }, {1617,1684,1683 ,904,1327,1151 }, - {1047,906,2844 ,1328,1019,1329 }, {1326,1325,1231 ,1330,1331,1332 }, - {1143,1142,991 ,1333,1334,1335 }, {1232,1326,1231 ,1295,1330,1332 }, - {1188,999,862 ,799,798,1225 }, {524,580,623 ,1278,1280,1100 }, - {2193,2192,2123 ,1007,1175,1008 }, {433,485,484 ,861,863,1227 }, - {432,433,484 ,1222,861,1227 }, {339,387,239 ,1143,1102,1103 }, - {1234,1233,1142 ,1178,1294,1334 }, {108,2134,35 ,1336,1337,1338 }, - {790,742,743 ,1339,972,971 }, {1113,4213,4212 ,10,1070,895 }, - {540,1113,4211 ,14,10,215 }, {364,365,4362 ,1340,402,342 }, {365,139,4362 ,402,145,342 }, - {139,963,962 ,145,1341,233 }, {703,660,4145 ,100,387,101 }, {1168,4571,6311 ,1098,1342,1097 }, - {8079,3421,8104 ,55,1156,1343 }, {544,653,4454 ,195,318,1068 }, - {4569,2454,2272 ,1344,1345,1201 }, {6071,6377,6082 ,1346,1347,1348 }, - {6950,4981,5006 ,1349,1350,1351 }, {6562,5967,404 ,1306,1352,761 }, - {6570,6562,4554 ,1252,1306,1307 }, {1353,1267,1354 ,1205,1353,1308 }, - {1498,1571,1570 ,1354,1355,1311 }, {1497,1498,1570 ,1310,1354,1311 }, - {1570,1571,1639 ,1311,1355,1312 }, {1144,1145,1234 ,957,1277,1178 }, - {2033,2124,2123 ,1288,1006,1008 }, {3719,3515,959 ,1356,1357,1358 }, - {1547,1616,1615 ,860,1150,1359 }, {1546,1547,1615 ,1360,860,1359 }, - {2084,1048,1049 ,1361,1236,1362 }, {742,828,741 ,972,1219,1221 }, - {689,3315,3828 ,1363,944,1364 }, {526,525,484 ,718,1279,1227 }, - {485,526,484 ,863,718,1227 }, {1240,1290,1918 ,796,795,1110 }, - {828,926,827 ,1219,1284,1220 }, {35,751,6228 ,1338,1365,1366 }, - {744,790,743 ,1367,1339,971 }, {829,828,742 ,1368,1219,972 }, - {5801,5800,5764 ,700,702,537 }, {6577,4426,6837 ,97,1056,1057 }, - {469,468,367 ,988,1369,1370 }, {653,4053,4135 ,318,1371,1069 }, - {4454,653,4135 ,1068,318,1069 }, {376,1343,1564 ,379,378,368 }, - {2259,6646,8103 ,1131,1133,1291 }, {4179,4095,1805 ,251,349,1071 }, - {5843,1028,2958 ,1372,1373,1374 }, {5497,4530,2239 ,1375,1376,1377 }, - {2158,4569,2272 ,1160,1344,1201 }, {3582,3454,3660 ,1378,710,709 }, - {6299,6562,404 ,760,1306,761 }, {1465,1498,1497 ,1379,1354,1310 }, - {1430,1465,1497 ,1309,1379,1310 }, {632,1184,1290 ,1380,797,795 }, - {506,632,690 ,1381,1380,1382 }, {170,506,690 ,794,1381,1382 }, - {3903,3957,3956 ,296,295,1383 }, {1000,860,1876 ,1384,1385,1386 }, - {1782,1844,1843 ,1105,911,901 }, {1777,1839,1838 ,856,1138,425 }, - {1803,1782,1843 ,1226,1105,901 }, {401,448,2445 ,1387,1172,1388 }, - {6612,6648,6611 ,1389,1390,1391 }, {790,829,742 ,1339,1368,972 }, - {198,197,126 ,1392,1393,1394 }, {127,198,126 ,1395,1392,1394 }, - {368,367,197 ,1396,1370,1393 }, {198,368,197 ,1392,1396,1393 }, - {368,469,367 ,1396,988,1370 }, {614,615,1805 ,1397,766,1071 }, - {6646,6295,8103 ,1133,1290,1291 }, {1564,1595,4145 ,368,99,101 }, - {1094,839,1481 ,1398,52,194 }, {2408,5231,2219 ,1399,115,177 }, - {6562,3898,5967 ,1306,1400,1352 }, {1116,5497,2239 ,1401,1375,1377 }, - {7478,7477,7422 ,1402,1403,1404 }, {8020,2320,8019 ,1405,1406,1407 }, - {1355,1354,1267 ,1408,1308,1353 }, {1314,1355,1267 ,1409,1408,1353 }, - {1431,1430,1354 ,1410,1309,1308 }, {1355,1431,1354 ,1408,1410,1308 }, - {1431,1466,1465 ,1410,1411,1379 }, {1430,1431,1465 ,1309,1410,1379 }, - {1466,1499,1498 ,1411,1412,1354 }, {1465,1466,1498 ,1379,1411,1354 }, - {1499,1572,1571 ,1412,1413,1355 }, {1498,1499,1571 ,1354,1412,1355 }, - {1640,1639,1571 ,1414,1312,1355 }, {1572,1640,1571 ,1413,1414,1355 }, - {1640,1707,1706 ,1414,1415,1313 }, {1639,1640,1706 ,1312,1414,1313 }, - {1756,1755,1706 ,1416,1314,1313 }, {1707,1756,1706 ,1415,1416,1313 }, - {1756,1817,1816 ,1416,1417,1315 }, {1755,1756,1816 ,1314,1416,1315 }, - {1817,1818,1863 ,1417,1418,1316 }, {1816,1817,1863 ,1315,1417,1316 }, - {1818,1890,1889 ,1418,1419,1317 }, {1863,1818,1889 ,1316,1418,1317 }, - {1890,1955,1954 ,1419,1420,1318 }, {1889,1890,1954 ,1317,1419,1318 }, - {1955,2056,2055 ,1420,1421,1319 }, {1954,1955,2055 ,1318,1420,1319 }, - {2056,2057,2076 ,1421,1422,1320 }, {2055,2056,2076 ,1319,1421,1320 }, - {2102,2101,2076 ,1423,1321,1320 }, {2057,2102,2076 ,1422,1423,1320 }, - {2102,2169,2168 ,1423,1424,1322 }, {2101,2102,2168 ,1321,1423,1322 }, - {2169,2135,2090 ,1424,1425,1324 }, {2168,2169,2090 ,1322,1424,1324 }, - {631,2090,2135 ,1426,1324,1425 }, {992,906,1045 ,958,1019,956 }, - {902,901,814 ,1427,1428,1054 }, {1845,1874,1873 ,912,962,913 }, - {692,293,1182 ,1429,1430,1235 }, {1683,1777,1776 ,1151,856,1431 }, - {1910,940,1842 ,1223,197,196 }, {1739,1775,1801 ,1011,1432,1433 }, - {1236,1235,1145 ,1434,1179,1277 }, {1980,1979,1911 ,828,830,1101 }, - {991,1142,990 ,1335,1334,1435 }, {1848,1916,1915 ,1436,832,1437 }, - {3654,3712,3653 ,1438,1439,1440 }, {927,926,828 ,1441,1284,1219 }, - {3378,3377,3351 ,1442,1443,1444 }, {3534,8081,8072 ,942,1445,511 }, - {829,927,828 ,1368,1441,1219 }, {4329,4276,4355 ,1247,1446,1447 }, - {864,839,1094 ,840,52,1398 }, {193,768,864 ,1448,41,840 }, {4717,367,468 ,1449,1370,1369 }, - {2245,6344,1265 ,1260,1450,1273 }, {1263,6323,6509 ,1199,1451,1452 }, - {6163,6029,6066 ,1453,1454,1455 }, {1431,1499,1466 ,1410,1412,1411 }, - {1756,1818,1817 ,1416,1418,1417 }, {1981,2008,2037 ,1456,1457,1458 }, - {5587,5626,5586 ,1459,1460,1461 }, {595,596,646 ,939,1462,954 }, - {728,726,727 ,1266,669,668 }, {305,440,243 ,1463,1464,1465 }, - {692,1182,1183 ,1429,1235,1238 }, {154,692,1183 ,1466,1429,1238 }, - {1235,1236,1237 ,1179,1434,1467 }, {2128,2129,2149 ,1468,1469,1470 }, - {1012,1011,926 ,1471,1285,1284 }, {927,1012,926 ,1441,1471,1284 }, - {1012,1060,1011 ,1471,1472,1285 }, {1104,1103,1011 ,1473,1474,1285 }, - {1060,1104,1011 ,1472,1473,1285 }, {1104,1157,1103 ,1473,1475,1474 }, - {1157,1040,1201 ,1475,1476,1477 }, {874,36,3866 ,636,1478,1479 }, - {1103,1157,1201 ,1474,1475,1477 }, {409,150,89 ,1480,1481,1482 }, - {880,4093,1441 ,1483,1484,1485 }, {4109,4149,4090 ,576,1486,1487 }, - {4613,278,4590 ,1488,1489,1490 }, {3898,4987,5967 ,1400,1491,1352 }, - {4568,185,3247 ,1492,1493,1494 }, {1955,2057,2056 ,1420,1422,1421 }, - {484,525,524 ,1227,1279,1278 }, {431,432,483 ,1268,1222,1228 }, - {483,484,524 ,1228,1227,1278 }, {596,647,646 ,1462,973,954 }, - {1687,1781,1780 ,1104,1106,900 }, {1327,1404,1403 ,996,975,974 }, - {1190,909,1189 ,1112,1109,1495 }, {2585,2650,3453 ,875,914,917 }, - {933,692,154 ,1496,1429,1466 }, {155,933,154 ,1497,1496,1466 }, - {990,1141,1140 ,1435,1498,1499 }, {1235,1370,1329 ,1179,1500,1134 }, - {1000,1373,1515 ,1384,1501,1502 }, {1978,1977,1867 ,847,1503,1504 }, - {2130,2198,2197 ,1505,1506,1507 }, {1224,1040,1906 ,1508,1476,1509 }, - {2036,2035,1978 ,887,889,847 }, {3286,8104,79 ,56,1343,1510 }, - {2007,2036,1978 ,829,887,847 }, {3855,3854,3812 ,1511,1512,1513 }, - {3381,3380,3354 ,871,1514,1293 }, {3813,3855,3812 ,1515,1511,1513 }, - {2651,2746,3768 ,1516,1517,1518 }, {1463,3258,3681 ,220,542,691 }, - {1874,1847,1913 ,962,1519,963 }, {2082,2081,2036 ,1520,888,887 }, - {6432,1941,3252 ,1032,1034,781 }, {369,470,469 ,1521,1522,988 }, - {368,369,469 ,1396,1521,988 }, {507,505,469 ,1523,986,988 }, - {470,507,469 ,1522,1523,988 }, {4213,4120,294 ,1070,23,945 }, - {277,1992,781 ,85,834,158 }, {1494,3862,1428 ,1083,550,1126 }, - {4569,2808,2454 ,1344,522,1345 }, {2245,6619,2336 ,1260,1272,1261 }, - {6480,5276,5350 ,1524,1525,1526 }, {7239,7261,7219 ,1527,1528,1529 }, - {1356,1432,1431 ,1530,1531,1410 }, {1355,1356,1431 ,1408,1530,1410 }, - {1500,1499,1431 ,1532,1412,1410 }, {1432,1500,1431 ,1531,1532,1410 }, - {1573,1572,1499 ,1533,1413,1412 }, {1500,1573,1499 ,1532,1533,1412 }, - {1573,1641,1640 ,1533,1534,1414 }, {1572,1573,1640 ,1413,1533,1414 }, - {1708,1707,1640 ,1535,1415,1414 }, {1641,1708,1640 ,1534,1535,1414 }, - {1708,1757,1756 ,1535,1536,1416 }, {1707,1708,1756 ,1415,1535,1416 }, - {1757,1796,1756 ,1536,1537,1416 }, {1796,1819,1818 ,1537,1538,1418 }, - {1756,1796,1818 ,1416,1537,1418 }, {1891,1890,1818 ,1539,1419,1418 }, - {1819,1891,1818 ,1538,1539,1418 }, {1956,1955,1890 ,1540,1420,1419 }, - {1891,1956,1890 ,1539,1540,1419 }, {1956,2058,2057 ,1540,1541,1422 }, - {1955,1956,2057 ,1420,1540,1422 }, {2058,2103,2102 ,1541,1542,1423 }, - {2057,2058,2102 ,1422,1541,1423 }, {2103,2170,2169 ,1542,1543,1424 }, - {2102,2103,2169 ,1423,1542,1424 }, {2226,2135,2169 ,1544,1425,1424 }, - {2170,2226,2169 ,1543,1544,1424 }, {2226,2152,2136 ,1544,1545,1546 }, - {2135,2226,2136 ,1425,1544,1546 }, {1184,1188,2009 ,797,799,1224 }, - {1980,1981,2036 ,828,1456,887 }, {1985,729,730 ,1547,1548,1549 }, - {2197,933,155 ,1507,1496,1497 }, {2196,2197,155 ,1550,1507,1497 }, - {2037,2038,2082 ,1458,1551,1520 }, {2083,2128,2127 ,1552,1468,1553 }, - {2038,2083,2082 ,1551,1552,1520 }, {2198,2199,2216 ,1506,1554,1555 }, - {992,1144,991 ,958,957,1335 }, {6393,3358,3305 ,1556,880,879 }, - {1911,1978,1867 ,1101,847,1504 }, {1263,4554,6323 ,1199,1307,1451 }, - {337,385,336 ,866,864,1013 }, {1549,1548,1476 ,903,902,859 }, - {1477,1476,1404 ,1045,859,975 }, {3664,296,3475 ,1557,1558,1559 }, - {2746,3566,3768 ,1517,1146,1518 }, {526,625,582 ,718,720,719 }, - {2122,2031,2032 ,1128,1560,1127 }, {2148,2147,2126 ,1561,1562,890 }, - {1618,1685,1684 ,1563,1005,1327 }, {525,581,580 ,1279,1274,1280 }, - {3987,4227,3946 ,1229,1564,1230 }, {294,4120,4375 ,945,23,312 }, - {4548,4568,3247 ,589,1492,1494 }, {5113,6098,5914 ,141,1565,1566 }, - {1501,1500,1432 ,1567,1532,1531 }, {2259,8103,6351 ,1131,1291,1568 }, - {860,1238,1183 ,1385,1569,1238 }, {2082,2083,2127 ,1520,1552,1553 }, - {2128,2149,2148 ,1468,1470,1561 }, {2149,2197,2196 ,1470,1507,1550 }, - {2127,2128,2148 ,1553,1468,1561 }, {2148,2149,2196 ,1561,1470,1550 }, - {2130,2131,2198 ,1505,656,1506 }, {724,723,624 ,722,1053,1099 }, - {2199,2200,2216 ,1554,1570,1555 }, {1684,1685,1721 ,1327,1005,854 }, - {1683,1721,1777 ,1151,854,856 }, {1618,1619,1685 ,1563,1003,1005 }, - {240,4183,260 ,1571,1572,1573 }, {3263,2746,2651 ,252,1517,1516 }, - {392,305,2190 ,857,1463,1574 }, {3915,3903,3956 ,1575,296,1383 }, - {2869,2832,2868 ,1576,638,1577 }, {1913,1981,1980 ,963,1456,828 }, - {1885,4698,1810 ,778,1578,779 }, {649,444,492 ,1579,922,1580 }, - {399,768,193 ,269,41,1448 }, {1591,399,1032 ,1072,269,1581 }, - {1032,399,193 ,1581,269,1448 }, {4375,399,1591 ,312,269,1072 }, - {3777,4261,5733 ,1582,1583,1584 }, {1492,1749,5075 ,1585,555,1586 }, - {5889,6163,6066 ,1587,1453,1455 }, {5511,5512,5548 ,1588,1589,1590 }, - {3252,6553,6432 ,781,780,1032 }, {1757,1820,1819 ,1536,1591,1538 }, - {1796,1757,1819 ,1537,1536,1538 }, {1820,1891,1819 ,1591,1539,1538 }, - {2129,2130,2149 ,1469,1505,1470 }, {1913,1914,1981 ,963,1000,1456 }, - {1982,1983,2008 ,1002,1001,1457 }, {1983,2038,2037 ,1001,1551,1458 }, - {1981,1982,2008 ,1456,1002,1457 }, {2008,1983,2037 ,1457,1001,1458 }, - {2067,2005,2006 ,1592,1593,1181 }, {1867,1977,2390 ,1504,1503,1594 }, - {2131,2199,2198 ,656,1554,1506 }, {625,724,624 ,720,722,1099 }, - {741,740,644 ,1221,1595,1176 }, {1239,1240,1190 ,1596,796,1112 }, - {645,741,644 ,940,1221,1176 }, {547,548,644 ,1170,938,1176 }, - {690,632,1290 ,1382,1380,795 }, {2034,2033,1977 ,1289,1288,1503 }, - {2120,2121,2189 ,1597,1598,1599 }, {440,394,243 ,1464,1600,1465 }, - {2609,744,691 ,1130,1367,1173 }, {1779,1780,1842 ,1275,900,196 }, - {4035,4036,2151 ,1601,1602,1603 }, {1088,1186,1452 ,1604,1605,1606 }, - {6347,7254,6348 ,451,450,1607 }, {271,370,369 ,1608,1609,1521 }, - {370,418,369 ,1609,1610,1521 }, {418,471,470 ,1610,1611,1522 }, - {508,507,470 ,1612,1523,1522 }, {471,508,470 ,1611,1612,1522 }, - {566,565,507 ,1613,1614,1523 }, {508,566,507 ,1612,1613,1523 }, - {755,4084,4113 ,1615,205,207 }, {2030,5203,2698 ,770,102,105 }, - {229,1112,356 ,221,292,310 }, {7826,7853,7801 ,1616,1617,1618 }, - {1030,978,4991 ,1619,1620,1621 }, {6736,6790,6754 ,1622,711,713 }, - {6092,6176,5940 ,1623,1624,1625 }, {1357,1356,1315 ,1626,1530,1627 }, - {4576,4596,7524 ,1628,1629,1630 }, {1357,1433,1432 ,1626,1631,1531 }, - {1356,1357,1432 ,1530,1626,1531 }, {1433,1502,1501 ,1631,1632,1567 }, - {1432,1433,1501 ,1531,1631,1567 }, {1535,1500,1501 ,1633,1532,1567 }, - {1502,1535,1501 ,1632,1633,1567 }, {1574,1573,1500 ,1634,1533,1532 }, - {1535,1574,1500 ,1633,1634,1532 }, {1574,1642,1641 ,1634,1635,1534 }, - {1573,1574,1641 ,1533,1634,1534 }, {1642,1709,1708 ,1635,1636,1535 }, - {1641,1642,1708 ,1534,1635,1535 }, {1709,1758,1757 ,1636,1637,1536 }, - {1708,1709,1757 ,1535,1636,1536 }, {1758,1821,1820 ,1637,1638,1591 }, - {1757,1758,1820 ,1536,1637,1591 }, {1892,1891,1820 ,1639,1539,1591 }, - {1821,1892,1820 ,1638,1639,1591 }, {1957,1956,1891 ,1640,1540,1539 }, - {1892,1957,1891 ,1639,1640,1539 }, {1957,2016,1956 ,1640,1641,1540 }, - {2016,2059,2058 ,1641,1642,1541 }, {1956,2016,2058 ,1540,1641,1541 }, - {2104,2103,2058 ,1643,1542,1541 }, {2059,2104,2058 ,1642,1643,1541 }, - {2171,2170,2103 ,1644,1543,1542 }, {2104,2171,2103 ,1643,1644,1542 }, - {2171,2227,2226 ,1644,1645,1544 }, {2170,2171,2226 ,1543,1644,1544 }, - {2227,2161,2152 ,1645,1646,1545 }, {2226,2227,2152 ,1544,1645,1545 }, - {2161,391,2152 ,1646,1647,1545 }, {776,782,777 ,1120,1648,421 }, - {1914,1982,1981 ,1000,1002,1456 }, {1142,1141,990 ,1334,1498,1435 }, - {1403,1475,1474 ,974,858,1649 }, {3645,3644,3591 ,1650,1651,1652 }, - {450,548,547 ,1653,938,1170 }, {548,645,644 ,938,940,1176 }, - {1240,1239,305 ,796,1596,1463 }, {1617,1618,1684 ,904,1563,1327 }, - {221,241,240 ,1296,314,1571 }, {102,221,240 ,432,1296,1571 }, - {109,2039,349 ,1654,1655,566 }, {7747,7745,7746 ,331,650,332 }, - {1104,1040,1157 ,1473,1476,1475 }, {3913,2030,2698 ,841,770,105 }, - {5641,5642,5657 ,510,526,48 }, {1463,4326,3258 ,220,219,542 }, - {5337,5338,4914 ,572,63,65 }, {639,715,950 ,291,168,330 }, {4222,4131,4251 ,530,1656,132 }, - {1357,1315,1316 ,1626,1627,1657 }, {1502,1574,1535 ,1632,1634,1633 }, - {1709,1759,1758 ,1636,1658,1637 }, {6686,3534,8070 ,750,942,941 }, - {1785,1849,1848 ,1659,1660,1436 }, {2216,968,293 ,1555,1661,1430 }, - {1784,1785,1848 ,1662,1659,1436 }, {1875,1917,1916 ,1663,833,832 }, - {1848,1875,1916 ,1436,1663,832 }, {449,450,547 ,1169,1653,1170 }, - {1106,1203,1202 ,1664,337,339 }, {1326,1327,1403 ,1330,996,974 }, - {687,1744,2088 ,1665,1666,1667 }, {596,595,548 ,1462,939,938 }, - {1685,1722,1721 ,1005,1668,854 }, {2216,2200,968 ,1555,1570,1661 }, - {102,1553,221 ,432,1669,1296 }, {7194,7208,7225 ,1670,1671,1672 }, - {1144,1234,1142 ,957,1178,1334 }, {471,566,508 ,1611,1613,1612 }, - {200,1348,714 ,244,148,265 }, {1348,639,714 ,148,291,265 }, {737,229,356 ,150,221,310 }, - {1033,896,888 ,306,256,238 }, {4483,4525,4482 ,549,623,583 }, - {4473,4497,4520 ,270,91,1673 }, {826,189,738 ,507,503,1674 }, - {1822,1821,1758 ,1675,1638,1637 }, {1759,1822,1758 ,1658,1675,1637 }, - {1821,1822,1892 ,1638,1675,1639 }, {1957,2059,2016 ,1640,1642,1641 }, - {2172,2171,2104 ,1676,1644,1643 }, {1849,1875,1848 ,1660,1663,1436 }, - {2033,2032,1976 ,1288,1127,1180 }, {1233,1234,1327 ,1294,1178,996 }, - {339,436,387 ,1143,1142,1102 }, {221,748,241 ,1296,1677,314 }, - {284,4283,1241 ,139,1678,313 }, {2893,5307,4393 ,1679,461,463 }, - {272,371,370 ,1680,1681,1609 }, {271,272,370 ,1608,1680,1609 }, - {371,419,418 ,1681,1682,1610 }, {370,371,418 ,1609,1681,1610 }, - {419,472,471 ,1682,1683,1611 }, {418,419,471 ,1610,1682,1611 }, - {567,566,471 ,1684,1613,1611 }, {472,567,471 ,1683,1684,1611 }, - {715,639,497 ,168,291,290 }, {4483,1652,4525 ,549,170,623 }, - {1021,3,4187 ,289,329,502 }, {4497,4534,136 ,91,403,1685 }, {4525,1673,4513 ,623,1686,624 }, - {1274,1275,1316 ,1687,1688,1657 }, {1275,1358,1357 ,1688,1689,1626 }, - {1316,1275,1357 ,1657,1688,1626 }, {1434,1433,1357 ,1690,1631,1626 }, - {1358,1434,1357 ,1689,1690,1626 }, {1503,1502,1433 ,1691,1632,1631 }, - {1434,1503,1433 ,1690,1691,1631 }, {1575,1574,1502 ,1692,1634,1632 }, - {1503,1575,1502 ,1691,1692,1632 }, {1643,1642,1574 ,1693,1635,1634 }, - {1575,1643,1574 ,1692,1693,1634 }, {1643,1710,1709 ,1693,1694,1636 }, - {1642,1643,1709 ,1635,1693,1636 }, {1710,1711,1709 ,1694,1695,1636 }, - {1711,1760,1759 ,1695,1696,1658 }, {1709,1711,1759 ,1636,1695,1658 }, - {1823,1822,1759 ,1697,1675,1658 }, {1760,1823,1759 ,1696,1697,1658 }, - {1823,1893,1892 ,1697,1698,1639 }, {1822,1823,1892 ,1675,1697,1639 }, - {1893,1958,1957 ,1698,1699,1640 }, {1892,1893,1957 ,1639,1698,1640 }, - {2060,2059,1957 ,1700,1642,1640 }, {1958,2060,1957 ,1699,1700,1640 }, - {2060,2077,2059 ,1700,1701,1642 }, {2105,2104,2059 ,1702,1643,1642 }, - {2077,2105,2059 ,1701,1702,1642 }, {2173,2172,2104 ,1703,1676,1643 }, - {2105,2173,2104 ,1702,1703,1643 }, {2173,2174,2171 ,1703,1704,1644 }, - {2172,2173,2171 ,1676,1703,1644 }, {2174,2228,2227 ,1704,1705,1645 }, - {2171,2174,2227 ,1644,1704,1645 }, {2228,2214,2161 ,1705,1706,1646 }, - {2227,2228,2161 ,1645,1705,1646 }, {680,391,2161 ,1707,1647,1646 }, - {2214,680,2161 ,1706,1707,1646 }, {680,1624,1623 ,1707,1708,1709 }, - {391,680,1623 ,1647,1707,1709 }, {8061,8097,8082 ,453,1710,454 }, - {2038,2069,2083 ,1551,1711,1552 }, {1778,1779,1840 ,855,1275,198 }, - {4426,4021,8100 ,1056,1712,1713 }, {2121,2122,2190 ,1598,1128,1574 }, - {170,690,1290 ,794,1382,795 }, {7977,7976,7927 ,1714,1715,1716 }, - {1847,1914,1913 ,1519,1000,963 }, {242,1688,1389 ,1717,1718,315 }, - {241,242,1389 ,314,1717,315 }, {1688,133,1241 ,1718,1719,313 }, - {1389,1688,1241 ,315,1718,313 }, {3451,3516,2582 ,1720,1721,873 }, - {1912,1980,1911 ,964,828,1101 }, {204,272,271 ,1722,1680,1608 }, - {568,567,472 ,1723,1684,1683 }, {4224,896,1033 ,309,256,306 }, - {888,1006,799 ,238,234,392 }, {4520,4497,136 ,1673,91,1685 }, - {7928,7927,7876 ,1724,1716,1725 }, {1576,1575,1503 ,1726,1692,1691 }, - {1576,1643,1575 ,1726,1693,1692 }, {1643,1711,1710 ,1693,1695,1694 }, - {8124,3271,2810 ,1141,1727,1728 }, {905,904,858 ,1729,1730,1731 }, - {2126,2147,2146 ,890,1562,1732 }, {859,905,858 ,1733,1729,1731 }, - {1841,1842,1840 ,1276,196,198 }, {1619,1618,1549 ,1003,1563,903 }, - {815,903,902 ,999,1734,1427 }, {2541,242,241 ,1298,1717,314 }, - {883,76,146 ,119,689,504 }, {3516,3537,2582 ,1721,1735,873 }, - {3477,5785,4162 ,1736,1737,1738 }, {5480,4527,4162 ,1739,1740,1738 }, - {999,1985,960 ,798,1547,1326 }, {272,204,205 ,1680,1722,1741 }, - {4106,8142,8078 ,1742,1743,1744 }, {4483,4482,4444 ,549,583,582 }, - {174,1147,1422 ,169,202,525 }, {136,4534,1628 ,1685,403,118 }, - {189,4187,4184 ,503,502,898 }, {1644,1643,1576 ,1745,1693,1726 }, - {1643,1644,1711 ,1693,1745,1695 }, {2105,2174,2173 ,1702,1704,1703 }, - {1726,1785,1784 ,1746,1659,1662 }, {1725,1726,1784 ,1747,1746,1662 }, - {1838,1839,4427 ,425,1138,426 }, {2031,2067,2029 ,1560,1592,1748 }, - {273,372,371 ,1749,1750,1681 }, {372,420,419 ,1750,1751,1682 }, - {371,372,419 ,1681,1750,1682 }, {420,473,472 ,1751,1752,1683 }, - {419,420,472 ,1682,1751,1683 }, {569,568,472 ,1753,1723,1683 }, - {473,569,472 ,1752,1753,1683 }, {569,665,664 ,1753,1754,1755 }, - {568,569,664 ,1723,1753,1755 }, {1422,997,826 ,525,328,507 }, - {826,997,1021 ,507,328,289 }, {1034,1127,1172 ,1756,1757,1758 }, - {1172,1127,1221 ,1758,1757,1759 }, {1127,1276,1275 ,1757,1760,1688 }, - {1221,1127,1275 ,1759,1757,1688 }, {1276,1359,1358 ,1760,1761,1689 }, - {1275,1276,1358 ,1688,1760,1689 }, {1359,1435,1434 ,1761,1762,1690 }, - {1358,1359,1434 ,1689,1761,1690 }, {1504,1503,1434 ,1763,1691,1690 }, - {1435,1504,1434 ,1762,1763,1690 }, {1577,1576,1503 ,1764,1726,1691 }, - {1504,1577,1503 ,1763,1764,1691 }, {1645,1644,1576 ,1765,1745,1726 }, - {1577,1645,1576 ,1764,1765,1726 }, {1645,1712,1711 ,1765,1766,1695 }, - {1644,1645,1711 ,1745,1765,1695 }, {1761,1760,1711 ,1767,1696,1695 }, - {1712,1761,1711 ,1766,1767,1695 }, {1761,1824,1823 ,1767,1768,1697 }, - {1760,1761,1823 ,1696,1767,1697 }, {1894,1893,1823 ,1769,1698,1697 }, - {1824,1894,1823 ,1768,1769,1697 }, {1894,1959,1958 ,1769,1770,1699 }, - {1893,1894,1958 ,1698,1769,1699 }, {1959,2061,2060 ,1770,1771,1700 }, - {1958,1959,2060 ,1699,1770,1700 }, {2061,2062,2077 ,1771,1772,1701 }, - {2060,2061,2077 ,1700,1771,1701 }, {2062,2106,2105 ,1772,1773,1702 }, - {2077,2062,2105 ,1701,1772,1702 }, {2106,2175,2174 ,1773,1774,1704 }, - {2105,2106,2174 ,1702,1773,1704 }, {2175,2229,2228 ,1774,1775,1705 }, - {2174,2175,2228 ,1704,1774,1705 }, {2229,1559,2214 ,1775,1776,1706 }, - {2228,2229,2214 ,1705,1775,1706 }, {633,680,2214 ,1777,1707,1706 }, - {1559,633,2214 ,1776,1777,1706 }, {633,1624,680 ,1777,1708,1707 }, - {1187,1186,1624 ,1778,1605,1708 }, {633,1187,1624 ,1777,1778,1708 }, - {1187,1452,1186 ,1778,1606,1605 }, {1187,1919,1452 ,1778,1779,1606 }, - {8110,5521,8125 ,1140,751,752 }, {1326,1403,1402 ,1330,974,1780 }, - {1657,1658,1725 ,1781,1782,1747 }, {1688,134,133 ,1718,1783,1719 }, - {134,80,284 ,1783,140,139 }, {133,134,284 ,1719,1783,139 }, {8125,8071,8068 ,752,738,1784 }, - {272,273,371 ,1680,1749,1681 }, {493,175,492 ,1785,211,1580 }, - {6384,3362,3387 ,1786,1200,1787 }, {1034,1035,1127 ,1756,1788,1757 }, - {1959,2062,2061 ,1770,1772,1771 }, {3712,3758,3711 ,1439,1789,1790 }, - {3445,3648,3596 ,1791,734,1792 }, {1017,3513,3452 ,1793,441,1794 }, - {108,35,36 ,1336,1338,1478 }, {3148,3008,2743 ,814,546,923 }, - {1658,1726,1725 ,1782,1746,1747 }, {5057,8096,6122 ,1795,1796,1797 }, - {3456,3405,2920 ,1145,1798,1799 }, {5237,5600,2086 ,1800,1801,1802 }, - {5151,5171,6114 ,1803,1804,1805 }, {1549,1618,1617 ,903,1563,904 }, - {982,1035,1034 ,1806,1788,1756 }, {943,982,1034 ,1807,1806,1756 }, - {1959,2017,2062 ,1770,1808,1772 }, {3687,2743,3873 ,924,923,1809 }, - {3597,3445,3596 ,1810,1791,1792 }, {2121,2120,2028 ,1598,1597,1811 }, - {3537,2072,2474 ,1735,1812,874 }, {581,624,623 ,1274,1099,1100 }, - {903,990,989 ,1734,1435,1813 }, {2148,2196,2147 ,1561,1550,1562 }, - {453,82,80 ,1814,138,140 }, {5137,4631,5136 ,1815,1816,1817 }, - {1477,1549,1476 ,1045,903,859 }, {4367,4390,4343 ,228,230,1818 }, - {412,4150,1793 ,358,320,319 }, {274,373,372 ,1819,1820,1750 }, - {273,274,372 ,1749,1819,1750 }, {373,374,420 ,1820,1821,1751 }, - {372,373,420 ,1750,1820,1751 }, {374,474,473 ,1821,1822,1752 }, - {420,374,473 ,1751,1821,1752 }, {474,570,569 ,1822,1823,1753 }, - {473,474,569 ,1752,1822,1753 }, {570,666,665 ,1823,1824,1754 }, - {569,570,665 ,1753,1823,1754 }, {666,762,761 ,1824,1825,1826 }, - {665,666,761 ,1754,1824,1826 }, {762,846,845 ,1825,1827,1828 }, - {761,762,845 ,1826,1825,1828 }, {846,944,943 ,1827,1829,1807 }, - {845,846,943 ,1828,1827,1807 }, {943,944,982 ,1807,1829,1806 }, - {944,1036,1035 ,1829,1830,1788 }, {982,944,1035 ,1806,1829,1788 }, - {1036,1128,1127 ,1830,1831,1757 }, {1035,1036,1127 ,1788,1830,1757 }, - {1277,1276,1127 ,1832,1760,1757 }, {1128,1277,1127 ,1831,1832,1757 }, - {1360,1359,1276 ,1833,1761,1760 }, {1277,1360,1276 ,1832,1833,1760 }, - {1360,1436,1435 ,1833,1834,1762 }, {1359,1360,1435 ,1761,1833,1762 }, - {1505,1504,1435 ,1835,1763,1762 }, {1436,1505,1435 ,1834,1835,1762 }, - {1505,1578,1577 ,1835,1836,1764 }, {1504,1505,1577 ,1763,1835,1764 }, - {1578,1646,1645 ,1836,1837,1765 }, {1577,1578,1645 ,1764,1836,1765 }, - {1646,1713,1712 ,1837,1838,1766 }, {1645,1646,1712 ,1765,1837,1766 }, - {1713,1762,1761 ,1838,1839,1767 }, {1712,1713,1761 ,1766,1838,1767 }, - {1825,1824,1761 ,1840,1768,1767 }, {1762,1825,1761 ,1839,1840,1767 }, - {1825,1895,1894 ,1840,1841,1769 }, {1824,1825,1894 ,1768,1840,1769 }, - {1895,1960,1959 ,1841,1842,1770 }, {1894,1895,1959 ,1769,1841,1770 }, - {1960,1997,1959 ,1842,1843,1770 }, {1959,1997,2017 ,1770,1843,1808 }, - {1997,2063,2062 ,1843,1844,1772 }, {2017,1997,2062 ,1808,1843,1772 }, - {2063,2107,2106 ,1844,1845,1773 }, {2062,2063,2106 ,1772,1844,1773 }, - {2107,2108,2106 ,1845,1846,1773 }, {2108,2176,2175 ,1846,1847,1774 }, - {2106,2108,2175 ,1773,1846,1774 }, {2176,2230,2229 ,1847,1848,1775 }, - {2175,2176,2229 ,1774,1847,1775 }, {2230,866,1559 ,1848,1849,1776 }, - {2229,2230,1559 ,1775,1848,1776 }, {866,550,633 ,1849,1850,1777 }, - {1559,866,633 ,1776,1849,1777 }, {550,1244,1187 ,1850,575,1778 }, - {633,550,1187 ,1777,1850,1778 }, {1244,1367,1187 ,575,574,1778 }, - {2195,341,2194 ,1851,1852,1853 }, {7275,7254,7253 ,1854,450,1855 }, - {1977,2033,1976 ,1503,1288,1180 }, {2582,3537,2474 ,873,1735,874 }, - {902,903,901 ,1427,1734,1428 }, {1232,1231,1140 ,1295,1332,1499 }, - {1141,1232,1140 ,1498,1295,1499 }, {2082,2127,2081 ,1520,1553,888 }, - {51,301,453 ,1856,1857,1814 }, {80,51,453 ,140,1856,1814 }, {94,82,301 ,1858,138,1857 }, - {1693,3425,3283 ,264,1859,262 }, {5219,5240,5218 ,1860,481,483 }, - {3344,4221,592 ,1861,1862,1863 }, {772,891,4540 ,18,189,19 }, - {274,374,373 ,1819,1821,1820 }, {4314,1561,1525 ,1864,1865,1866 }, - {3591,3644,3590 ,1652,1651,1867 }, {2743,3931,3873 ,923,1868,1809 }, - {2125,2126,2146 ,892,890,1732 }, {723,815,814 ,1053,999,1054 }, - {2196,155,165 ,1550,1497,1869 }, {2195,2196,165 ,1851,1550,1869 }, - {2939,80,134 ,1870,140,1783 }, {5680,2453,5698 ,50,42,44 }, {274,320,374 ,1819,1871,1821 }, - {2063,2108,2107 ,1844,1846,1845 }, {550,1408,1244 ,1850,1872,575 }, - {1367,2070,614 ,574,573,1397 }, {7510,7509,7452 ,1873,1874,1875 }, - {859,858,816 ,1733,1731,998 }, {305,243,2189 ,1463,1465,1599 }, - {51,355,301 ,1856,1876,1857 }, {94,157,196 ,1858,1877,152 }, - {2743,3008,3944 ,923,546,729 }, {5180,5179,5136 ,1878,1879,1817 }, - {5658,2453,5680 ,49,42,50 }, {770,2352,805 ,275,390,389 }, {4064,4069,3317 ,1880,1881,1882 }, - {375,475,474 ,1883,1884,1822 }, {374,375,474 ,1821,1883,1822 }, - {571,570,474 ,1885,1823,1822 }, {475,571,474 ,1884,1885,1822 }, - {667,666,570 ,1886,1824,1823 }, {571,667,570 ,1885,1886,1823 }, - {763,762,666 ,1887,1825,1824 }, {667,763,666 ,1886,1887,1824 }, - {847,846,762 ,1888,1827,1825 }, {763,847,762 ,1887,1888,1825 }, - {945,944,846 ,1889,1829,1827 }, {847,945,846 ,1888,1889,1827 }, - {1037,1036,944 ,1890,1830,1829 }, {945,1037,944 ,1889,1890,1829 }, - {1129,1128,1036 ,1891,1831,1830 }, {1037,1129,1036 ,1890,1891,1830 }, - {1129,1278,1277 ,1891,1892,1832 }, {1128,1129,1277 ,1831,1891,1832 }, - {1361,1360,1277 ,1893,1833,1832 }, {1278,1361,1277 ,1892,1893,1832 }, - {1437,1436,1360 ,1894,1834,1833 }, {1361,1437,1360 ,1893,1894,1833 }, - {1506,1505,1436 ,1895,1835,1834 }, {1437,1506,1436 ,1894,1895,1834 }, - {1506,1579,1578 ,1895,1896,1836 }, {1505,1506,1578 ,1835,1895,1836 }, - {1579,1647,1646 ,1896,1897,1837 }, {1578,1579,1646 ,1836,1896,1837 }, - {1647,1714,1713 ,1897,1898,1838 }, {1646,1647,1713 ,1837,1897,1838 }, - {1714,1763,1762 ,1898,1899,1839 }, {1713,1714,1762 ,1838,1898,1839 }, - {1826,1825,1762 ,1900,1840,1839 }, {1763,1826,1762 ,1899,1900,1839 }, - {1896,1895,1825 ,1901,1841,1840 }, {1826,1896,1825 ,1900,1901,1840 }, - {1961,1960,1895 ,1902,1842,1841 }, {1896,1961,1895 ,1901,1902,1841 }, - {1961,1997,1960 ,1902,1843,1842 }, {1961,2018,1997 ,1902,1903,1843 }, - {2018,2064,2063 ,1903,1904,1844 }, {1997,2018,2063 ,1843,1903,1844 }, - {2109,2108,2063 ,1905,1846,1844 }, {2064,2109,2063 ,1904,1905,1844 }, - {2109,2177,2176 ,1905,1906,1847 }, {2108,2109,2176 ,1846,1905,1847 }, - {2177,780,2230 ,1906,1907,1848 }, {2176,2177,2230 ,1847,1906,1848 }, - {2230,780,866 ,1848,1907,1849 }, {780,389,550 ,1907,1908,1850 }, - {866,780,550 ,1849,1907,1850 }, {389,1409,1408 ,1908,1909,1872 }, - {550,389,1408 ,1850,1908,1872 }, {1409,1095,1244 ,1909,1910,575 }, - {1408,1409,1244 ,1872,1909,575 }, {1095,2070,1244 ,1910,573,575 }, - {3364,3363,3330 ,1184,1911,1185 }, {5817,5816,5800 ,701,545,702 }, - {3869,3890,3854 ,1912,1913,1512 }, {3975,2812,3684 ,728,1914,1915 }, - {1547,1548,1616 ,860,902,1150 }, {723,722,623 ,1053,1052,1100 }, - {905,992,904 ,1729,958,1730 }, {250,157,94 ,1916,1877,1858 }, - {301,250,94 ,1857,1916,1858 }, {3944,3975,3684 ,729,728,1915 }, - {1455,297,140 ,1917,1918,1919 }, {1192,398,117 ,8,15,9 }, {946,945,847 ,1920,1889,1888 }, - {1764,1826,1763 ,1921,1900,1899 }, {1065,921,1340 ,821,1922,822 }, - {2192,170,392 ,1175,794,857 }, {991,990,903 ,1335,1435,1734 }, - {2149,2130,2197 ,1470,1505,1507 }, {2746,3263,8139 ,1517,252,1923 }, - {173,398,1192 ,12,15,8 }, {772,809,891 ,18,20,189 }, {4514,4483,4465 ,259,549,257 }, - {1038,1037,945 ,1924,1890,1889 }, {946,1038,945 ,1920,1924,1889 }, - {1038,1129,1037 ,1924,1891,1890 }, {1714,1764,1763 ,1898,1921,1899 }, - {1827,1826,1764 ,1925,1900,1921 }, {2110,2109,2064 ,1926,1905,1904 }, - {3997,4039,4038 ,380,382,1927 }, {3996,3997,4038 ,1928,380,1927 }, - {3999,4041,4040 ,1023,1063,460 }, {1106,1204,1203 ,1664,338,337 }, - {906,1046,1045 ,1019,1929,956 }, {909,910,1189 ,1109,1930,1495 }, - {3572,3590,3589 ,1931,1867,1932 }, {1302,1303,13 ,909,1933,910 }, - {1844,1873,1912 ,911,913,964 }, {340,4223,593 ,1107,1934,1108 }, - {1850,251,1517 ,601,603,600 }, {1334,3871,138 ,1935,397,434 }, - {4202,562,700 ,260,1936,255 }, {4682,1376,3899 ,1191,1937,1938 }, - {106,5139,5138 ,1073,1939,1940 }, {1245,57,735 ,36,222,224 }, - {463,467,360 ,1941,346,86 }, {3749,3662,4011 ,652,1942,395 }, - {1135,1285,5067 ,1943,1944,1945 }, {6898,6563,8063 ,1946,464,465 }, - {572,611,571 ,1947,1948,1885 }, {668,667,571 ,1949,1886,1885 }, - {611,668,571 ,1948,1949,1885 }, {764,763,667 ,1950,1887,1886 }, - {668,764,667 ,1949,1950,1886 }, {848,847,763 ,1951,1888,1887 }, - {764,848,763 ,1950,1951,1887 }, {947,946,847 ,1952,1920,1888 }, - {848,947,847 ,1951,1952,1888 }, {1039,1038,946 ,1953,1924,1920 }, - {947,1039,946 ,1952,1953,1920 }, {1039,1129,1038 ,1953,1891,1924 }, - {1039,1173,1129 ,1953,1954,1891 }, {1279,1278,1129 ,1955,1892,1891 }, - {1173,1279,1129 ,1954,1955,1891 }, {1362,1361,1278 ,1956,1893,1892 }, - {1279,1362,1278 ,1955,1956,1892 }, {1438,1437,1361 ,1957,1894,1893 }, - {1362,1438,1361 ,1956,1957,1893 }, {1507,1506,1437 ,1958,1895,1894 }, - {1438,1507,1437 ,1957,1958,1894 }, {1580,1579,1506 ,1959,1896,1895 }, - {1507,1580,1506 ,1958,1959,1895 }, {1580,1648,1647 ,1959,1960,1897 }, - {1579,1580,1647 ,1896,1959,1897 }, {1648,1715,1714 ,1960,1961,1898 }, - {1647,1648,1714 ,1897,1960,1898 }, {1715,1735,1714 ,1961,1962,1898 }, - {1735,1765,1764 ,1962,1963,1921 }, {1714,1735,1764 ,1898,1962,1921 }, - {1828,1827,1764 ,1964,1925,1921 }, {1765,1828,1764 ,1963,1964,1921 }, - {1864,1826,1827 ,1965,1900,1925 }, {1828,1864,1827 ,1964,1965,1925 }, - {1897,1896,1826 ,1966,1901,1900 }, {1864,1897,1826 ,1965,1966,1900 }, - {1962,1961,1896 ,1967,1902,1901 }, {1897,1962,1896 ,1966,1967,1901 }, - {2019,2018,1961 ,1968,1903,1902 }, {1962,2019,1961 ,1967,1968,1902 }, - {2065,2064,2018 ,1969,1904,1903 }, {2019,2065,2018 ,1968,1969,1903 }, - {2111,2110,2064 ,1970,1926,1904 }, {2065,2111,2064 ,1969,1970,1904 }, - {2144,2109,2110 ,1971,1905,1926 }, {2111,2144,2110 ,1970,1971,1926 }, - {2178,2177,2109 ,1972,1906,1905 }, {2144,2178,2109 ,1971,1972,1905 }, - {2178,734,780 ,1972,1973,1907 }, {2177,2178,780 ,1906,1972,1907 }, - {390,389,780 ,1974,1908,1907 }, {734,390,780 ,1973,1974,1907 }, - {1372,1409,389 ,1975,1909,1908 }, {390,1372,389 ,1974,1975,1908 }, - {615,1095,1409 ,766,1910,1909 }, {1372,615,1409 ,1975,766,1909 }, - {3430,3489,3429 ,1976,1977,1978 }, {3380,3430,3379 ,1514,1976,1979 }, - {4038,4039,2662 ,1927,382,805 }, {3489,3488,3429 ,1977,1980,1978 }, - {580,581,623 ,1280,1274,1100 }, {293,1181,1182 ,1430,1981,1235 }, - {1616,1683,1682 ,1150,1151,1010 }, {2037,2082,2036 ,1458,1520,887 }, - {239,2290,2292 ,1103,1982,1983 }, {906,992,905 ,1019,958,1729 }, - {157,91,223 ,1877,1984,1985 }, {681,302,14 ,620,622,1986 }, {694,4165,2477 ,1987,640,642 }, - {562,708,700 ,1936,401,255 }, {467,4110,503 ,346,372,374 }, {3293,7133,7110 ,1988,1989,1990 }, - {765,764,668 ,1991,1950,1949 }, {1174,1173,1039 ,1992,1954,1953 }, - {1174,1279,1173 ,1992,1955,1954 }, {1828,1897,1864 ,1964,1966,1965 }, - {1962,2065,2019 ,1967,1969,1968 }, {2111,2178,2144 ,1970,1972,1971 }, - {2243,2325,2324 ,1993,1994,1995 }, {3323,3355,3322 ,1051,1292,1182 }, - {1142,1233,1141 ,1334,1294,1498 }, {830,928,927 ,1996,1997,1441 }, - {829,830,927 ,1368,1996,1441 }, {526,582,525 ,718,719,1279 }, - {6577,8088,8094 ,97,1998,98 }, {2127,2126,2081 ,1553,890,888 }, - {1980,2036,2007 ,828,887,829 }, {1876,460,822 ,1386,1999,2000 }, - {4244,1599,4223 ,753,391,1934 }, {14,38,681 ,1986,742,620 }, - {3662,3749,5304 ,1942,652,654 }, {4631,5180,5136 ,1816,1878,1817 }, - {959,535,6686 ,1358,2001,750 }, {700,708,757 ,255,401,239 }, - {4187,3,1023 ,502,329,308 }, {765,848,764 ,1991,1951,1950 }, - {1280,1279,1174 ,2002,1955,1992 }, {1363,1362,1279 ,2003,1956,1955 }, - {1280,1363,1279 ,2002,2003,1955 }, {1898,1897,1828 ,2004,1966,1964 }, - {2231,734,2178 ,2005,1973,1972 }, {2697,3327,1211 ,2006,439,2007 }, - {254,2662,2472 ,2008,805,2009 }, {1013,1012,927 ,2010,1471,1441 }, - {928,1013,927 ,1997,2010,1441 }, {1686,1687,1780 ,1004,1104,900 }, - {1089,2893,4393 ,103,1679,463 }, {1260,1857,1311 ,11,13,213 }, - {1319,1521,729 ,322,2011,1548 }, {139,777,963 ,145,421,1341 }, - {2785,3878,3419 ,1246,1248,2012 }, {7515,7573,7538 ,1079,2013,2014 }, - {2141,8085,973 ,2015,2016,2017 }, {3534,8138,8081 ,942,2018,1445 }, - {766,765,668 ,2019,1991,1949 }, {669,766,668 ,2020,2019,1949 }, - {849,848,765 ,2021,1951,1991 }, {766,849,765 ,2019,2021,1991 }, - {948,947,848 ,2022,1952,1951 }, {849,948,848 ,2021,2022,1951 }, - {948,983,947 ,2022,2023,1952 }, {1082,1039,947 ,2024,1953,1952 }, - {983,1082,947 ,2023,2024,1952 }, {1175,1174,1039 ,2025,1992,1953 }, - {1082,1175,1039 ,2024,2025,1953 }, {1281,1280,1174 ,2026,2002,1992 }, - {1175,1281,1174 ,2025,2026,1992 }, {1364,1363,1280 ,2027,2003,2002 }, - {1281,1364,1280 ,2026,2027,2002 }, {1364,1362,1363 ,2027,1956,2003 }, - {1439,1438,1362 ,2028,1957,1956 }, {1364,1439,1362 ,2027,2028,1956 }, - {1508,1507,1438 ,2029,1958,1957 }, {1439,1508,1438 ,2028,2029,1957 }, - {1581,1580,1507 ,2030,1959,1958 }, {1508,1581,1507 ,2029,2030,1958 }, - {1581,1649,1648 ,2030,2031,1960 }, {1580,1581,1648 ,1959,2030,1960 }, - {1649,1716,1715 ,2031,2032,1961 }, {1648,1649,1715 ,1960,2031,1961 }, - {1717,1735,1715 ,2033,1962,1961 }, {1716,1717,1715 ,2032,2033,1961 }, - {1766,1765,1735 ,2034,1963,1962 }, {1717,1766,1735 ,2033,2034,1962 }, - {1766,1829,1828 ,2034,2035,1964 }, {1765,1766,1828 ,1963,2034,1964 }, - {1899,1898,1828 ,2036,2004,1964 }, {1829,1899,1828 ,2035,2036,1964 }, - {1930,1897,1898 ,2037,1966,2004 }, {1899,1930,1898 ,2036,2037,2004 }, - {1963,1962,1897 ,2038,1967,1966 }, {1930,1963,1897 ,2037,2038,1966 }, - {2066,2065,1962 ,2039,1969,1967 }, {1963,2066,1962 ,2038,2039,1967 }, - {2066,2078,2065 ,2039,2040,1969 }, {2112,2111,2065 ,2041,1970,1969 }, - {2078,2112,2065 ,2040,2041,1969 }, {2179,2178,2111 ,2042,1972,1970 }, - {2112,2179,2111 ,2041,2042,1970 }, {2232,2231,2178 ,2043,2005,1972 }, - {2179,2232,2178 ,2042,2043,1972 }, {1448,734,2231 ,2044,1973,2005 }, - {2232,1448,2231 ,2043,2044,2005 }, {775,390,734 ,94,1974,1973 }, - {1448,775,734 ,2044,94,1973 }, {654,1372,390 ,93,1975,1974 }, - {775,654,390 ,94,93,1974 }, {1372,654,615 ,1975,93,766 }, {3080,13,2472 ,908,910,2009 }, - {2922,2923,2972 ,2045,2046,2047 }, {1061,1060,1012 ,2048,1472,1471 }, - {1013,1061,1012 ,2010,2048,1471 }, {1105,1104,1060 ,2049,1473,1472 }, - {1061,1105,1060 ,2048,2049,1472 }, {1521,730,729 ,2011,1549,1548 }, - {5180,5199,5179 ,1878,422,1879 }, {1683,1776,1775 ,1151,1431,1432 }, - {6647,5471,6611 ,2050,2051,1391 }, {1776,1777,1802 ,1431,856,2052 }, - {14,74,38 ,1986,2053,742 }, {3349,3422,3684 ,2054,2055,1915 }, - {3289,3307,3288 ,2056,2057,2058 }, {6139,4240,3797 ,2059,2060,2061 }, - {2045,30,211 ,417,307,415 }, {18,826,738 ,896,507,1674 }, {984,983,948 ,2062,2023,2022 }, - {849,984,948 ,2021,2062,2022 }, {1439,1440,1508 ,2028,2063,2029 }, - {1767,1766,1717 ,2064,2034,2033 }, {1716,1767,1717 ,2032,2064,2033 }, - {1330,654,1481 ,53,93,194 }, {2833,3054,3076 ,2065,916,2066 }, - {593,539,910 ,1108,2067,1930 }, {172,1743,3122 ,667,763,2068 }, - {394,440,1449 ,1600,1464,2069 }, {1615,1682,1614 ,1359,1010,2070 }, - {1239,1190,1449 ,1596,1112,2069 }, {1778,1840,1839 ,855,198,1138 }, - {786,963,777 ,2071,1341,421 }, {2588,74,14 ,2072,2053,1986 }, - {5453,5923,6118 ,937,2073,2074 }, {708,365,757 ,401,402,239 }, - {120,364,4362 ,240,1340,342 }, {365,364,120 ,402,1340,240 }, - {4362,139,962 ,342,145,233 }, {757,365,120 ,239,402,240 }, {5569,3121,5570 ,2075,2076,508 }, - {478,277,613 ,2077,85,298 }, {984,1082,983 ,2062,2024,2023 }, - {8079,8077,3421 ,55,2078,1156 }, {2093,4921,2257 ,553,2079,554 }, - {1536,1582,1581 ,2080,2081,2030 }, {1582,1650,1649 ,2081,2082,2031 }, - {1717,1716,1649 ,2033,2032,2031 }, {1672,1717,1649 ,2083,2033,2031 }, - {1327,1326,1232 ,996,1330,1295 }, {3592,3645,3591 ,2084,1650,1652 }, - {908,862,340 ,1111,1225,1107 }, {2029,2121,2028 ,1748,1598,1811 }, - {2127,2148,2126 ,1553,1561,890 }, {1615,1616,1682 ,1359,1150,1010 }, - {2196,2195,2147 ,1550,1851,1562 }, {1365,1440,1439 ,2085,2063,2028 }, - {5199,5219,5198 ,422,1860,423 }, {423,383,325 ,2086,2087,2088 }, - {4691,324,383 ,2089,2090,2087 }, {669,707,766 ,2020,2091,2019 }, - {850,849,766 ,2092,2021,2019 }, {767,850,766 ,2093,2092,2019 }, - {985,984,849 ,2094,2062,2021 }, {850,985,849 ,2092,2094,2021 }, - {985,1083,1082 ,2094,2095,2024 }, {984,985,1082 ,2062,2094,2024 }, - {1083,1176,1175 ,2095,2096,2025 }, {1082,1083,1175 ,2024,2095,2025 }, - {1176,1282,1281 ,2096,2097,2026 }, {1175,1176,1281 ,2025,2096,2026 }, - {1282,1365,1364 ,2097,2085,2027 }, {1281,1282,1364 ,2026,2097,2027 }, - {3347,4060,3317 ,2098,2099,1882 }, {1521,4244,730 ,2011,753,1549 }, - {4481,4480,4421 ,2100,2101,229 }, {2451,549,450 ,2102,1129,1653 }, - {3948,4326,3670 ,280,219,281 }, {3861,8097,8083 ,1147,1710,2103 }, - {732,283,871 ,2104,2105,2106 }, {4481,1674,4462 ,2100,2107,1076 }, - {1718,1716,1717 ,2108,2032,2033 }, {1768,1767,1716 ,2109,2064,2032 }, - {1718,1768,1716 ,2108,2109,2032 }, {1767,1768,1766 ,2064,2109,2034 }, - {1768,1830,1829 ,2109,2110,2035 }, {1766,1768,1829 ,2034,2109,2035 }, - {1830,1900,1899 ,2110,2111,2036 }, {1829,1830,1899 ,2035,2110,2036 }, - {1899,1900,1930 ,2036,2111,2037 }, {1900,1964,1963 ,2111,2112,2038 }, - {1930,1900,1963 ,2037,2111,2038 }, {2020,2066,1963 ,2113,2039,2038 }, - {1964,2020,1963 ,2112,2113,2038 }, {2079,2078,2066 ,2114,2040,2039 }, - {2020,2079,2066 ,2113,2114,2039 }, {2113,2112,2078 ,2115,2041,2040 }, - {2079,2113,2078 ,2114,2115,2040 }, {2180,2179,2112 ,2116,2042,2041 }, - {2113,2180,2112 ,2115,2116,2041 }, {2233,2232,2179 ,2117,2043,2042 }, - {2180,2233,2179 ,2116,2117,2042 }, {1371,1448,2232 ,2118,2044,2043 }, - {2233,1371,2232 ,2117,2118,2043 }, {231,775,1448 ,92,94,2044 }, - {1371,231,1448 ,2118,92,2044 }, {5180,5220,5199 ,1878,2119,422 }, - {5241,5240,5199 ,2120,481,422 }, {3699,3698,3645 ,2121,2122,1650 }, - {3646,3699,3645 ,2123,2121,1650 }, {7232,3288,7233 ,2124,2058,2125 }, - {26,70,460 ,2126,323,1999 }, {290,335,334 ,1042,1014,1267 }, - {2190,305,2189 ,1574,1463,1599 }, {1914,1943,1983 ,1000,2127,1001 }, - {2198,293,692 ,1506,1430,1429 }, {2197,2198,692 ,1507,1506,1429 }, - {1132,981,1591 ,61,2128,1072 }, {8118,8126,4835 ,2129,812,2130 }, - {8133,8107,2301 ,2131,658,2132 }, {965,799,1419 ,366,392,367 }, - {4131,2026,4251 ,1656,130,132 }, {767,766,707 ,2093,2019,2091 }, - {985,949,1083 ,2094,2133,2095 }, {5030,5061,1130 ,2134,2135,2136 }, - {324,4691,325 ,2090,2089,2088 }, {810,732,716 ,2137,2104,2138 }, - {4441,4481,4421 ,2139,2100,229 }, {412,736,1080 ,358,843,2140 }, - {770,1932,2352 ,275,2141,390 }, {2181,2180,2113 ,2142,2116,2115 }, - {5220,5241,5199 ,2119,2120,422 }, {2582,2585,3372 ,873,875,2143 }, - {3355,3381,3354 ,1292,871,1293 }, {3572,3573,3590 ,1931,980,1867 }, - {6230,3436,5876 ,2144,2145,2146 }, {815,857,903 ,999,2147,1734 }, - {1402,1403,1474 ,1780,974,1649 }, {1682,1681,1614 ,1010,1009,2070 }, - {1337,1845,1844 ,2148,912,911 }, {817,816,724 ,1020,998,722 }, - {1182,1181,1049 ,1235,1981,1362 }, {3316,1295,2810 ,2149,618,1728 }, - {440,1239,1449 ,1464,1596,2069 }, {741,2730,740 ,1221,2150,1595 }, - {2029,2080,2121 ,1748,2151,1598 }, {4202,885,562 ,260,216,1936 }, - {326,423,325 ,2152,2086,2088 }, {479,514,423 ,2153,2154,2086 }, - {4378,4430,4354 ,375,341,376 }, {4214,4215,4254 ,226,370,416 }, - {892,1597,810 ,506,505,2137 }, {767,851,850 ,2093,2155,2092 }, - {58,8128,227 ,2156,959,2157 }, {4972,949,851 ,2158,2133,2155 }, - {850,949,985 ,2092,2133,2094 }, {5029,1130,1083 ,2159,2136,2095 }, - {1083,1130,1176 ,2095,2136,2096 }, {5029,5030,1130 ,2159,2134,2136 }, - {884,614,4095 ,2160,1397,349 }, {1080,459,980 ,2140,696,2161 }, - {732,738,283 ,2104,1674,2105 }, {4180,1258,412 ,2162,2163,358 }, - {1319,980,1521 ,322,2161,2011 }, {732,871,716 ,2104,2106,2138 }, - {1224,1904,3048 ,1508,2164,2165 }, {4426,8100,6837 ,1056,1713,1057 }, - {283,1057,871 ,2105,354,2106 }, {1830,1865,1900 ,2110,2166,2111 }, - {8085,8091,8067 ,2016,2167,2168 }, {5285,5284,5240 ,2169,571,481 }, - {3404,2582,3372 ,2170,873,2143 }, {862,999,960 ,1225,798,1326 }, - {2193,506,170 ,1007,1381,794 }, {989,990,1140 ,1813,1435,1499 }, - {1912,1913,1980 ,964,963,828 }, {1722,1686,1779 ,1668,1004,1275 }, - {1404,1476,1475 ,975,859,858 }, {1290,2009,1918 ,795,1224,1110 }, - {5370,5328,6091 ,2171,2172,2173 }, {8107,8137,3006 ,658,2174,414 }, - {280,279,4692 ,2175,2176,2177 }, {5241,5285,5240 ,2120,2169,481 }, - {424,423,326 ,2178,2086,2152 }, {424,479,423 ,2178,2153,2086 }, - {515,514,479 ,2179,2154,2153 }, {575,574,514 ,2180,2181,2154 }, - {515,575,514 ,2179,2180,2154 }, {1223,4160,57 ,2182,223,222 }, - {635,1854,2657 ,2183,2184,2185 }, {1258,2014,736 ,2163,842,843 }, - {1080,980,25 ,2140,2161,2186 }, {1258,736,412 ,2163,843,358 }, - {4471,5295,4472 ,2187,2188,2189 }, {4354,4430,4402 ,376,341,2190 }, - {1866,1865,1830 ,2191,2166,2110 }, {1866,1901,1900 ,2191,2192,2111 }, - {1865,1866,1900 ,2166,2191,2111 }, {1901,1902,1900 ,2192,2193,2111 }, - {1965,1964,1900 ,2194,2112,2111 }, {1902,1965,1900 ,2193,2194,2111 }, - {1965,1998,1964 ,2194,2195,2112 }, {2021,2020,1964 ,2196,2113,2112 }, - {1998,2021,1964 ,2195,2196,2112 }, {2021,2079,2020 ,2196,2114,2113 }, - {2114,2113,2079 ,2197,2115,2114 }, {2021,2114,2079 ,2196,2197,2114 }, - {2182,2181,2113 ,2198,2142,2115 }, {2114,2182,2113 ,2197,2198,2115 }, - {2215,2180,2181 ,2199,2116,2142 }, {2182,2215,2181 ,2198,2199,2142 }, - {9,2233,2180 ,2200,2117,2116 }, {2215,9,2180 ,2199,2200,2116 }, - {9,1371,2233 ,2200,2118,2117 }, {232,231,1371 ,2201,92,2118 }, - {9,232,1371 ,2200,2201,2118 }, {1094,1481,231 ,1398,194,92 }, - {232,1094,231 ,2201,1398,92 }, {2147,2195,2194 ,1562,1851,1853 }, - {2198,2216,293 ,1506,1555,1430 }, {1744,1059,3932 ,1666,678,1096 }, - {2009,862,908 ,1224,1225,1111 }, {388,437,339 ,2202,1149,1143 }, - {388,339,239 ,2202,1143,1103 }, {1144,1143,991 ,957,1333,1335 }, - {1329,1406,1405 ,1134,1135,995 }, {259,410,455 ,2203,2204,2205 }, - {817,859,816 ,1020,1733,998 }, {1345,1093,840 ,203,66,68 }, {196,124,607 ,152,2206,2207 }, - {576,4907,673 ,2208,2209,2210 }, {4525,892,1673 ,623,506,1686 }, - {4160,1163,2012 ,223,2211,2212 }, {810,1597,18 ,2137,505,896 }, - {5599,5640,5639 ,2213,2214,2215 }, {736,459,1080 ,843,696,2140 }, - {5598,5599,5639 ,2216,2213,2215 }, {5237,5573,5307 ,1800,2217,461 }, - {1206,138,1734 ,2218,434,2219 }, {4520,136,4496 ,1673,1685,2220 }, - {4473,4520,4496 ,270,1673,2220 }, {1831,1866,1830 ,2221,2191,2110 }, - {2182,9,2215 ,2198,2200,2199 }, {1052,1094,232 ,2222,1398,2201 }, - {5339,5338,5284 ,2223,63,571 }, {5285,5339,5284 ,2169,2223,571 }, - {2033,2068,2124 ,1288,891,1006 }, {2068,2125,2124 ,891,892,1006 }, - {1144,1142,1143 ,957,1334,1333 }, {336,385,432 ,1013,864,1222 }, - {1722,1779,1778 ,1668,1275,855 }, {2080,2067,2121 ,2151,1592,1598 }, - {2029,2067,2080 ,1748,1592,2151 }, {239,339,338 ,1103,1143,867 }, - {628,627,528 ,1177,670,1055 }, {3697,3698,3743 ,2224,2122,2225 }, - {582,581,525 ,719,1274,1279 }, {327,326,281 ,2226,2152,2227 }, - {327,384,326 ,2226,2228,2152 }, {425,424,326 ,2229,2178,2152 }, - {384,425,326 ,2228,2229,2152 }, {480,479,424 ,2230,2153,2178 }, - {425,480,424 ,2229,2230,2178 }, {516,515,479 ,2231,2179,2153 }, - {480,516,479 ,2230,2231,2153 }, {576,575,515 ,2208,2180,2179 }, - {516,576,515 ,2231,2208,2179 }, {575,576,673 ,2180,2208,2210 }, - {5817,5834,5816 ,701,543,545 }, {892,810,1673 ,506,2137,1686 }, - {4442,4441,4391 ,991,2139,992 }, {283,738,358 ,2105,1674,897 }, - {459,4412,980 ,696,744,2161 }, {46,739,5 ,2232,2233,350 }, {883,146,76 ,119,504,689 }, - {1057,283,188 ,354,2105,2234 }, {1903,1966,1965 ,406,405,2194 }, - {1902,1903,1965 ,2193,406,2194 }, {1999,1998,1965 ,2235,2195,2194 }, - {1966,1999,1965 ,405,2235,2194 }, {2022,2021,1998 ,2236,2196,2195 }, - {1999,2022,1998 ,2235,2236,2195 }, {2115,2114,2021 ,2237,2197,2196 }, - {2022,2115,2021 ,2236,2237,2196 }, {2115,2145,2114 ,2237,2238,2197 }, - {2183,2182,2114 ,2239,2198,2197 }, {2145,2183,2114 ,2238,2239,2197 }, - {2183,9,2182 ,2239,2200,2198 }, {1513,232,9 ,2240,2201,2200 }, - {1632,76,129 ,2241,689,730 }, {2013,58,877 ,2242,2156,2243 }, - {728,819,726 ,1266,2244,669 }, {1153,6797,8123 ,2245,2246,2247 }, - {1182,1049,1048 ,1235,1362,1236 }, {335,336,431 ,1014,1013,1268 }, - {901,903,989 ,1428,1734,1813 }, {5339,4916,4915 ,2223,2248,64 }, - {1868,3760,1783 ,2249,2250,2251 }, {3784,4884,4239 ,2252,2253,2254 }, - {5338,5339,4915 ,63,2223,64 }, {4513,1673,4481 ,624,1686,2100 }, - {1295,3316,3348 ,618,2149,2255 }, {4244,4223,340 ,753,1934,1107 }, - {730,4244,340 ,1549,753,1107 }, {1114,1115,2047 ,2256,2257,2258 }, - {4480,4462,4421 ,2101,1076,229 }, {798,5103,5378 ,78,77,359 }, - {40,9,2183 ,2259,2200,2239 }, {40,163,9 ,2259,2260,2200 }, {233,1513,9 ,2261,2240,2200 }, - {163,233,9 ,2260,2261,2200 }, {1514,232,1513 ,2262,2201,2240 }, - {233,1514,1513 ,2261,2262,2240 }, {1055,1052,232 ,2263,2222,2201 }, - {1514,1055,232 ,2262,2263,2201 }, {1054,1094,1052 ,2264,1398,2222 }, - {1055,1054,1052 ,2263,2264,2222 }, {1054,865,1094 ,2264,1119,1398 }, - {2893,3946,5307 ,1679,1230,461 }, {227,1482,58 ,2157,2265,2156 }, - {1238,860,1000 ,1569,1385,1384 }, {305,1239,440 ,1463,1596,1464 }, - {1657,1656,1552 ,1781,1166,2266 }, {814,815,902 ,1054,999,1427 }, - {8092,8120,8130 ,2267,906,905 }, {2131,2200,2199 ,656,1570,1554 }, - {817,905,859 ,1020,1729,1733 }, {2032,2033,2123 ,1127,1288,1008 }, - {3946,4227,5307 ,1230,1564,461 }, {249,1664,268 ,644,2268,645 }, - {1234,1328,1327 ,1178,994,996 }, {864,865,867 ,840,1119,1121 }, - {8140,8063,8102 ,2269,465,253 }, {577,576,516 ,2270,2208,2231 }, - {576,577,674 ,2208,2270,2271 }, {358,4184,2014 ,897,898,842 }, - {6553,6295,6646 ,780,1290,1133 }, {1441,23,4181 ,1485,2272,2273 }, - {1927,870,710 ,1196,2274,33 }, {810,716,1674 ,2137,2138,2107 }, - {593,1599,539 ,1108,391,2067 }, {4152,4180,4448 ,2275,2162,2276 }, - {358,4180,4152 ,897,2162,2275 }, {188,358,4152 ,2234,897,2275 }, - {4480,4481,4462 ,2101,2100,1076 }, {941,119,1049 ,2277,2278,1362 }, - {188,4152,4138 ,2234,2275,278 }, {4152,188,4138 ,2275,2234,278 }, - {1674,716,4512 ,2107,2138,2279 }, {6509,6531,8092 ,1452,2280,2267 }, - {4060,4064,3317 ,2099,1880,1882 }, {1999,1966,2022 ,2235,405,2236 }, - {233,1055,1514 ,2261,2263,2262 }, {1055,865,1054 ,2263,1119,2264 }, - {2137,867,776 ,147,1121,1120 }, {3758,3757,3711 ,1789,2281,1790 }, - {3194,3016,3189 ,1065,1028,1027 }, {442,441,357 ,673,609,672 }, - {1910,1911,1867 ,1223,1101,1504 }, {1049,1181,1050 ,1362,1981,2282 }, - {1802,1777,1838 ,2052,856,425 }, {336,432,431 ,1013,1222,1268 }, - {5305,5572,3147 ,2283,2284,2285 }, {904,991,903 ,1730,1335,1734 }, - {1406,1407,1447 ,1135,1269,1136 }, {8114,8108,6797 ,2286,2287,2246 }, - {437,436,339 ,1149,1142,1143 }, {1190,1189,1449 ,1112,1495,2069 }, - {8081,8093,8072 ,1445,2288,511 }, {940,1910,1867 ,197,1223,1504 }, - {328,426,425 ,2289,2290,2229 }, {384,328,425 ,2228,2289,2229 }, - {426,481,480 ,2290,2291,2230 }, {425,426,480 ,2229,2290,2230 }, - {481,517,516 ,2291,2292,2231 }, {480,481,516 ,2230,2291,2231 }, - {578,577,516 ,2293,2270,2231 }, {517,578,516 ,2292,2293,2231 }, - {675,676,677 ,2294,2295,2296 }, {577,578,675 ,2270,2293,2294 }, - {738,189,358 ,1674,503,897 }, {661,1441,4181 ,2297,1485,2273 }, - {4513,4481,4463 ,624,2100,993 }, {5,739,413 ,350,2233,351 }, - {980,4244,1521 ,2161,753,2011 }, {1424,379,608 ,2298,2299,2300 }, - {416,604,502 ,556,486,2301 }, {25,980,1319 ,2186,2161,322 }, - {4448,4180,412 ,2276,2162,358 }, {138,878,1734 ,434,398,2219 }, - {5558,3121,5569 ,2302,2076,2075 }, {4430,4473,4402 ,341,270,2190 }, - {879,3397,3370 ,1155,136,2303 }, {4152,4448,4138 ,2275,2276,278 }, - {4108,4148,4124 ,2304,2305,2306 }, {8131,8075,8107 ,2307,2308,658 }, - {1967,1968,1966 ,404,2309,405 }, {1968,2023,2022 ,2309,2310,2236 }, - {1966,1968,2022 ,405,2309,2236 }, {2116,2115,2022 ,2311,2237,2236 }, - {2023,2116,2022 ,2310,2311,2236 }, {2116,2145,2115 ,2311,2238,2237 }, - {2184,2183,2145 ,2312,2239,2238 }, {2116,2184,2145 ,2311,2312,2238 }, - {83,40,2183 ,2313,2259,2239 }, {2184,83,2183 ,2312,2313,2239 }, - {1001,163,40 ,2314,2260,2259 }, {83,1001,40 ,2313,2314,2259 }, - {234,233,163 ,2315,2261,2260 }, {1001,234,163 ,2314,2315,2260 }, - {1053,1055,233 ,2316,2263,2261 }, {234,1053,233 ,2315,2316,2261 }, - {776,865,1055 ,1120,1119,2263 }, {1053,776,1055 ,2316,1120,2263 }, - {5194,1102,1454 ,727,2317,2318 }, {1744,3932,2088 ,1666,1096,1667 }, - {1721,1722,1778 ,854,1668,855 }, {2197,692,933 ,1507,1429,1496 }, - {1775,1776,1802 ,1432,1431,2052 }, {1240,1918,1190 ,796,1110,1112 }, - {1446,1447,1478 ,1137,1136,2319 }, {3880,3868,3831 ,2320,970,2321 }, - {3832,3880,3831 ,2322,2320,2321 }, {2191,392,2190 ,1174,857,1574 }, - {4587,2320,8020 ,774,1406,1405 }, {1843,1911,1910 ,901,1101,1223 }, - {5013,2256,6484 ,684,2323,685 }, {1867,2390,940 ,1504,1594,197 }, - {578,579,676 ,2293,2324,2295 }, {1338,1257,4214 ,1077,208,226 }, - {4215,4255,4254 ,370,165,416 }, {4412,314,980 ,744,578,2161 }, - {810,18,732 ,2137,896,2104 }, {980,314,4244 ,2161,578,753 }, - {4464,4513,4463 ,584,624,993 }, {1673,810,1674 ,1686,2137,2107 }, - {4463,4481,4441 ,993,2100,2139 }, {8066,8092,8098 ,960,2267,907 }, - {1225,490,1223 ,327,469,2182 }, {412,1080,69 ,358,2140,321 }, - {4150,412,69 ,320,358,321 }, {880,1441,661 ,1483,1485,2297 }, - {3644,3697,3696 ,1651,2224,2325 }, {188,4152,4138 ,2234,2275,278 }, - {83,234,1001 ,2313,2315,2314 }, {782,776,1053 ,1648,1120,2316 }, - {1691,1670,1733 ,2326,2327,2328 }, {392,1240,305 ,857,796,1463 }, - {2122,2191,2190 ,1128,1174,1574 }, {2067,2122,2121 ,1592,1128,1598 }, - {1479,1477,1478 ,1270,1045,2319 }, {1602,1610,749 ,2329,2330,2331 }, - {1478,1477,1405 ,2319,1045,995 }, {3704,6140,6169 ,2332,2333,2334 }, - {1365,1439,1364 ,2085,2028,2027 }, {3918,3917,3868 ,2335,968,970 }, - {517,579,578 ,2292,2324,2293 }, {2223,6484,2256 ,2336,685,2323 }, - {5834,1942,141 ,543,2337,681 }, {1462,4177,4116 ,2338,2339,2340 }, - {130,89,150 ,2341,1482,1481 }, {136,1628,883 ,1685,118,119 }, - {4441,4421,4367 ,2139,229,228 }, {1677,1676,1610 ,2342,2343,2330 }, - {69,1080,25 ,321,2140,2186 }, {3643,3644,3696 ,2344,1651,2325 }, - {1069,188,4138 ,277,2234,278 }, {1660,1053,234 ,2345,2316,2315 }, - {1378,3148,2743 ,925,814,923 }, {3880,3918,3868 ,2320,2335,970 }, - {1094,865,864 ,1398,1119,840 }, {1802,1838,1837 ,2052,425,997 }, - {1634,1423,396 ,768,151,153 }, {742,741,645 ,972,1221,940 }, - {1915,1916,1943 ,1437,832,2127 }, {1914,1915,1943 ,1000,1437,2127 }, - {1682,1683,1775 ,1010,1151,1432 }, {1446,1478,1405 ,1137,2319,995 }, - {1235,1329,1328 ,1179,1134,994 }, {3961,3960,3917 ,2346,1021,968 }, - {3918,3961,3917 ,2335,2346,968 }, {1145,1235,1234 ,1277,1179,1178 }, - {7151,3290,7175 ,1202,1204,2347 }, {329,427,426 ,2348,2349,2290 }, - {328,329,426 ,2289,2348,2290 }, {426,427,481 ,2290,2349,2291 }, - {427,518,517 ,2349,2350,2292 }, {481,427,517 ,2291,2349,2292 }, - {518,519,579 ,2350,2351,2324 }, {517,518,579 ,2292,2350,2324 }, - {519,617,579 ,2351,2352,2324 }, {579,617,677 ,2324,2352,2296 }, - {2026,870,1927 ,130,2274,1196 }, {732,18,738 ,2104,896,1674 }, - {4442,4463,4441 ,991,993,2139 }, {4068,4067,1253 ,408,185,2353 }, - {358,2014,4180 ,897,842,2162 }, {4391,4441,4367 ,992,2139,228 }, - {1226,1321,1320 ,2354,2355,2356 }, {1321,1398,1397 ,2355,2357,2358 }, - {1320,1321,1397 ,2356,2355,2358 }, {1397,1398,1445 ,2358,2357,2359 }, - {1398,1470,1469 ,2357,2360,2361 }, {1445,1398,1469 ,2359,2357,2361 }, - {1470,1542,1541 ,2360,2362,2363 }, {1469,1470,1541 ,2361,2360,2363 }, - {1611,1610,1541 ,2364,2330,2363 }, {1542,1611,1541 ,2362,2364,2363 }, - {1678,1677,1610 ,2365,2342,2330 }, {1611,1678,1610 ,2364,2365,2330 }, - {1720,1676,1677 ,2366,2343,2342 }, {1678,1720,1677 ,2365,2366,2342 }, - {1720,1771,4817 ,2366,2367,2368 }, {4138,4448,412 ,278,2276,358 }, - {1674,4512,4462 ,2107,2279,1076 }, {6837,8088,6577 ,1057,1998,97 }, - {4036,109,2151 ,1602,1654,1603 }, {1969,2024,2023 ,2369,2370,2310 }, - {1968,1969,2023 ,2309,2369,2310 }, {2024,2117,2116 ,2370,2371,2311 }, - {2023,2024,2116 ,2310,2370,2311 }, {2185,2184,2116 ,2372,2312,2311 }, - {2117,2185,2116 ,2371,2372,2311 }, {152,83,2184 ,2373,2313,2312 }, - {2185,152,2184 ,2372,2373,2312 }, {1288,234,83 ,2374,2315,2313 }, - {152,1288,83 ,2373,2374,2313 }, {861,1660,234 ,2375,2345,2315 }, - {1288,861,234 ,2374,2375,2315 }, {998,1053,1660 ,2376,2316,2345 }, - {861,998,1660 ,2375,2376,2345 }, {786,782,1053 ,2071,1648,2316 }, - {998,786,1053 ,2376,2071,2316 }, {4327,1427,561 ,2377,2378,2379 }, - {169,1880,1296 ,248,250,335 }, {652,169,1296 ,334,248,335 }, - {4000,4042,4041 ,1022,1061,1063 }, {3999,4000,4041 ,1023,1022,1063 }, - {3961,4001,4000 ,2346,2380,1022 }, {2129,2069,2130 ,1469,1711,1505 }, - {1981,2037,2036 ,1456,1458,887 }, {858,904,903 ,1731,1730,1734 }, - {647,742,645 ,973,972,940 }, {1943,1916,1983 ,2127,832,1001 }, - {1916,1984,1983 ,832,831,1001 }, {3372,2585,3453 ,2143,875,917 }, - {1046,1145,1045 ,1929,1277,956 }, {6098,5113,6174 ,1565,141,2381 }, - {518,427,519 ,2350,2349,2351 }, {870,1396,710 ,2274,34,33 }, - {1673,1674,4481 ,1686,2107,2100 }, {716,1675,4512 ,2138,2382,2279 }, - {4138,412,44 ,278,358,357 }, {2474,2072,8096 ,874,1812,1796 }, - {5021,1969,5019 ,2383,2369,2384 }, {5019,1969,1968 ,2384,2369,2309 }, - {2186,2185,2117 ,2385,2372,2371 }, {861,786,998 ,2375,2071,2376 }, - {3712,3711,3653 ,1439,1790,1440 }, {6169,6141,6154 ,2334,2386,2387 }, - {3356,3355,3323 ,872,1292,1051 }, {3960,3961,4000 ,1021,2346,1022 }, - {1801,1802,1837 ,1433,2052,997 }, {725,817,724 ,721,1020,722 }, - {2518,448,546 ,2388,1172,1171 }, {2069,2038,2530 ,1711,1551,2389 }, - {1784,1848,1847 ,1662,1436,1519 }, {647,645,646 ,973,940,954 }, - {723,724,815 ,1053,722,999 }, {815,816,857 ,999,998,2147 }, {3698,3744,3743 ,2122,2390,2225 }, - {237,337,336 ,869,866,1013 }, {519,618,617 ,2351,2391,2352 }, - {855,897,951 ,2392,2393,2394 }, {897,952,951 ,2393,2395,2394 }, - {4180,2014,1258 ,2162,842,2163 }, {952,5034,951 ,2395,2396,2394 }, - {1321,1369,1398 ,2355,2397,2357 }, {1678,1771,1720 ,2365,2367,2366 }, - {1596,188,1069 ,355,2234,277 }, {4536,4452,4820 ,89,2398,2399 }, - {393,4042,4000 ,2400,1061,1022 }, {4001,393,4000 ,2380,2400,1022 }, - {632,341,1184 ,1380,1852,797 }, {341,1373,1184 ,1852,1501,797 }, - {1682,1775,1739 ,1010,1432,1011 }, {1475,1547,1546 ,858,860,1360 }, - {2083,2069,2128 ,1552,1711,1468 }, {2069,2129,2128 ,1711,1469,1468 }, - {7175,3290,7196 ,2347,1204,2401 }, {857,858,903 ,2147,1731,1734 }, - {816,858,857 ,998,1731,2147 }, {1325,1326,1402 ,1331,1330,1780 }, - {1303,1302,687 ,1933,909,1665 }, {330,331,329 ,2402,2403,2348 }, - {331,428,427 ,2403,2404,2349 }, {329,331,427 ,2348,2403,2349 }, - {428,520,519 ,2404,2405,2351 }, {427,428,519 ,2349,2404,2351 }, - {520,619,618 ,2405,2406,2391 }, {519,520,618 ,2351,2405,2391 }, - {718,717,618 ,2407,2408,2391 }, {619,718,618 ,2406,2407,2391 }, - {717,718,855 ,2408,2407,2392 }, {1042,1041,952 ,2409,2410,2395 }, - {898,1042,952 ,2411,2409,2395 }, {1136,1135,1041 ,2412,1943,2410 }, - {1042,1136,1041 ,2409,2412,2410 }, {1227,1226,1135 ,2413,2354,1943 }, - {1136,1227,1135 ,2412,2413,1943 }, {1227,1322,1321 ,2413,2414,2355 }, - {1226,1227,1321 ,2354,2413,2355 }, {1321,1322,1369 ,2355,2414,2397 }, - {1322,1399,1398 ,2414,2415,2357 }, {1369,1322,1398 ,2397,2414,2357 }, - {1399,1471,1470 ,2415,2416,2360 }, {1398,1399,1470 ,2357,2415,2360 }, - {1471,1543,1542 ,2416,2417,2362 }, {1470,1471,1542 ,2360,2416,2362 }, - {1543,1612,1611 ,2417,2418,2364 }, {1542,1543,1611 ,2362,2417,2364 }, - {1679,1678,1611 ,2419,2365,2364 }, {1612,1679,1611 ,2418,2419,2364 }, - {1772,1771,1678 ,2420,2367,2365 }, {1679,1772,1678 ,2419,2420,2365 }, - {1835,1834,1771 ,2421,2422,2367 }, {1772,1835,1771 ,2420,2421,2367 }, - {322,6203,843 ,1250,1249,2423 }, {3380,3379,3353 ,1514,1979,2424 }, - {3354,3380,3353 ,1293,1514,2424 }, {4644,4740,1970 ,2425,2426,2427 }, - {1970,2000,1969 ,2427,2428,2369 }, {1969,2000,2024 ,2369,2428,2370 }, - {8090,8065,8080 ,412,96,1094 }, {2118,2117,2024 ,2429,2371,2370 }, - {2025,2118,2024 ,2430,2429,2370 }, {2187,2186,2117 ,2431,2385,2371 }, - {2118,2187,2117 ,2429,2431,2371 }, {2187,2185,2186 ,2431,2372,2385 }, - {161,152,2185 ,2432,2373,2372 }, {2187,161,2185 ,2431,2432,2372 }, - {1193,1288,152 ,2433,2374,2373 }, {161,1193,152 ,2432,2433,2373 }, - {1193,1287,1288 ,2433,2434,2374 }, {907,861,1288 ,2435,2375,2374 }, - {1287,907,1288 ,2434,2435,2374 }, {629,786,861 ,2436,2071,2375 }, - {907,629,861 ,2435,2436,2375 }, {629,962,786 ,2436,233,2071 }, - {3356,3381,3355 ,872,871,1292 }, {3004,2946,4042 ,2437,1062,1061 }, - {8106,8135,3449 ,2438,2439,2440 }, {529,628,528 ,1148,1177,1055 }, - {1848,1915,1914 ,1436,1437,1000 }, {1847,1848,1914 ,1519,1436,1000 }, - {2476,2310,3844 ,2441,2442,2443 }, {1686,1780,1779 ,1004,900,1275 }, - {236,237,336 ,2444,869,1013 }, {330,2393,286 ,2402,2445,2446 }, - {520,521,619 ,2405,2447,2406 }, {8115,8136,8140 ,2448,2449,2269 }, - {1519,79,2544 ,2450,1510,2451 }, {4021,4835,8106 ,1712,2130,2438 }, - {4446,1335,2607 ,237,236,2452 }, {5833,5834,141 ,544,543,681 }, - {3430,3429,3379 ,1976,1978,1979 }, {488,832,1302 ,533,613,909 }, - {3080,488,1302 ,908,533,909 }, {1057,188,1596 ,354,2234,355 }, - {871,594,893 ,2106,2453,2454 }, {716,871,893 ,2138,2106,2454 }, - {393,3004,4042 ,2400,2437,1061 }, {8139,3263,8089 ,1923,252,254 }, - {1876,822,1985 ,1386,2000,1547 }, {822,729,1985 ,2000,1548,1547 }, - {1685,1686,1722 ,1005,1004,1668 }, {2193,632,506 ,1007,1380,1381 }, - {1684,1721,1683 ,1327,854,1151 }, {2131,2201,2200 ,656,2455,1570 }, - {2193,2194,341 ,1007,1853,1852 }, {1184,1373,999 ,797,1501,798 }, - {1779,1842,1841 ,1275,196,1276 }, {286,331,330 ,2446,2403,2402 }, - {428,521,520 ,2404,2447,2405 }, {916,913,863 ,445,444,284 }, - {283,358,188 ,2105,897,2234 }, {1227,1286,1322 ,2413,2456,2414 }, - {1773,1772,1679 ,2457,2420,2419 }, {1871,1835,1872 ,2458,2421,2459 }, - {8074,8092,8066 ,2460,2267,960 }, {3354,3353,3321 ,1293,2424,2461 }, - {2796,304,3080 ,2462,532,908 }, {1675,716,893 ,2382,2138,2454 }, - {1193,907,1287 ,2433,2435,2434 }, {820,629,907 ,2463,2436,2435 }, - {6102,3831,3868 ,2464,2321,970 }, {3004,2087,2571 ,2437,2465,1064 }, - {1006,1100,799 ,234,2466,392 }, {729,822,1319 ,1548,2000,322 }, - {1146,1145,1046 ,2467,1277,1929 }, {1047,1146,1046 ,1328,2467,1929 }, - {1474,1475,1546 ,1649,858,1360 }, {1373,1000,999 ,1501,1384,798 }, - {3264,8144,2301 ,2468,2469,2132 }, {1000,1876,999 ,1384,1386,798 }, - {287,332,331 ,2470,2471,2403 }, {332,429,428 ,2471,2472,2404 }, - {331,332,428 ,2403,2471,2404 }, {429,522,521 ,2472,2473,2447 }, - {428,429,521 ,2404,2472,2447 }, {522,620,619 ,2473,2474,2406 }, - {521,522,619 ,2447,2473,2406 }, {720,718,719 ,2475,2407,2476 }, - {619,620,718 ,2406,2474,2407 }, {812,899,898 ,559,2477,2411 }, - {811,812,898 ,557,559,2411 }, {1043,898,899 ,2478,2411,2477 }, - {1043,1137,1136 ,2478,2479,2412 }, {1137,1228,1227 ,2479,2480,2413 }, - {1136,1137,1227 ,2412,2479,2413 }, {1228,1229,1286 ,2480,2481,2456 }, - {1227,1228,1286 ,2413,2480,2456 }, {1229,1323,1322 ,2481,2482,2414 }, - {1286,1229,1322 ,2456,2481,2414 }, {1323,1400,1399 ,2482,2483,2415 }, - {1322,1323,1399 ,2414,2482,2415 }, {1400,1472,1471 ,2483,2484,2416 }, - {1399,1400,1471 ,2415,2483,2416 }, {1472,1544,1543 ,2484,2485,2417 }, - {1471,1472,1543 ,2416,2484,2417 }, {1613,1612,1543 ,2486,2418,2417 }, - {1544,1613,1543 ,2485,2486,2417 }, {1613,1680,1679 ,2486,2487,2419 }, - {1612,1613,1679 ,2418,2486,2419 }, {1680,1774,1773 ,2487,2488,2457 }, - {1679,1680,1773 ,2419,2487,2457 }, {1800,1772,1773 ,2489,2420,2457 }, - {1774,1800,1773 ,2488,2489,2457 }, {1836,1835,1772 ,2490,2421,2420 }, - {1800,1836,1772 ,2489,2490,2420 }, {1836,1872,1835 ,2490,2459,2421 }, - {296,630,3475 ,1558,2491,1559 }, {2027,2000,2002 ,2492,2428,2493 }, - {1675,893,4512 ,2382,2454,2279 }, {8069,8100,3482 ,1095,1713,2494 }, - {2119,2118,2025 ,2495,2429,2430 }, {2027,2119,2025 ,2492,2495,2430 }, - {2188,2187,2118 ,2496,2431,2429 }, {2119,2188,2118 ,2495,2496,2429 }, - {179,161,2187 ,2497,2432,2431 }, {2188,179,2187 ,2496,2497,2431 }, - {1374,1193,161 ,2498,2433,2432 }, {179,1374,161 ,2497,2498,2432 }, - {954,907,1193 ,2499,2435,2433 }, {1374,954,1193 ,2498,2499,2433 }, - {914,820,907 ,2500,2463,2435 }, {954,914,907 ,2499,2500,2435 }, - {487,629,820 ,2501,2436,2463 }, {914,487,820 ,2500,2501,2463 }, - {1100,962,629 ,2466,233,2436 }, {487,1100,629 ,2501,2466,2436 }, - {3491,3490,3461 ,955,2502,1152 }, {2946,3004,2571 ,1062,2437,1064 }, - {3931,3684,3664 ,1868,1915,1557 }, {1843,1844,1911 ,901,911,1101 }, - {8068,8071,3264 ,1784,738,2468 }, {2087,132,3016 ,2465,2503,1028 }, - {909,593,910 ,1109,1108,1930 }, {1233,1232,1141 ,1294,1295,1498 }, - {1447,1479,1478 ,1136,1270,2319 }, {1844,1912,1911 ,911,964,1101 }, - {3434,3494,3463 ,737,736,1271 }, {2571,2087,3016 ,1064,2465,1028 }, - {1775,1802,1801 ,1432,2052,1433 }, {1876,1985,999 ,1386,1547,798 }, - {718,720,4954 ,2407,2475,558 }, {4258,4217,85 ,84,83,2504 }, - {6853,6905,6892 ,2505,2506,2507 }, {1137,1229,1228 ,2479,2481,2480 }, - {1302,832,1744 ,909,613,1666 }, {832,1059,1744 ,613,678,1666 }, - {222,179,2188 ,2508,2497,2496 }, {2222,2210,6563 ,2509,2510,464 }, - {132,2837,584 ,2503,2511,2512 }, {2364,3342,3343 ,2513,2514,2515 }, - {1548,1617,1616 ,902,904,1150 }, {239,238,2290 ,1103,868,1982 }, - {822,460,70 ,2000,1999,323 }, {3698,3697,3644 ,2122,2224,1651 }, - {5988,5972,4147 ,2516,399,2517 }, {620,720,719 ,2474,2475,2476 }, - {5309,505,469 ,987,986,988 }, {1137,1180,1229 ,2479,2518,2481 }, - {1349,2002,1971 ,2519,2493,2520 }, {3647,3646,3594 ,2521,2123,2522 }, - {2698,4369,5335 ,105,104,2523 }, {3016,132,584 ,1028,2503,2512 }, - {626,725,625 ,801,721,720 }, {290,291,335 ,1042,1012,1014 }, - {992,991,904 ,958,1335,1730 }, {1302,1744,687 ,909,1666,1665 }, - {1978,2034,1977 ,847,1289,1503 }, {289,333,332 ,1044,1043,2471 }, - {333,430,429 ,1043,2524,2472 }, {332,333,429 ,2471,1043,2472 }, - {430,482,429 ,2524,2525,2472 }, {482,523,522 ,2525,2526,2473 }, - {429,482,522 ,2472,2525,2473 }, {523,621,620 ,2526,2527,2474 }, - {522,523,620 ,2473,2526,2474 }, {621,721,720 ,2527,2528,2475 }, - {620,621,720 ,2474,2527,2475 }, {721,813,812 ,2528,2529,559 }, - {720,721,812 ,2475,2528,559 }, {813,900,899 ,2529,2530,2477 }, - {812,813,899 ,559,2529,2477 }, {900,988,899 ,2530,2531,2477 }, - {988,1044,1043 ,2531,2532,2478 }, {899,988,1043 ,2477,2531,2478 }, - {1044,1138,1137 ,2532,2533,2479 }, {1043,1044,1137 ,2478,2532,2479 }, - {1138,1139,1180 ,2533,2534,2518 }, {1137,1138,1180 ,2479,2533,2518 }, - {1139,1230,1229 ,2534,2535,2481 }, {1180,1139,1229 ,2518,2534,2481 }, - {1230,1324,1323 ,2535,2536,2482 }, {1229,1230,1323 ,2481,2535,2482 }, - {1324,1401,1400 ,2536,2537,2483 }, {1323,1324,1400 ,2482,2536,2483 }, - {1473,1472,1400 ,2538,2484,2483 }, {1401,1473,1400 ,2537,2538,2483 }, - {1473,1545,1544 ,2538,2539,2485 }, {1472,1473,1544 ,2484,2538,2485 }, - {1614,1613,1544 ,2070,2486,2485 }, {1545,1614,1544 ,2539,2070,2485 }, - {1614,1681,1680 ,2070,1009,2487 }, {1613,1614,1680 ,2486,2070,2487 }, - {1681,1739,1680 ,1009,1011,2487 }, {1739,1774,1680 ,1011,2488,2487 }, - {1801,1800,1774 ,1433,2489,2488 }, {1739,1801,1774 ,1011,1433,2488 }, - {1801,1837,1836 ,1433,997,2490 }, {1800,1801,1836 ,2489,1433,2490 }, - {1837,380,1836 ,997,2540,2490 }, {5497,3350,4530 ,1375,2541,1376 }, - {2003,2002,1349 ,2542,2493,2519 }, {1349,1971,1948 ,2519,2520,2543 }, - {2028,2027,2002 ,1811,2492,2493 }, {2003,2028,2002 ,2542,1811,2493 }, - {2028,2120,2119 ,1811,1597,2495 }, {2027,2028,2119 ,2492,1811,2495 }, - {2189,2188,2119 ,1599,2496,2495 }, {2120,2189,2119 ,1597,1599,2495 }, - {243,222,2188 ,1465,2508,2496 }, {2189,243,2188 ,1599,1465,2496 }, - {394,179,222 ,1600,2497,2508 }, {243,394,222 ,1465,1600,2508 }, - {1449,1374,179 ,2069,2498,2497 }, {394,1449,179 ,1600,2069,2497 }, - {1449,910,954 ,2069,1930,2499 }, {1374,1449,954 ,2498,2069,2499 }, - {539,914,954 ,2067,2500,2499 }, {910,539,954 ,1930,2067,2499 }, - {77,487,914 ,2544,2501,2500 }, {539,77,914 ,2067,2544,2500 }, - {1194,1100,487 ,393,2466,2501 }, {77,1194,487 ,2544,393,2501 }, - {1194,799,1100 ,393,392,2466 }, {3699,3700,3745 ,2121,2545,2546 }, - {2837,2501,108 ,2511,2547,1336 }, {584,2837,108 ,2512,2511,1336 }, - {2501,107,108 ,2547,2548,1336 }, {929,1014,1013 ,1234,1233,2010 }, - {928,929,1013 ,1997,1234,2010 }, {1014,1062,1061 ,1233,1232,2048 }, - {1013,1014,1061 ,2010,1233,2048 }, {1062,1106,1105 ,1232,1664,2049 }, - {1061,1062,1105 ,2048,1232,2049 }, {1105,1106,1202 ,2049,1664,339 }, - {304,2796,2662 ,532,2462,805 }, {3868,3916,3879 ,970,969,2549 }, - {239,387,339 ,1103,1102,1143 }, {621,622,721 ,2527,2550,2528 }, - {1044,1139,1138 ,2532,2534,2533 }, {391,1623,1088 ,1647,1709,1604 }, - {108,107,2134 ,1336,2548,1337 }, {2243,2324,2242 ,1993,1995,2551 }, - {2121,2190,2189 ,1598,1574,1599 }, {1189,910,1449 ,1495,1930,2069 }, - {107,751,35 ,2548,1365,1338 }, {2134,107,35 ,1337,2548,1338 }, - {5698,5697,5679 ,44,2552,2553 }, {523,622,621 ,2526,2550,2527 }, - {1044,988,1139 ,2532,2531,2534 }, {7271,7270,7229 ,2554,2555,2556 }, - {3547,3546,3494 ,803,2557,736 }, {2742,2029,2003 ,2558,1748,2542 }, - {539,1194,77 ,2067,393,2544 }, {7139,7161,7138 ,1025,2559,2560 }, - {2005,2031,2742 ,1593,1560,2558 }, {290,334,333 ,1042,1267,1043 }, - {334,431,430 ,1267,1268,2524 }, {333,334,430 ,1043,1267,2524 }, - {431,483,482 ,1268,1228,2525 }, {430,431,482 ,2524,1268,2525 }, - {483,524,523 ,1228,1278,2526 }, {482,483,523 ,2525,1228,2526 }, - {524,623,622 ,1278,1100,2550 }, {523,524,622 ,2526,1278,2550 }, - {623,722,721 ,1100,1052,2528 }, {622,623,721 ,2550,1100,2528 }, - {814,813,721 ,1054,2529,2528 }, {722,814,721 ,1052,1054,2528 }, - {901,900,813 ,1428,2530,2529 }, {814,901,813 ,1054,1428,2529 }, - {901,989,988 ,1428,1813,2531 }, {900,901,988 ,2530,1428,2531 }, - {989,1140,1139 ,1813,1499,2534 }, {988,989,1139 ,2531,1813,2534 }, - {1140,1231,1230 ,1499,1332,2535 }, {1139,1140,1230 ,2534,1499,2535 }, - {1231,1325,1324 ,1332,1331,2536 }, {1230,1231,1324 ,2535,1332,2536 }, - {1402,1401,1324 ,1780,2537,2536 }, {1325,1402,1324 ,1331,1780,2536 }, - {1474,1473,1401 ,1649,2538,2537 }, {1402,1474,1401 ,1780,1649,2537 }, - {1474,1546,1545 ,1649,1360,2539 }, {1473,1474,1545 ,2538,1649,2539 }, - {1546,1615,1614 ,1360,1359,2070 }, {1545,1546,1614 ,2539,1360,2070 }, - {2293,2358,292 ,2561,2562,2563 }, {2292,2293,292 ,1983,2561,2563 }, - {253,966,921 ,2564,2565,1922 }, {7129,7139,7138 ,1026,1025,2560 }, - {406,2408,2219 ,2566,1399,177 }, {8085,8073,973 ,2016,2567,2017 }, - {2421,4056,2420 ,2568,1123,273 }, {3315,1195,5194 ,944,725,727 }, - {247,253,921 ,2569,2564,1922 }, {8143,8123,8128 ,2570,2247,959 }, - {2363,2364,2440 ,2571,2513,2572 }, {2914,2895,2857 ,2573,2574,2575 }, - {2437,2436,2358 ,2576,2577,2562 }, {2928,2927,2883 ,2578,516,2579 }, - {3152,3196,1619 ,2580,2581,1003 }, {2626,2732,2625 ,2582,2583,2584 }, - {3151,3152,1550 ,2585,2580,2586 }, {1479,3151,1550 ,1270,2585,2586 }, - {1550,3152,1619 ,2586,2580,1003 }, {2942,554,2366 ,2587,2588,2589 }, - {2857,2765,2914 ,2575,2590,2573 }, {2880,2881,2924 ,2591,2592,2593 }, - {2840,3250,2875 ,2594,2595,2596 }, {2895,2380,2581 ,2574,2597,2598 }, - {3197,3196,3152 ,2599,2581,2580 }, {2515,2599,2598 ,2600,2601,2602 }, - {2890,2889,2848 ,2603,2604,2605 }, {1010,2890,2848 ,1286,2603,2605 }, - {1630,56,3081 ,1016,2606,1017 }, {2635,2388,2389 ,2607,2608,2609 }, - {2952,2489,2570 ,2610,2611,2612 }, {2430,91,2133 ,2613,1984,2614 }, - {6951,6870,6796 ,2615,2616,2617 }, {2804,2786,1062 ,2618,2619,1232 }, - {2786,2829,1062 ,2619,2620,1232 }, {2879,2878,2846 ,2621,2622,2623 }, - {2847,2879,2846 ,2624,2621,2623 }, {2736,2737,2786 ,2625,2626,2619 }, - {2544,2744,3137 ,2451,2627,2628 }, {1201,1200,1103 ,1477,2629,1474 }, - {2508,2507,388 ,2630,2631,2202 }, {6945,6944,6913 ,2632,2633,2634 }, - {2566,2526,2527 ,2635,2636,2637 }, {2566,2614,2526 ,2635,2638,2636 }, - {2476,1304,2300 ,2441,2639,2640 }, {3357,3356,3323 ,883,872,1051 }, - {1010,2848,925 ,1286,2605,1287 }, {2738,2737,2685 ,2641,2626,2642 }, - {2787,2786,2737 ,2643,2619,2626 }, {2738,2787,2737 ,2641,2643,2626 }, - {2684,2683,2612 ,2644,2645,2646 }, {437,2559,2590 ,1149,2647,2648 }, - {2900,2633,2300 ,2649,2650,2640 }, {3596,3648,3595 ,1792,734,927 }, - {2507,2508,2559 ,2631,2630,2647 }, {2508,2590,2559 ,2630,2648,2647 }, - {630,3317,1377 ,2491,1882,2651 }, {2787,2788,2786 ,2643,2652,2619 }, - {4587,135,2320 ,774,2653,1406 }, {2830,2829,2786 ,2654,2620,2619 }, - {2788,2830,2786 ,2652,2654,2619 }, {2830,2866,1107 ,2654,2655,2656 }, - {2829,2830,1107 ,2620,2654,2656 }, {2684,2737,2683 ,2644,2626,2645 }, - {2737,2736,2683 ,2626,2625,2645 }, {2633,2552,2300 ,2650,2657,2640 }, - {2507,437,388 ,2631,1149,2202 }, {2507,2559,437 ,2631,2647,1149 }, - {6435,6480,6479 ,2658,1524,2659 }, {406,2224,746 ,2566,2660,2661 }, - {2265,2297,2296 ,2662,2663,2664 }, {2613,2612,2526 ,2665,2646,2636 }, - {172,244,534 ,667,606,632 }, {2725,2726,2724 ,2666,2667,2668 }, - {172,2543,244 ,667,2669,606 }, {2833,3981,3075 ,2065,915,2670 }, - {6321,7251,3288 ,706,2671,2058 }, {2583,2629,685 ,2672,2673,2674 }, - {2718,2717,2665 ,2675,2676,2677 }, {549,2522,2609 ,1129,2678,1130 }, - {2769,2847,2846 ,2679,2624,2623 }, {6479,6480,6507 ,2659,1524,2680 }, - {2718,2770,2769 ,2675,2681,2679 }, {6809,6860,6859 ,712,473,472 }, - {4672,5892,5878 ,2682,2683,2684 }, {2343,8097,8061 ,2685,1710,453 }, - {966,3039,1090 ,2565,2686,2687 }, {819,818,726 ,2244,1018,669 }, - {3468,3439,3440 ,2688,2689,2690 }, {2445,448,2518 ,1388,1172,2388 }, - {2717,2718,2769 ,2676,2675,2679 }, {691,647,2609 ,1173,973,1130 }, - {921,966,1090 ,1922,2565,2687 }, {1047,2921,1146 ,1328,2691,2467 }, - {3154,3197,3153 ,2692,2599,2693 }, {978,1030,1077 ,1620,1619,2694 }, - {1479,1407,1480 ,1270,1269,2695 }, {7196,3288,7232 ,2401,2058,2124 }, - {2770,2815,2769 ,2681,2696,2679 }, {5328,2238,5301 ,2172,2697,2698 }, - {589,590,244 ,671,607,606 }, {2543,589,244 ,2669,671,606 }, {649,175,702 ,1579,211,2699 }, - {3180,2967,2385 ,2700,2701,2702 }, {2141,4985,6707 ,2015,2703,2704 }, - {2671,2724,2723 ,2705,2668,2706 }, {2193,2125,2563 ,1007,892,2707 }, - {3700,3746,3745 ,2545,2708,2546 }, {8140,8102,3263 ,2269,253,252 }, - {3019,3058,1407 ,2709,2710,1269 }, {204,271,203 ,1722,1608,2711 }, - {2769,2815,2847 ,2679,2696,2624 }, {2636,5650,5452 ,2712,2713,2714 }, - {2343,1074,8073 ,2685,2715,2567 }, {744,743,691 ,1367,971,1173 }, - {1370,3019,1407 ,1500,2709,1269 }, {2553,171,395 ,2716,921,966 }, - {3236,2792,3269 ,2717,2718,2719 }, {2084,860,953 ,1361,1385,1237 }, - {8076,2810,1295 ,617,1728,618 }, {2637,165,1238 ,2720,1869,1569 }, - {2664,2717,628 ,2721,2676,1177 }, {584,108,1294 ,2512,1336,635 }, - {3122,2543,172 ,2068,2669,667 }, {2543,2897,589 ,2669,2722,671 }, - {2897,442,589 ,2722,673,671 }, {289,332,288 ,1044,2471,2723 }, - {3352,3353,3378 ,2724,2424,1442 }, {1098,2760,1096 ,2725,2726,2727 }, - {292,388,239 ,2563,2202,1103 }, {2129,2131,2130 ,1469,656,1505 }, - {6039,6134,5488 ,2728,2729,2730 }, {4881,4293,4957 ,2731,2732,2733 }, - {1477,1550,1549 ,1045,2586,903 }, {4827,4887,5334 ,2734,2735,2736 }, - {2041,1743,553 ,2737,763,792 }, {3273,2543,3122 ,2738,2669,2068 }, - {3273,2623,2543 ,2738,2739,2669 }, {2623,2404,2897 ,2739,2740,2722 }, - {2543,2623,2897 ,2669,2739,2722 }, {2404,442,2897 ,2740,673,2722 }, - {2515,2514,2442 ,2600,2741,2742 }, {748,2541,241 ,1677,1298,314 }, - {252,966,1158 ,2743,2565,2744 }, {3461,3490,3430 ,1152,2502,1976 }, - {4924,1166,7073 ,2745,2746,662 }, {7074,4924,7073 ,2747,2745,662 }, - {3247,6430,144 ,1494,2748,853 }, {7344,7343,7285 ,2749,2750,2751 }, - {2903,2425,1411 ,2752,2753,850 }, {597,2903,1411 ,791,2752,850 }, - {2425,2759,2041 ,2753,2754,2737 }, {1411,2425,2041 ,850,2753,2737 }, - {2759,2458,1743 ,2754,2755,763 }, {2041,2759,1743 ,2737,2754,763 }, - {3122,2623,3273 ,2068,2739,2738 }, {2404,2479,442 ,2740,2756,673 }, - {2842,310,442 ,2757,674,673 }, {2479,2842,442 ,2756,2757,673 }, - {2842,2694,310 ,2757,811,674 }, {4887,5377,5376 ,2735,361,2758 }, - {3353,3379,3378 ,2424,1979,1442 }, {2728,2727,2676 ,2759,2760,2761 }, - {2870,2528,2367 ,2762,2763,2764 }, {2666,2719,2718 ,2765,2766,2675 }, - {2687,2635,2761 ,2767,2607,2768 }, {2718,2719,2770 ,2675,2766,2681 }, - {1407,1406,1370 ,1269,1135,1500 }, {8092,6531,8120 ,2267,2280,906 }, - {2614,2612,2613 ,2638,2646,2665 }, {3153,3197,3152 ,2693,2599,2580 }, - {2597,2640,2596 ,2769,2770,2771 }, {2372,597,2654 ,2772,791,2773 }, - {2372,2903,597 ,2772,2752,791 }, {2458,2546,3122 ,2755,2774,2068 }, - {1743,2458,3122 ,763,2755,2068 }, {2546,2699,3122 ,2774,2775,2068 }, - {3122,2699,2623 ,2068,2775,2739 }, {2479,2627,2842 ,2756,2776,2757 }, - {2627,2694,2842 ,2776,811,2757 }, {2411,2528,2870 ,2777,2763,2762 }, - {2424,2411,2870 ,2778,2777,2762 }, {2635,3250,2388 ,2607,2595,2608 }, - {2556,2430,2388 ,2779,2613,2608 }, {2931,2979,2978 ,2780,2781,2782 }, - {3136,2372,2654 ,2783,2772,2773 }, {2372,2425,2903 ,2772,2753,2752 }, - {2458,2457,2546 ,2755,2784,2774 }, {2546,2828,2623 ,2774,2785,2739 }, - {2699,2546,2623 ,2775,2774,2739 }, {2854,2703,2479 ,2786,2787,2756 }, - {2404,2854,2479 ,2740,2786,2756 }, {2479,2703,2627 ,2756,2787,2776 }, - {2615,2614,2566 ,2788,2638,2635 }, {198,127,199 ,1392,1395,2789 }, - {3236,3269,2456 ,2717,2719,2790 }, {2649,3114,2536 ,2791,2792,2793 }, - {2687,2761,2857 ,2767,2768,2575 }, {2840,2388,3250 ,2594,2608,2595 }, - {3089,3112,3132 ,2794,2795,2796 }, {3181,2425,2372 ,2797,2753,2772 }, - {2758,2759,2425 ,2798,2754,2753 }, {3181,2758,2425 ,2797,2798,2753 }, - {2758,2457,2458 ,2798,2784,2755 }, {2759,2758,2458 ,2754,2798,2755 }, - {2828,2992,2623 ,2785,2799,2739 }, {2992,2348,2404 ,2799,2800,2740 }, - {2623,2992,2404 ,2739,2799,2740 }, {2404,2348,2854 ,2740,2800,2786 }, - {3513,2582,3404 ,441,873,2170 }, {2739,2738,2685 ,2801,2641,2642 }, - {2705,2739,2685 ,2802,2801,2642 }, {3048,1904,3049 ,2165,2164,2803 }, - {2728,2756,2727 ,2759,2804,2760 }, {3090,3994,3993 ,2805,2806,2807 }, - {3112,3090,3993 ,2795,2805,2807 }, {1840,940,1869 ,198,197,2808 }, - {3128,3169,3127 ,2809,2810,2811 }, {2616,3136,2548 ,2812,2783,2813 }, - {2486,2485,7615 ,2814,2815,2816 }, {2616,2372,3136 ,2812,2772,2783 }, - {2642,2758,3181 ,2817,2798,2797 }, {2288,2642,3181 ,2818,2817,2797 }, - {2758,2642,2457 ,2798,2817,2784 }, {2546,2992,2828 ,2774,2799,2785 }, - {2348,2757,2703 ,2800,2819,2787 }, {2854,2348,2703 ,2786,2800,2787 }, - {2757,2632,2627 ,2819,2820,2776 }, {2703,2757,2627 ,2787,2819,2776 }, - {2627,2689,145 ,2776,2821,810 }, {162,238,100 ,2822,868,2823 }, - {2777,2823,2822 ,2824,2825,2826 }, {2788,2787,2738 ,2652,2643,2641 }, - {2739,2788,2738 ,2801,2652,2641 }, {3069,3070,3111 ,2827,2828,2829 }, - {2780,2779,2727 ,2830,2831,2760 }, {2756,2780,2727 ,2804,2830,2760 }, - {2528,3183,3135 ,2763,2832,2833 }, {2367,2528,3135 ,2764,2763,2833 }, - {2838,2372,2616 ,2834,2772,2812 }, {2838,2996,2372 ,2834,2835,2772 }, - {2288,3181,2372 ,2818,2797,2772 }, {2996,2288,2372 ,2835,2818,2772 }, - {2642,2605,2457 ,2817,2836,2784 }, {2605,3225,2546 ,2836,2837,2774 }, - {2457,2605,2546 ,2784,2836,2774 }, {2546,3225,2992 ,2774,2837,2799 }, - {2348,2574,2757 ,2800,2838,2819 }, {2574,2448,2632 ,2838,2839,2820 }, - {2757,2574,2632 ,2819,2838,2820 }, {2632,2448,2627 ,2820,2839,2776 }, - {2448,2553,2689 ,2839,2716,2821 }, {2627,2448,2689 ,2776,2839,2821 }, - {5698,5699,5726 ,44,43,515 }, {2622,2549,2567 ,2840,2841,2842 }, - {2890,2936,2889 ,2603,2843,2604 }, {2830,2867,2866 ,2654,2844,2655 }, - {2692,3081,56 ,2845,1017,2606 }, {2534,198,199 ,2846,1392,2789 }, - {2764,2839,3142 ,2847,2848,2849 }, {1907,1248,3878 ,1245,2850,1248 }, - {3142,2839,90 ,2849,2848,2851 }, {2344,2554,2702 ,2852,2853,2854 }, - {2401,2995,2702 ,2855,2856,2854 }, {2554,2401,2702 ,2853,2855,2854 }, - {3070,3069,3031 ,2828,2827,2857 }, {3032,3070,3031 ,2858,2828,2857 }, - {2804,1062,929 ,2618,1232,1234 }, {3097,2838,2616 ,2859,2834,2812 }, - {2834,3097,2616 ,2860,2859,2812 }, {3097,2996,2838 ,2859,2835,2834 }, - {2904,2288,2996 ,2861,2818,2835 }, {3097,2904,2996 ,2859,2861,2835 }, - {2606,2642,2288 ,2862,2817,2818 }, {2904,2606,2288 ,2861,2862,2818 }, - {2606,2783,2605 ,2862,2863,2836 }, {2642,2606,2605 ,2817,2862,2836 }, - {2783,2519,3225 ,2863,2864,2837 }, {2605,2783,3225 ,2836,2863,2837 }, - {3225,2519,2992 ,2837,2864,2799 }, {2767,299,2348 ,2865,2866,2800 }, - {2992,2767,2348 ,2799,2865,2800 }, {2348,299,2574 ,2800,2866,2838 }, - {8083,8099,5771 ,2103,2867,2868 }, {2820,2819,2773 ,2869,2870,2871 }, - {369,199,271 ,1521,2789,1608 }, {2152,821,2136 ,1545,2872,1546 }, - {5013,5950,8108 ,684,2873,2287 }, {1285,1135,1226 ,1944,1943,2354 }, - {2205,2222,6563 ,2874,2509,464 }, {2839,2202,90 ,2848,2875,2851 }, - {1249,2488,2617 ,2876,2877,2878 }, {2488,2542,2371 ,2877,2879,2880 }, - {2617,2488,2371 ,2878,2877,2880 }, {2269,2506,2505 ,2881,2882,2883 }, - {3207,3237,3206 ,2884,2885,2886 }, {2736,2786,929 ,2625,2619,1234 }, - {2735,2736,929 ,2887,2625,1234 }, {2855,3097,2834 ,2888,2859,2860 }, - {2519,2766,2992 ,2864,2889,2799 }, {2992,2766,2767 ,2799,2889,2865 }, - {3020,3021,3059 ,2890,2891,2892 }, {2665,2717,2664 ,2677,2676,2721 }, - {2006,2005,2742 ,1181,1593,2558 }, {2633,2656,2584 ,2650,2893,2894 }, - {2656,2331,2584 ,2893,2895,2894 }, {3054,2763,1787 ,916,2896,2897 }, - {2504,2331,2461 ,2898,2895,2899 }, {5914,6098,5191 ,1566,1565,2900 }, - {3236,3237,2792 ,2717,2885,2718 }, {1663,3081,115 ,1015,1017,2901 }, - {2786,2804,929 ,2619,2618,1234 }, {3317,1804,3347 ,1882,2902,2098 }, - {3191,2403,4961 ,2903,2904,2905 }, {2403,2970,2834 ,2904,2906,2860 }, - {2970,2855,2834 ,2906,2888,2860 }, {2855,2904,3097 ,2888,2861,2859 }, - {2783,2520,2519 ,2863,2907,2864 }, {2519,2520,2766 ,2864,2907,2889 }, - {2766,3015,299 ,2889,2908,2866 }, {2767,2766,299 ,2865,2889,2866 }, - {3015,3078,299 ,2908,2909,2866 }, {3078,2752,2574 ,2909,2910,2838 }, - {299,3078,2574 ,2866,2909,2838 }, {2752,2951,2448 ,2910,2911,2839 }, - {2574,2752,2448 ,2838,2910,2839 }, {2951,2378,2553 ,2911,2912,2716 }, - {2448,2951,2553 ,2839,2911,2716 }, {2553,2378,171 ,2716,2912,921 }, - {1687,1686,3196 ,1104,1004,2581 }, {2886,2885,2821 ,2913,2914,2915 }, - {2774,2773,2721 ,2916,2871,2917 }, {2526,2612,2565 ,2636,2646,2918 }, - {2626,2839,2764 ,2582,2848,2847 }, {411,2495,2899 ,2919,2920,2921 }, - {3223,2495,2911 ,2922,2920,2923 }, {2899,2495,3223 ,2921,2920,2922 }, - {2495,2366,2911 ,2920,2589,2923 }, {2911,2366,1336 ,2923,2589,2924 }, - {2371,2656,2633 ,2880,2893,2650 }, {3747,3746,3700 ,2925,2708,2545 }, - {2946,2338,4040 ,1062,458,460 }, {2696,2970,2403 ,2926,2906,2904 }, - {2696,2855,2970 ,2926,2888,2906 }, {2603,2904,2855 ,2927,2861,2888 }, - {2898,2606,2904 ,2928,2862,2861 }, {2603,2898,2904 ,2927,2928,2861 }, - {2898,2784,2783 ,2928,2929,2863 }, {2606,2898,2783 ,2862,2928,2863 }, - {2783,2784,2520 ,2863,2929,2907 }, {2766,3043,3015 ,2889,2930,2908 }, - {3015,3043,3078 ,2908,2930,2909 }, {3043,2712,2752 ,2930,2931,2910 }, - {3078,3043,2752 ,2909,2930,2910 }, {2641,2951,2752 ,2932,2911,2910 }, - {2712,2641,2752 ,2931,2932,2910 }, {2641,2498,2378 ,2932,2933,2912 }, - {2951,2641,2378 ,2911,2932,2912 }, {5681,5699,2453 ,2934,43,42 }, - {2638,2592,2666 ,2935,2936,2765 }, {2526,2565,2525 ,2636,2918,2937 }, - {8116,8109,8119 ,172,2938,184 }, {1088,1452,1592 ,1604,1606,2939 }, - {2820,2884,2883 ,2869,2940,2579 }, {2444,2443,2368 ,2941,2942,2943 }, - {2715,3095,3013 ,2944,2945,2946 }, {3179,2617,2503 ,2947,2878,2948 }, - {2666,2667,2719 ,2765,2949,2766 }, {987,3452,3977 ,2950,1794,440 }, - {3327,1387,3636 ,439,2951,1060 }, {1336,785,2085 ,2924,2952,657 }, - {3061,3101,3100 ,2953,2954,2955 }, {2868,2869,2907 ,1577,1576,111 }, - {3237,3236,3206 ,2885,2717,2886 }, {2165,2696,2403 ,1041,2926,2904 }, - {2969,2855,2696 ,2956,2888,2926 }, {2483,2898,2603 ,2957,2928,2927 }, - {3186,2483,2603 ,2958,2957,2927 }, {3220,2784,2898 ,2959,2929,2928 }, - {2483,3220,2898 ,2957,2959,2928 }, {2784,3220,2520 ,2929,2959,2907 }, - {2520,2917,2766 ,2907,2960,2889 }, {2766,2917,3043 ,2889,2960,2930 }, - {2498,2496,171 ,2933,2961,921 }, {2378,2498,171 ,2912,2933,921 }, - {3264,2301,872 ,2468,2132,2962 }, {2492,493,2496 ,2963,1785,2961 }, - {1390,131,151 ,2964,2965,2966 }, {3215,3013,2354 ,2967,2946,2968 }, - {4240,3796,3797 ,2060,2969,2061 }, {8084,8127,8110 ,1139,2970,1140 }, - {2631,2840,2586 ,2971,2594,2972 }, {2380,2586,2581 ,2597,2972,2598 }, - {2599,2600,2673 ,2601,2973,2974 }, {2600,2674,2673 ,2973,2975,2974 }, - {3596,3595,3545 ,1792,927,926 }, {3595,3594,3544 ,927,2522,1153 }, - {1002,2431,1283 ,2976,2977,2978 }, {2363,2362,2297 ,2571,2979,2663 }, - {2362,2363,2439 ,2979,2571,2980 }, {2363,2440,2439 ,2571,2572,2980 }, - {2440,2512,2439 ,2572,2981,2980 }, {2671,2670,2595 ,2705,2982,2983 }, - {3138,2537,1050 ,2984,2985,2282 }, {2515,2600,2599 ,2600,2973,2601 }, - {3504,3468,3441 ,2986,2688,2987 }, {2166,2947,2696 ,1040,2988,2926 }, - {2165,2166,2696 ,1041,1040,2926 }, {2253,2603,2855 ,2989,2927,2888 }, - {2969,2253,2855 ,2956,2989,2888 }, {2253,3186,2603 ,2989,2958,2927 }, - {3220,2561,2520 ,2959,2990,2907 }, {2561,2562,2520 ,2990,2991,2907 }, - {2520,2562,2917 ,2907,2991,2960 }, {3043,2539,2712 ,2930,2992,2931 }, - {2539,2716,2712 ,2992,2993,2931 }, {2490,2641,2712 ,2994,2932,2931 }, - {2716,2490,2712 ,2993,2994,2931 }, {2490,2498,2641 ,2994,2933,2932 }, - {2845,2844,2800 ,2995,1329,2996 }, {2977,2999,2976 ,2997,2998,2999 }, - {2364,2441,2440 ,2513,3000,2572 }, {111,258,1653 ,1154,3001,106 }, - {4543,4547,4980 ,3002,242,241 }, {2929,2930,2928 ,3003,3004,2578 }, - {2493,2467,1789 ,3005,3006,3007 }, {2434,2400,2545 ,1118,1117,3008 }, - {3492,3491,3461 ,930,955,1152 }, {2673,2674,2700 ,2974,2975,3009 }, - {2653,2964,2131 ,3010,3011,656 }, {3382,3432,3407 ,870,929,3012 }, - {1049,119,2084 ,1362,2278,1361 }, {2570,2489,2298 ,2612,2611,3013 }, - {2723,2722,2669 ,2706,3014,3015 }, {2671,2723,2669 ,2705,2706,3015 }, - {2671,2669,2670 ,2705,3015,2982 }, {4554,6299,1989 ,1307,760,3016 }, - {355,250,301 ,1876,1916,1857 }, {2947,2969,2696 ,2988,2956,2926 }, - {2919,2253,2969 ,3017,2989,2956 }, {2253,2483,3186 ,2989,2957,2958 }, - {3220,2562,2561 ,2959,2991,2990 }, {2562,114,2917 ,2991,3018,2960 }, - {2989,3043,2917 ,3019,2930,2960 }, {114,2989,2917 ,3018,3019,2960 }, - {2989,2539,3043 ,3019,2992,2930 }, {2751,2498,2490 ,3020,2933,2994 }, - {2751,2492,2496 ,3020,2963,2961 }, {2498,2751,2496 ,2933,3020,2961 }, - {3431,3461,3430 ,3021,1152,1976 }, {2133,157,250 ,2614,1877,1916 }, - {925,2848,2802 ,1287,2605,3022 }, {3123,3153,3152 ,3023,2693,2580 }, - {4563,2382,126 ,3024,3025,1394 }, {1047,2877,2921 ,1328,3026,2691 }, - {3212,2942,2366 ,3027,2587,2589 }, {3154,1590,3198 ,2692,3028,1168 }, - {1480,3123,3152 ,2695,3023,2580 }, {2625,2732,2839 ,2584,2583,2848 }, - {2732,3116,2839 ,2583,3029,2848 }, {3462,3461,3431 ,931,1152,3021 }, - {835,8127,4106 ,3030,2970,1742 }, {2862,1984,1917 ,3031,831,833 }, - {2069,2530,1984 ,1711,2389,831 }, {2862,2069,1984 ,3031,1711,831 }, - {1238,1000,1515 ,1569,1384,1502 }, {2570,2298,2963 ,2612,3013,3032 }, - {2537,2677,1050 ,2985,3033,2282 }, {1972,2003,1349 ,3034,2542,2519 }, - {8109,8110,8127 ,2938,1140,2970 }, {2619,2969,2947 ,3035,2956,2988 }, - {2089,2619,2947 ,1325,3035,2988 }, {2619,2919,2969 ,3035,3017,2956 }, - {2253,2491,2483 ,2989,3036,2957 }, {2491,3214,3220 ,3036,3037,2959 }, - {2483,2491,3220 ,2957,3036,2959 }, {3214,2562,3220 ,3037,2991,2959 }, - {2482,2539,2989 ,3038,2992,3019 }, {2858,2873,2492 ,3039,3040,2963 }, - {2751,2858,2492 ,3020,3039,2963 }, {2873,494,2492 ,3040,3041,2963 }, - {6430,3777,5733 ,2748,1582,1584 }, {3228,1725,178 ,3042,1747,3043 }, - {3221,8127,835 ,183,2970,3030 }, {3116,3219,2839 ,3029,3044,2848 }, - {2988,1336,2653 ,3045,2924,3010 }, {2604,2964,2653 ,3046,3011,3010 }, - {2768,221,1553 ,1297,1296,1669 }, {3698,3699,3744 ,2122,2121,2390 }, - {2475,3215,2793 ,3047,2967,3048 }, {3433,3432,3382 ,3049,929,870 }, - {3957,3997,3996 ,295,380,1928 }, {3956,3957,3996 ,1383,295,1928 }, - {2343,8085,8067 ,2685,2016,2168 }, {3432,3462,3431 ,929,931,3021 }, - {1337,1844,1782 ,2148,911,1105 }, {2537,2572,968 ,2985,3050,1661 }, - {2851,2908,2503 ,3051,3052,2948 }, {2908,3179,2503 ,3052,2947,2948 }, - {5681,5659,5660 ,2934,3053,3054 }, {2943,2851,2503 ,3055,3051,2948 }, - {2919,2679,2253 ,3017,3056,2989 }, {2679,2463,2491 ,3056,3057,3036 }, - {2253,2679,2491 ,2989,3056,3036 }, {2463,2398,3214 ,3057,3058,3037 }, - {2491,2463,3214 ,3036,3057,3037 }, {2575,2562,3214 ,3059,2991,3037 }, - {2398,2575,3214 ,3058,3059,3037 }, {2575,114,2562 ,3059,3018,2991 }, - {2482,2989,114 ,3038,3019,3018 }, {2762,2716,2539 ,3060,2993,2992 }, - {2482,2762,2539 ,3038,3060,2992 }, {2762,3280,2716 ,3060,3061,2993 }, - {3092,2490,2716 ,3062,2994,2993 }, {3280,3092,2716 ,3061,3062,2993 }, - {3092,2858,2751 ,3062,3039,3020 }, {2490,3092,2751 ,2994,3062,3020 }, - {3192,3285,6689 ,3063,3064,3065 }, {2383,199,127 ,3066,2789,1395 }, - {4254,4255,4019 ,416,165,227 }, {2316,2383,2382 ,3067,3066,3025 }, - {2315,2316,2382 ,3068,3067,3025 }, {2383,127,2382 ,3066,1395,3025 }, - {4031,2650,2585 ,3069,914,875 }, {2646,2614,2615 ,3070,2638,2788 }, - {2686,2685,2614 ,3071,2642,2638 }, {925,2782,2730 ,1287,3072,2150 }, - {845,943,4970 ,1828,1807,3073 }, {2839,3219,2202 ,2848,3044,2875 }, - {3219,650,2202 ,3044,3074,2875 }, {3432,3431,3407 ,929,3021,3012 }, - {3543,3542,3488 ,3075,979,1980 }, {2576,1665,2967 ,3076,3077,2701 }, - {3745,3746,3744 ,2546,2708,2390 }, {2628,3180,2835 ,3078,2700,3079 }, - {2293,2263,2294 ,2561,3080,3081 }, {3592,3591,3542 ,2084,1652,979 }, - {3543,3592,3542 ,3075,2084,979 }, {1183,155,154 ,1238,1497,1466 }, - {2537,3138,2572 ,2985,2984,3050 }, {2619,2902,2919 ,3035,3082,3017 }, - {2919,2902,2679 ,3017,3082,3056 }, {3044,114,2575 ,3083,3018,3059 }, - {3044,2402,114 ,3083,3084,3018 }, {2402,2482,114 ,3084,3038,3018 }, - {2540,2762,2482 ,3085,3060,3038 }, {2762,2540,3280 ,3060,3085,3061 }, - {2794,3092,3280 ,3086,3062,3061 }, {2540,2794,3280 ,3085,3086,3061 }, - {2492,494,493 ,2963,3041,1785 }, {3904,3958,3903 ,1264,294,296 }, - {3183,219,1855 ,2832,3087,3088 }, {2646,2686,2614 ,3070,3071,2638 }, - {3671,978,1077 ,3089,1620,2694 }, {1304,2431,4377 ,2639,2977,3090 }, - {2686,2705,2685 ,3071,2802,2642 }, {2544,3137,2966 ,2451,2628,3091 }, - {2298,2793,2744 ,3013,3048,2627 }, {925,2802,2782 ,1287,3022,3072 }, - {6348,7253,6349 ,1607,1855,705 }, {3064,3063,3025 ,3092,3093,3094 }, - {1336,2604,2653 ,2924,3046,3010 }, {3026,3064,3025 ,3095,3092,3094 }, - {2628,2576,2967 ,3078,3076,2701 }, {3061,3062,3101 ,2953,3096,2954 }, - {3062,3102,3101 ,3096,3097,2954 }, {3024,3062,3023 ,3098,3096,3099 }, - {3878,106,1156 ,1248,1073,3100 }, {3431,3430,3380 ,3021,1976,1514 }, - {460,1876,1853 ,1999,1386,3101 }, {2619,631,2902 ,3035,1426,3082 }, - {2902,631,2679 ,3082,1426,3056 }, {2402,3044,2575 ,3084,3083,3059 }, - {2916,2482,2402 ,3102,3038,3084 }, {2714,2858,3092 ,3103,3039,3062 }, - {2794,2714,3092 ,3086,3103,3062 }, {3082,2873,2858 ,3104,3040,3039 }, - {2714,3082,2858 ,3103,3104,3039 }, {3495,3434,3496 ,735,737,3105 }, - {2619,2090,631 ,3035,1324,1426 }, {845,4970,760 ,1828,3073,3106 }, - {2131,2865,2201 ,656,3107,2455 }, {2973,3021,2972 ,3108,2891,2047 }, - {4614,4613,4590 ,3109,1488,1490 }, {2594,2593,2511 ,3110,3111,3112 }, - {3062,3061,3023 ,3096,2953,3099 }, {3215,2354,2426 ,2967,2968,3113 }, - {2354,3013,3173 ,2968,2946,3114 }, {2793,3215,2426 ,3048,2967,3113 }, - {2924,2925,2974 ,2593,3115,3116 }, {2744,2793,3193 ,2627,3048,3117 }, - {631,2944,2679 ,1426,3118,3056 }, {2395,2463,2679 ,3119,3057,3056 }, - {2480,2398,2463 ,3120,3058,3057 }, {2395,2480,2463 ,3119,3120,3057 }, - {2398,2480,2575 ,3058,3120,3059 }, {2575,3174,2402 ,3059,3121,3084 }, - {2289,2482,2916 ,3122,3038,3102 }, {2482,2289,2540 ,3038,3122,3085 }, - {2836,2873,3082 ,3123,3040,3104 }, {1806,494,2873 ,3124,3041,3040 }, - {2836,1806,2873 ,3123,3124,3040 }, {494,1806,802 ,3041,3124,400 }, - {3890,3926,3889 ,1913,3125,3126 }, {6434,6435,6479 ,3127,2658,2659 }, - {4576,7524,4575 ,1628,1630,3128 }, {203,2383,2316 ,2711,3066,3067 }, - {2317,203,2316 ,3129,2711,3067 }, {270,199,2383 ,3130,2789,3066 }, - {203,270,2383 ,2711,3130,3066 }, {2609,790,744 ,1130,1339,1367 }, - {3011,2624,2914 ,3131,3132,2573 }, {6707,6643,8101 ,2704,3133,383 }, - {3149,2537,3143 ,3134,2985,3135 }, {3064,3104,3063 ,3092,3136,3093 }, - {3104,3103,3063 ,3136,3137,3093 }, {2152,391,821 ,1545,1647,2872 }, - {2669,2668,2593 ,3015,3138,3111 }, {2576,795,1665 ,3076,302,3077 }, - {3193,2630,2894 ,3117,3139,3140 }, {2628,2967,3180 ,3078,2701,2700 }, - {3193,2793,2630 ,3117,3048,3139 }, {2570,2963,2544 ,2612,3032,2451 }, - {2341,8064,3008 ,845,3141,546 }, {4212,4213,294 ,895,1070,945 }, - {928,830,929 ,1997,1996,1234 }, {2644,2944,631 ,3142,3118,1426 }, - {2478,2644,631 ,3143,3142,1426 }, {2644,2679,2944 ,3142,3056,3118 }, - {2396,2395,2679 ,3144,3119,3056 }, {2644,2396,2679 ,3142,3144,3056 }, - {2312,2339,2575 ,3145,3146,3059 }, {2480,2312,2575 ,3120,3145,3059 }, - {2575,2339,3174 ,3059,3146,3121 }, {2339,2648,2402 ,3146,3147,3084 }, - {3174,2339,2402 ,3121,3146,3084 }, {2916,3115,2289 ,3102,3148,3122 }, - {3077,2794,2540 ,3149,3086,3085 }, {2289,3077,2540 ,3122,3149,3085 }, - {2347,2714,2794 ,3150,3103,3086 }, {3077,2347,2794 ,3149,3150,3086 }, - {2836,3082,2714 ,3123,3104,3103 }, {2347,2836,2714 ,3150,3123,3103 }, - {3496,3434,3464 ,3105,737,3151 }, {2316,2275,2317 ,3067,3152,3129 }, - {1165,4831,3472 ,3153,3154,3155 }, {2293,2294,2358 ,2561,3081,2562 }, - {3489,3543,3488 ,1977,3075,1980 }, {2544,2966,2622 ,2451,3091,2840 }, - {6796,8063,8136 ,2617,465,2449 }, {2669,2667,2668 ,3015,2949,3138 }, - {2818,2882,2881 ,3156,518,2592 }, {2882,2926,2925 ,518,517,3115 }, - {2881,2882,2925 ,2592,518,3115 }, {1550,1477,1479 ,2586,1045,1270 }, - {953,1048,2084 ,1237,1236,1361 }, {2926,2975,2974 ,517,3157,3116 }, - {2975,2997,2974 ,3157,3158,3116 }, {2925,2926,2974 ,3115,517,3116 }, - {3155,1552,3100 ,3159,2266,2955 }, {3101,3155,3100 ,2954,3159,2955 }, - {2295,2296,2360 ,3160,2664,3161 }, {3024,3023,2997 ,3098,3099,3158 }, - {2511,2510,2438 ,3112,3162,3163 }, {2975,3024,2997 ,3157,3098,3158 }, - {3156,3155,3101 ,3164,3159,2954 }, {3137,3193,2894 ,2628,3117,3140 }, - {2312,2480,2395 ,3145,3120,3119 }, {2396,2312,2395 ,3144,3145,3119 }, - {2648,2806,2916 ,3147,3165,3102 }, {2402,2648,2916 ,3084,3147,3102 }, - {2916,2806,3115 ,3102,3165,3148 }, {2377,2347,3077 ,3166,3150,3149 }, - {3042,2377,3077 ,3167,3166,3149 }, {2355,1806,2836 ,3168,3124,3123 }, - {3490,3489,3430 ,2502,1977,1976 }, {1923,211,459 ,418,415,696 }, - {1145,1146,1236 ,1277,2467,1434 }, {1187,1367,1919 ,1778,574,1779 }, - {2597,2596,2512 ,2769,2771,2981 }, {2691,2353,2570 ,3169,3170,2612 }, - {3149,3143,968 ,3134,3135,1661 }, {5616,5615,3274 ,646,3171,3172 }, - {2721,2720,2667 ,2917,3173,2949 }, {2669,2721,2667 ,3015,2917,2949 }, - {2817,2818,2881 ,3174,3156,2592 }, {6968,7027,7008 ,595,3175,3176 }, - {3277,8066,8098 ,961,960,907 }, {3155,3156,1552 ,3159,3164,2266 }, - {2438,2437,2360 ,3163,2576,3161 }, {2361,2438,2360 ,3177,3163,3161 }, - {2667,2720,2719 ,2949,3173,2766 }, {3137,2744,3193 ,2628,2627,3117 }, - {119,460,2084 ,2278,1999,1361 }, {1443,5616,3274 ,182,646,3172 }, - {2135,2136,2478 ,1425,1546,3143 }, {2648,298,2806 ,3147,3178,3165 }, - {2806,2860,2289 ,3165,3179,3122 }, {3115,2806,2289 ,3148,3165,3122 }, - {2466,3042,3077 ,3180,3167,3149 }, {2289,2466,3077 ,3122,3180,3149 }, - {2377,2355,2836 ,3166,3168,3123 }, {2347,2377,2836 ,3150,3166,3123 }, - {2355,2465,1806 ,3168,3181,3124 }, {3041,1860,3618 ,3182,3183,37 }, - {553,1743,1727 ,792,763,793 }, {6388,6435,6434 ,3184,2658,3127 }, - {204,203,2317 ,1722,2711,3129 }, {2318,204,2317 ,3185,1722,3129 }, - {5191,6388,6434 ,2900,3184,3127 }, {3228,178,2532 ,3042,3043,3186 }, - {1107,2866,1205 ,2656,2655,3187 }, {3260,3149,968 ,3188,3134,1661 }, - {2909,2911,2678 ,3189,2923,3190 }, {2777,2801,2776 ,2824,3191,3192 }, - {3104,3158,3157 ,3136,3193,3194 }, {2963,2744,2544 ,3032,2627,2451 }, - {1657,1725,3228 ,1781,1747,3042 }, {2874,2628,2386 ,3195,3078,3196 }, - {2818,2817,2771 ,3156,3174,3197 }, {2772,2818,2771 ,3198,3156,3197 }, - {2136,1512,2478 ,1546,3199,3143 }, {3246,2644,2478 ,3200,3142,3143 }, - {1512,3246,2478 ,3199,3200,3143 }, {2399,2396,2644 ,3201,3144,3142 }, - {2399,2529,2312 ,3201,3202,3145 }, {2396,2399,2312 ,3144,3201,3145 }, - {2312,2529,2339 ,3145,3202,3146 }, {3245,298,2648 ,3203,3178,3147 }, - {2339,3245,2648 ,3146,3203,3147 }, {2860,2753,2289 ,3179,456,3122 }, - {2289,2753,2466 ,3122,456,3180 }, {110,111,226 ,743,1154,108 }, - {2590,2589,437 ,2648,3204,1149 }, {5390,5037,6317 ,3205,3206,3207 }, - {2521,2533,2506 ,3208,3209,2882 }, {2867,2940,1205 ,2844,110,3187 }, - {2011,3001,5615 ,129,3210,3171 }, {1208,1668,1942 ,3211,3212,2337 }, - {1687,1740,1782 ,1104,3213,1105 }, {2966,3137,2894 ,3091,2628,3140 }, - {3060,3061,3100 ,3214,2953,2955 }, {2779,2778,2727 ,2831,3215,2760 }, - {165,1373,341 ,1869,1501,1852 }, {787,802,4130 ,209,400,210 }, - {3173,2385,2434 ,3114,2702,1118 }, {2385,2433,2434 ,2702,1116,1118 }, - {2011,3913,3001 ,129,841,3210 }, {2296,2361,2360 ,2664,3177,3161 }, - {2720,2772,2771 ,3173,3198,3197 }, {2719,2720,2771 ,2766,3173,3197 }, - {2883,2882,2818 ,2579,518,3156 }, {2386,2628,2835 ,3196,3078,3079 }, - {2549,2894,2370 ,2841,3140,3216 }, {3102,3156,3101 ,3097,3164,2954 }, - {2266,3246,1512 ,3217,3200,3199 }, {821,2266,1512 ,2872,3217,3199 }, - {2266,2644,3246 ,3217,3142,3200 }, {2414,2399,2644 ,3218,3201,3142 }, - {2266,2414,2644 ,3217,3218,3142 }, {2414,2299,2529 ,3218,3219,3202 }, - {2399,2414,2529 ,3201,3218,3202 }, {2299,2447,2339 ,3219,3220,3146 }, - {2529,2299,2339 ,3202,3219,3146 }, {2339,2447,3245 ,3146,3220,3203 }, - {2447,2446,298 ,3220,3221,3178 }, {3245,2447,298 ,3203,3220,3178 }, - {2806,2753,2860 ,3165,456,3179 }, {2753,2538,3042 ,456,3222,3167 }, - {2466,2753,3042 ,3180,456,3167 }, {3119,2377,3042 ,3223,3166,3167 }, - {2538,3119,3042 ,3222,3223,3167 }, {3119,2747,2355 ,3223,3224,3168 }, - {2377,3119,2355 ,3166,3223,3168 }, {2355,2747,2465 ,3168,3224,3181 }, - {3970,3969,3925 ,3225,3226,3227 }, {2319,204,2318 ,3228,1722,3185 }, - {1211,2255,2697 ,2007,3229,2006 }, {2489,2715,2475 ,2611,2944,3047 }, - {2506,2533,2805 ,2882,3209,3230 }, {3990,3299,3254 ,3231,3232,3233 }, - {2602,2675,2600 ,3234,3235,2973 }, {2417,2874,2386 ,3236,3195,3196 }, - {2427,2379,2677 ,3237,3238,3033 }, {286,287,331 ,2446,2470,2403 }, - {2624,2949,3405 ,3132,3239,1798 }, {3429,3460,3459 ,1978,3240,3241 }, - {2886,2863,2931 ,2913,3242,2780 }, {2863,2932,2931 ,3242,3243,2780 }, - {2512,2511,2438 ,2981,3112,3163 }, {593,4223,1599 ,1108,1934,391 }, - {3199,1726,1658 ,3244,1746,1782 }, {2511,2512,2595 ,3112,2981,2983 }, - {2510,2593,2592 ,3162,3111,2936 }, {2532,1874,1337 ,3186,962,2148 }, - {2549,2370,2567 ,2841,3216,2842 }, {2038,1983,1984 ,1551,1001,831 }, - {2963,2298,2744 ,3032,3013,2627 }, {2819,2883,2818 ,2870,2579,3156 }, - {2475,3013,3215 ,3047,2946,2967 }, {2462,2413,2417 ,3245,3246,3236 }, - {2413,2900,2417 ,3246,2649,3236 }, {2715,2462,2417 ,2944,3245,3236 }, - {2900,2551,2874 ,2649,3247,3195 }, {1304,1255,2576 ,2639,3248,3076 }, - {2551,2576,3175 ,3247,3076,3249 }, {2551,1304,2576 ,3247,2639,3076 }, - {5616,2011,5615 ,646,129,3171 }, {2446,2849,2806 ,3221,3250,3165 }, - {298,2446,2806 ,3178,3221,3165 }, {2849,3144,2806 ,3250,3251,3165 }, - {2806,3144,2753 ,3165,3251,456 }, {2346,3119,2538 ,3252,3223,3222 }, - {2573,2346,2538 ,3253,3252,3222 }, {2747,2681,2465 ,3224,3254,3181 }, - {8118,1218,8126 ,2129,3255,812 }, {135,204,2319 ,2653,1722,3228 }, - {2320,135,2319 ,1406,2653,3228 }, {135,205,204 ,2653,1741,1722 }, - {8138,4106,8078 ,2018,1742,1744 }, {135,273,205 ,2653,1749,1741 }, - {3913,4248,3001 ,841,3256,3210 }, {2369,2445,2368 ,3257,1388,2943 }, - {2351,3149,2201 ,3258,3134,2455 }, {2588,2449,2556 ,2072,3259,2779 }, - {6911,6912,6942 ,474,519,521 }, {6943,6963,6962 ,520,1048,3260 }, - {3428,3429,3459 ,3261,1978,3241 }, {788,1390,3091 ,976,2964,3262 }, - {3260,968,2201 ,3188,1661,2455 }, {3325,3359,3305 ,825,824,879 }, - {2417,2386,2715 ,3236,3196,2944 }, {3199,1658,3156 ,3244,1782,3164 }, - {2439,2512,2438 ,2980,2981,3163 }, {6531,6897,8134 ,2280,54,3263 }, - {2354,3173,2434 ,2968,3114,1118 }, {3103,3104,3157 ,3137,3136,3194 }, - {2622,2966,2894 ,2840,3091,3140 }, {795,456,1665 ,302,301,3077 }, - {336,291,236 ,1013,1012,2444 }, {2356,2909,1785 ,3264,3189,1659 }, - {3267,2356,1785 ,3265,3264,1659 }, {3267,1785,1726 ,3265,1659,1746 }, - {3229,3267,1726 ,3266,3265,1746 }, {5346,5364,5363 ,3267,3268,3269 }, - {2754,2349,2849 ,3270,457,3250 }, {2446,2754,2849 ,3221,3270,3250 }, - {2849,2349,3144 ,3250,457,3251 }, {3144,2349,2753 ,3251,457,456 }, - {2811,2573,2538 ,3271,3253,3222 }, {2753,2811,2538 ,456,3271,3222 }, - {2792,2732,2626 ,2718,2583,2582 }, {8062,8065,8090 ,3272,96,412 }, - {2445,2481,2444 ,1388,3273,2941 }, {2822,2886,2821 ,2826,2913,2915 }, - {3212,2587,2942 ,3027,3274,2587 }, {1383,788,3091 ,336,976,3262 }, - {2932,2979,2931 ,3243,2781,2780 }, {2943,2503,2691 ,3055,2948,3169 }, - {2617,2852,2647 ,2878,3275,3276 }, {4571,972,2162 ,1342,3277,3278 }, - {3158,3200,3199 ,3193,3279,3244 }, {3157,3158,3199 ,3194,3193,3244 }, - {2653,2129,2069 ,3010,1469,1711 }, {2900,2874,2417 ,2649,3195,3236 }, - {2678,2911,1917 ,3190,2923,833 }, {2911,1336,2988 ,2923,2924,3045 }, - {821,3185,2266 ,2872,3280,3217 }, {3005,2414,2266 ,3281,3218,3217 }, - {3272,2754,2446 ,3282,3270,3221 }, {2447,3272,2446 ,3220,3282,3221 }, - {2349,890,2660 ,457,3283,455 }, {2753,2660,2811 ,456,455,3271 }, - {2380,2895,2914 ,2597,2574,2573 }, {2370,1482,227 ,3216,2265,2157 }, - {270,203,271 ,3130,2711,1608 }, {3134,3135,1855 ,3284,2833,3088 }, - {2367,3135,3134 ,2764,2833,3284 }, {643,2676,2602 ,3285,2761,3234 }, - {2760,2749,1096 ,2726,3286,2727 }, {4395,4347,4373 ,726,3287,3288 }, - {2807,2555,2545 ,3289,1066,3008 }, {329,2393,330 ,2348,2445,2402 }, - {3293,3291,7151 ,1988,1203,1202 }, {3089,3088,3048 ,2794,3290,2165 }, - {3049,3089,3048 ,2803,2794,2165 }, {554,2569,2366 ,2588,3291,2589 }, - {554,2268,2085 ,2588,3292,657 }, {3013,3095,3173 ,2946,2945,3114 }, - {2894,2630,2370 ,3140,3139,3216 }, {3231,411,2356 ,3293,2919,3264 }, - {3230,3231,2356 ,3294,3293,3264 }, {3199,3200,3229 ,3244,3279,3266 }, - {3200,3230,3229 ,3279,3294,3266 }, {2653,2069,2862 ,3010,1711,3031 }, - {2462,2715,2489 ,3245,2944,2611 }, {3157,3199,3156 ,3194,3244,3164 }, - {1725,1784,178 ,1747,1662,3043 }, {2031,2067,2006 ,1560,1592,1181 }, - {2551,3175,2874 ,3247,3249,3195 }, {8080,8069,8141 ,1094,1095,3295 }, - {1917,2911,2988 ,833,2923,3045 }, {3159,3158,3104 ,3296,3193,3136 }, - {3105,3159,3104 ,3297,3296,3136 }, {3065,3064,3026 ,3298,3092,3095 }, - {2464,840,1697 ,3299,68,69 }, {1088,3185,821 ,1604,3280,2872 }, - {1088,821,391 ,1604,2872,1647 }, {1088,2266,3185 ,1604,3217,3280 }, - {2309,3005,2266 ,3300,3281,3217 }, {1088,2309,2266 ,1604,3300,3217 }, - {3005,2309,2414 ,3281,3300,3218 }, {2309,2734,2299 ,3300,3301,3219 }, - {2414,2309,2299 ,3218,3300,3219 }, {2734,2311,2447 ,3301,3302,3220 }, - {2299,2734,2447 ,3219,3301,3220 }, {2447,2311,3272 ,3220,3302,3282 }, - {3272,2311,2754 ,3282,3302,3270 }, {2811,2660,2573 ,3271,455,3253 }, - {2591,2592,2638 ,3303,2936,2935 }, {2380,2914,2624 ,2597,2573,3132 }, - {2895,2581,2857 ,2574,2598,2575 }, {2930,2931,2977 ,3004,2780,2997 }, - {3000,3031,2980 ,3304,2857,3305 }, {3165,3207,3164 ,3306,2884,3307 }, - {2587,3256,554 ,3274,3308,2588 }, {2821,2885,2820 ,2915,2914,2869 }, - {3673,4185,52 ,648,409,411 }, {2949,2624,3011 ,3239,3132,3131 }, - {3429,3488,3460 ,1978,1980,3240 }, {2726,2777,2776 ,2667,2824,3192 }, - {5284,5338,5337 ,571,63,572 }, {4904,5377,4887 ,3309,361,2735 }, - {368,2534,369 ,1396,2846,1521 }, {3102,3103,3156 ,3097,3137,3164 }, - {2411,3081,2692 ,2777,1017,2845 }, {2936,2935,2889 ,2843,3310,2604 }, - {5284,5283,5239 ,571,570,482 }, {2268,2132,2085 ,3292,655,657 }, - {2979,3029,2978 ,2781,3311,2782 }, {2617,2647,2353 ,2878,3276,3170 }, - {78,2302,2495 ,3312,3313,2920 }, {2503,2617,2353 ,2948,2878,3170 }, - {3204,3234,3233 ,3314,3315,3316 }, {2302,2741,2495 ,3313,3317,2920 }, - {3162,3204,3203 ,3318,3314,3319 }, {3161,3162,3203 ,3320,3318,3319 }, - {3268,2302,3233 ,3321,3313,3316 }, {3234,3268,3233 ,3315,3321,3316 }, - {2302,2332,2741 ,3313,3322,3317 }, {3160,3161,3202 ,3323,3320,3324 }, - {3203,3233,3232 ,3319,3316,3325 }, {3107,3161,3140 ,3326,3320,3327 }, - {3161,3203,3202 ,3320,3319,3324 }, {3200,3201,3230 ,3279,3328,3294 }, - {2988,2653,2862 ,3045,3010,3031 }, {860,460,1853 ,1385,1999,3101 }, - {2508,2509,2592 ,2630,3329,2936 }, {840,2464,3450 ,68,3299,3330 }, - {2597,2673,2672 ,2769,2974,3331 }, {2311,2750,2754 ,3302,3332,3270 }, - {2750,890,2349 ,3332,3283,457 }, {2754,2750,2349 ,3270,3332,457 }, - {254,109,4036 ,2008,1654,1602 }, {687,1155,831 ,1665,3333,3334 }, - {546,2602,2560 ,1171,3234,3335 }, {2497,2132,2268 ,3336,655,3292 }, - {5264,5284,5239 ,1192,571,482 }, {8094,8088,8100 ,98,1998,1713 }, - {4041,2946,4040 ,1063,1062,460 }, {2456,2792,2626 ,2790,2718,2582 }, - {3207,3206,3164 ,2884,2886,3307 }, {3111,3165,3110 ,2829,3306,3337 }, - {486,437,529 ,1144,1149,1148 }, {2971,3019,1370 ,3338,2709,1500 }, - {2683,2736,2735 ,2645,2625,2887 }, {2704,2683,2735 ,3339,2645,2887 }, - {2730,741,827 ,2150,1221,1220 }, {220,131,8 ,3340,2965,3341 }, - {8093,8078,8076 ,2288,1744,617 }, {2801,2777,2822 ,3191,2824,2826 }, - {2675,2727,2674 ,3235,2760,2975 }, {3232,3233,78 ,3325,3316,3312 }, - {3233,2302,78 ,3316,3313,3312 }, {3203,3204,3233 ,3319,3314,3316 }, - {2445,2444,2368 ,1388,2941,2943 }, {6804,6805,6854 ,3342,3343,3344 }, - {5276,5330,5350 ,1525,3345,1526 }, {1294,108,874 ,635,1336,636 }, - {3684,3422,3664 ,1915,2055,1557 }, {554,90,2987 ,2588,2851,3346 }, - {90,2269,2987 ,2851,2881,3346 }, {3161,3160,3140 ,3320,3323,3327 }, - {3201,3200,3158 ,3328,3279,3193 }, {3159,3201,3158 ,3296,3328,3193 }, - {2630,2948,1482 ,3139,3347,2265 }, {2630,2577,2948 ,3139,3348,3347 }, - {2630,2853,2577 ,3139,806,3348 }, {2977,3028,3027 ,2997,3349,3350 }, - {2817,2881,2880 ,3174,2592,2591 }, {3105,3104,3064 ,3297,3136,3092 }, - {3065,3105,3064 ,3298,3297,3092 }, {2365,2441,2364 ,3351,3000,2513 }, - {3029,3066,3065 ,3311,3352,3298 }, {3028,3029,3065 ,3349,3311,3298 }, - {2978,3029,3028 ,2782,3311,3349 }, {2977,2978,3028 ,2997,2782,3349 }, - {2311,2419,2750 ,3302,3353,3332 }, {787,494,802 ,209,3041,400 }, - {2750,2419,890 ,3332,3353,3283 }, {1211,3636,939 ,2007,1060,3354 }, - {3636,1453,939 ,1060,3355,3354 }, {3487,3541,3540 ,3356,981,3357 }, - {221,2541,748 ,1296,1298,1677 }, {2532,1337,3226 ,3186,2148,3358 }, - {2263,2293,2262 ,3080,2561,3359 }, {3206,3236,3205 ,2886,2717,3360 }, - {3206,3205,3163 ,2886,3360,3361 }, {3165,3164,3110 ,3306,3307,3337 }, - {3036,3074,3035 ,3362,3363,3364 }, {2665,2664,2590 ,2677,2721,2648 }, - {1146,2921,1237 ,2467,2691,1467 }, {1237,2971,1370 ,1467,3338,1500 }, - {2930,2977,2928 ,3004,2997,2578 }, {3994,4036,4035 ,2806,1602,1601 }, - {3283,1556,2968 ,262,3365,263 }, {3182,2536,49 ,3366,2793,3367 }, - {2536,1015,3017 ,2793,3368,3369 }, {2533,2536,3182 ,3209,2793,3366 }, - {2535,2536,2533 ,3370,2793,3209 }, {2649,2536,2535 ,2791,2793,3370 }, - {2597,2672,2671 ,2769,3331,2705 }, {3227,3226,3198 ,1167,3358,1168 }, - {3067,3066,3029 ,3371,3352,3311 }, {3046,3067,3029 ,3372,3371,3311 }, - {3202,3203,3232 ,3324,3319,3325 }, {2781,2780,2756 ,3373,2830,2804 }, - {2729,2728,2676 ,3374,2759,2761 }, {2701,2729,2676 ,3375,3374,2761 }, - {2729,2756,2728 ,3374,2804,2759 }, {8087,8145,6797 ,385,3376,2246 }, - {2879,2923,2922 ,2621,2046,2045 }, {2878,2879,2922 ,2622,2621,2045 }, - {3209,3239,3238 ,3377,3378,3379 }, {199,270,271 ,2789,3130,1608 }, - {3066,3107,3106 ,3352,3326,3380 }, {3085,3066,3106 ,3381,3352,3380 }, - {1071,3661,2455 ,3382,789,475 }, {2822,2821,2776 ,2826,2915,3192 }, - {3027,3065,3026 ,3350,3298,3095 }, {3605,3604,3556 ,3383,3384,3385 }, - {1011,2864,1010 ,1285,3386,1286 }, {1688,451,134 ,1718,3387,1783 }, - {1592,1056,2309 ,2939,3388,3300 }, {1088,1592,2309 ,1604,2939,3300 }, - {2918,2734,2309 ,3389,3301,3300 }, {1056,2918,2309 ,3388,3389,3300 }, - {2918,2412,2311 ,3389,3390,3302 }, {2734,2918,2311 ,3301,3389,3302 }, - {2311,2412,2419 ,3302,3390,3353 }, {2840,2875,2687 ,2594,2596,2767 }, - {2629,2494,794 ,2673,3391,3392 }, {2637,1373,165 ,2720,1501,1869 }, - {3061,3060,3022 ,2953,3214,3393 }, {3236,3235,3205 ,2717,3394,3360 }, - {2565,2612,2524 ,2918,2646,3395 }, {2424,2870,2367 ,2778,2762,2764 }, - {3744,3746,3796 ,2390,2708,2969 }, {2905,2424,2367 ,399,2778,2764 }, - {2931,2930,2885 ,2780,3004,2914 }, {3169,3168,3127 ,2810,3396,2811 }, - {5363,6260,5346 ,3269,3397,3267 }, {2601,2600,2517 ,3398,2973,3399 }, - {2727,2778,2755 ,2760,3215,3400 }, {2597,2598,2673 ,2769,2602,2974 }, - {819,2769,2846 ,2244,2679,2623 }, {2436,2435,2358 ,2577,3401,2562 }, - {2729,2781,2756 ,3374,3373,2804 }, {2698,3187,4248 ,105,3402,3256 }, - {3065,3066,3085 ,3298,3352,3381 }, {2297,2362,2361 ,2663,2979,3177 }, - {3072,3125,3071 ,3403,3404,3405 }, {2999,2977,3027 ,2998,2997,3350 }, - {2359,2437,2358 ,3406,2576,2562 }, {2427,3117,2379 ,3237,3407,3238 }, - {6748,6757,1990 ,3408,3409,1305 }, {2581,2687,2857 ,2598,2767,2575 }, - {455,410,1665 ,2205,2204,3077 }, {2155,5444,2157 ,580,3410,3411 }, - {2443,2515,2442 ,2942,2600,2742 }, {2987,2497,2268 ,3346,3336,3292 }, - {2125,2193,2124 ,892,1007,1006 }, {3129,3086,3130 ,3412,3413,3414 }, - {1346,1806,2465 ,484,3124,3181 }, {2525,2565,2524 ,2937,2918,3395 }, - {2801,2822,2776 ,3191,2826,3192 }, {1740,1337,1782 ,3213,2148,1105 }, - {3405,2949,2920 ,1798,3239,1799 }, {2629,2583,2461 ,2673,2672,2899 }, - {2675,2674,2600 ,3235,2975,2973 }, {3108,3107,3066 ,3415,3326,3352 }, - {3067,3108,3066 ,3371,3415,3352 }, {2488,2693,2542 ,2877,3416,2879 }, - {2673,2725,2724 ,2974,2666,2668 }, {3256,90,554 ,3308,2851,2588 }, - {3011,2914,2965 ,3131,2573,3417 }, {7250,7233,3288 ,3418,2125,2058 }, - {1479,1480,3151 ,1270,2695,2585 }, {1480,3152,3151 ,2695,2580,2585 }, - {2884,2929,2928 ,2940,3003,2578 }, {2296,2297,2361 ,2664,2663,3177 }, - {2672,2673,2671 ,3331,2974,2705 }, {3742,3793,3792 ,3419,3420,3421 }, - {6742,4784,3192 ,3422,3423,3063 }, {3228,3227,1656 ,3042,1167,1166 }, - {2694,145,60 ,811,810,675 }, {2652,2918,1056 ,3424,3389,3388 }, - {2652,2745,2412 ,3424,3425,3390 }, {2918,2652,2412 ,3389,3424,3390 }, - {2412,2420,2419 ,3390,273,3353 }, {2513,2512,2440 ,3426,2981,2572 }, - {5166,6257,5473 ,3427,3428,3429 }, {219,3195,1855 ,3087,3430,3088 }, - {199,369,2534 ,2789,1521,2846 }, {2823,2863,2822 ,2825,3242,2826 }, - {2825,2824,2778 ,3431,3432,3215 }, {4256,4275,4255 ,3433,699,165 }, - {2555,2807,2416 ,1066,3289,808 }, {2915,2631,2711 ,3434,2971,3435 }, - {2525,2524,2485 ,2937,3395,2815 }, {4216,4256,4255 ,1241,3433,165 }, - {4215,4216,4255 ,370,1241,165 }, {2612,2611,2524 ,2646,3436,3395 }, - {4548,3247,2252 ,589,1494,590 }, {2779,2825,2778 ,2831,3431,3215 }, - {2294,2359,2358 ,3081,3406,2562 }, {2925,2924,2881 ,3115,2593,2592 }, - {3162,3161,3107 ,3318,3320,3326 }, {3108,3162,3107 ,3415,3318,3326 }, - {2693,2494,2542 ,3416,3391,2879 }, {6349,7252,6321 ,705,3437,706 }, - {2577,2416,2710 ,3348,808,3438 }, {4190,1265,1271 ,3439,1273,588 }, - {6416,6418,5089 ,3440,3441,3442 }, {2841,2521,2506 ,3443,3208,2882 }, - {2597,2671,2640 ,2769,2705,2770 }, {818,819,2800 ,1018,2244,2996 }, - {2450,3192,6689 ,3444,3063,3065 }, {2802,2827,2781 ,3022,3445,3373 }, - {2802,2848,2827 ,3022,2605,3445 }, {2497,2506,2344 ,3336,2882,2852 }, - {2702,2427,3149 ,2854,3237,3134 }, {2998,3025,2975 ,3446,3094,3157 }, - {3741,3742,3792 ,3447,3419,3421 }, {3744,3795,3794 ,2390,3448,3449 }, - {2782,2802,2781 ,3072,3022,3373 }, {31,2859,2652 ,3450,3451,3424 }, - {1056,1592,1004 ,3388,2939,3452 }, {2859,2695,2745 ,3451,3453,3425 }, - {2652,2859,2745 ,3424,3451,3425 }, {2745,2695,2412 ,3425,3453,3390 }, - {2695,2421,2420 ,3453,2568,273 }, {2412,2695,2420 ,3390,3453,273 }, - {3742,3743,3793 ,3419,2225,3420 }, {3324,3357,3323 ,881,883,1051 }, - {3743,3794,3793 ,2225,3449,3420 }, {1549,1550,1619 ,903,2586,1003 }, - {287,288,332 ,2470,2723,2471 }, {3269,2792,2456 ,2719,2718,2790 }, - {8114,5950,8108 ,2286,2873,2287 }, {2710,2416,2631 ,3438,808,2971 }, - {3166,3209,3208 ,3454,3377,3455 }, {2740,2739,2705 ,3456,2801,2802 }, - {2686,2740,2705 ,3071,3456,2802 }, {503,1633,466 ,374,373,347 }, - {1032,193,867 ,1581,1448,1121 }, {2985,3036,2984 ,3457,3362,3458 }, - {2740,2788,2739 ,3456,2652,2801 }, {7287,7286,7239 ,3459,3460,1527 }, - {2506,2805,2554 ,2882,3230,2853 }, {2437,2510,2509 ,2576,3162,3329 }, - {2436,2437,2509 ,2577,2576,3329 }, {2567,2370,227 ,2842,3216,2157 }, - {2413,2387,2900 ,3246,3461,2649 }, {2367,3134,3116 ,2764,3284,3029 }, - {2387,2633,2900 ,3461,2650,2649 }, {3824,8131,8133 ,3462,2307,2131 }, - {3954,8062,4957 ,3463,3272,2733 }, {2677,2379,886 ,3033,3238,3464 }, - {2445,2517,2481 ,1388,3399,3273 }, {2681,2464,2465 ,3254,3299,3181 }, - {2505,2506,2497 ,2883,2882,3336 }, {2202,650,2841 ,2875,3074,3443 }, - {6809,6808,6754 ,712,3465,713 }, {2514,2515,2513 ,2741,2600,3426 }, - {3743,3744,3794 ,2225,2390,3449 }, {2560,2518,546 ,3335,2388,1171 }, - {2782,2781,2729 ,3072,3373,3374 }, {2730,2782,2729 ,2150,3072,3374 }, - {6353,8121,6686 ,749,3466,750 }, {3460,3488,3487 ,3240,1980,3356 }, - {3478,3900,8141 ,885,884,3295 }, {4377,1255,1304 ,3090,3248,2639 }, - {3697,3743,3742 ,2224,2225,3419 }, {2774,2820,2773 ,2916,2869,2871 }, - {3025,3063,3062 ,3094,3093,3096 }, {3135,3183,1855 ,2833,2832,3088 }, - {7273,7251,7252 ,3467,2671,3437 }, {2567,3277,2901 ,2842,961,3468 }, - {2867,2868,2940 ,2844,1577,110 }, {1387,3372,1908 ,2951,2143,1058 }, - {147,4027,146 ,3469,3470,504 }, {5103,5418,5412 ,77,3471,360 }, - {1318,1032,867 ,164,1581,1121 }, {1787,1098,1908 ,2897,2725,1058 }, - {6735,6711,6308 ,3472,3473,3474 }, {8123,8108,8128 ,2247,2287,959 }, - {3959,3958,3904 ,982,294,1264 }, {2141,6707,8101 ,2015,2704,383 }, - {2816,2880,2879 ,3475,2591,2621 }, {3345,4106,8138 ,3476,1742,2018 }, - {2774,2776,2820 ,2916,3192,2869 }, {2775,2776,2774 ,3477,3192,2916 }, - {2776,2821,2820 ,3192,2915,2869 }, {3216,1657,3228 ,3478,1781,3042 }, - {2610,2682,790 ,3479,3480,1339 }, {2577,2710,2915 ,3348,3438,3434 }, - {220,4522,95 ,3340,3481,3482 }, {2545,2791,1789 ,3008,3483,3007 }, - {3227,2532,3226 ,1167,3186,3358 }, {2923,2973,2972 ,2046,3108,2047 }, - {2885,2930,2884 ,2914,3004,2940 }, {1590,1656,3198 ,3028,1166,1168 }, - {3212,2366,2495 ,3027,2589,2920 }, {3408,3383,3357 ,3484,882,883 }, - {3129,3128,3074 ,3412,2809,3363 }, {3086,3129,3074 ,3413,3412,3363 }, - {2506,2554,2344 ,2882,2853,2852 }, {2901,8098,2659 ,3468,907,3485 }, - {1917,2988,2862 ,833,3045,3031 }, {2353,2952,2570 ,3170,2610,2612 }, - {1235,1237,1370 ,1179,1467,1500 }, {1249,2693,2488 ,2876,3416,2877 }, - {2841,3213,2521 ,3443,3486,3208 }, {8096,8115,8140 ,1796,2448,2269 }, - {1847,178,1784 ,1519,3043,1662 }, {355,51,2939 ,1876,1856,1870 }, - {4248,3187,3972 ,3256,3402,3487 }, {4236,1334,4371 ,3488,1935,3489 }, - {3031,3030,2980 ,2857,3490,3305 }, {2724,2776,2723 ,2668,3192,2706 }, - {3031,3069,3030 ,2857,2827,3490 }, {2416,2807,1789 ,808,3289,3007 }, - {3890,3889,3854 ,1913,3126,1512 }, {3012,1332,2380 ,3491,3492,2597 }, - {1218,6891,8126 ,3255,813,812 }, {3275,2962,74 ,3493,3494,2053 }, - {2791,3275,2588 ,3483,3493,2072 }, {2278,2323,2322 ,3495,3496,3497 }, - {2323,282,281 ,3496,3498,2227 }, {2322,2323,281 ,3497,3496,2227 }, - {2484,2522,2451 ,3499,2678,2102 }, {3111,3110,3069 ,2829,3337,2827 }, - {3275,74,2588 ,3493,2053,2072 }, {2880,2924,2923 ,2591,2593,2046 }, - {2508,2592,2591 ,2630,2936,3303 }, {2493,2388,2840 ,3005,2608,2594 }, - {2986,3037,2985 ,3500,3501,3457 }, {5353,5352,4022 ,851,3502,3503 }, - {3037,3036,2985 ,3501,3362,3457 }, {2631,2467,2840 ,2971,3006,2594 }, - {3239,3241,2411 ,3378,3504,2777 }, {100,7960,162 ,2823,3505,2822 }, - {3213,2533,2521 ,3486,3209,3208 }, {2587,3142,90 ,3274,2849,2851 }, - {2515,2598,2597 ,2600,2602,2769 }, {2513,2515,2597 ,3426,2600,2769 }, - {7747,7797,7745 ,331,3506,650 }, {55,300,1155 ,3507,3508,3333 }, - {3855,3869,3854 ,1511,1912,1512 }, {2656,2461,2331 ,2893,2899,2895 }, - {3364,3390,3363 ,1184,3509,1911 }, {3129,3170,3128 ,3412,3510,2809 }, - {5556,5535,5536 ,3511,3512,754 }, {7702,7752,7701 ,3513,3514,3515 }, - {2835,2385,3173 ,3079,2702,3114 }, {3074,3128,3073 ,3363,2809,3516 }, - {2586,2840,2687 ,2972,2594,2767 }, {4371,1334,3864 ,3489,1935,3517 }, - {5970,2504,4104 ,3518,2898,3519 }, {5445,6577,4293 ,3520,97,2732 }, - {7874,7873,7847 ,344,817,3521 }, {2322,2277,2278 ,3497,3522,3495 }, - {1168,6643,4985 ,1098,3133,2703 }, {2948,2915,1482 ,3347,3434,2265 }, - {2915,2710,2631 ,3434,3438,2971 }, {1201,2986,1200 ,1477,3500,2629 }, - {2986,2985,1200 ,3500,3457,2629 }, {2449,2588,91 ,3259,2072,1984 }, - {1553,102,347 ,1669,432,431 }, {2879,2880,2923 ,2621,2591,2046 }, - {3103,3157,3156 ,3137,3194,3164 }, {2649,2535,2533 ,2791,3370,3209 }, - {2949,3011,2965 ,3239,3131,3417 }, {3213,2649,2533 ,3486,2791,3209 }, - {2875,3250,2635 ,2596,2595,2607 }, {817,906,905 ,1020,1019,1729 }, - {2789,2788,2740 ,637,2652,3456 }, {2948,2577,2915 ,3347,3348,3434 }, - {2435,2436,2508 ,3401,2577,2630 }, {2831,2830,2788 ,639,2654,2652 }, - {2789,2831,2788 ,637,639,2652 }, {6796,8136,8096 ,2617,2449,1796 }, - {2683,2682,2611 ,2645,3480,3436 }, {2807,2545,1789 ,3289,3008,3007 }, - {2533,2709,2805 ,3209,3523,3230 }, {2542,2494,2656 ,2879,3391,2893 }, - {3232,78,411 ,3325,3312,2919 }, {3231,3232,411 ,3293,3325,2919 }, - {411,78,2495 ,2919,3312,2920 }, {3027,3028,3065 ,3350,3349,3298 }, - {3485,3539,2686 ,3524,3525,3071 }, {1787,2620,1098 ,2897,3526,2725 }, - {2831,2868,2867 ,639,1577,2844 }, {2830,2831,2867 ,2654,639,2844 }, - {4240,6139,4260 ,2060,2059,3527 }, {3024,3025,3062 ,3098,3094,3096 }, - {2875,2635,2687 ,2596,2607,2767 }, {2923,2924,2973 ,2046,2593,3108 }, - {1204,1106,1205 ,338,1664,3187 }, {347,2423,2428 ,431,433,371 }, - {5308,5309,564 ,3528,987,3529 }, {2812,3349,3684 ,1914,2054,1915 }, - {3349,296,3422 ,2054,1558,2055 }, {2835,3180,2385 ,3079,2700,2702 }, - {821,1512,2136 ,2872,3199,1546 }, {6707,4985,6643 ,2704,2703,3133 }, - {2650,8096,8140 ,914,1796,2269 }, {8078,8142,8084 ,1744,1743,1139 }, - {2426,3190,2853 ,3113,807,806 }, {6351,8112,6322 ,1568,3530,3531 }, - {6914,6913,6861 ,3532,2634,3533 }, {1804,3317,296 ,2902,1882,1558 }, - {2436,2509,2508 ,2577,3329,2630 }, {2846,2877,1047 ,2623,3026,1328 }, - {2354,2555,3190 ,2968,1066,807 }, {1194,539,1599 ,393,2067,391 }, - {2426,2354,3190 ,3113,2968,807 }, {2741,2332,3212 ,3317,3322,3027 }, - {2609,2610,790 ,1130,3479,1339 }, {2443,2442,2365 ,2942,2742,3351 }, - {2612,2683,2611 ,2646,2645,3436 }, {1255,4377,795 ,3248,3090,302 }, - {2141,8091,8085 ,2015,2167,2016 }, {2400,111,2962 ,1117,1154,3494 }, - {3238,2424,2792 ,3379,2778,2718 }, {2691,2851,2943 ,3169,3051,3055 }, - {2555,2354,2434 ,1066,2968,1118 }, {3278,2851,2691 ,1158,3051,3169 }, - {382,1005,3732 ,3534,3535,3536 }, {2369,2368,2333 ,3257,2943,3537 }, - {3182,49,2709 ,3366,3367,3523 }, {4039,2680,2662 ,382,459,805 }, - {3746,3797,3796 ,2708,2061,2969 }, {2400,3275,2791 ,1117,3493,3483 }, - {2545,2400,2791 ,3008,1117,3483 }, {3915,3956,3955 ,1575,1383,3538 }, - {3939,3915,3955 ,3539,1575,3538 }, {3956,3996,3995 ,1383,1928,3540 }, - {3955,3956,3995 ,3538,1383,3540 }, {4038,4037,3995 ,1927,3541,3540 }, - {3996,4038,3995 ,1928,1927,3540 }, {238,237,100 ,868,869,2823 }, - {1853,1876,860 ,3101,1386,1385 }, {2760,2906,2428 ,2726,3542,371 }, - {2749,2760,2428 ,3286,2726,371 }, {2906,3270,2428 ,3542,3543,371 }, - {3270,347,2428 ,3543,431,371 }, {964,584,1294 ,535,2512,635 }, - {2719,2771,2770 ,2766,3197,2681 }, {2400,2962,3275 ,1117,3494,3493 }, - {4211,1113,4212 ,215,10,895 }, {8141,8069,3478 ,3295,1095,885 }, - {2242,2324,2323 ,2551,1995,3496 }, {2278,2242,2323 ,3495,2551,3496 }, - {2324,2391,282 ,1995,3544,3498 }, {2323,2324,282 ,3496,1995,3498 }, - {3226,1337,1740 ,3358,2148,3213 }, {2742,2031,2029 ,2558,1560,1748 }, - {2523,2564,2522 ,3545,3546,2678 }, {2610,2609,2522 ,3479,1130,2678 }, - {2564,2610,2522 ,3546,3479,2678 }, {5383,5396,6506 ,3547,3548,3549 }, - {2981,3032,3000 ,3550,2858,3304 }, {1103,1200,2890 ,1474,2629,2603 }, - {2353,2462,2489 ,3170,3245,2611 }, {872,836,3264 ,2962,3551,2468 }, - {3086,3074,3036 ,3413,3363,3362 }, {3037,3086,3036 ,3501,3413,3362 }, - {2682,2683,2704 ,3480,2645,3339 }, {5570,5641,5599 ,508,510,2213 }, - {2578,2635,2389 ,3552,2607,2609 }, {3238,3237,3207 ,3379,2885,2884 }, - {3208,3238,3207 ,3455,3379,2884 }, {3109,3108,3067 ,3553,3415,3371 }, - {2516,2600,2515 ,3554,2973,2600 }, {3068,3109,3067 ,3555,3553,3371 }, - {2933,2980,2979 ,3556,3305,2781 }, {2932,2933,2979 ,3243,3556,2781 }, - {3030,3029,2979 ,3490,3311,2781 }, {3030,3046,3029 ,3490,3372,3311 }, - {2980,3030,2979 ,3305,3490,2781 }, {3068,3067,3046 ,3555,3371,3372 }, - {3030,3068,3046 ,3490,3555,3372 }, {3235,2456,3268 ,3394,2790,3321 }, - {2533,3182,2709 ,3209,3366,3523 }, {2388,2430,2389 ,2608,2613,2609 }, - {2497,2865,2132 ,3336,3107,655 }, {8102,8082,8089 ,253,454,254 }, - {3594,3646,3592 ,2522,2123,2084 }, {3544,3594,3543 ,1153,2522,3075 }, - {3646,3645,3592 ,2123,1650,2084 }, {3594,3592,3593 ,2522,2084,3557 }, - {3594,3593,3543 ,2522,3557,3075 }, {4038,2662,4037 ,1927,805,3541 }, - {2662,254,4037 ,805,2008,3541 }, {5371,5404,5350 ,3558,3559,1526 }, - {562,885,708 ,1936,216,401 }, {80,2939,51 ,140,1870,1856 }, {2013,2711,2586 ,2242,3435,2972 }, - {2380,2013,2586 ,2597,2242,2972 }, {1011,1103,2864 ,1285,1474,3386 }, - {1103,2891,2864 ,1474,3560,3386 }, {2620,2760,1098 ,3526,2726,2725 }, - {2620,2305,2906 ,3526,3561,3542 }, {2760,2620,2906 ,2726,3526,3542 }, - {2305,3270,2906 ,3561,3543,3542 }, {1553,347,3270 ,1669,431,3543 }, - {2305,1553,3270 ,3561,1669,3543 }, {7704,7727,7682 ,3562,3563,3564 }, - {124,1423,5482 ,2206,151,3565 }, {2325,2392,2391 ,1994,3566,3544 }, - {2324,2325,2391 ,1995,1994,3544 }, {1929,1950,1884 ,899,786,3567 }, - {2392,328,2391 ,3566,2289,3544 }, {3166,3208,3207 ,3454,3455,2884 }, - {3165,3166,3207 ,3306,3454,2884 }, {3239,2411,2424 ,3378,2777,2778 }, - {2523,2522,2484 ,3545,2678,3499 }, {2967,111,2433 ,2701,1154,1116 }, - {2385,2967,2433 ,2702,2701,1116 }, {2967,3014,111 ,2701,3568,1154 }, - {511,2003,1972 ,3569,2542,3034 }, {1200,2985,2937 ,2629,3457,3570 }, - {2555,2434,2545 ,1066,1118,3008 }, {3237,3238,2792 ,2885,3379,2718 }, - {3048,3088,3047 ,2165,3290,3571 }, {2592,2667,2666 ,2936,2949,2765 }, - {2967,259,3014 ,2701,2203,3568 }, {2517,2516,2444 ,3399,3554,2941 }, - {2481,2517,2444 ,3273,3399,2941 }, {3234,3235,3268 ,3315,3394,3321 }, - {3205,3235,3204 ,3360,3394,3314 }, {3938,3939,3090 ,3572,3539,2805 }, - {3166,3165,3111 ,3454,3306,2829 }, {3088,3087,3047 ,3290,3573,3571 }, - {2586,2687,2581 ,2972,2767,2598 }, {70,1319,822 ,323,322,2000 }, - {3595,3648,3594 ,927,734,2522 }, {3544,3543,3489 ,1153,3075,1977 }, - {3490,3544,3489 ,2502,1153,1977 }, {2846,2844,2845 ,2623,1329,2995 }, - {2846,2845,819 ,2623,2995,2244 }, {3134,1855,2267 ,3284,3088,3574 }, - {3314,2333,2368 ,3575,3537,2943 }, {2150,3016,964 ,534,1028,535 }, - {3048,3047,1224 ,2165,3571,1508 }, {2790,2789,2740 ,3576,637,3456 }, - {2790,2832,2789 ,3576,638,637 }, {2883,2927,2882 ,2579,516,518 }, - {3399,6659,4550 ,715,3577,716 }, {6353,4544,5444 ,749,748,3410 }, - {1908,3453,1787 ,1058,917,2897 }, {2977,2976,2928 ,2997,2999,2578 }, - {3998,3999,4040 ,381,1023,460 }, {113,697,4539 ,677,3578,633 }, - {3134,2267,650 ,3284,3574,3074 }, {2732,2367,3116 ,2583,2764,3029 }, - {3116,3134,3219 ,3029,3284,3044 }, {3219,3134,650 ,3044,3284,3074 }, - {3033,3032,2981 ,3579,2858,3550 }, {2852,2387,2647 ,3275,3461,3276 }, - {906,1047,1046 ,1019,1328,1929 }, {3058,3123,1407 ,2710,3023,1269 }, - {3069,3110,3068 ,2827,3337,3555 }, {4298,141,4186 ,3580,681,683 }, - {1688,242,451 ,1718,1717,3387 }, {3125,3166,3111 ,3404,3454,2829 }, - {3644,3643,3590 ,1651,2344,1867 }, {28,88,3636 ,1059,3581,1060 }, - {4037,254,4036 ,3541,2008,1602 }, {3381,3407,3380 ,871,3012,1514 }, - {3407,3431,3380 ,3012,3021,1514 }, {1200,2937,2890 ,2629,3570,2603 }, - {2614,2684,2612 ,2638,2644,2646 }, {7910,2164,6483 ,3582,3583,3584 }, - {2298,2475,2793 ,3013,3047,3048 }, {7252,7251,6321 ,3437,2671,706 }, - {3016,584,964 ,1028,2512,535 }, {3227,3228,2532 ,1167,3042,3186 }, - {3241,3081,2411 ,3504,1017,2777 }, {2496,492,171 ,2961,1580,921 }, - {3349,1804,296 ,2054,2902,1558 }, {7067,7066,7028 ,3585,3586,3587 }, - {2326,2393,2392 ,3588,2445,3566 }, {2325,2326,2392 ,1994,3588,3566 }, - {2393,329,2392 ,2445,2348,3566 }, {329,328,2392 ,2348,2289,3566 }, - {3434,3382,3408 ,737,870,3484 }, {2936,2983,2935 ,2843,3589,3310 }, - {3240,3241,3239 ,3590,3504,3378 }, {3198,3226,3197 ,1168,3358,2599 }, - {2441,2513,2440 ,3000,3426,2572 }, {2853,2416,2577 ,806,808,3348 }, - {2805,2709,651 ,3230,3523,3591 }, {2764,3142,2587 ,2847,2849,3274 }, - {2702,3149,2351 ,2854,3134,3258 }, {2344,2702,2351 ,2852,2854,3258 }, - {2848,2826,2827 ,2605,3592,3445 }, {2682,830,829 ,3480,1996,1368 }, - {493,492,2496 ,1785,1580,2961 }, {2663,921,688 ,3593,1922,765 }, - {3198,3197,3154 ,1168,2599,2692 }, {3226,1740,3197 ,3358,3213,2599 }, - {2837,930,107 ,2511,3594,2548 }, {2726,2755,2777 ,2667,3400,2824 }, - {2517,2600,2516 ,3399,2973,3554 }, {2602,2600,2601 ,3234,2973,3398 }, - {3072,3071,3033 ,3403,3405,3579 }, {3034,3072,3033 ,3595,3403,3579 }, - {3087,3086,3037 ,3573,3413,3501 }, {2704,2735,830 ,3339,2887,1996 }, - {2682,2704,830 ,3480,3339,1996 }, {1168,8122,6643 ,1098,384,3133 }, - {4901,5591,6162 ,3596,3597,3598 }, {688,921,1065 ,765,1922,821 }, - {921,1090,1340 ,1922,2687,822 }, {2590,529,2589 ,2648,1148,3204 }, - {2097,7910,2096 ,846,3582,788 }, {2942,2587,554 ,2587,3274,2588 }, - {2590,2664,529 ,2648,2721,1148 }, {2763,2620,1787 ,2896,3526,2897 }, - {2763,3120,2620 ,2896,3599,3526 }, {2500,2305,2620 ,3600,3561,3526 }, - {3120,2500,2620 ,3599,3600,3526 }, {2500,2768,1553 ,3600,1297,1669 }, - {2305,2500,1553 ,3561,3600,1669 }, {2982,2981,2934 ,3601,3550,3602 }, - {2935,2982,2934 ,3310,3601,3602 }, {3047,3087,3037 ,3571,3573,3501 }, - {2610,2611,2682 ,3479,3436,3480 }, {2039,1626,349 ,1655,564,566 }, - {2730,2729,2701 ,2150,3374,3375 }, {2770,2816,2847 ,2681,3475,2624 }, - {3059,3099,3058 ,2892,3603,2710 }, {3099,3123,3058 ,3603,3023,2710 }, - {3019,3020,3058 ,2709,2890,2710 }, {2135,2478,631 ,1425,3143,1426 }, - {2770,2771,2816 ,2681,3197,3475 }, {2424,2905,2367 ,2778,399,2764 }, - {2267,1855,2649 ,3574,3088,2791 }, {3648,3647,3594 ,734,2521,2522 }, - {3574,3595,3544 ,928,927,1153 }, {3107,3105,3106 ,3326,3297,3380 }, - {3107,3140,3105 ,3326,3327,3297 }, {2933,2932,2863 ,3556,3243,3242 }, - {1590,3154,3123 ,3028,2692,3023 }, {3124,1590,3123 ,3604,3028,3023 }, - {2084,460,860 ,1361,1999,1385 }, {2674,2726,2700 ,2975,2667,3009 }, - {2727,2755,2726 ,2760,3400,2667 }, {3169,3211,3168 ,2810,3605,3396 }, - {2677,213,123 ,3033,3606,3607 }, {3211,3210,3168 ,3605,3608,3396 }, - {2796,3080,2472 ,2462,908,2009 }, {2255,1211,939 ,3229,2007,3354 }, - {3866,35,783 ,1479,1338,679 }, {2846,2878,2877 ,2623,2622,3026 }, - {2435,388,292 ,3401,2202,2563 }, {2358,2435,292 ,2562,3401,2563 }, - {2833,2763,3054 ,2065,2896,916 }, {2833,3120,2763 ,2065,3599,2896 }, - {2550,2500,3120 ,3609,3600,3599 }, {2833,2550,3120 ,2065,3609,3599 }, - {2550,2768,2500 ,3609,1297,3600 }, {2167,2089,2947 ,1323,1325,2988 }, - {2167,2947,2166 ,1323,2988,1040 }, {388,2435,2508 ,2202,3401,2630 }, - {3069,3068,3030 ,2827,3555,3490 }, {2591,2590,2508 ,3303,2648,2630 }, - {7514,7513,7484 ,3610,3611,3612 }, {2280,2325,2243 ,3613,1994,1993 }, - {2662,2796,2472 ,805,2462,2009 }, {2997,3023,3022 ,3158,3099,3393 }, - {2591,2638,2590 ,3303,2935,2648 }, {2666,2665,2590 ,2765,2677,2648 }, - {2563,2194,2193 ,2707,1853,1007 }, {2983,2982,2935 ,3589,3601,3310 }, - {1098,1096,28 ,2725,2727,1059 }, {1908,1098,28 ,1058,2725,1059 }, - {1197,1987,2808 ,478,3614,522 }, {401,2445,2369 ,1387,1388,3257 }, - {3322,3321,7387 ,1182,2461,3615 }, {2792,2424,2367 ,2718,2778,2764 }, - {3593,3592,3543 ,3557,2084,3075 }, {3090,3955,3994 ,2805,3538,2806 }, - {600,131,1390 ,978,2965,2964 }, {3163,3205,3162 ,3361,3360,3318 }, - {788,600,1390 ,976,978,2964 }, {2626,2764,2587 ,2582,2847,3274 }, - {2332,2626,2587 ,3322,2582,3274 }, {2442,2441,2365 ,2742,3000,3351 }, - {2441,2442,2513 ,3000,2742,3426 }, {2638,2666,2590 ,2935,2765,2648 }, - {2617,2371,2387 ,2878,2880,3461 }, {2887,2933,2863 ,3616,3556,3242 }, - {2827,2826,2780 ,3445,3592,2830 }, {2791,2588,2429 ,3483,2072,3617 }, - {818,2800,2844 ,1018,2996,1329 }, {2593,2668,2667 ,3111,3138,2949 }, - {740,2730,2701 ,1595,2150,3375 }, {2755,2778,2777 ,3400,3215,2824 }, - {2727,2726,2674 ,2760,2667,2975 }, {2885,2884,2820 ,2914,2940,2869 }, - {2332,2587,3212 ,3322,3274,3027 }, {3123,1480,1407 ,3023,2695,1269 }, - {2364,2363,177 ,2513,2571,3618 }, {3357,3382,3356 ,883,870,872 }, - {2768,2460,2541 ,1297,3619,1298 }, {3654,3653,3604 ,1438,1440,3384 }, - {492,444,171 ,1580,922,921 }, {2557,3566,3456 ,3620,1146,1145 }, - {5837,4771,5804 ,3621,3622,3623 }, {2665,2666,2718 ,2677,2765,2675 }, - {2878,2922,2921 ,2622,2045,2691 }, {2550,2460,2768 ,3609,3619,1297 }, - {108,36,874 ,1336,1478,636 }, {2857,2761,2765 ,2575,2768,2590 }, - {7923,7973,7948 ,816,3624,3625 }, {2281,2327,2326 ,3626,3627,3588 }, - {2327,286,2393 ,3627,2446,2445 }, {2326,2327,2393 ,3588,3627,2445 }, - {5038,4743,5702 ,3628,3629,3630 }, {2156,6783,6464 ,3631,3632,3633 }, - {2528,924,3183 ,2763,3634,2832 }, {3195,3114,2649 ,3430,2792,2791 }, - {3494,3546,3492 ,736,2557,930 }, {2143,2099,2166 ,953,1093,1040 }, - {2611,2610,2524 ,3436,3479,3395 }, {3845,6215,1949 ,3635,3636,3637 }, - {3130,4032,3129 ,3414,3638,3412 }, {2982,3033,2981 ,3601,3579,3550 }, - {3071,3125,3111 ,3405,3404,2829 }, {489,3761,2955 ,3639,218,3640 }, - {3163,3162,3108 ,3361,3318,3415 }, {3109,3163,3108 ,3553,3361,3415 }, - {3205,3204,3162 ,3360,3314,3318 }, {3235,3234,3204 ,3394,3315,3314 }, - {5337,4866,4830 ,572,3641,3642 }, {2673,2724,2671 ,2974,2668,2705 }, - {3201,3231,3230 ,3328,3293,3294 }, {7704,7753,7727 ,3562,3643,3563 }, - {2815,2770,2847 ,2696,2681,2624 }, {2781,2827,2780 ,3373,3445,2830 }, - {1984,2530,2038 ,831,2389,1551 }, {1004,2652,1056 ,3452,3424,3388 }, - {7910,2097,2164 ,3582,846,3583 }, {2974,2997,3022 ,3116,3158,3393 }, - {2494,2629,2656 ,3391,2673,2893 }, {2973,2974,3022 ,3108,3116,3393 }, - {2869,2868,2832 ,1576,1577,638 }, {2194,2563,2146 ,1853,2707,1732 }, - {8135,4835,3148 ,2439,2130,814 }, {2952,2353,2489 ,2610,3170,2611 }, - {3216,1656,1657 ,3478,1166,1781 }, {2869,2832,2907 ,1576,638,111 }, - {5653,350,6115 ,3644,1114,3645 }, {2877,2878,2921 ,3026,2622,2691 }, - {2793,2426,2853 ,3048,3113,806 }, {1845,1337,1874 ,912,2148,962 }, - {1519,2990,79 ,2450,3646,1510 }, {6554,6619,4190 ,3647,1272,3439 }, - {777,2137,776 ,421,147,1120 }, {4445,2871,712 ,3648,3649,3650 }, - {2572,3138,1181 ,3050,2984,1981 }, {2868,2907,2940 ,1577,111,110 }, - {3331,3330,3291 ,1183,1185,1203 }, {2497,2201,2865 ,3336,2455,3107 }, - {3032,3031,3000 ,2858,2857,3304 }, {2889,2888,2826 ,2604,3651,3592 }, - {2626,2625,2839 ,2582,2584,2848 }, {2848,2889,2826 ,2605,2604,3592 }, - {3071,3111,3070 ,3405,2829,2828 }, {3071,3070,3032 ,3405,2828,2858 }, - {3033,3071,3032 ,3579,3405,2858 }, {2351,2201,2497 ,3258,2455,3336 }, - {2516,2515,2443 ,3554,2600,2942 }, {2444,2516,2443 ,2941,3554,2942 }, - {2442,2514,2513 ,2742,2741,3426 }, {3545,3574,3544 ,926,928,1153 }, - {3931,3944,3684 ,1868,729,1915 }, {3541,3572,3571 ,981,1931,3652 }, - {3195,219,3114 ,3430,3087,2792 }, {2711,2013,877 ,3435,2242,2243 }, - {689,3828,4206 ,1363,1364,682 }, {5488,6257,6039 ,2730,3428,2728 }, - {3114,2471,2536 ,2792,3653,2793 }, {1238,165,155 ,1569,1869,1497 }, - {2973,3022,3021 ,3108,3393,2891 }, {2930,2929,2884 ,3004,3003,2940 }, - {2387,2531,2647 ,3461,3654,3276 }, {3194,1487,2338 ,1065,531,458 }, - {3022,3060,3059 ,3393,3214,2892 }, {3021,3022,3059 ,2891,3393,2892 }, - {3075,2803,2833 ,2670,3655,2065 }, {2608,2550,2833 ,3656,3609,2065 }, - {2850,2608,2833 ,3657,3656,2065 }, {2608,2470,2460 ,3656,3658,3619 }, - {2550,2608,2460 ,3609,3656,3619 }, {2470,2541,2460 ,3658,1298,3619 }, - {3422,296,3664 ,2055,1558,1557 }, {3060,3100,3099 ,3214,2955,3603 }, - {3194,3189,2150 ,1065,1027,534 }, {3400,2410,3402 ,3659,1,3660 }, - {1218,1742,3008 ,3255,707,546 }, {3170,4032,1160 ,3510,3638,3661 }, - {2099,2100,2166 ,1093,1218,1040 }, {3059,3060,3099 ,2892,3214,3603 }, - {3100,3124,3099 ,2955,3604,3603 }, {2972,3020,3019 ,2047,2890,2709 }, - {3183,924,219 ,2832,3634,3087 }, {2889,2935,2888 ,2604,3310,3651 }, - {2935,2934,2888 ,3310,3602,3651 }, {740,2676,643 ,1595,2761,3285 }, - {2006,2032,2031 ,1181,1127,1560 }, {740,2701,2676 ,1595,3375,2761 }, - {2852,2617,2387 ,3275,2878,3461 }, {2360,2437,2359 ,3161,2576,3406 }, - {2294,2295,2359 ,3081,3160,3406 }, {2971,2972,3019 ,3338,2047,2709 }, - {1224,3047,3037 ,1508,3571,3501 }, {2922,2972,2971 ,2045,2047,3338 }, - {2793,2853,2630 ,3048,806,3139 }, {2592,2593,2667 ,2936,3111,2949 }, - {628,2717,728 ,1177,2676,1266 }, {2921,2922,2971 ,2691,2045,3338 }, - {3100,1590,3124 ,2955,3028,3604 }, {3211,3241,3240 ,3605,3504,3590 }, - {3210,3211,3240 ,3608,3605,3590 }, {2983,3034,2982 ,3589,3595,3601 }, - {3463,3432,3433 ,1271,929,3049 }, {2651,2803,3075 ,1516,3655,2670 }, - {2651,2850,2803 ,1516,3657,3655 }, {2651,2608,2850 ,1516,3656,3657 }, - {2418,2541,2470 ,3662,1298,3658 }, {451,242,2541 ,3387,1717,1298 }, - {2418,451,2541 ,3662,3387,1298 }, {2931,2978,2977 ,2780,2782,2997 }, - {2841,2649,3213 ,3443,2791,3486 }, {596,549,647 ,1462,1129,973 }, - {3034,3033,2982 ,3595,3579,3601 }, {875,6836,6353 ,579,852,749 }, - {2282,2328,2327 ,3663,3664,3627 }, {2328,287,286 ,3664,2470,2446 }, - {2327,2328,286 ,3627,3664,2446 }, {4246,1729,3837 ,3665,3666,3667 }, - {4377,2431,967 ,3090,2977,3668 }, {3020,3059,3058 ,2890,2892,2710 }, - {650,2267,2841 ,3074,3574,3443 }, {219,2471,3114 ,3087,3653,2792 }, - {2823,2824,2863 ,2825,3432,3242 }, {3065,3085,3105 ,3298,3381,3297 }, - {3085,3106,3105 ,3381,3380,3297 }, {2596,2640,2595 ,2771,2770,2983 }, - {2723,2775,2774 ,2706,3477,2916 }, {2722,2723,2774 ,3014,2706,2916 }, - {2509,2510,2592 ,3329,3162,2936 }, {2295,2360,2359 ,3160,3161,3406 }, - {3229,1726,3199 ,3266,1746,3244 }, {2300,1304,2551 ,2640,2639,3247 }, - {1336,2085,2604 ,2924,657,3046 }, {3566,2397,3768 ,1146,3669,1518 }, - {2267,2649,2841 ,3574,2791,3443 }, {1920,2155,2157 ,581,580,3411 }, - {3459,3460,3487 ,3241,3240,3356 }, {1789,2791,2429 ,3007,3483,3617 }, - {2656,2629,2461 ,2893,2673,2899 }, {3110,3164,3109 ,3337,3307,3553 }, - {1224,3037,2986 ,1508,3501,3500 }, {6071,6082,6088 ,1346,1348,3670 }, - {155,1183,1238 ,1497,1238,1569 }, {4978,5592,2206 ,178,3671,176 }, - {3546,3545,3492 ,2557,926,930 }, {2381,2608,2651 ,3672,3656,1516 }, - {2381,2470,2608 ,3672,3658,3656 }, {2468,2418,2470 ,3673,3662,3658 }, - {1313,5085,2251 ,3674,3675,3676 }, {1606,4055,4054 ,3677,3678,3679 }, - {689,1586,3315 ,1363,943,944 }, {2741,3212,2495 ,3317,3027,2920 }, - {2329,288,287 ,3680,2723,2470 }, {2328,2329,287 ,3664,3680,2470 }, - {3345,8138,5352 ,3476,2018,3502 }, {2647,2531,2413 ,3276,3654,3246 }, - {2778,2824,2823 ,3215,3432,2825 }, {2777,2778,2823 ,2824,3215,2825 }, - {2824,2887,2863 ,3432,3616,3242 }, {2387,2371,2633 ,3461,2880,2650 }, - {3202,3201,3159 ,3324,3328,3296 }, {3202,3232,3201 ,3324,3325,3328 }, - {2640,2671,2595 ,2770,2705,2983 }, {2900,2300,2551 ,2649,2640,3247 }, - {2604,2085,2964 ,3046,657,3011 }, {2964,2085,2131 ,3011,657,656 }, - {2677,886,213 ,3033,3464,3606 }, {3268,2456,2302 ,3321,2790,3313 }, - {6436,5255,6480 ,3681,3682,1524 }, {3916,3904,3879 ,969,1264,2549 }, - {2524,2610,2564 ,3395,3479,3546 }, {282,327,281 ,3498,2226,2227 }, - {3421,3278,2851 ,1156,1158,3051 }, {2792,2367,2732 ,2718,2764,2583 }, - {5191,5170,5914 ,2900,3683,1566 }, {2547,2470,2381 ,3684,3658,3672 }, - {2397,2547,2381 ,3669,3684,3672 }, {2547,3053,2470 ,3684,3685,3658 }, - {2655,2468,2470 ,3686,3673,3658 }, {3053,2655,2470 ,3685,3686,3658 }, - {2655,2418,2468 ,3686,3662,3673 }, {2467,2493,2840 ,3006,3005,2594 }, - {2524,2564,2523 ,3395,3546,3545 }, {2946,3194,2338 ,1062,1065,458 }, - {178,1847,1874 ,3043,1519,962 }, {2924,2974,2973 ,2593,3116,3108 }, - {2328,2283,2329 ,3664,3687,3680 }, {2909,1849,1785 ,3189,1660,1659 }, - {3148,1378,8135 ,814,925,2439 }, {6098,6388,5191 ,1565,3184,2900 }, - {2524,2523,2484 ,3395,3545,3499 }, {6970,3340,4831 ,3688,114,3154 }, - {3126,3125,3072 ,3689,3404,3403 }, {2664,628,529 ,2721,1177,1148 }, - {2584,2310,2476 ,2894,2442,2441 }, {2552,2584,2476 ,2657,2894,2441 }, - {2633,2584,2552 ,2650,2894,2657 }, {3160,3202,3159 ,3323,3324,3296 }, - {3647,3700,3646 ,2521,2545,2123 }, {2928,2926,2927 ,2578,517,516 }, - {2976,2998,2975 ,2999,3446,3157 }, {2362,2439,2438 ,2979,2980,3163 }, - {2361,2362,2438 ,3177,2979,3163 }, {2456,2626,2332 ,2790,2582,3322 }, - {2302,2456,2332 ,3313,2790,3322 }, {3164,3163,3109 ,3307,3361,3553 }, - {2532,178,1874 ,3186,3043,962 }, {2670,2669,2595 ,2982,3015,2983 }, - {3873,3931,3475 ,1809,1868,1559 }, {6309,6735,6308 ,3690,3472,3474 }, - {6088,5255,6436 ,3670,3682,3681 }, {1265,4548,1271 ,1273,589,588 }, - {2195,165,341 ,1851,1869,1852 }, {2547,2469,2655 ,3684,3691,3686 }, - {3053,2547,2655 ,3685,3684,3686 }, {2469,2418,2655 ,3691,3662,3686 }, - {2469,451,2418 ,3691,3387,3662 }, {2939,134,451 ,1870,1783,3387 }, - {3167,3209,3166 ,3692,3377,3454 }, {8078,8084,8124 ,1744,1139,1141 }, - {3216,3228,1656 ,3478,3042,1166 }, {2330,289,288 ,3693,1044,2723 }, - {2329,2330,288 ,3680,3693,2723 }, {925,2730,827 ,1287,2150,1220 }, - {1010,925,926 ,1286,1287,1284 }, {1146,1237,1236 ,2467,1467,1434 }, - {2844,2846,1047 ,1329,2623,1328 }, {3022,3023,3061 ,3393,3099,2953 }, - {2937,2936,2890 ,3570,2843,2603 }, {3105,3140,3159 ,3297,3327,3296 }, - {3140,3160,3159 ,3327,3323,3296 }, {3232,3231,3201 ,3325,3293,3328 }, - {3021,3020,2972 ,2891,2890,2047 }, {2976,2975,2926 ,2999,3157,517 }, - {2928,2976,2926 ,2578,2999,517 }, {2595,2639,2594 ,2983,3694,3110 }, - {2595,2594,2511 ,2983,3110,3112 }, {2356,3267,3229 ,3264,3265,3266 }, - {2909,3223,2911 ,3189,2922,2923 }, {2891,2890,1010 ,3560,2603,1286 }, - {3238,3239,2424 ,3379,3378,2778 }, {1103,2890,2891 ,1474,2603,3560 }, - {3167,3166,3125 ,3692,3454,3404 }, {3306,7276,3326 ,3695,3696,826 }, - {2497,2344,2351 ,3336,2852,3258 }, {1482,2915,2711 ,2265,3434,3435 }, - {3434,3433,3382 ,737,3049,870 }, {5219,5218,5198 ,1860,483,423 }, - {8101,8087,8099 ,383,385,2867 }, {3208,3209,3238 ,3455,3377,3379 }, - {2397,2651,3768 ,3669,1516,1518 }, {2688,451,2469 ,3697,3387,3691 }, - {2658,2939,451 ,3698,1870,3387 }, {2688,2658,451 ,3697,3698,3387 }, - {3645,3698,3644 ,1650,2122,1651 }, {6639,1213,4983 ,3699,3700,480 }, - {2985,2984,2937 ,3457,3458,3570 }, {3546,3597,3545 ,2557,1810,926 }, - {6257,5166,6039 ,3428,3427,2728 }, {2283,2285,2329 ,3687,3701,3680 }, - {2129,2130,2069 ,1469,1505,1711 }, {1855,3195,2649 ,3088,3430,2791 }, - {5327,6525,6524 ,3702,3703,3704 }, {2702,2254,2427 ,2854,3705,3237 }, - {2475,2715,3013 ,3047,2944,2946 }, {3095,2715,2835 ,2945,2944,3079 }, - {2512,2596,2595 ,2981,2771,2983 }, {2563,2125,2146 ,2707,892,1732 }, - {2691,2570,2544 ,3169,2612,2451 }, {2639,2669,2593 ,3694,3015,3111 }, - {2595,2669,2639 ,2983,3015,3694 }, {3026,3025,2998 ,3095,3094,3446 }, - {2899,3223,2909 ,2921,2922,3189 }, {3700,3699,3646 ,2545,2121,2123 }, - {3073,3127,3072 ,3516,2811,3403 }, {2429,2588,2556 ,3617,2072,2779 }, - {1789,2429,2556 ,3007,3617,2779 }, {2864,2891,1010 ,3386,3560,1286 }, - {3126,3167,3125 ,3689,3692,3404 }, {1482,2711,877 ,2265,3435,2243 }, - {2518,2517,2445 ,2388,3399,1388 }, {2984,2983,2936 ,3458,3589,2843 }, - {1740,1687,3196 ,3213,1104,2581 }, {3197,1740,3196 ,2599,3213,2581 }, - {2493,1789,2556 ,3005,3007,2779 }, {554,2987,2268 ,2588,3346,3292 }, - {2876,2706,2469 ,3706,3707,3691 }, {2547,2876,2469 ,3684,3706,3691 }, - {2706,2688,2469 ,3707,3697,3691 }, {2658,355,2939 ,3698,1876,1870 }, - {3035,3034,2983 ,3364,3595,3589 }, {2388,2493,2556 ,2608,3005,2779 }, - {685,3371,1309 ,2674,3708,3709 }, {3187,4236,4371 ,3402,3488,3489 }, - {157,2133,91 ,1877,2614,1984 }, {5455,1263,6509 ,686,1199,1452 }, - {4452,4795,4820 ,2398,3710,2399 }, {3073,3072,3034 ,3516,3403,3595 }, - {3035,3073,3034 ,3364,3516,3595 }, {6173,6088,6388 ,3711,3670,3184 }, - {110,74,2962 ,743,2053,3494 }, {2715,2386,2835 ,2944,3196,3079 }, - {369,418,470 ,1521,1610,1522 }, {2549,2622,2894 ,2841,2840,3140 }, - {2639,2593,2594 ,3694,3111,3110 }, {2773,2772,2720 ,2871,3198,3173 }, - {2721,2773,2720 ,2917,2871,3173 }, {2676,2675,2602 ,2761,3235,3234 }, - {3168,3167,3126 ,3396,3692,3689 }, {1452,1004,1592 ,1606,3452,2939 }, - {1936,5140,5359 ,848,3712,3713 }, {5326,5327,6524 ,3714,3702,3704 }, - {2201,968,2200 ,2455,1661,1570 }, {2401,651,2995 ,2855,3591,2856 }, - {2531,2387,2413 ,3654,3461,3246 }, {2937,2984,2936 ,3570,3458,2843 }, - {3168,3210,3167 ,3396,3608,3692 }, {2194,2146,2147 ,1853,1732,1562 }, - {2837,107,2501 ,2511,2548,2547 }, {2652,1004,31 ,3424,3452,3450 }, - {3054,3981,3076 ,916,915,2066 }, {2557,2397,3052 ,3620,3669,3715 }, - {2876,2547,2397 ,3706,3684,3669 }, {2557,2876,2397 ,3620,3706,3669 }, - {2984,3035,2983 ,3458,3364,3589 }, {2250,2286,2330 ,3716,3717,3693 }, - {2285,2250,2330 ,3701,3716,3693 }, {2286,290,289 ,3717,1042,1044 }, - {2330,2286,289 ,3693,3717,1044 }, {8067,8083,8097 ,2168,2103,1710 }, - {2000,2025,2024 ,2428,2430,2370 }, {3127,3126,3072 ,2811,3689,3403 }, - {3179,1249,2617 ,2947,2876,2878 }, {3472,3446,1165 ,3155,3718,3153 }, - {2647,2413,2462 ,3276,3246,3245 }, {3230,2356,3229 ,3294,3264,3266 }, - {2370,2630,1482 ,3216,3139,2265 }, {2637,1238,1373 ,2720,1569,1501 }, - {2131,2129,2653 ,656,1469,3010 }, {411,2899,2909 ,2919,2921,3189 }, - {2356,411,2909 ,3264,2919,3189 }, {3534,8072,3668 ,942,511,513 }, - {3127,3168,3126 ,2811,3396,3689 }, {2513,2597,2512 ,3426,2769,2981 }, - {6170,3537,3451 ,3719,1735,1720 }, {3210,3209,3167 ,3608,3377,3692 }, - {2587,90,3256 ,3274,2851,3308 }, {2717,2769,819 ,2676,2679,2244 }, - {2805,651,2401 ,3230,3591,2855 }, {2528,56,924 ,2763,2606,3634 }, - {2416,1789,2467 ,808,3007,3006 }, {2711,2631,2586 ,3435,2971,2972 }, - {2748,2876,2557 ,3720,3706,3620 }, {2580,2688,2706 ,3721,3697,3707 }, - {2688,2580,2658 ,3697,3721,3698 }, {2459,355,2658 ,3722,1876,3698 }, - {355,2459,250 ,1876,3722,1916 }, {3210,3240,3239 ,3608,3590,3378 }, - {3209,3210,3239 ,3377,3608,3378 }, {437,2589,529 ,1149,3204,1148 }, - {2151,109,349 ,1603,1654,566 }, {790,2682,829 ,1339,3480,1368 }, - {2003,2029,2028 ,2542,1748,1811 }, {2518,2560,2517 ,2388,3335,3399 }, - {2269,2505,2497 ,2881,2883,3336 }, {2987,2269,2497 ,3346,2881,3336 }, - {2819,2818,2772 ,2870,3156,3198 }, {3095,2835,3173 ,2945,3079,3114 }, - {162,2290,238 ,2822,1982,868 }, {2724,2726,2776 ,2668,2667,3192 }, - {2723,2776,2775 ,2706,3192,3477 }, {4086,284,557 ,3723,139,3724 }, - {1255,795,2576 ,3248,302,3076 }, {3025,3024,2975 ,3094,3098,3157 }, - {2884,2928,2883 ,2940,2578,2579 }, {2537,2427,2677 ,2985,3237,3033 }, - {2598,2599,2673 ,2602,2601,2974 }, {2269,2841,2506 ,2881,3443,2882 }, - {2552,2476,2300 ,2657,2441,2640 }, {8065,8094,8080 ,96,98,1094 }, - {1238,1515,1373 ,1569,1502,1501 }, {2489,2475,2298 ,2611,3047,3013 }, - {3429,3428,3378 ,1978,3261,1442 }, {3143,2537,968 ,3135,2985,1661 }, - {3699,3745,3744 ,2121,2546,2390 }, {2554,2805,2401 ,2853,3230,2855 }, - {1969,4644,1970 ,2369,2425,2427 }, {1482,877,58 ,2265,2243,2156 }, - {2748,2579,2706 ,3720,3725,3707 }, {2876,2748,2706 ,3706,3720,3707 }, - {2579,2580,2706 ,3725,3721,3707 }, {2580,2578,2658 ,3721,3552,3698 }, - {2578,2459,2658 ,3552,3722,3698 }, {2614,2613,2526 ,2638,2665,2636 }, - {3124,3123,3099 ,3604,3023,3603 }, {3597,3596,3545 ,1810,1792,926 }, - {2544,79,2691 ,2451,1510,3169 }, {6155,6413,6970 ,3726,112,3688 }, - {4302,4303,166 ,3727,3728,3729 }, {2685,2737,2684 ,2642,2626,2644 }, - {2692,56,2528 ,2845,2606,2763 }, {2411,2692,2528 ,2777,2845,2763 }, - {2602,2601,2517 ,3234,3398,3399 }, {2569,554,1336 ,3291,2588,2924 }, - {2647,2462,2353 ,3276,3245,3170 }, {2773,2819,2772 ,2871,2870,3198 }, - {2438,2510,2437 ,3163,3162,2576 }, {2771,2817,2816 ,3197,3174,3475 }, - {2816,2817,2880 ,3475,3174,2591 }, {3359,6393,3305 ,824,1556,879 }, - {4146,4170,3844 ,3730,3731,2443 }, {2819,2820,2883 ,2870,2869,2579 }, - {2202,2841,2269 ,2875,3443,2881 }, {2888,2887,2824 ,3651,3616,3432 }, - {2826,2888,2824 ,3592,3651,3432 }, {2676,2727,2675 ,2761,2760,3235 }, - {3379,3429,3378 ,1979,1978,1442 }, {554,785,1336 ,2588,2952,2924 }, - {2569,1336,2366 ,3291,2924,2589 }, {3087,3088,3131 ,3573,3290,3732 }, - {4068,4091,4077 ,408,123,126 }, {2826,2825,2779 ,3592,3431,2831 }, - {2780,2826,2779 ,2830,3592,2831 }, {1849,2909,1875 ,1660,3189,1663 }, - {2685,2684,2614 ,2642,2644,2638 }, {1205,1106,1107 ,3187,1664,2656 }, - {2949,2748,2557 ,3239,3720,3620 }, {2949,2965,2579 ,3239,3417,3725 }, - {2748,2949,2579 ,3720,3239,3725 }, {2765,2580,2579 ,2590,3721,3725 }, - {2389,2459,2578 ,2609,3722,3552 }, {2389,250,2459 ,2609,1916,3722 }, - {3164,3206,3163 ,3307,2886,3361 }, {725,818,817 ,721,1018,1020 }, - {4172,4173,4215 ,135,134,370 }, {6525,6573,6572 ,3703,3733,3734 }, - {291,290,2286 ,1012,1042,3717 }, {2287,291,2286 ,3735,1012,3717 }, - {6524,6525,6572 ,3704,3703,3734 }, {2371,2542,2656 ,2880,2879,2893 }, - {554,2085,785 ,2588,657,2952 }, {2572,1181,293 ,3050,1981,1430 }, - {2678,1917,1875 ,3190,833,1663 }, {2909,2678,1875 ,3189,3190,1663 }, - {1665,410,2967 ,3077,2204,2701 }, {2847,2816,2879 ,2624,3475,2621 }, - {149,2471,219 ,3736,3653,3087 }, {3175,2576,2628 ,3249,3076,3078 }, - {2427,2537,3149 ,3237,2985,3134 }, {3074,3073,3035 ,3363,3516,3364 }, - {3154,3153,3123 ,2692,2693,3023 }, {2742,2003,1565 ,2558,2542,3737 }, - {511,1565,2003 ,3569,3737,2542 }, {3494,3492,3493 ,736,930,3738 }, - {13,1303,1626 ,910,1933,564 }, {3792,2941,3791 ,3421,109,3739 }, - {2504,2310,2502 ,2898,2442,3740 }, {2331,2502,2310 ,2895,3740,2442 }, - {2584,2331,2310 ,2894,2895,2442 }, {90,2202,2269 ,2851,2875,2881 }, - {2826,2824,2825 ,3592,3432,3431 }, {3110,3109,3068 ,3337,3553,3555 }, - {2965,2765,2579 ,3417,2590,3725 }, {2761,2580,2765 ,2768,3721,2590 }, - {2761,2578,2580 ,2768,3552,3721 }, {2133,250,2389 ,2614,1916,2609 }, - {253,247,2663 ,2564,2569,3593 }, {3494,3493,3432 ,736,3738,929 }, - {2921,2971,1237 ,2691,3338,1467 }, {2886,2931,2885 ,2913,2780,2914 }, - {3434,3463,3433 ,737,1271,3049 }, {972,1073,2314 ,3277,3741,3742 }, - {2286,2250,2287 ,3717,3716,3735 }, {236,291,2287 ,2444,1012,3735 }, - {99,236,2287 ,3743,2444,3735 }, {1172,2993,1081 ,1758,3744,3745 }, - {819,2845,2800 ,2244,2995,2996 }, {2560,2602,2517 ,3335,3234,3399 }, - {3993,3994,4035 ,2807,2806,1601 }, {2999,3027,3026 ,2998,3350,3095 }, - {968,2572,293 ,1661,3050,1430 }, {2976,3026,2998 ,2999,3095,3446 }, - {2510,2511,2593 ,3162,3112,3111 }, {2166,2100,2167 ,1040,1218,1323 }, - {292,239,2292 ,2563,1103,1983 }, {2874,3175,2628 ,3195,3249,3078 }, - {3063,3103,3102 ,3093,3137,3097 }, {3062,3063,3102 ,3096,3093,3097 }, - {2722,2774,2721 ,3014,2916,2917 }, {2503,2353,2691 ,2948,3170,3169 }, - {3149,3260,2201 ,3134,3188,2455 }, {2981,2980,2933 ,3550,3305,3556 }, - {2981,3000,2980 ,3550,3304,3305 }, {6388,6088,6436 ,3184,3670,3681 }, - {2416,2467,2631 ,808,3006,2971 }, {3128,3127,3073 ,2809,2811,3516 }, - {4426,6837,6577 ,1056,1057,97 }, {2908,1249,3179 ,3052,2876,2947 }, - {3138,1050,1181 ,2984,2282,1981 }, {1406,1329,1370 ,1135,1134,1500 }, - {2700,2726,2725 ,3009,2667,2666 }, {2673,2700,2725 ,2974,3009,2666 }, - {2888,2934,2933 ,3651,3602,3556 }, {2976,2999,3026 ,2999,2998,3095 }, - {2887,2888,2933 ,3616,3651,3556 }, {6573,6613,6612 ,3733,3746,1389 }, - {2722,2721,2669 ,3014,2917,3015 }, {2949,2557,2920 ,3239,3620,1799 }, - {2914,2765,2965 ,2573,2590,3417 }, {2635,2578,2761 ,2607,3552,2768 }, - {2430,2133,2389 ,2613,2614,2609 }, {2131,2132,2865 ,656,655,3107 }, - {3036,3035,2984 ,3362,3364,3458 }, {6572,6573,6612 ,3734,3733,1389 }, - {2735,929,830 ,2887,1234,1996 }, {5702,3009,5038 ,3630,3747,3628 }, - {3482,3478,8069 ,2494,885,1095 }, {2556,2449,2430 ,2779,3259,2613 }, - {2449,91,2430 ,3259,1984,2613 }, {2934,2981,2933 ,3602,3550,3556 }, - {3235,3236,2456 ,3394,2717,2790 }, {2863,2886,2822 ,3242,2913,2826 }, - {7371,7423,7370 ,3748,3749,3750 }, {2249,6897,6531 ,3751,54,2280 }, - {3258,3484,1009 ,542,283,3752 }, {7797,7848,7823 ,3506,343,345 }, - {3763,2707,1305 ,3753,235,466 }, {4083,4157,5458 ,3754,3755,3756 }, - {1376,4610,4788 ,1937,3757,3758 }, {7826,7876,7853 ,1616,1725,1617 }, - {5352,8138,4022 ,3502,2018,3503 }, {6649,6648,6612 ,3759,1390,1389 }, - {1156,106,5138 ,3100,1073,1940 }, {2622,2567,2901 ,2840,2842,3468 }, - {3648,3701,3647 ,734,733,2521 }, {4248,3972,1159 ,3256,3487,3760 }, - {836,1068,1385 ,3551,3761,3762 }, {3819,1159,5414 ,3763,3760,3764 }, - {7412,7410,7411 ,3765,3766,3767 }, {3306,3326,3325 ,3695,826,825 }, - {1668,689,4206 ,3212,1363,682 }, {1668,4206,141 ,3212,682,681 }, - {7825,7850,7824 ,3768,3769,3770 }, {1009,2607,1250 ,3752,2452,3771 }, - {7246,7268,7291 ,3772,3773,3774 }, {7979,8003,8002 ,3775,3776,3777 }, - {3690,958,872 ,3778,3779,2962 }, {5414,1159,3673 ,3764,3760,648 }, - {2731,3690,872 ,659,3778,2962 }, {3690,2394,958 ,3778,3780,3779 }, - {1594,3312,958 ,3781,3782,3779 }, {2394,1594,958 ,3780,3781,3779 }, - {5731,3615,5682 ,934,201,3783 }, {1594,3098,3420 ,3781,3784,3785 }, - {3312,1594,3420 ,3782,3781,3785 }, {3098,3254,3299 ,3784,3233,3232 }, - {3420,3098,3299 ,3785,3784,3232 }, {6355,6356,5151 ,3786,3787,1803 }, - {6311,8114,8122 ,1097,2286,384 }, {3169,3128,3170 ,2810,2809,3510 }, - {1510,3893,5862 ,3788,3789,3790 }, {8075,8105,8107 ,2308,3791,658 }, - {3454,3340,4424 ,710,114,3792 }, {4424,3340,6414 ,3792,114,113 }, - {5327,5300,6525 ,3702,3793,3703 }, {1942,1668,141 ,2337,3212,681 }, - {6415,4424,6414 ,386,3792,113 }, {8089,8097,3861 ,254,1710,1147 }, - {5259,4827,5282 ,3794,2734,1194 }, {5302,5706,6008 ,3795,3796,3797 }, - {2892,1669,771 ,918,3798,3799 }, {2582,3513,1017 ,873,441,1793 }, - {5299,6041,5251 ,3800,3801,3802 }, {7796,7823,7795 ,3803,345,3804 }, - {3371,685,794 ,3708,2674,3392 }, {3306,3325,3305 ,3695,825,879 }, - {3932,652,55 ,1096,334,3507 }, {3998,4040,4039 ,381,460,382 }, - {637,3585,3736 ,3805,3806,3807 }, {3474,637,3736 ,3808,3805,3807 }, - {1068,3685,3057 ,3761,3809,3810 }, {3685,3474,3736 ,3809,3808,3807 }, - {1385,1068,3057 ,3762,3761,3810 }, {3685,3736,3057 ,3809,3807,3810 }, - {541,1385,3057 ,3811,3762,3810 }, {3147,3477,4162 ,2285,1736,1738 }, - {8096,8136,8115 ,1796,2449,2448 }, {3477,4129,5785 ,1736,3812,1737 }, - {5680,5698,5679 ,50,44,2553 }, {836,1385,541 ,3551,3762,3811 }, - {2746,8089,3861 ,1517,254,1147 }, {3113,1734,269 ,410,2219,3813 }, - {3413,3441,3391 ,3814,2987,3815 }, {3701,3700,3647 ,733,2545,2521 }, - {296,3317,630 ,1558,1882,2491 }, {3493,3492,3432 ,3738,930,929 }, - {8124,8110,3271 ,1141,1140,1727 }, {3939,3955,3090 ,3539,3538,2805 }, - {4027,4712,1020 ,3470,3816,3817 }, {5231,922,5000 ,115,117,286 }, - {6041,5298,5273 ,3801,3818,3819 }, {3891,3890,3869 ,3820,1913,1912 }, - {7823,7847,7795 ,345,3521,3804 }, {2856,588,3549 ,3821,3822,3823 }, - {3690,1594,2394 ,3778,3781,3780 }, {5698,5726,5725 ,44,515,3824 }, - {4178,5297,4023 ,3825,3826,3827 }, {1694,836,541 ,3828,3551,3811 }, - {3453,3054,1787 ,917,916,2897 }, {531,34,62 ,3829,3830,3831 }, - {3441,3468,3440 ,2987,2688,2690 }, {3187,4371,3972 ,3402,3489,3487 }, - {3491,3544,3490 ,955,1153,2502 }, {7074,7073,7038 ,2747,662,3832 }, - {6613,6649,6612 ,3746,3759,1389 }, {6650,6680,6648 ,3833,3834,1390 }, - {3855,3891,3869 ,1511,3820,1912 }, {3504,3503,3468 ,2986,3835,2688 }, - {3441,3440,3391 ,2987,2690,3815 }, {3549,3369,62 ,3823,3836,3831 }, - {3529,3371,794 ,3837,3708,3392 }, {3369,531,62 ,3836,3829,3831 }, - {3529,794,3476 ,3837,3392,3838 }, {3568,3529,3476 ,3839,3837,3838 }, - {1783,543,1341 ,2251,3840,3841 }, {3891,3926,3890 ,3820,3125,1913 }, - {3612,3819,3473 ,3842,3763,649 }, {5785,4129,4162 ,1737,3812,1738 }, - {5242,5241,5220 ,3843,2120,2119 }, {7253,7252,6349 ,1855,3437,705 }, - {3764,3718,3316 ,3844,3845,2149 }, {3948,915,4326 ,280,443,219 }, - {3264,836,1694 ,2468,3551,3828 }, {882,3264,1694 ,3846,2468,3828 }, - {5258,5259,5282 ,1193,3794,1194 }, {3924,3968,3923 ,3847,3848,3849 }, - {5224,5244,5223 ,3850,79,3851 }, {5224,5223,4679 ,3850,3851,3852 }, - {7982,8007,7958 ,3853,3854,3855 }, {3339,3690,2731 ,3856,3778,659 }, - {3006,3339,2731 ,414,3856,659 }, {3279,1594,3690 ,3857,3781,3778 }, - {3339,3279,3690 ,3856,3857,3778 }, {1415,3098,1594 ,3858,3784,3781 }, - {3279,1415,1594 ,3857,3858,3781 }, {5286,5285,5241 ,3859,2169,2120 }, - {3392,3413,3391 ,3860,3814,3815 }, {5640,5679,5678 ,2214,2553,3861 }, - {1974,3549,62 ,3862,3823,3831 }, {4157,5481,5304 ,3755,3863,654 }, - {5639,5640,5656 ,2215,2214,3864 }, {5656,5640,5678 ,3864,2214,3861 }, - {5380,5385,5304 ,653,3865,654 }, {6649,6650,6648 ,3759,3833,1390 }, - {3511,3254,3098 ,539,3233,3784 }, {1415,3511,3098 ,3858,539,3784 }, - {3511,4019,3254 ,539,227,3233 }, {5013,8074,5950 ,684,2460,2873 }, - {6698,6697,6680 ,629,3866,3834 }, {3396,3764,3316 ,3867,3844,2149 }, - {2256,6390,2162 ,2323,3868,3278 }, {3828,4199,4186 ,1364,3869,683 }, - {4206,3828,4186 ,682,1364,683 }, {3864,138,1206 ,3517,434,2218 }, - {3972,3864,1206 ,3487,3517,2218 }, {6650,6698,6680 ,3833,629,3834 }, - {4009,4008,3967 ,3870,3871,3872 }, {6073,6055,3659 ,3873,3874,3875 }, - {834,96,1539 ,3876,836,835 }, {4861,4896,4669 ,3877,3878,3879 }, - {1724,3425,1249 ,3880,1859,2876 }, {834,1588,2856 ,3876,3881,3821 }, - {5354,4866,3907 ,3882,3641,3883 }, {3266,543,1783 ,3884,3840,2251 }, - {7796,7795,7745 ,3803,3804,650 }, {2785,1907,3878 ,1246,1245,1248 }, - {6574,6614,6613 ,3885,3886,3746 }, {3652,3651,3602 ,3887,3888,3889 }, - {3603,3652,3602 ,3890,3887,3889 }, {3392,3391,3332 ,3860,3815,3891 }, - {3309,3333,3308 ,3892,3893,3894 }, {3333,3392,3332 ,3893,3860,3891 }, - {3309,3308,3294 ,3892,3894,3895 }, {3333,3332,3308 ,3893,3891,3894 }, - {1415,3279,3339 ,3858,3857,3856 }, {3476,794,3252 ,3838,3392,781 }, - {1207,5153,5146 ,1074,3896,1075 }, {4291,920,4926 ,58,57,3897 }, - {3681,3258,1250 ,691,542,3771 }, {2813,3911,3738 ,3898,3899,3900 }, - {3294,3308,7110 ,3895,3894,1990 }, {3810,3853,3809 ,3901,3902,3903 }, - {5816,5833,5832 ,545,544,3904 }, {3968,4009,3967 ,3848,3870,3872 }, - {2472,13,1626 ,2009,910,564 }, {2659,3286,601 ,3485,56,3905 }, - {4005,2422,4004 ,3906,3907,3908 }, {4007,2798,4005 ,3909,420,3906 }, - {789,3878,1156 ,3910,1248,3100 }, {1510,1410,3893 ,3788,3911,3789 }, - {28,1096,88 ,1059,2727,3581 }, {3439,3438,3389 ,2689,3912,3913 }, - {3604,3603,3554 ,3384,3890,3914 }, {3861,8083,3456 ,1147,2103,1145 }, - {109,254,2039 ,1654,2008,1655 }, {3286,79,2990 ,56,1510,3646 }, - {2832,3694,2907 ,638,3915,111 }, {1882,4543,4980 ,894,3002,241 }, - {4714,4778,4777 ,1031,3916,3917 }, {6310,6742,6735 ,3918,3422,3472 }, - {3243,1111,4845 ,3919,3920,3921 }, {3336,6285,7095 ,3922,3923,3924 }, - {3911,1940,3738 ,3899,3925,3900 }, {3764,1412,3841 ,3844,3926,3927 }, - {3718,3764,3841 ,3845,3844,3927 }, {1412,2813,3738 ,3926,3898,3900 }, - {3841,1412,3738 ,3927,3926,3900 }, {3911,3447,1940 ,3899,3928,3925 }, - {552,3900,2945 ,3929,884,1239 }, {978,1029,977 ,1620,3930,3931 }, - {3373,206,1804 ,693,3932,2902 }, {3425,1693,1249 ,1859,264,2876 }, - {2357,2912,2422 ,3933,3934,3907 }, {3981,8140,3263 ,915,2269,252 }, - {3713,3712,3654 ,3935,1439,1438 }, {3655,3713,3654 ,3936,3935,1438 }, - {1215,6950,5006 ,3937,1349,1351 }, {5701,5682,5683 ,3938,3783,3939 }, - {8112,6351,8079 ,3530,1568,55 }, {5732,5731,5682 ,3940,934,3783 }, - {5701,5732,5682 ,3938,3940,3783 }, {4186,4199,1607 ,683,3869,3941 }, - {5832,3727,5831 ,3904,3942,3943 }, {931,1256,2910 ,3944,3945,3946 }, - {3224,931,2910 ,3947,3944,3946 }, {3653,3678,3652 ,1440,3948,3887 }, - {5732,5770,5769 ,3940,3949,932 }, {5731,5732,5769 ,934,3940,932 }, - {5770,5768,5769 ,3949,933,932 }, {7649,7699,7648 ,3950,3951,3952 }, - {5092,3766,4585 ,3953,3954,3955 }, {3619,2790,2740 ,3956,3576,3456 }, - {3554,3553,3502 ,3914,3957,3958 }, {3503,3554,3502 ,3835,3914,3958 }, - {592,1018,3368 ,1863,3959,3960 }, {20,348,75 ,3961,643,3962 }, - {7452,7451,7424 ,1875,3963,1188 }, {4005,4004,3964 ,3906,3908,3964 }, - {2422,731,4004 ,3907,3965,3908 }, {2798,2357,2422 ,420,3933,3907 }, - {6279,6278,7092 ,3966,3967,3968 }, {6870,6898,6796 ,2616,1946,2617 }, - {5308,564,4868 ,3528,3529,3969 }, {3712,3713,3714 ,1439,3935,3970 }, - {8138,3534,4022 ,2018,942,3503 }, {3537,3725,2072 ,1735,3971,1812 }, - {1556,3283,3252 ,3365,262,781 }, {406,746,2958 ,2566,2661,1374 }, - {3329,3362,3328 ,3972,1200,3973 }, {3616,4186,2795 ,3974,683,3975 }, - {3218,5480,4162 ,3976,1739,1738 }, {3962,3961,3918 ,3977,2346,2335 }, - {1256,931,1518 ,3945,3944,3978 }, {3652,3677,3651 ,3887,3979,3888 }, - {3708,3707,3651 ,3980,3981,3888 }, {4764,4765,4797 ,3982,3983,3984 }, - {6603,6744,1116 ,3985,3986,1401 }, {5838,6015,6083 ,3987,3988,3989 }, - {4837,1375,955 ,3990,325,3991 }, {3899,3760,5146 ,1938,2250,1075 }, - {3503,3502,3467 ,3835,3958,3992 }, {3440,3439,3390 ,2690,2689,3509 }, - {3391,3440,3390 ,3815,2690,3509 }, {635,20,75 ,2183,3961,3962 }, - {8134,6897,8120 ,3263,54,906 }, {5266,5288,5243 ,81,3993,3994 }, - {5306,5305,5335 ,462,2283,2523 }, {7425,7454,7397 ,3995,3996,1186 }, - {4868,4888,5379 ,3969,3997,3998 }, {5805,4129,5385 ,3999,3812,3865 }, - {6467,2407,6484 ,4000,4001,685 }, {4868,5340,5287 ,3969,4002,4003 }, - {6847,6899,3891 ,4004,4005,3820 }, {4129,5458,5385 ,3812,3756,3865 }, - {4199,694,4487 ,3869,1987,4006 }, {1333,2812,8064 ,849,1914,3141 }, - {3601,3650,3624 ,4007,4008,4009 }, {3257,5855,1974 ,4010,4011,3862 }, - {1584,694,4199 ,4012,1987,3869 }, {3809,3808,3753 ,3903,4013,4014 }, - {3252,1941,3283 ,781,1034,262 }, {4713,5768,5770 ,4015,933,3949 }, - {3907,4914,917 ,3883,65,4016 }, {1561,1459,407 ,1865,4017,4018 }, - {7595,7649,7594 ,4019,3950,4020 }, {4252,4157,4083 ,4021,3755,3754 }, - {2945,3339,3006 ,1239,3856,414 }, {7874,7924,7873 ,344,815,817 }, - {5392,5717,5122 ,4022,4023,4024 }, {3755,3809,3753 ,4025,3903,4014 }, - {5217,4797,5258 ,4026,3984,1193 }, {1018,3681,1486 ,3959,691,4027 }, - {3750,3681,1018 ,690,691,3959 }, {3681,1250,1486 ,691,3771,4027 }, - {4221,2955,592 ,1862,3640,1863 }, {592,3750,1018 ,1863,690,3959 }, - {4516,1152,1692 ,4028,4029,4030 }, {588,592,3368 ,3822,1863,3960 }, - {3274,3819,3612 ,3172,3763,3842 }, {834,1670,1588 ,3876,2327,3881 }, - {2314,6467,2223 ,3742,4000,2336 }, {530,2044,959 ,512,4031,1358 }, - {3747,3701,6249 ,2925,733,4032 }, {2203,1415,3339 ,4033,3858,3856 }, - {2945,2203,3339 ,1239,4033,3856 }, {3534,8121,6353 ,942,3466,749 }, - {3603,3602,3553 ,3890,3889,3957 }, {3554,3603,3553 ,3914,3890,3957 }, - {3748,3218,5385 ,4034,3976,3865 }, {1444,382,3318 ,4035,3534,4036 }, - {6030,5475,5576 ,4037,4038,4039 }, {3663,3511,1415 ,4040,539,3858 }, - {2203,3663,1415 ,4033,4040,3858 }, {5858,5254,3436 ,4041,4042,2145 }, - {556,5295,4471 ,4043,2188,2187 }, {4394,4323,4273 ,4044,4045,120 }, - {4043,2798,4007 ,419,420,3909 }, {6750,6749,6697 ,631,4046,3866 }, - {530,8072,3040 ,512,511,619 }, {4199,4487,1607 ,3869,4006,3941 }, - {2246,7067,5755 ,591,3585,4047 }, {4323,1297,2042 ,4045,4048,121 }, - {3809,3833,3808 ,3903,4049,4013 }, {4273,4323,2042 ,120,4045,121 }, - {803,6204,6203 ,144,4050,1249 }, {7797,7796,7745 ,3506,3803,650 }, - {3663,4029,3511 ,4040,225,539 }, {8092,8130,8098 ,2267,905,907 }, - {733,184,5006 ,4051,4052,1351 }, {4105,5392,5122 ,4053,4022,4024 }, - {1152,3274,3612 ,4029,3172,3842 }, {3819,4468,3473 ,3763,647,649 }, - {3001,1159,3819 ,3210,3760,3763 }, {3819,5414,4468 ,3763,3764,647 }, - {5957,4105,5122 ,4054,4053,4024 }, {3886,3887,3885 ,4055,4056,4057 }, - {8105,3006,8137 ,3791,414,2174 }, {3612,3473,2843 ,3842,649,4058 }, - {3577,2843,4469 ,4059,4058,4060 }, {1102,1733,4165 ,2317,2328,640 }, - {1692,2843,3577 ,4030,4058,4059 }, {1692,3612,2843 ,4030,3842,4058 }, - {3368,1018,3577 ,3960,3959,4059 }, {1486,1692,3577 ,4027,4030,4059 }, - {3344,592,588 ,1861,1863,3822 }, {1211,3327,3636 ,2007,439,1060 }, - {3844,1283,2476 ,2443,2978,2441 }, {3668,530,959 ,513,512,1358 }, - {3807,3806,3752 ,4061,4062,4063 }, {5799,5800,5815 ,4064,702,4065 }, - {3828,1454,4199 ,1364,2318,3869 }, {22,1468,2042 ,4066,174,121 }, - {2013,2380,1332 ,2242,2597,3492 }, {3292,3331,3291 ,4067,1183,1203 }, - {2607,4516,1250 ,2452,4028,3771 }, {3922,3965,3921 ,4068,4069,4070 }, - {3755,3754,3707 ,4025,4071,3981 }, {3677,3708,3651 ,3979,3980,3888 }, - {3708,3755,3707 ,3980,4025,3981 }, {3755,3753,3754 ,4025,4014,4071 }, - {1297,22,2042 ,4048,4066,121 }, {22,1451,1468 ,4066,175,174 }, - {3289,3288,7196 ,2056,2058,2401 }, {5928,3903,3915 ,4072,296,1575 }, - {7102,7129,7101 ,1240,1026,4073 }, {22,3786,1451 ,4066,4074,175 }, - {5693,5715,5714 ,4075,4076,4077 }, {3484,1300,1009 ,283,285,3752 }, - {4009,4007,4008 ,3870,3909,3871 }, {1018,1486,3577 ,3959,4027,4059 }, - {6281,6280,7090 ,4078,4079,4080 }, {6698,6750,6697 ,629,631,3866 }, - {3981,2833,3076 ,915,2065,2066 }, {2155,6353,5444 ,580,749,3410 }, - {2681,3119,2346 ,3254,3223,3252 }, {4856,4570,3834 ,4081,4082,4083 }, - {3006,552,2945 ,414,3929,1239 }, {2265,177,2297 ,2662,3618,2663 }, - {1483,834,1539 ,4084,3876,835 }, {3887,3923,3922 ,4056,3849,4068 }, - {3885,3887,3922 ,4057,4056,4068 }, {6386,4856,3834 ,4085,4081,4083 }, - {303,915,3948 ,4086,443,280 }, {68,4813,1655 ,4087,4088,4089 }, - {8100,4021,3482 ,1713,1712,2494 }, {1335,1443,1152 ,236,182,4029 }, - {3753,3807,3752 ,4014,4061,4063 }, {3871,1334,3748 ,397,1935,4034 }, - {1250,4516,1486 ,3771,4028,4027 }, {3555,3554,3503 ,4090,3914,3835 }, - {3972,1206,5389 ,3487,2218,4091 }, {6096,3765,6050 ,4092,4093,4094 }, - {3258,1009,1250 ,542,3752,3771 }, {4527,5305,3147 ,1740,2283,2285 }, - {4915,917,4914 ,64,4016,65 }, {3965,3964,3921 ,4069,3964,4070 }, - {5228,5247,5227 ,4095,4096,4097 }, {1935,913,915 ,4098,444,443 }, - {4866,5337,5354 ,3641,572,3882 }, {3968,3967,3923 ,3848,3872,3849 }, - {303,1935,915 ,4086,4098,443 }, {3263,2651,3075 ,252,1516,2670 }, - {3747,3700,3701 ,2925,2545,733 }, {3278,2691,79 ,1158,3169,1510 }, - {177,2363,2297 ,3618,2571,2663 }, {106,5146,5139 ,1073,1075,1939 }, - {3457,3348,2043 ,4099,2255,4100 }, {3348,684,2043 ,2255,4101,4100 }, - {2910,1256,3004 ,3946,3945,2437 }, {1219,1170,3471 ,4102,4103,4104 }, - {2795,4186,1607 ,3975,683,3941 }, {202,5957,5122 ,4105,4054,4024 }, - {1935,3622,913 ,4098,4106,444 }, {3850,3851,3885 ,4107,4108,4057 }, - {3851,3886,3885 ,4108,4055,4057 }, {3851,3850,3808 ,4108,4107,4013 }, - {3833,3851,3808 ,4049,4108,4013 }, {3966,4007,3965 ,4109,3909,4069 }, - {4008,4007,3967 ,3871,3909,3872 }, {4007,4005,4006 ,3909,3906,4110 }, - {7108,7095,7109 ,4111,3924,4112 }, {2607,1335,4516 ,2452,236,4028 }, - {5806,248,3350 ,4113,4114,2541 }, {3330,3329,3290 ,1185,3972,1204 }, - {3291,3330,3290 ,1203,1185,1204 }, {3330,3363,3329 ,1185,1911,3972 }, - {3389,3388,3329 ,3913,4115,3972 }, {3363,3389,3329 ,1911,3913,3972 }, - {7899,7898,7875 ,4116,4117,4118 }, {3931,3664,3475 ,1868,1557,1559 }, - {8125,8068,8117 ,752,1784,4119 }, {4516,1692,1486 ,4028,4030,4027 }, - {3972,5389,4185 ,3487,4091,409 }, {3001,4248,1159 ,3210,3256,3760 }, - {3709,3708,3652 ,4120,3980,3887 }, {8038,8052,8022 ,4121,4122,4123 }, - {5871,3337,5116 ,4124,4125,4126 }, {3294,7110,3309 ,3895,1990,3892 }, - {2380,2624,3012 ,2597,3132,3491 }, {3732,3818,2785 ,3536,1244,1246 }, - {5592,5705,1608 ,3671,4127,4128 }, {2813,3447,3911 ,3898,3928,3899 }, - {684,11,2043 ,4101,299,4100 }, {3926,3925,3889 ,3125,3227,3126 }, - {2968,2693,1693 ,263,3416,264 }, {1295,3348,3040 ,618,2255,619 }, - {2039,2472,1626 ,1655,2009,564 }, {3727,3616,1794 ,3942,3974,4129 }, - {3808,3850,3806 ,4013,4107,4062 }, {3849,3850,3884 ,4130,4107,4131 }, - {3724,5644,5495 ,4132,4133,4134 }, {3348,3457,3040 ,2255,4099,619 }, - {3556,3554,3555 ,3385,3914,4090 }, {7995,8020,7973 ,4135,1405,3624 }, - {273,272,205 ,1749,1680,1741 }, {5198,4710,5177 ,423,4136,424 }, - {2912,1379,931 ,3934,4137,3944 }, {4007,4006,3965 ,3909,4110,4069 }, - {3966,3965,3922 ,4109,4069,4068 }, {3923,3966,3922 ,3849,4109,4068 }, - {2912,3178,731 ,3934,4138,3965 }, {2798,2422,4005 ,420,3907,3906 }, - {6786,6785,6749 ,4139,4140,4046 }, {6750,6786,6749 ,631,4139,4046 }, - {3412,3387,3388 ,4141,1787,4115 }, {3389,3412,3388 ,3913,4141,4115 }, - {3438,3437,3387 ,3912,4142,1787 }, {1670,834,1483 ,2327,3876,4084 }, - {2698,5335,4236 ,105,2523,3488 }, {3706,3752,3705 ,4143,4063,4144 }, - {3624,3650,3601 ,4009,4008,4007 }, {6611,5401,6571 ,1391,4145,4146 }, - {5800,5816,5815 ,702,545,4065 }, {1588,2856,5855 ,3881,3821,4011 }, - {1005,3338,4368 ,3535,4147,4148 }, {3883,3922,3921 ,4149,4068,4070 }, - {3849,3884,3883 ,4130,4131,4149 }, {918,558,2044 ,4150,4151,4031 }, - {530,918,2044 ,512,4150,4031 }, {2868,2832,2869 ,1577,638,1576 }, - {3447,3736,3585 ,3928,3807,3806 }, {915,3341,4326 ,443,541,219 }, - {3622,4289,2892 ,4106,4152,918 }, {7090,6280,7091 ,4080,4079,4153 }, - {3283,3476,3252 ,262,3838,781 }, {913,3622,2892 ,444,4106,918 }, - {3880,3881,3918 ,2320,4154,2335 }, {4289,3172,2892 ,4152,4155,918 }, - {3850,3885,3884 ,4107,4057,4131 }, {694,2477,1607 ,1987,642,3941 }, - {5438,5439,6705 ,4156,4157,4158 }, {3296,3313,177 ,4159,4160,3618 }, - {3313,3343,3342 ,4160,2515,2514 }, {177,3313,3342 ,3618,4160,2514 }, - {166,85,4250 ,3729,2504,4161 }, {3178,2912,931 ,4138,3934,3944 }, - {7847,7846,7795 ,3521,4162,3804 }, {5831,1794,5830 ,3943,4129,4163 }, - {3257,1588,5855 ,4010,3881,4011 }, {2856,3549,1974 ,3821,3823,3862 }, - {5458,4157,5385 ,3756,3755,3865 }, {1152,3612,1692 ,4029,3842,4030 }, - {531,3577,4469 ,3829,4059,4060 }, {96,834,3909 ,836,3876,4164 }, - {3412,3438,3387 ,4141,3912,1787 }, {1733,1483,4165 ,2328,4084,640 }, - {1733,1670,1483 ,2328,2327,4084 }, {5305,4527,4236 ,2283,1740,3488 }, - {2405,4900,5578 ,4165,585,587 }, {2296,2264,2265 ,2664,4166,2662 }, - {3553,3601,3552 ,3957,4007,4167 }, {3849,3848,3806 ,4130,4168,4062 }, - {3848,3849,3883 ,4168,4130,4149 }, {1335,1152,4516 ,236,4029,4028 }, - {4162,5805,5385 ,1738,3999,3865 }, {3696,3697,3742 ,2325,2224,3419 }, - {3540,3541,3571 ,3357,981,3652 }, {6804,6803,6785 ,3342,4169,4140 }, - {5354,3907,4866 ,3882,3883,3641 }, {3285,4900,2405 ,3064,585,4165 }, - {6116,3336,7095 ,4170,3922,3924 }, {7974,7995,7973 ,4171,4135,3624 }, - {2088,3932,55 ,1667,1096,3507 }, {5764,5800,5799 ,537,702,4064 }, - {36,35,3866 ,1478,1338,1479 }, {3967,4007,3966 ,3872,3909,4109 }, - {3172,3093,1669 ,4155,4172,3798 }, {1538,3402,2410 ,0,3660,1 }, - {882,3271,8117 ,3846,1727,4119 }, {3613,2203,2945 ,4173,4033,1239 }, - {3455,3613,2945 ,886,4173,1239 }, {2892,3172,1669 ,918,4155,3798 }, - {3652,3708,3677 ,3887,3980,3979 }, {3468,3503,3467 ,2688,3835,3992 }, - {1248,1207,3878 ,2850,1074,1248 }, {5138,5139,5260 ,1940,1939,4174 }, - {834,1588,3257 ,3876,3881,4010 }, {635,2657,20 ,2183,2185,3961 }, - {3438,3466,3437 ,3912,4175,4142 }, {3501,3500,3437 ,4176,4177,4142 }, - {3466,3501,3437 ,4175,4176,4142 }, {3579,3550,3551 ,4178,4179,4180 }, - {3552,3579,3551 ,4167,4178,4180 }, {1454,1102,694 ,2318,2317,1987 }, - {1102,4165,694 ,2317,640,1987 }, {3473,3673,2153 ,649,648,4181 }, - {5109,5107,5108 ,4182,4183,4184 }, {874,3866,783 ,636,1479,679 }, - {4913,4866,3907 ,4185,3641,3883 }, {2368,2443,2365 ,2943,2942,3351 }, - {4003,1003,4002 ,4186,4187,4188 }, {1909,3663,2203 ,4189,4040,4033 }, - {3613,1909,2203 ,4173,4189,4033 }, {1338,4029,3663 ,1077,225,4040 }, - {1909,1338,3663 ,4189,1077,4040 }, {3093,5119,4942 ,4172,4190,4191 }, - {1669,3093,4942 ,3798,4172,4191 }, {6226,5562,3905 ,4192,4193,4194 }, - {3656,3655,3626 ,4195,3936,4196 }, {5705,5992,1608 ,4127,4197,4128 }, - {1022,969,793 ,4198,4199,4200 }, {4855,4809,1469 ,4201,4202,2361 }, - {3297,3314,3313 ,4203,3575,4160 }, {3313,3314,3343 ,4160,3575,2515 }, - {6786,6804,6785 ,4139,3342,4140 }, {3653,3652,3603 ,1440,3887,3890 }, - {5573,1525,407 ,2217,1866,4018 }, {3888,3924,3887 ,4204,3847,4056 }, - {3391,3390,3331 ,3815,3509,1183 }, {3332,3391,3331 ,3891,3815,1183 }, - {6803,6853,5587 ,4169,2505,1459 }, {3579,3601,3550 ,4178,4007,4179 }, - {3601,3578,3550 ,4007,4205,4179 }, {3624,3623,3578 ,4009,4206,4205 }, - {3601,3624,3578 ,4007,4009,4205 }, {3727,1794,5831 ,3942,4129,3943 }, - {3341,915,863 ,541,443,284 }, {3389,3438,3412 ,3913,3912,4141 }, - {931,1629,1518 ,3944,4207,3978 }, {1588,3344,2856 ,3881,1861,3821 }, - {3552,3601,3579 ,4167,4007,4178 }, {4003,4002,3963 ,4186,4188,4208 }, - {4393,5306,5335 ,463,462,2523 }, {3573,3591,3590 ,980,1652,1867 }, - {5572,407,3147 ,2284,4018,2285 }, {3290,3329,3289 ,1204,3972,2056 }, - {3218,4162,5385 ,3976,1738,3865 }, {8103,3283,3425 ,1291,262,1859 }, - {4558,4599,4631 ,4209,4210,1816 }, {1454,1584,4199 ,2318,4012,3869 }, - {5335,5305,4236 ,2523,2283,3488 }, {3314,2368,2365 ,3575,2943,3351 }, - {3343,3314,2365 ,2515,3575,3351 }, {2428,2872,784 ,371,311,4211 }, - {687,2088,1155 ,1665,1667,3333 }, {5697,5698,5725 ,2552,44,3824 }, - {5725,5726,5763 ,3824,515,4212 }, {3628,5045,6235 ,4213,4214,4215 }, - {5726,5764,5763 ,515,537,4212 }, {3248,6076,5982 ,4216,4217,4218 }, - {5045,6165,6235 ,4214,4219,4215 }, {6103,5988,6123 ,4220,2516,4221 }, - {4713,5837,5804 ,4015,3621,3623 }, {1333,3300,2812 ,849,694,1914 }, - {3300,3349,2812 ,694,2054,1914 }, {3336,3335,3309 ,3922,4222,3892 }, - {5471,5435,6640 ,2051,4223,4224 }, {5026,5165,4881 ,4225,4226,2731 }, - {8106,4835,8135 ,2438,2130,2439 }, {3998,3997,3957 ,381,380,295 }, - {3224,3178,931 ,3947,4138,3944 }, {3624,3650,3623 ,4009,4008,4206 }, - {75,348,268 ,3962,643,645 }, {5119,5424,5420 ,4190,4227,4228 }, - {1300,2607,1009 ,285,2452,3752 }, {4866,4913,4865 ,3641,4185,4229 }, - {4942,5119,5420 ,4191,4190,4228 }, {5424,201,84 ,4227,4230,4231 }, - {5420,5424,84 ,4228,4227,4231 }, {201,2643,3759 ,4230,4232,4233 }, - {84,201,3759 ,4231,4230,4233 }, {1160,3096,3241 ,3661,4234,3504 }, - {2316,8059,2275 ,3067,4235,3152 }, {3573,3572,3541 ,980,1931,981 }, - {3678,3709,3652 ,3948,4120,3887 }, {3710,3708,3709 ,4236,3980,4120 }, - {4846,1622,1517 ,4237,4238,600 }, {6324,3365,3335 ,4239,4240,4222 }, - {1851,1733,1102 ,4241,2328,2317 }, {3744,3796,3795 ,2390,2969,3448 }, - {4373,1851,1102 ,3288,4241,2317 }, {5763,5764,5799 ,4212,537,4064 }, - {2955,3750,592 ,3640,690,1863 }, {3850,3849,3806 ,4107,4130,4062 }, - {5877,5474,5489 ,4242,4243,4244 }, {5414,3673,4468 ,3764,648,647 }, - {7436,7464,7412 ,4245,4246,3765 }, {3338,1005,4207 ,4147,3535,4247 }, - {3852,3887,3886 ,4248,4056,4055 }, {3729,3772,3728 ,4249,4250,4251 }, - {3718,684,3348 ,3845,4101,2255 }, {1940,11,684 ,3925,299,4101 }, - {6257,5488,5473 ,3428,2730,3429 }, {7981,7980,7955 ,4252,4253,4254 }, - {6804,6854,6853 ,3342,3344,2505 }, {3756,3755,3708 ,4255,4025,3980 }, - {3656,3627,6534 ,4195,4256,4257 }, {3627,3656,3626 ,4256,4195,4196 }, - {5356,5663,5909 ,4258,4259,4260 }, {4928,3907,917 ,4261,3883,4016 }, - {1334,4236,5480 ,1935,3488,1739 }, {1851,1691,1733 ,4241,2326,2328 }, - {3373,3897,3349 ,693,4262,2054 }, {3751,3806,3729 ,4263,4062,4249 }, - {3806,3805,3729 ,4062,4264,4249 }, {3473,2153,4469 ,649,4181,4060 }, - {2843,3473,4469 ,4058,649,4060 }, {3324,3323,3304 ,881,1051,1050 }, - {976,7335,975 ,782,4265,4266 }, {3881,3920,3919 ,4154,4267,4268 }, - {3920,3963,3962 ,4267,4208,3977 }, {3919,3920,3962 ,4268,4267,3977 }, - {3963,4002,3962 ,4208,4188,3977 }, {2634,21,3759 ,4269,1231,4233 }, - {2643,2634,3759 ,4232,4269,4233 }, {3752,3751,3730 ,4063,4263,4270 }, - {3705,3752,3730 ,4144,4063,4270 }, {3919,3962,3918 ,4268,3977,2335 }, - {7720,7770,7747 ,4271,4272,331 }, {3547,6556,6598 ,803,4273,804 }, - {3372,3453,1908 ,2143,917,1058 }, {5923,6162,5591 ,2073,3598,3597 }, - {3837,1729,4286 ,3667,3666,4274 }, {3883,3885,3922 ,4149,4057,4068 }, - {3332,3331,3292 ,3891,1183,4067 }, {3714,3713,3655 ,3970,3935,3936 }, - {5870,3248,5939 ,4275,4216,4276 }, {3851,3852,3886 ,4108,4248,4055 }, - {3884,3885,3883 ,4131,4057,4149 }, {5283,5337,4830 ,570,572,3642 }, - {3316,3718,3348 ,2149,3845,2255 }, {3718,3841,684 ,3845,3927,4101 }, - {3841,1940,684 ,3927,3925,4101 }, {2634,3672,3987 ,4269,4277,1229 }, - {7930,7981,7955 ,4278,4252,4254 }, {6803,6804,6853 ,4169,3342,2505 }, - {3757,3758,3773 ,2281,1789,4279 }, {4105,3411,5392 ,4053,4280,4022 }, - {3398,3613,3455 ,4281,4173,886 }, {3478,3398,3455 ,885,4281,886 }, - {21,2634,3987 ,1231,4269,1229 }, {3300,3373,3349 ,694,693,2054 }, - {3848,3847,3805 ,4168,4282,4264 }, {3806,3848,3805 ,4062,4168,4264 }, - {7310,7344,7286 ,4283,2749,3460 }, {7698,7697,7648 ,333,651,3952 }, - {5411,5410,5376 ,4284,4285,2758 }, {3729,3728,3674 ,4249,4251,4286 }, - {3847,3846,3805 ,4282,4287,4264 }, {5307,5573,5572 ,461,2217,2284 }, - {6154,6141,3725 ,2387,2386,3971 }, {5306,5307,5572 ,462,461,2284 }, - {3881,3882,3920 ,4154,4288,4267 }, {3672,4423,3987 ,4277,4289,1229 }, - {3808,3806,3807 ,4013,4062,4061 }, {5239,5283,4830 ,482,570,3642 }, - {3252,794,2693 ,781,3392,3416 }, {3146,1909,3613 ,4290,4189,4173 }, - {3398,3146,3613 ,4281,4290,4173 }, {3735,1338,1909 ,4291,1077,4189 }, - {3146,3735,1909 ,4290,4291,4189 }, {3397,1257,1338 ,136,208,1077 }, - {3735,3397,1338 ,4291,136,1077 }, {3308,3332,3292 ,3894,3891,4067 }, - {3809,3852,3833 ,3903,4248,4049 }, {3852,3851,3833 ,4248,4108,4049 }, - {6279,7091,6280 ,3966,4153,4079 }, {5922,3445,5908 ,4292,1791,4293 }, - {3327,3404,1387 ,439,2170,2951 }, {6906,6905,6853 ,4294,2506,2505 }, - {6854,6906,6853 ,3344,4294,2505 }, {5194,4373,1102 ,727,3288,2317 }, - {1412,541,2813 ,3926,3811,3898 }, {3736,3447,2813 ,3807,3928,3898 }, - {3925,3924,3889 ,3227,3847,3126 }, {4423,160,4227 ,4289,4295,1564 }, - {3808,3807,3753 ,4013,4061,4014 }, {3883,3882,3847 ,4149,4288,4282 }, - {132,1518,2837 ,2503,3978,2511 }, {5296,5322,4023 ,4296,4297,3827 }, - {6283,7102,7088 ,4298,1240,4299 }, {3315,5194,1454 ,944,727,2318 }, - {3388,3387,3329 ,4115,1787,3972 }, {3675,3729,3674 ,4300,4249,4286 }, - {3729,3805,3772 ,4249,4264,4250 }, {3315,1454,3828 ,944,2318,1364 }, - {3987,4423,4227 ,1229,4289,1564 }, {7091,6279,7092 ,4153,3966,3968 }, - {160,5236,5237 ,4295,4301,1800 }, {4227,160,5237 ,1564,4295,1800 }, - {5263,5239,4830 ,4302,482,3642 }, {3711,3710,3653 ,1790,4236,1440 }, - {1670,3344,1588 ,2327,1861,3881 }, {541,3057,2813 ,3811,3810,3898 }, - {794,2494,2693 ,3392,3391,3416 }, {3764,1694,1412 ,3844,3828,3926 }, - {3309,3333,3334 ,3892,3893,399 }, {1606,1253,4055 ,3677,2353,3678 }, - {3178,3224,731 ,4138,3947,3965 }, {3967,3966,3923 ,3872,4109,3849 }, - {3344,2473,4221 ,1861,4303,1862 }, {5236,4834,5600 ,4301,4304,1801 }, - {3252,2693,2968 ,781,3416,263 }, {1556,3252,2968 ,3365,781,263 }, - {3864,1334,138 ,3517,1935,434 }, {1694,541,1412 ,3828,3811,3926 }, - {3404,3372,1387 ,2170,2143,2951 }, {882,1694,3396 ,3846,3828,3867 }, - {5237,5236,5600 ,1800,4301,1801 }, {4834,5787,2086 ,4304,4305,1802 }, - {7171,7208,7194 ,4306,1671,1670 }, {3556,3604,3554 ,3385,3384,3914 }, - {3521,3556,3503 ,4307,3385,3835 }, {3504,3521,3503 ,2986,4307,3835 }, - {3556,3555,3503 ,3385,4090,3835 }, {3542,3541,3487 ,979,981,3356 }, - {7495,7494,7462 ,4308,4309,4310 }, {4293,8065,3954 ,2732,96,3463 }, - {3969,3968,3924 ,3226,3848,3847 }, {3889,3924,3888 ,3126,3847,4204 }, - {3329,3328,3289 ,3972,3973,2056 }, {3848,3883,3847 ,4168,4149,4282 }, - {253,1158,966 ,2564,2744,2565 }, {5600,4834,2086 ,1801,4304,1802 }, - {2086,5787,377 ,1802,4305,4311 }, {7240,7287,7239 ,4312,3459,1527 }, - {3846,3881,3832 ,4287,4154,2322 }, {8120,2659,8098 ,906,3485,907 }, - {959,2044,501 ,1358,4031,4313 }, {3719,959,501 ,1356,1358,4313 }, - {6958,6957,6905 ,4314,4315,2506 }, {6276,7094,7093 ,4316,4317,4318 }, - {3882,3881,3846 ,4288,4154,4287 }, {3752,3806,3751 ,4063,4062,4263 }, - {141,4298,5832 ,681,3580,3904 }, {3925,3969,3924 ,3227,3226,3847 }, - {5181,5180,4631 ,4319,1878,1816 }, {2473,2955,4221 ,4303,3640,1862 }, - {3965,4005,3964 ,4069,3906,3964 }, {2422,2912,731 ,3907,3934,3965 }, - {3457,918,530 ,4099,4150,512 }, {75,2938,635 ,3962,4320,2183 }, - {3040,3457,530 ,619,4099,512 }, {3711,3757,3710 ,1790,2281,4236 }, - {6261,4044,4570 ,4321,4322,4082 }, {3057,3736,2813 ,3810,3807,3898 }, - {1694,3764,3396 ,3828,3844,3867 }, {1159,3972,4185 ,3760,3487,409 }, - {3274,3001,3819 ,3172,3210,3763 }, {5289,5288,5266 ,80,3993,81 }, - {3810,3811,3853 ,3901,4323,3902 }, {3889,3888,3853 ,3126,4204,3902 }, - {75,268,107 ,3962,645,2548 }, {6906,6958,6905 ,4294,4314,2506 }, - {1256,1518,132 ,3945,3978,2503 }, {2087,1256,132 ,2465,3945,2503 }, - {3846,3832,3804 ,4287,2322,4324 }, {3897,1804,3349 ,4262,2902,2054 }, - {5180,5242,5220 ,1878,3843,2119 }, {3800,1524,4697 ,4325,4326,4327 }, - {3676,3675,3623 ,4328,4300,4206 }, {6680,5471,6647 ,3834,2051,2050 }, - {3847,3882,3846 ,4282,4288,4287 }, {3650,3676,3623 ,4008,4328,4206 }, - {3964,3963,3920 ,3964,4208,4267 }, {3651,3706,3650 ,3888,4143,4008 }, - {3748,5385,5380 ,4034,3865,653 }, {5022,4669,1196 ,4329,3879,4330 }, - {3854,3889,3853 ,1512,3126,3902 }, {6116,7095,7094 ,4170,3924,4317 }, - {1159,4185,3673 ,3760,409,648 }, {7225,7246,7267 ,1672,3772,4331 }, - {7752,7751,7701 ,3514,4332,3515 }, {4797,5259,5258 ,3984,3794,1193 }, - {834,2856,1588 ,3876,3821,3881 }, {3909,834,3257 ,4164,3876,4010 }, - {5855,2856,1974 ,4011,3821,3862 }, {7312,7311,7262 ,4333,4334,4335 }, - {7797,7823,7796 ,3506,345,3803 }, {7825,7824,7771 ,3768,3770,4336 }, - {5286,5339,5285 ,3859,2223,2169 }, {107,268,751 ,2548,645,1365 }, - {7096,5473,3518 ,4337,3429,4338 }, {4369,4393,5335 ,104,463,2523 }, - {1339,3398,3478 ,4339,4281,885 }, {3449,1339,3478 ,2440,4339,885 }, - {3811,3810,3756 ,4323,3901,4255 }, {3757,3811,3756 ,2281,4323,4255 }, - {3757,3773,3811 ,2281,4279,4323 }, {3812,3854,3811 ,1513,1512,4323 }, - {407,3477,3147 ,4018,1736,2285 }, {1339,3564,3146 ,4339,4340,4290 }, - {3398,1339,3146 ,4281,4339,4290 }, {1334,5480,3218 ,1935,1739,3976 }, - {1670,1691,3344 ,2327,2326,1861 }, {1691,2473,3344 ,2326,4303,1861 }, - {3710,3709,3678 ,4236,4120,3948 }, {3653,3710,3678 ,1440,4236,3948 }, - {3962,4002,3961 ,3977,4188,2346 }, {3602,3601,3553 ,3889,4007,3957 }, - {4002,4001,3961 ,4188,2380,2346 }, {731,1003,4003 ,3965,4187,4186 }, - {3805,3846,3804 ,4264,4287,4324 }, {2219,5231,5000 ,177,115,286 }, - {8064,3975,3008 ,3141,728,546 }, {4078,1004,1919 ,4341,3452,1779 }, - {3368,3577,3369 ,3960,4059,3836 }, {3542,3591,3573 ,979,1652,980 }, - {7424,7423,7371 ,1188,3749,3748 }, {3038,1783,1341 ,4342,2251,3841 }, - {5288,4868,5287 ,3993,3969,4003 }, {4487,694,1607 ,4006,1987,3941 }, - {3969,4010,3968 ,3226,4343,3848 }, {3564,3782,3735 ,4340,4344,4291 }, - {3146,3564,3735 ,4290,4340,4291 }, {3370,3397,3735 ,2303,136,4291 }, - {3782,3370,3735 ,4344,2303,4291 }, {1454,694,1584 ,2318,1987,4012 }, - {4710,5218,4770 ,4136,483,4345 }, {1443,3274,1152 ,182,3172,4029 }, - {4236,4527,5480 ,3488,1740,1739 }, {4527,3147,4162 ,1740,2285,1738 }, - {4006,4005,3965 ,4110,3906,4069 }, {5572,5573,407 ,2284,2217,4018 }, - {1256,2087,3004 ,3945,2465,2437 }, {1309,3935,685 ,3709,4346,2674 }, - {1483,1539,87 ,4084,835,641 }, {3871,3748,5850 ,397,4034,394 }, - {3329,3387,3362 ,3972,1787,1200 }, {3566,2557,3052 ,1146,3620,3715 }, - {4653,4654,4679 ,4347,4348,3852 }, {6116,6276,6286 ,4170,4316,4349 }, - {6853,6892,5626 ,2505,2507,1460 }, {147,4712,4027 ,3469,3816,3470 }, - {3243,1099,1111 ,3919,4350,3920 }, {3187,2698,4236 ,3402,105,3488 }, - {5218,5238,4770 ,483,4351,4345 }, {3748,3749,5850 ,4034,652,394 }, - {2713,4091,3259 ,4352,123,407 }, {3304,3303,7333 ,1050,1049,4353 }, - {7948,7947,7896 ,3625,4354,4355 }, {3446,3472,5608 ,3718,3155,4356 }, - {6276,6116,7094 ,4316,4170,4317 }, {3309,7110,7109 ,3892,1990,4112 }, - {3707,3706,3651 ,3981,4143,3888 }, {3553,3552,3519 ,3957,4167,4357 }, - {3520,3553,3519 ,4358,3957,4357 }, {4004,731,4003 ,3908,3965,4186 }, - {3773,3758,3812 ,4279,1789,1513 }, {1003,2910,393 ,4187,3946,2400 }, - {3881,3880,3832 ,4154,2320,2322 }, {3271,3396,3316 ,1727,3867,2149 }, - {3289,3328,3307 ,2056,3973,2057 }, {4022,8111,5353 ,3503,4359,851 }, - {1630,924,56 ,1016,3634,2606 }, {3451,3537,3516 ,1720,1735,1721 }, - {4600,4653,4599 ,4360,4347,4210 }, {3566,3052,2397 ,1146,3715,3669 }, - {5385,4157,5304 ,3865,3755,654 }, {3883,3921,3920 ,4149,4070,4267 }, - {3753,3752,3706 ,4014,4063,4143 }, {7983,8095,8105 ,4361,4362,3791 }, - {4002,1003,4001 ,4188,4187,2380 }, {2544,2622,601 ,2451,2840,3905 }, - {149,454,2471 ,3736,4363,3653 }, {3456,2920,2557 ,1145,1799,3620 }, - {4165,1483,87 ,640,4084,641 }, {3502,3553,3520 ,3958,3957,4358 }, - {3331,3390,3364 ,1183,3509,1184 }, {2043,143,918 ,4100,157,4150 }, - {4056,2421,4161 ,1123,2568,4364 }, {3457,2043,918 ,4099,4100,4150 }, - {5833,141,5832 ,544,681,3904 }, {3757,3756,3710 ,2281,4255,4236 }, - {6186,3518,5488 ,4365,4338,2730 }, {7203,7240,7220 ,4366,4312,4367 }, - {3130,3086,3087 ,3414,3413,3573 }, {6997,6996,6957 ,4368,4369,4315 }, - {507,5309,505 ,1523,987,986 }, {3812,3758,3813 ,1513,1789,1515 }, - {115,3081,3241 ,2901,1017,3504 }, {3096,115,3241 ,4234,2901,3504 }, - {1657,1552,3156 ,1781,2266,3164 }, {923,924,1630 ,4370,3634,1016 }, - {1663,923,1630 ,1015,4370,1016 }, {923,3640,924 ,4370,4371,3634 }, - {149,219,924 ,3736,3087,3634 }, {3640,149,924 ,4371,3736,3634 }, - {1383,1296,788 ,336,335,976 }, {53,2346,2573 ,4372,3252,3253 }, - {3882,3883,3920 ,4288,4149,4267 }, {6958,6997,6957 ,4314,4368,4315 }, - {7397,7371,7372 ,1186,3748,4373 }, {3513,3404,3327 ,441,2170,439 }, - {268,1664,751 ,645,2268,1365 }, {3811,3854,3853 ,4323,1512,3902 }, - {2651,2397,2381 ,1516,3669,3672 }, {6997,5752,6996 ,4368,4374,4369 }, - {3112,3993,3132 ,2795,2807,2796 }, {6285,7109,7095 ,3923,4112,3924 }, - {3170,1160,3211 ,3510,3661,3605 }, {869,2681,2346 ,4375,3254,3252 }, - {53,869,2346 ,4372,4375,3252 }, {3450,2464,2681 ,3330,3299,3254 }, - {869,3450,2681 ,4375,3330,3254 }, {7039,7038,5752 ,4376,3832,4374 }, - {7109,6285,3309 ,4112,3923,3892 }, {3651,3650,3624 ,3888,4008,4009 }, - {3749,3748,5380 ,652,4034,653 }, {3373,1804,3897 ,693,2902,4262 }, - {6276,6287,6286 ,4316,4377,4349 }, {4770,5238,5263 ,4345,4351,4302 }, - {3009,5701,5683 ,3747,3938,3939 }, {2624,3405,1153 ,3132,1798,2245 }, - {1794,3616,2795 ,4129,3974,3975 }, {3377,3378,3427 ,1443,1442,4378 }, - {6509,8092,8074 ,1452,2267,2460 }, {4032,3170,3129 ,3638,3510,3412 }, - {2829,1107,1106 ,2620,2656,1664 }, {6997,7039,5752 ,4368,4376,4374 }, - {1066,2558,105 ,680,977,249 }, {2850,2833,2803 ,3657,2065,3655 }, - {2910,3004,393 ,3946,2437,2400 }, {5238,5239,5263 ,4351,482,4302 }, - {5198,5218,4710 ,423,483,4136 }, {3486,3487,3540 ,4379,3356,3357 }, - {6390,2256,5950 ,3868,2323,2873 }, {538,53,3569 ,4380,4372,4381 }, - {3468,3467,3439 ,2688,3992,2689 }, {1387,1908,3636 ,2951,1058,1060 }, - {1378,1339,3449 ,925,4339,2440 }, {3334,3333,3309 ,399,3893,3892 }, - {3502,3520,3501 ,3958,4358,4176 }, {3921,3964,3920 ,4070,3964,4267 }, - {3706,3705,3650 ,4143,4144,4008 }, {3501,3519,3500 ,4176,4357,4177 }, - {3519,3552,3500 ,4357,4167,4177 }, {3552,3551,3500 ,4167,4180,4177 }, - {3602,3625,3601 ,3889,4382,4007 }, {3625,3651,3601 ,4382,3888,4007 }, - {1693,2693,1249 ,264,3416,2876 }, {1524,1907,3818 ,4326,1245,1244 }, - {1109,1160,4032 ,4383,3661,3638 }, {1109,3096,1160 ,4383,4234,3661 }, - {149,3640,923 ,3736,4371,4370 }, {2218,409,454 ,4384,1480,4363 }, - {1303,687,831 ,1933,1665,3334 }, {3428,3459,3458 ,3261,3241,4385 }, - {3378,3428,3427 ,1442,3261,4378 }, {88,3637,1453 ,3581,4386,3355 }, - {3636,88,1453 ,1060,3581,3355 }, {3378,3428,3406 ,1442,3261,399 }, - {6277,6287,6276 ,4387,4377,4316 }, {3266,4775,495 ,3884,4388,4389 }, - {3913,2698,4248 ,841,105,3256 }, {6133,3518,7084 ,4390,4338,4391 }, - {1487,3194,2150 ,531,1065,534 }, {3571,3572,3589 ,3652,1931,1932 }, - {3531,53,538 ,4392,4372,4380 }, {5936,6143,6125 ,4393,4394,4395 }, - {382,3732,3318 ,3534,3536,4036 }, {4630,4710,4709 ,827,4136,4396 }, - {5815,5816,5832 ,4065,545,3904 }, {3439,3467,3438 ,2689,3992,3912 }, - {3502,3501,3466 ,3958,4176,4175 }, {3650,3705,3676 ,4008,4144,4328 }, - {3705,3730,3676 ,4144,4270,4328 }, {3730,3675,3676 ,4270,4300,4328 }, - {3730,3751,3675 ,4270,4263,4300 }, {3751,3729,3675 ,4263,4249,4300 }, - {4004,4003,3963 ,3908,4186,4208 }, {3964,4004,3963 ,3964,3908,4208 }, - {3651,3624,3601 ,3888,4009,4007 }, {3602,3651,3625 ,3889,3888,4382 }, - {6186,7084,3518 ,4365,4391,4338 }, {1334,3218,3748 ,1935,3976,4034 }, - {1003,393,4001 ,4187,2400,2380 }, {3321,3322,3354 ,2461,1182,1293 }, - {3853,3888,3852 ,3902,4204,4248 }, {3756,3810,3755 ,4255,3901,4025 }, - {3772,5882,3728 ,4250,4397,4251 }, {3131,4033,4032 ,3732,4398,3638 }, - {3130,3131,4032 ,3414,3732,3638 }, {225,1109,4032 ,4399,4383,3638 }, - {4033,225,4032 ,4398,4399,3638 }, {3901,3096,1109 ,4400,4234,4383 }, - {225,3901,1109 ,4399,4400,4383 }, {3901,3949,3096 ,4400,4401,4234 }, - {2010,115,3096 ,4402,2901,4234 }, {3949,2010,3096 ,4401,4402,4234 }, - {2415,1663,115 ,4403,1015,2901 }, {2010,2415,115 ,4402,4403,2901 }, - {1301,923,1663 ,4404,4370,1015 }, {2415,1301,1663 ,4403,4404,1015 }, - {182,149,923 ,4405,3736,4370 }, {1301,182,923 ,4404,4405,4370 }, - {182,230,149 ,4405,4406,3736 }, {12,454,149 ,4407,4363,3736 }, - {230,12,149 ,4406,4407,3736 }, {130,2218,454 ,2341,4384,4363 }, - {12,130,454 ,4407,2341,4363 }, {150,409,2218 ,1481,1480,4384 }, - {6509,8074,5013 ,1452,2460,684 }, {2218,130,150 ,4384,2341,1481 }, - {3427,3428,3458 ,4378,3261,4385 }, {3459,3487,3486 ,3241,3356,4379 }, - {3958,3998,3957 ,294,381,295 }, {1946,131,4384 ,4408,2965,4409 }, - {2522,549,2451 ,2678,1129,2102 }, {495,3788,1341 ,4389,4410,3841 }, - {7777,7776,7730 ,4411,4412,4413 }, {1378,3687,3564 ,925,924,4340 }, - {1339,1378,3564 ,4339,925,4340 }, {3382,3407,3381 ,870,3012,871 }, - {3050,538,3532 ,4414,4380,4415 }, {3479,3531,538 ,4416,4392,4380 }, - {3050,3479,538 ,4414,4416,4380 }, {3479,53,3531 ,4416,4372,4392 }, - {295,869,53 ,4417,4375,4372 }, {3479,295,53 ,4416,4417,4372 }, - {295,2645,3450 ,4417,4418,3330 }, {869,295,3450 ,4375,4417,3330 }, - {3535,840,3450 ,442,68,3330 }, {2645,3535,3450 ,4418,442,3330 }, - {3687,3873,3782 ,924,1809,4344 }, {3488,3542,3487 ,1980,979,3356 }, - {3888,3887,3852 ,4204,4056,4248 }, {3853,3852,3809 ,3902,4248,3903 }, - {3707,3754,3706 ,3981,4071,4143 }, {3754,3753,3706 ,4071,4014,4143 }, - {3520,3519,3501 ,4358,4357,4176 }, {3467,3502,3466 ,3992,3958,4175 }, - {731,3224,1003 ,3965,3947,4187 }, {3224,2910,1003 ,3947,3946,4187 }, - {7691,450,449 ,4419,1653,1169 }, {3390,3439,3389 ,3509,2689,3913 }, - {3467,3466,3438 ,3992,4175,3912 }, {3738,1940,3841 ,3900,3925,3927 }, - {3710,3756,3708 ,4236,4255,3980 }, {3564,3687,3782 ,4340,924,4344 }, - {3873,3475,3370 ,1809,1559,2303 }, {3782,3873,3370 ,4344,1809,2303 }, - {4162,4129,5805 ,1738,3812,3999 }, {7075,7074,7038 ,4420,2747,3832 }, - {498,2010,3949 ,4421,4402,4401 }, {3901,498,3949 ,4400,4421,4401 }, - {2088,55,1155 ,1667,3507,3333 }, {3458,3459,3486 ,4385,3241,4379 }, - {1096,1975,3637 ,2727,4422,4386 }, {88,1096,3637 ,3581,2727,4386 }, - {7039,7075,7038 ,4376,4420,3832 }, {4600,4653,4679 ,4360,4347,3852 }, - {7451,7479,7423 ,3963,4423,3749 }, {630,879,3370 ,2491,1155,2303 }, - {3475,630,3370 ,1559,2491,2303 }, {543,495,1341 ,3840,4389,3841 }, - {7983,4744,5026 ,4361,4424,4225 }, {3617,3532,3375 ,4425,4415,4426 }, - {1208,1586,689 ,3211,943,1363 }, {2527,2486,2487 ,2637,2814,4427 }, - {2831,2832,2868 ,639,638,1577 }, {5845,6174,5113 ,143,2381,141 }, - {3604,3653,3603 ,3384,1440,3890 }, {3810,3809,3755 ,3901,3903,4025 }, - {1975,1096,784 ,4422,2727,4211 }, {498,2415,2010 ,4421,4403,4402 }, - {3696,3742,3741 ,2325,3419,3447 }, {3695,3696,3741 ,4428,2325,3447 }, - {300,183,499 ,3508,4429,4430 }, {3091,1390,300 ,3262,2964,3508 }, - {4617,4924,7074 ,4431,2745,2747 }, {7075,4617,7074 ,4420,4431,2747 }, - {5337,4866,5354 ,572,3641,3882 }, {1922,3244,4397 ,4432,4433,4434 }, - {2407,2258,6484 ,4001,1198,685 }, {3924,3923,3887 ,3847,3849,4056 }, - {6316,2162,6390 ,4435,3278,3868 }, {1299,295,3479 ,4436,4417,4416 }, - {295,3041,2645 ,4417,3182,4418 }, {3902,5970,4104 ,4437,3518,3519 }, - {2314,2223,2256 ,3742,2336,2323 }, {3426,3485,2615 ,4438,3524,2788 }, - {2566,3426,2615 ,2635,4438,2788 }, {2615,3485,2646 ,2788,3524,3070 }, - {2646,3485,2686 ,3070,3524,3071 }, {3539,3588,2740 ,3525,4439,3456 }, - {2686,3539,2740 ,3071,3525,3456 }, {2740,3588,3619 ,3456,4439,3956 }, - {3588,3641,2790 ,4439,4440,3576 }, {3619,3588,2790 ,3956,4439,3576 }, - {3641,3694,2832 ,4440,3915,638 }, {2790,3641,2832 ,3576,4440,638 }, - {3393,3392,3333 ,4441,3860,3893 }, {6467,6484,2223 ,4000,685,2336 }, - {3365,3333,3309 ,4240,3893,3892 }, {3132,4034,4033 ,2796,4442,4398 }, - {3131,3132,4033 ,3732,2796,4398 }, {4034,97,225 ,4442,4443,4399 }, - {4033,4034,225 ,4398,4442,4399 }, {1110,3901,225 ,4444,4400,4399 }, - {97,1110,225 ,4443,4444,4399 }, {585,498,3901 ,4445,4421,4400 }, - {1110,585,3901 ,4444,4445,4400 }, {919,2415,498 ,4446,4403,4421 }, - {585,919,498 ,4445,4446,4421 }, {54,1301,2415 ,4447,4404,4403 }, - {919,54,2415 ,4446,4447,4403 }, {224,182,1301 ,4448,4405,4404 }, - {54,224,1301 ,4447,4448,4404 }, {3056,230,182 ,4449,4406,4405 }, - {224,3056,182 ,4448,4449,4405 }, {400,12,230 ,4450,4407,4406 }, - {3056,400,230 ,4449,4450,4406 }, {95,130,12 ,3482,2341,4407 }, - {400,95,12 ,4450,3482,4407 }, {1798,89,130 ,4451,1482,2341 }, - {1155,300,499 ,3333,3508,4430 }, {1096,2749,784 ,2727,3286,4211 }, - {784,2749,2428 ,4211,3286,371 }, {1155,499,957 ,3333,4430,4452 }, - {1626,831,3253 ,564,3334,565 }, {3184,2618,3895 ,4453,4454,4455 }, - {831,1155,957 ,3334,3333,4452 }, {1004,4078,31 ,3452,4341,3450 }, - {8108,8066,8128 ,2287,960,959 }, {3770,3050,3617 ,4456,4414,4425 }, - {3346,3770,3617 ,4457,4456,4425 }, {3424,3479,3050 ,4458,4416,4414 }, - {3770,3424,3050 ,4456,4458,4414 }, {3635,1299,3479 ,4459,4436,4416 }, - {3424,3635,3479 ,4458,4459,4416 }, {3635,295,1299 ,4459,4417,4436 }, - {3635,1860,3041 ,4459,3183,3182 }, {295,3635,3041 ,4417,4459,3182 }, - {3618,1860,4204 ,37,3183,38 }, {832,3094,1059 ,613,634,678 }, - {3955,3995,3994 ,3538,3540,2806 }, {4617,1166,4924 ,4431,2746,2745 }, - {3365,3393,3333 ,4240,4441,3893 }, {2471,454,2536 ,3653,4363,2793 }, - {55,652,1383 ,3507,334,336 }, {1296,2558,788 ,335,977,976 }, - {3442,3441,3413 ,4460,2987,3814 }, {3393,3413,3392 ,4441,3814,3860 }, - {3342,2364,177 ,2514,2513,3618 }, {1558,919,585 ,4461,4446,4445 }, - {3643,3696,3695 ,2344,2325,4428 }, {3642,3643,3695 ,4462,2344,4428 }, - {3378,3406,3428 ,1442,399,3261 }, {6260,6053,5320 ,3397,4463,4464 }, - {7241,7240,7203 ,4465,4312,4366 }, {6996,5752,6957 ,4369,4374,4315 }, - {3335,3365,3309 ,4222,4240,3892 }, {2536,454,409 ,2793,4363,1480 }, - {3346,3375,4098 ,4457,4426,353 }, {1303,831,1626 ,1933,3334,564 }, - {2743,3944,3931 ,923,729,1868 }, {53,2573,3569 ,4372,3253,4381 }, - {3895,2618,3376 ,4455,4454,4466 }, {3539,3570,3588 ,3525,4467,4439 }, - {730,960,1985 ,1549,1326,1547 }, {1378,3449,8135 ,925,2440,2439 }, - {3420,3299,3474 ,3785,3232,3808 }, {58,2013,1332 ,2156,2242,3492 }, - {224,400,3056 ,4448,4450,4449 }, {8,4522,220 ,3341,3481,3340 }, - {1390,151,183 ,2964,2966,4429 }, {300,1390,183 ,3508,2964,4429 }, - {8131,7714,7983 ,2307,4468,4361 }, {1383,3091,300 ,336,3262,3508 }, - {55,1383,300 ,3507,336,3508 }, {3390,3389,3363 ,3509,3913,1911 }, - {3119,2681,2747 ,3223,3254,3224 }, {3805,3804,3772 ,4264,4324,4250 }, - {831,957,3253 ,3334,4452,565 }, {3299,637,3474 ,3232,3805,3808 }, - {366,1202,1204 ,4469,339,338 }, {3826,3770,3346 ,4470,4456,4457 }, - {784,4204,1860 ,4211,38,3183 }, {912,309,1166 ,4471,4472,2746 }, - {2162,2314,2256 ,3278,3742,2323 }, {3211,1160,3241 ,3605,3661,3504 }, - {4617,912,1166 ,4431,4471,2746 }, {79,3421,3278 ,1510,1156,1158 }, - {1537,4191,3802 ,4473,4474,4475 }, {3377,3427,3426 ,1443,4378,4438 }, - {2487,3377,3426 ,4427,1443,4438 }, {3427,3486,3485 ,4378,4379,3524 }, - {3426,3427,3485 ,4438,4378,3524 }, {3486,3540,3539 ,4379,3357,3525 }, - {3485,3486,3539 ,3524,4379,3525 }, {3540,3571,3570 ,3357,3652,4467 }, - {3539,3540,3570 ,3525,3357,4467 }, {3571,3589,3588 ,3652,1932,4439 }, - {3570,3571,3588 ,4467,3652,4439 }, {3589,3642,3641 ,1932,4462,4440 }, - {3588,3589,3641 ,4439,1932,4440 }, {3642,3695,3694 ,4462,4428,3915 }, - {3641,3642,3694 ,4440,4462,3915 }, {3695,3741,2907 ,4428,3447,111 }, - {3694,3695,2907 ,3915,4428,111 }, {3792,3791,2907 ,3421,3739,111 }, - {3741,3792,2907 ,3447,3421,111 }, {3881,3919,3918 ,4154,4268,2335 }, - {3420,3474,3685 ,3785,3808,3809 }, {3312,3420,3685 ,3782,3785,3809 }, - {4035,4034,3132 ,1601,4442,2796 }, {3993,4035,3132 ,2807,1601,2796 }, - {4035,2151,97 ,1601,1603,4443 }, {4034,4035,97 ,4442,1601,4443 }, - {2151,349,1110 ,1603,566,4444 }, {97,2151,1110 ,4443,1603,4444 }, - {3253,585,1110 ,565,4445,4444 }, {349,3253,1110 ,566,565,4444 }, - {957,1558,585 ,4452,4461,4445 }, {3253,957,585 ,565,4452,4445 }, - {2071,919,1558 ,4476,4446,4461 }, {957,2071,1558 ,4452,4476,4461 }, - {499,54,919 ,4430,4447,4446 }, {2071,499,919 ,4476,4430,4446 }, - {183,224,54 ,4429,4448,4447 }, {499,183,54 ,4430,4429,4447 }, - {151,400,224 ,2966,4450,4448 }, {183,151,224 ,4429,2966,4448 }, - {220,95,400 ,3340,3482,4450 }, {151,220,400 ,2966,3340,4450 }, - {3590,3643,3642 ,1867,2344,4462 }, {3589,3590,3642 ,1932,1867,4462 }, - {4037,4036,3994 ,3541,1602,2806 }, {958,3312,3685 ,3779,3782,3809 }, - {3393,3442,3413 ,4441,4460,3814 }, {1068,958,3685 ,3761,3779,3809 }, - {939,3346,4350 ,3354,4457,740 }, {1453,3826,3346 ,3355,4470,4457 }, - {939,1453,3346 ,3354,3355,4457 }, {3992,3770,3826 ,4477,4456,4470 }, - {1453,3992,3826 ,3355,4477,4470 }, {3637,3424,3770 ,4386,4458,4456 }, - {3992,3637,3770 ,4477,4386,4456 }, {1975,3635,3424 ,4422,4459,4458 }, - {3637,1975,3424 ,4386,4422,4458 }, {1975,784,1860 ,4422,4211,3183 }, - {3635,1975,1860 ,4459,4422,3183 }, {2829,1106,1062 ,2620,1664,1232 }, - {4031,2585,2474 ,3069,875,874 }, {8007,2287,2250 ,3854,3735,3716 }, - {8077,8113,3421 ,2078,1157,1156 }, {8096,5057,6796 ,1796,1795,2617 }, - {957,499,2071 ,4452,4430,4476 }, {131,220,151 ,2965,3340,2966 }, - {912,2240,2375 ,4471,4478,4479 }, {254,2472,2039 ,2008,2009,1655 }, - {3995,4037,3994 ,3540,3541,2806 }, {3278,1724,2851 ,1158,3880,3051 }, - {1668,1208,689 ,3212,3211,1363 }, {872,958,1068 ,2962,3779,3761 }, - {836,872,1068 ,3551,2962,3761 }, {1453,3637,3992 ,3355,4386,4477 }, - {3211,3169,3170 ,3605,2810,3510 }, {309,912,2375 ,4472,4471,4479 }, - {3427,3458,3486 ,4378,4385,4379 }, {1564,1922,1085 ,368,4432,369 }, - {1085,1859,703 ,369,4480,100 }, {1859,1625,703 ,4480,388,100 }, - {1859,4222,1625 ,4480,530,388 }, {4181,23,4100 ,2273,2272,4481 }, - {1933,4181,1695 ,470,2273,471 }, {4131,1087,2026 ,1656,4482,130 }, - {2026,1087,870 ,130,4482,2274 }, {1063,1092,1366 ,4483,4484,4485 }, - {1092,1424,1366 ,4484,2298,4485 }, {5728,5766,5727 ,4486,4487,514 }, - {4181,4100,1695 ,2273,4481,471 }, {245,1458,1148 ,4488,4489,160 }, - {1148,1458,1925 ,160,4489,161 }, {4061,4064,4060 ,4490,1880,2099 }, - {5766,5765,5727 ,4487,540,514 }, {4107,1932,770 ,4491,2141,275 }, - {1396,4107,770 ,34,4491,275 }, {4262,2,702 ,4492,4493,2699 }, - {4090,4148,4108 ,1487,2305,2304 }, {416,2091,604 ,556,4494,486 }, - {4090,4108,4089 ,1487,2304,4495 }, {2,265,443 ,4493,4496,920 }, - {1932,1792,2352 ,2141,324,390 }, {4090,4089,4070 ,1487,4495,4497 }, - {1600,311,209 ,4498,246,4499 }, {4257,4276,4275 ,698,1446,699 }, - {461,2,443 ,399,4493,920 }, {1792,955,1375 ,324,3991,325 }, {4109,4126,4175 ,576,124,4500 }, - {5700,5728,5727 ,4501,4486,514 }, {4061,4060,3347 ,4490,2099,2098 }, - {494,787,175 ,3041,209,211 }, {1872,1836,1808 ,2459,2490,4502 }, - {443,697,59 ,920,3578,967 }, {493,494,175 ,1785,3041,211 }, {8119,5261,8116 ,184,173,172 }, - {4175,3784,4218 ,4500,2252,4503 }, {5699,5700,5727 ,43,4501,514 }, - {6311,6390,8114 ,1097,3868,2286 }, {121,4155,1730 ,4504,4505,4506 }, - {665,761,760 ,1754,1826,3106 }, {1310,229,737 ,149,221,150 }, - {3867,1101,1851 ,4507,2,4241 }, {251,491,1517 ,603,487,600 }, - {3794,3795,3796 ,3449,3448,2969 }, {2423,1225,2428 ,433,327,371 }, - {2427,2254,3117 ,3237,3705,3407 }, {4357,4405,2941 ,4508,4509,109 }, - {3792,4357,2941 ,3421,4508,109 }, {4405,2940,2941 ,4509,110,109 }, - {4499,1205,2940 ,4510,3187,110 }, {5282,4827,5334 ,1194,2734,2736 }, - {2310,2504,4146 ,2442,2898,3730 }, {3794,3796,4259 ,3449,2969,4511 }, - {3794,4305,3793 ,3449,4512,3420 }, {3793,4357,3792 ,3420,4508,3421 }, - {4474,2940,4405 ,4513,110,4509 }, {4474,4499,2940 ,4513,4510,110 }, - {4474,1205,4499 ,4513,3187,4510 }, {596,548,549 ,1462,938,1129 }, - {23,1441,1063 ,2272,1485,4483 }, {4070,4069,4064 ,4497,1881,1880 }, - {4146,3844,2310 ,3730,2443,2442 }, {3585,4493,3447 ,3806,4514,3928 }, - {4533,64,3447 ,4515,297,3928 }, {4493,4533,3447 ,4514,4515,3928 }, - {4533,207,64 ,4515,4516,297 }, {4472,4491,1653 ,2189,107,106 }, - {237,236,99 ,869,2444,3743 }, {3794,4259,4305 ,3449,4511,4512 }, - {4434,4405,4357 ,4517,4509,4508 }, {4434,4474,4405 ,4517,4513,4509 }, - {4499,1205,4474 ,4510,3187,4513 }, {549,548,450 ,1129,938,1653 }, - {1425,121,1730 ,4518,4504,4506 }, {477,478,64 ,4519,2077,297 }, - {207,477,64 ,4516,4519,297 }, {1212,1178,4075 ,4520,206,4521 }, - {8109,5521,8110 ,2938,751,1140 }, {4357,4381,4434 ,4508,4522,4517 }, - {4474,4500,4499 ,4513,4523,4510 }, {1529,277,478 ,4524,85,2077 }, - {477,1529,478 ,4519,4524,2077 }, {1529,276,277 ,4524,4525,85 }, - {5641,5657,5640 ,510,48,2214 }, {4381,4357,4305 ,4522,4508,4512 }, - {4332,4381,4305 ,4526,4522,4512 }, {4434,4453,4474 ,4517,4527,4513 }, - {4453,4500,4474 ,4527,4523,4513 }, {4371,3864,3972 ,3489,3517,3487 }, - {276,463,277 ,4525,1941,85 }, {38,74,110 ,742,2053,743 }, {5680,5679,5640 ,50,2553,2214 }, - {8037,8050,4589 ,4528,4529,776 }, {3950,5352,3799 ,4530,3502,4531 }, - {4277,4259,4240 ,4532,4511,2060 }, {4332,4305,4259 ,4526,4512,4511 }, - {4277,4332,4259 ,4532,4526,4511 }, {4406,4381,4434 ,399,4522,4517 }, - {4381,4406,4434 ,4522,399,4517 }, {4381,4453,4434 ,4522,4527,4517 }, - {4500,366,1204 ,4523,4469,338 }, {4099,4327,561 ,4533,2377,2379 }, - {122,1467,755 ,4534,4535,1615 }, {4113,1178,1212 ,207,206,4520 }, - {504,4330,513 ,4536,399,377 }, {467,504,513 ,346,4536,377 }, - {4161,2421,2695 ,4364,2568,3453 }, {4259,3796,4240 ,4511,2969,2060 }, - {5641,5640,5599 ,510,2214,2213 }, {4260,4277,4240 ,3527,4532,2060 }, - {4358,4381,4332 ,4537,4522,4526 }, {4407,4406,4381 ,4538,399,4522 }, - {4358,4407,4381 ,4537,4538,4522 }, {4407,4435,4381 ,4538,4539,4522 }, - {4406,4407,4381 ,399,4538,4522 }, {4381,4435,4453 ,4522,4539,4527 }, - {4453,4501,4500 ,4527,4540,4523 }, {4501,4538,366 ,4540,4541,4469 }, - {4500,4501,366 ,4523,4540,4469 }, {342,343,1993 ,4542,4543,4544 }, - {4471,4472,1653 ,2187,2189,106 }, {513,1154,1343 ,377,4545,378 }, - {1343,1154,4399 ,378,4545,4546 }, {8111,4022,6836 ,4359,3503,852 }, - {2697,3977,3327 ,2006,440,439 }, {6892,6905,5626 ,2507,2506,1460 }, - {4359,4358,4332 ,4547,4537,4526 }, {4277,4359,4332 ,4532,4547,4526 }, - {4359,4407,4358 ,4547,4538,4537 }, {4453,4475,4501 ,4527,4548,4540 }, - {4538,1040,366 ,4541,1476,4469 }, {2240,3978,3945 ,4478,4549,4550 }, - {2313,321,1222 ,438,60,62 }, {378,1467,122 ,4551,4535,4534 }, - {4397,1859,1085 ,4434,4480,369 }, {8095,8090,8105 ,4362,412,3791 }, - {8131,7983,8105 ,2307,4361,3791 }, {2955,3761,3750 ,3640,218,690 }, - {5569,5570,5599 ,2075,508,2213 }, {4306,4359,4277 ,4552,4547,4532 }, - {4407,4408,4435 ,4538,4553,4539 }, {4435,4408,4453 ,4539,4553,4527 }, - {4453,4408,4475 ,4527,4553,4548 }, {4475,1904,4501 ,4548,2164,4540 }, - {1904,1906,4538 ,2164,1509,4541 }, {4501,1904,4538 ,4540,2164,4541 }, - {1906,1040,4538 ,1509,1476,4541 }, {1224,1201,1040 ,1508,1477,1476 }, - {887,4131,4222 ,4554,1656,530 }, {4156,887,4222 ,4555,4554,530 }, - {887,1087,4131 ,4554,4482,1656 }, {8113,8077,1724 ,1157,2078,3880 }, - {4360,4359,4306 ,4556,4547,4552 }, {4360,4382,4359 ,4556,4557,4547 }, - {4408,4407,4359 ,4553,4538,4547 }, {4382,4408,4359 ,4557,4553,4547 }, - {4476,1904,4475 ,4558,2164,4548 }, {1904,1224,1906 ,2164,1508,1509 }, - {649,492,175 ,1579,1580,211 }, {365,4521,606 ,402,179,180 }, - {1424,1528,1807 ,2298,4559,4560 }, {1807,1528,608 ,4560,4559,2300 }, - {1366,1424,1807 ,4485,2298,4560 }, {1087,1531,870 ,4482,4561,2274 }, - {1531,4107,1396 ,4561,4491,34 }, {3761,1463,3750 ,218,220,690 }, - {4307,4360,4306 ,4562,4556,4552 }, {4307,4382,4360 ,4562,4557,4556 }, - {4476,4475,4408 ,4558,4548,4553 }, {3977,2697,66 ,440,2006,4563 }, - {1222,4521,365 ,62,179,402 }, {4515,1651,1609 ,30,188,31 }, {260,4311,4312 ,1573,468,467 }, - {870,1531,1396 ,2274,4561,34 }, {1284,23,1063 ,4564,2272,4483 }, - {1509,377,1792 ,4565,4311,324 }, {1932,1509,1792 ,2141,4565,324 }, - {5223,5222,5182 ,3851,4566,4567 }, {1268,5301,2238 ,4568,2698,2697 }, - {1691,1101,2473 ,2326,2,4303 }, {6735,6742,3192 ,3472,3422,3063 }, - {489,2473,1101 ,3639,4303,2 }, {1868,1783,2217 ,2249,2251,4569 }, - {1783,3038,2217 ,2251,4342,4569 }, {4409,4436,4408 ,4570,4571,4553 }, - {4382,4409,4408 ,4557,4570,4553 }, {4436,4437,4408 ,4571,4572,4553 }, - {4437,3049,4476 ,4572,2803,4558 }, {4408,4437,4476 ,4553,4572,4558 }, - {4476,3049,1904 ,4558,2803,2164 }, {5834,5835,1942 ,543,4573,2337 }, - {4280,4159,413 ,1242,1299,351 }, {1837,363,380 ,997,427,2540 }, - {102,4312,4313 ,432,467,4574 }, {1079,987,1832 ,4575,2950,4576 }, - {4103,1731,604 ,4577,485,486 }, {4104,2504,3902 ,3519,2898,4437 }, - {23,1284,4100 ,2272,4564,4481 }, {2588,14,91 ,2072,1986,1984 }, - {1792,377,955 ,324,4311,3991 }, {3784,4239,4217 ,2252,2254,83 }, - {465,604,4304 ,4578,486,4579 }, {4888,4932,5379 ,3997,4580,3998 }, - {4653,4679,5182 ,4347,3852,4567 }, {8000,8023,7999 ,4581,4582,4583 }, - {4361,3938,4382 ,4584,3572,4557 }, {4307,4361,4382 ,4562,4584,4557 }, - {4382,3938,4409 ,4557,3572,4570 }, {3938,4437,4436 ,3572,4572,4571 }, - {4409,3938,4436 ,4570,3572,4571 }, {659,1730,802 ,71,4506,400 }, - {6949,6989,6947 ,4585,4586,4587 }, {2834,4961,2403 ,2860,2905,2904 }, - {1051,6,1858 ,4588,4589,4590 }, {1305,2892,3763 ,466,918,3753 }, - {1940,64,11 ,3925,297,299 }, {4356,4433,4432 ,155,4591,156 }, - {2504,2583,3902 ,2898,2672,4437 }, {4383,4311,490 ,399,468,469 }, - {210,1695,194 ,4592,471,4593 }, {4218,3784,4217 ,4503,2252,83 }, - {1695,4100,1933 ,471,4481,470 }, {4890,4918,4933 ,4594,4595,4596 }, - {3088,3132,3131 ,3290,2796,3732 }, {1091,5236,160 ,4597,4301,4295 }, - {1101,1691,1851 ,2,2326,4241 }, {4361,3939,3938 ,4584,3539,3572 }, - {3938,3112,4437 ,3572,2795,4572 }, {4437,3112,3049 ,4572,2795,2803 }, - {4253,4398,4048 ,4598,4599,4600 }, {1625,4251,4192 ,388,132,4601 }, - {4380,4452,4451 ,4602,2398,271 }, {2375,2240,3945 ,4479,4478,4550 }, - {771,1669,2707 ,3799,3798,235 }, {5986,1251,5563 ,4603,4604,4605 }, - {1976,4351,2390 ,1180,4606,1594 }, {4074,890,2959 ,4607,3283,4608 }, - {1421,1223,490 ,4609,2182,469 }, {207,4533,4493 ,4516,4515,4514 }, - {4494,207,4493 ,4610,4516,4514 }, {50,651,2709 ,4611,3591,3523 }, - {2856,3344,588 ,3821,1861,3822 }, {3938,3090,3112 ,3572,2805,2795 }, - {3112,3089,3049 ,2795,2794,2803 }, {0,4253,4048 ,4612,4598,4600 }, - {376,1564,842 ,379,368,4613 }, {5835,212,1942 ,4573,4614,2337 }, - {1633,4103,466 ,373,4577,347 }, {1051,793,6 ,4588,4200,4589 }, - {4889,4890,4933 ,4615,4594,4596 }, {5571,5643,1350 ,4616,4617,509 }, - {302,683,223 ,622,621,1985 }, {987,66,1832 ,2950,4563,4576 }, - {1748,1421,490 ,4618,4609,469 }, {1225,1223,57 ,327,2182,222 }, - {3786,1418,1934 ,4074,4619,4620 }, {275,1529,477 ,4621,4524,4519 }, - {1,4062,969 ,4622,4623,4199 }, {4080,1883,4253 ,4624,4625,4598 }, - {735,2012,1345 ,224,2212,203 }, {1462,1927,710 ,2338,1196,33 }, - {4829,4799,4770 ,4626,4627,4345 }, {5194,4395,4373 ,727,726,3288 }, - {2892,771,3763 ,918,3799,3753 }, {4192,4182,118 ,4601,435,1124 }, - {7008,7007,6967 ,3176,4628,4629 }, {275,276,1529 ,4621,4525,4524 }, - {1162,463,276 ,4630,1941,4525 }, {275,1162,276 ,4621,4630,4525 }, - {1631,504,467 ,4631,4536,346 }, {2044,558,465 ,4031,4151,4578 }, - {463,1631,467 ,1941,4631,346 }, {504,513,4330 ,4536,377,399 }, - {1070,1560,245 ,4632,4633,4488 }, {7804,7856,7803 ,4634,4635,4636 }, - {4062,500,969 ,4623,4637,4199 }, {802,439,1346 ,400,4638,484 }, - {4080,4253,316 ,4624,4598,4639 }, {5817,5818,5834 ,701,4640,543 }, - {4398,759,4242 ,4599,4641,4642 }, {1949,217,216 ,3637,4643,4644 }, - {1976,2390,1977 ,1180,1594,1503 }, {1747,1731,979 ,266,485,267 }, - {1154,513,4331 ,4545,377,4645 }, {4075,1993,344 ,4521,4544,562 }, - {4933,4918,4966 ,4596,4595,4646 }, {4239,85,4217 ,2254,2504,83 }, - {4714,4777,5267 ,1031,3917,4647 }, {1426,4062,500 ,4648,4623,4637 }, - {1377,4069,630 ,2651,1881,2491 }, {4329,4355,4380 ,1247,1447,4602 }, - {1742,1562,7051 ,707,4649,547 }, {1153,8087,6797 ,2245,385,2246 }, - {4149,4174,4148 ,1486,769,2305 }, {379,1114,1467 ,2299,2256,4535 }, - {1070,245,1163 ,4632,4488,2211 }, {4156,4222,1859 ,4555,530,4480 }, - {4502,4156,1859 ,4650,4555,4480 }, {1212,4075,447 ,4520,4521,4651 }, - {122,755,4113 ,4534,1615,207 }, {245,1560,1458 ,4488,4633,4489 }, - {1441,1092,1063 ,1485,4484,4483 }, {1308,1306,4245 ,4652,4653,4654 }, - {510,2092,191 ,4655,4656,4657 }, {759,4265,4242 ,4641,4658,4642 }, - {1858,6,217 ,4590,4589,4643 }, {4088,4124,4087 ,4659,2306,4660 }, - {4355,4356,4380 ,1447,155,4602 }, {196,607,94 ,152,2207,1858 }, - {2261,608,672 ,4661,2300,4662 }, {887,4050,1087 ,4554,4663,4482 }, - {1087,4050,1531 ,4482,4663,4561 }, {4107,4396,1932 ,4491,4664,2141 }, - {4145,660,67 ,101,387,1125 }, {4175,4218,4217 ,4500,4503,83 }, - {2660,890,4074 ,455,3283,4607 }, {512,1308,4245 ,4665,4652,4654 }, - {4279,1489,4139 ,4666,4667,4668 }, {362,4048,192 ,4669,4600,4670 }, - {215,71,81 ,4671,4672,4673 }, {5818,5835,5834 ,4640,4573,543 }, - {4124,4123,4087 ,2306,133,4660 }, {4109,4175,4149 ,576,4500,1486 }, - {1925,698,1425 ,161,4674,4518 }, {4396,377,1509 ,4664,4311,4565 }, - {1932,4396,1509 ,2141,4664,4565 }, {608,378,672 ,2300,4551,4662 }, - {754,1063,800 ,4675,4483,4676 }, {1063,1366,800 ,4483,4485,4676 }, - {1807,608,2261 ,4560,2300,4661 }, {4262,699,2 ,4492,4677,4493 }, - {4197,4258,4238 ,82,84,4678 }, {3532,4074,4057 ,4415,4607,272 }, - {209,311,648 ,4499,246,4679 }, {4141,1489,4279 ,4680,4667,4666 }, - {4398,4242,192 ,4599,4642,4670 }, {5802,5801,5765 ,4681,700,540 }, - {783,2663,688 ,679,3593,765 }, {4253,4049,4398 ,4598,4682,4599 }, - {4088,4087,630 ,4659,4660,2491 }, {4069,4088,630 ,1881,4659,2491 }, - {1308,512,1883 ,4652,4665,4625 }, {5684,4106,3345 ,4683,1742,3476 }, - {1595,4145,67 ,99,101,1125 }, {4356,4403,4380 ,155,154,4602 }, - {376,979,1731 ,379,267,485 }, {3532,2660,4074 ,4415,455,4607 }, - {4137,4095,1259 ,399,349,348 }, {124,5482,2661 ,2206,3565,4684 }, - {1284,1063,754 ,4564,4483,4675 }, {229,457,116 ,221,214,217 }, - {1695,1933,701 ,471,470,4685 }, {1933,4100,4274 ,470,4481,4686 }, - {1933,4274,701 ,470,4686,4685 }, {4257,4238,4276 ,698,4678,1446 }, - {4111,1871,1872 ,4687,2458,2459 }, {889,770,844 ,35,275,4688 }, - {4048,4398,192 ,4600,4599,4670 }, {215,81,422 ,4671,4673,4689 }, - {216,215,422 ,4644,4671,4689 }, {5766,5802,5765 ,4487,4681,540 }, - {4087,879,630 ,4660,1155,2491 }, {65,71,215 ,4690,4672,4671 }, - {1926,1308,1883 ,4691,4652,4625 }, {1462,710,4177 ,2338,33,2339 }, - {4160,2012,735 ,223,2212,224 }, {3375,3532,4057 ,4426,4415,272 }, - {1425,698,121 ,4518,4674,4504 }, {4350,3346,4098 ,740,4457,353 }, - {3585,4494,4493 ,3806,4610,4514 }, {5199,5240,5219 ,422,481,1860 }, - {476,275,477 ,4692,4621,4519 }, {2,658,265 ,4493,4693,4496 }, - {4137,1259,4095 ,399,348,349 }, {4251,4470,4182 ,132,4694,435 }, - {4352,3299,3990 ,4695,3232,3231 }, {345,1489,4119 ,4696,4667,4697 }, - {362,192,71 ,4669,4670,4672 }, {1306,655,345 ,4653,1122,4696 }, - {3324,3304,3305 ,881,1050,879 }, {4098,3375,4057 ,353,4426,272 }, - {1935,3172,4289 ,4098,4155,4152 }, {275,318,463 ,4621,4698,1941 }, - {1162,275,463 ,4630,4621,1941 }, {1695,701,194 ,471,4685,4593 }, - {463,318,1631 ,1941,4698,4631 }, {504,4118,513 ,4536,4699,377 }, - {1113,117,4213 ,10,9,1070 }, {4117,4156,4502 ,4700,4555,4650 }, - {4117,4157,4156 ,4700,3755,4555 }, {4252,887,4156 ,4021,4554,4555 }, - {3141,4127,4176 ,4701,4702,4703 }, {4227,5237,5307 ,1564,1800,461 }, - {443,444,702 ,920,922,2699 }, {2255,939,4350 ,3229,3354,740 }, - {683,196,223 ,621,152,1985 }, {345,4161,1489 ,4696,4364,4667 }, - {4161,4210,1489 ,4364,4704,4667 }, {5801,5802,5817 ,700,4681,701 }, - {65,362,71 ,4690,4669,4672 }, {2859,31,4139 ,3451,3450,4668 }, - {824,4245,2092 ,4705,4654,4656 }, {4245,1306,345 ,4654,4653,4696 }, - {4177,889,379 ,2339,35,2299 }, {265,4539,697 ,4496,633,3578 }, - {4157,4252,4156 ,3755,4021,4555 }, {4252,4102,887 ,4021,4706,4554 }, - {4155,699,4262 ,4505,4677,4492 }, {5237,2086,1525 ,1800,1802,1866 }, - {4102,4050,887 ,4706,4663,4554 }, {1531,1530,4107 ,4561,4707,4491 }, - {1530,4314,4396 ,4707,1864,4664 }, {4107,1530,4396 ,4491,4707,4664 }, - {4058,4061,3347 ,4708,4490,2098 }, {4081,1079,1926 ,4709,4575,4691 }, - {759,824,2092 ,4641,4705,4656 }, {4279,4139,563 ,4666,4668,4710 }, - {0,4048,362 ,4612,4600,4669 }, {4062,1426,500 ,4623,4648,4637 }, - {3317,4069,1377 ,1882,1881,2651 }, {3452,987,1079 ,1794,2950,4575 }, - {416,466,2091 ,556,347,4494 }, {466,604,2091 ,347,486,4494 }, - {3622,1935,4289 ,4106,4098,4152 }, {4201,4181,4051 ,436,2273,437 }, - {4314,2086,377 ,1864,1802,4311 }, {4396,4314,377 ,4664,1864,4311 }, - {447,4075,344 ,4651,4521,562 }, {4977,4999,4998 ,4711,4712,4713 }, - {4276,4302,4356 ,1446,3727,155 }, {6563,2343,8061 ,464,2685,453 }, - {5573,5237,1525 ,2217,1800,1866 }, {558,416,465 ,4151,556,4578 }, - {4109,4090,4076 ,576,1487,577 }, {1467,4084,755 ,4535,205,1615 }, - {66,2697,45 ,4563,2006,4714 }, {3532,3617,3050 ,4415,4425,4414 }, - {21,3946,1089 ,1231,1230,103 }, {133,284,1241 ,1719,139,313 }, - {2695,2859,4210 ,3453,3451,4704 }, {4161,2695,4210 ,4364,3453,4704 }, - {759,2092,510 ,4641,4656,4655 }, {5802,5818,5817 ,4681,4640,701 }, - {510,191,263 ,4655,4657,4715 }, {71,27,81 ,4672,303,4673 }, {4087,4123,879 ,4660,133,1155 }, - {4062,1426,4082 ,4623,4648,4716 }, {502,604,465 ,2301,486,4578 }, - {4058,4065,4061 ,4708,4717,4490 }, {279,325,4691 ,2176,2088,2089 }, - {1163,4160,1223 ,2211,223,2182 }, {4151,510,263 ,839,4655,4715 }, - {175,4262,702 ,211,4492,2699 }, {1619,3196,1686 ,1003,2581,1004 }, - {192,4242,43 ,4670,4642,304 }, {4312,490,1225 ,467,469,327 }, - {413,4159,4235 ,351,1299,985 }, {4082,3452,1079 ,4716,1794,4575 }, - {4238,4258,4302 ,4678,84,3727 }, {193,864,867 ,1448,840,1121 }, - {4079,4113,1212 ,4718,207,4520 }, {672,378,122 ,4662,4551,4534 }, - {4824,1602,4886 ,4719,2329,4720 }, {84,3759,2030 ,4231,4233,770 }, - {2995,2254,2702 ,2856,3705,2854 }, {4400,4450,3585 ,4721,4722,3806 }, - {637,4400,3585 ,3805,4721,3806 }, {4495,4494,3585 ,4723,4610,3806 }, - {4450,4495,3585 ,4722,4723,3806 }, {4238,4302,4276 ,4678,3727,1446 }, - {4257,4238,4276 ,698,4678,1446 }, {4258,4303,4302 ,84,3728,3727 }, - {1150,683,681 ,741,621,620 }, {2697,2255,45 ,2006,3229,4714 }, - {1006,962,1100 ,234,233,2466 }, {4101,1600,209 ,4724,4498,4499 }, - {192,43,27 ,4670,304,303 }, {4059,4193,609 ,363,4725,4726 }, - {1195,4347,4395 ,725,3287,726 }, {1150,774,683 ,741,767,621 }, - {4139,31,4078 ,4668,3450,4341 }, {7799,7825,7798 ,4727,3768,4728 }, - {4779,4778,4716 ,4729,3916,1030 }, {122,4113,4079 ,4534,207,4718 }, - {841,122,4079 ,4730,4534,4718 }, {4065,1253,4067 ,4717,2353,185 }, - {756,1748,490 ,4731,4618,469 }, {4311,756,490 ,468,4731,469 }, - {4494,4495,207 ,4610,4723,4516 }, {1366,1807,4133 ,4485,4560,4732 }, - {4263,2420,4056 ,274,273,1123 }, {38,1150,681 ,742,741,620 }, - {4062,1,4063 ,4623,4622,4733 }, {808,4472,5295 ,4734,2189,2188 }, - {71,192,27 ,4672,4670,303 }, {4051,1695,210 ,437,471,4592 }, - {5681,5700,5699 ,2934,4501,43 }, {4071,4070,4064 ,186,4497,1880 }, - {4335,4265,4151 ,838,4658,839 }, {4242,642,43 ,4642,1243,304 }, - {3347,206,4058 ,2098,3932,4708 }, {4121,4139,4078 ,4735,4668,4341 }, - {0,362,65 ,4612,4669,4690 }, {3271,8125,8117 ,1727,752,4119 }, - {216,65,215 ,4644,4690,4671 }, {5618,5420,103 ,127,4228,128 }, - {1931,4644,5019 ,4736,2425,2384 }, {4067,4071,4065 ,185,186,4717 }, - {240,4724,1790 ,1571,4737,4738 }, {260,1210,4311 ,1573,4739,468 }, - {4183,1210,260 ,1572,4739,1573 }, {1070,4073,1560 ,4632,4740,4633 }, - {1730,4262,175 ,4506,4492,211 }, {476,477,207 ,4692,4519,4516 }, - {1134,476,207 ,4741,4692,4516 }, {800,1366,4133 ,4676,4485,4732 }, - {1441,4093,1092 ,1485,1484,4484 }, {4182,661,4201 ,435,2297,436 }, - {4470,880,661 ,4694,1483,2297 }, {4242,4265,642 ,4642,4658,1243 }, - {770,805,844 ,275,389,4688 }, {208,4114,1259 ,4742,362,348 }, - {143,2043,781 ,157,4100,158 }, {1421,1163,1223 ,4609,2211,2182 }, - {4313,2423,102 ,4574,433,432 }, {4265,4335,642 ,4658,838,1243 }, - {1481,654,231 ,194,93,92 }, {759,510,4151 ,4641,4655,839 }, {5986,5563,4550 ,4603,4605,716 }, - {4148,4123,4124 ,2305,133,2306 }, {322,46,5 ,1250,2232,350 }, - {4942,5420,5618 ,4191,4228,127 }, {1092,1462,4116 ,4484,2338,2340 }, - {4376,4073,1070 ,4743,4740,4632 }, {1560,2001,1458 ,4633,4744,4489 }, - {4116,4177,379 ,2340,2339,2299 }, {4376,1421,1748 ,4743,4609,4618 }, - {275,129,318 ,4621,730,4698 }, {4274,4100,72 ,4686,4481,4745 }, - {4376,1163,1421 ,4743,2211,4609 }, {4093,1462,1092 ,1484,2338,4484 }, - {5420,84,103 ,4228,4231,128 }, {5162,4942,5618 ,181,4191,127 }, - {4491,4519,226 ,107,4746,108 }, {1926,1832,1308 ,4691,4576,4652 }, - {4049,512,824 ,4682,4665,4705 }, {1992,214,781 ,834,87,158 }, - {3132,3088,3089 ,2796,3290,2794 }, {21,1089,5203 ,1231,103,102 }, - {614,609,1367 ,1397,4726,574 }, {4059,609,614 ,363,4726,1397 }, - {4265,759,4151 ,4658,4641,839 }, {802,1730,4130 ,400,4506,210 }, - {608,379,378 ,2300,2299,4551 }, {824,512,4245 ,4705,4665,4654 }, - {3577,531,3369 ,4059,3829,3836 }, {4403,4432,4452 ,154,156,2398 }, - {4148,4173,4123 ,2305,134,133 }, {4196,4195,4173 ,4747,4748,134 }, - {4540,891,4526 ,19,189,187 }, {1163,4376,1070 ,2211,4743,4632 }, - {4274,72,701 ,4686,4745,4685 }, {1631,753,504 ,4631,4749,4536 }, - {504,753,4118 ,4536,4749,4699 }, {4134,658,2 ,4750,4693,4493 }, - {4100,1284,1368 ,4481,4564,4751 }, {1458,825,1925 ,4489,4752,161 }, - {3562,5944,3943 ,4753,4754,4755 }, {4394,4273,4796 ,4044,120,4756 }, - {1445,1469,1397 ,2359,2361,2358 }, {825,698,1925 ,4752,4674,161 }, - {4100,1368,72 ,4481,4751,4745 }, {4081,1926,4080 ,4709,4691,4624 }, - {844,805,1115 ,4688,389,2257 }, {1345,2012,1846 ,203,2212,204 }, - {705,4132,659 ,70,162,71 }, {4151,263,208 ,839,4715,4742 }, {4504,4151,208 ,4757,839,4742 }, - {1833,4151,4504 ,317,839,4757 }, {111,3014,258 ,1154,3568,3001 }, - {1625,4192,660 ,388,4601,387 }, {316,4253,0 ,4639,4598,4612 }, - {4380,4403,4452 ,4602,154,2398 }, {1308,1832,1306 ,4652,4576,4653 }, - {4148,4196,4173 ,2305,4747,134 }, {3946,2893,1089 ,1230,1679,103 }, - {214,466,142 ,87,347,159 }, {4076,4090,4070 ,577,1487,4497 }, - {262,194,312 ,4758,4593,4759 }, {4083,4102,4252 ,3754,4706,4021 }, - {670,4144,5043 ,4760,4761,4762 }, {1459,4050,4102 ,4017,4663,4706 }, - {4083,1459,4102 ,3754,4017,4706 }, {1459,4066,4050 ,4017,4763,4663 }, - {658,4243,265 ,4693,4764,4496 }, {376,1731,4103 ,379,485,4577 }, - {1926,1883,4080 ,4691,4625,4624 }, {4051,4181,1933 ,437,2273,470 }, - {2092,4245,4141 ,4656,4654,4680 }, {4093,4234,1462 ,1484,1197,2338 }, - {4234,1927,1462 ,1197,1196,2338 }, {563,4139,4121 ,4710,4668,4735 }, - {2031,2122,2067 ,1560,1128,1592 }, {81,27,545 ,4673,303,305 }, - {104,774,1150 ,4765,767,741 }, {4280,4335,1833 ,1242,838,317 }, - {4195,4216,4173 ,4748,1241,134 }, {979,1595,67 ,267,99,1125 }, - {702,444,649 ,2699,922,1579 }, {4243,317,265 ,4764,561,4496 }, - {4066,1459,1531 ,4763,4017,4561 }, {4050,4066,1531 ,4663,4763,4561 }, - {1459,1561,1530 ,4017,1865,4707 }, {1531,1459,1530 ,4561,4017,4707 }, - {266,699,4155 ,4766,4677,4505 }, {121,266,4155 ,4504,4766,4505 }, - {21,5203,2030 ,1231,102,770 }, {3476,1941,3568 ,3838,1034,3839 }, - {1530,1561,4314 ,4707,1865,1864 }, {4174,4175,4217 ,769,4500,83 }, - {3532,538,2660 ,4415,4380,455 }, {5643,5642,1350 ,4617,526,509 }, - {655,4056,345 ,1122,1123,4696 }, {4141,4119,1489 ,4680,4697,4667 }, - {81,545,323 ,4673,305,4767 }, {4065,4071,4064 ,4717,186,1880 }, - {4081,4080,500 ,4709,4624,4637 }, {963,786,962 ,1341,2071,233 }, - {2536,3017,49 ,2793,3369,3367 }, {191,4279,4114 ,4657,4666,362 }, - {263,191,4114 ,4715,4657,362 }, {793,316,0 ,4200,4639,4612 }, - {4978,6414,6413 ,178,113,112 }, {2502,2331,2504 ,3740,2895,2898 }, - {4067,4068,4077 ,185,408,126 }, {702,2,443 ,2699,4493,920 }, - {699,4134,2 ,4677,4750,4493 }, {6351,8103,8077 ,1568,1291,2078 }, - {416,502,465 ,556,2301,4578 }, {604,1747,4304 ,486,266,4579 }, - {885,321,2313 ,216,60,438 }, {1591,1032,1318 ,1072,1581,164 }, - {4201,661,4181 ,436,2297,2273 }, {2707,1669,5162 ,235,3798,181 }, - {1489,4210,4139 ,4667,4704,4668 }, {4234,4093,880 ,1197,1484,1483 }, - {191,4141,4279 ,4657,4680,4666 }, {208,263,4114 ,4742,4715,362 }, - {1331,1411,2041 ,790,850,2737 }, {5839,5807,5840 ,4768,4769,4770 }, - {1333,1936,3300 ,849,848,694 }, {5288,5308,4868 ,3993,3528,3969 }, - {5970,4146,2504 ,3518,3730,2898 }, {609,1919,1367 ,4726,1779,574 }, - {609,4078,1919 ,4726,4341,1779 }, {4195,4237,4216 ,4748,697,1241 }, - {4347,3867,1851 ,3287,4507,4241 }, {793,0,6 ,4200,4612,4589 }, - {4237,4275,4256 ,697,699,3433 }, {500,4080,316 ,4637,4624,4639 }, - {45,195,655 ,4714,739,1122 }, {8096,4031,2474 ,1796,3069,874 }, - {8110,8125,3271 ,1140,752,1727 }, {2558,1066,19 ,977,680,1067 }, - {318,129,695 ,4698,730,731 }, {447,344,317 ,4651,562,561 }, {265,317,4539 ,4496,561,633 }, - {1186,1623,1624 ,1605,1709,1708 }, {658,1212,447 ,4693,4520,4651 }, - {4079,1212,658 ,4718,4520,4693 }, {94,607,82 ,1858,2207,138 }, - {315,413,4235 ,352,351,985 }, {1669,4942,5162 ,3798,4191,181 }, - {4056,4161,345 ,1123,4364,4696 }, {43,642,739 ,304,1243,2233 }, - {934,880,4470 ,131,1483,4694 }, {653,1259,4053 ,318,348,1371 }, - {49,3017,1015 ,3367,3369,3368 }, {805,24,1115 ,389,247,2257 }, - {5240,5284,5264 ,481,571,1192 }, {1532,217,1949 ,4771,4643,3637 }, - {500,316,793 ,4637,4639,4200 }, {969,500,793 ,4199,4637,4200 }, - {147,792,4712 ,3469,95,3816 }, {979,67,970 ,267,1125,268 }, {4251,4182,4192 ,132,435,4601 }, - {4375,1591,981 ,312,1072,2128 }, {4400,4401,4450 ,4721,4772,4722 }, - {1730,4155,4262 ,4506,4505,4492 }, {1633,376,4103 ,373,379,4577 }, - {664,760,663 ,1755,3106,4773 }, {672,122,266 ,4662,4534,4766 }, - {1179,207,4495 ,4774,4516,4723 }, {1210,261,4311 ,4739,4775,468 }, - {294,4375,1132 ,945,312,61 }, {4779,4803,4778 ,4729,4776,3916 }, - {237,99,100 ,869,3743,2823 }, {4095,614,1805 ,349,1397,1071 }, - {6122,8096,2072 ,1797,1796,1812 }, {180,1946,4385 ,4777,4408,4778 }, - {3299,4352,4400 ,3232,4695,4721 }, {1131,1728,1015 ,4779,4780,3368 }, - {89,1131,1015 ,1482,4779,3368 }, {1728,408,1015 ,4780,4781,3368 }, - {7,49,1015 ,4782,3367,3368 }, {408,7,1015 ,4781,4782,3368 }, - {4114,4279,563 ,362,4666,4710 }, {2709,7,50 ,3523,4782,4611 }, - {842,1564,1595 ,4613,368,99 }, {4049,759,4398 ,4682,4641,4599 }, - {1665,456,455 ,3077,301,2205 }, {2866,2867,1205 ,2655,2844,3187 }, - {806,706,843 ,4783,4784,2423 }, {1132,4375,981 ,61,312,2128 }, - {266,122,841 ,4766,4534,4730 }, {1179,1134,207 ,4774,4741,4516 }, - {4133,1807,672 ,4732,4560,4662 }, {1601,476,1134 ,4785,4692,4741 }, - {1179,1601,1134 ,4774,4785,4741 }, {6643,8122,8101 ,3133,384,383 }, - {3452,3513,3977 ,1794,441,440 }, {1284,754,4073 ,4564,4675,4740 }, - {476,129,275 ,4692,730,4621 }, {1368,1284,4073 ,4751,4564,4740 }, - {4706,4763,4704 ,4786,4787,4788 }, {4431,4380,4451 ,568,4602,271 }, - {1066,4336,19 ,680,4789,1067 }, {4336,4384,600 ,4789,4409,978 }, - {19,4336,600 ,1067,4789,978 }, {4063,1426,4062 ,4733,4648,4623 }, - {260,4312,102 ,1573,467,432 }, {8,4505,1798 ,3341,4790,4451 }, - {4505,1799,1798 ,4790,4791,4451 }, {1799,1131,89 ,4791,4779,1482 }, - {1798,1799,89 ,4451,4791,1482 }, {176,408,1728 ,4792,4781,4780 }, - {1131,176,1728 ,4779,4792,4780 }, {4114,563,4059 ,362,4710,363 }, - {3308,3294,7110 ,3894,3895,1990 }, {4059,563,4193 ,363,4710,4725 }, - {563,4121,4193 ,4710,4735,4725 }, {1595,1564,4145 ,99,368,101 }, - {1092,4116,1424 ,4484,2340,2298 }, {318,753,1631 ,4698,4749,4631 }, - {1807,2261,672 ,4560,4661,4662 }, {261,4333,4311 ,4775,4793,468 }, - {1368,4073,4376 ,4751,4740,4743 }, {5458,4129,4083 ,3756,3812,3754 }, - {226,4519,1150 ,108,4746,741 }, {4177,710,889 ,2339,33,35 }, - {4315,4337,4336 ,4794,4795,4789 }, {1066,4315,4336 ,680,4794,4789 }, - {4337,4385,4384 ,4795,4778,4409 }, {4336,4337,4384 ,4789,4795,4409 }, - {180,4455,8 ,4777,4796,3341 }, {4455,4505,8 ,4796,4790,3341 }, - {1797,176,1131 ,4797,4792,4779 }, {1799,1797,1131 ,4791,4797,4779 }, - {782,786,777 ,1648,2071,421 }, {4121,4078,609 ,4735,4341,4726 }, - {759,4049,824 ,4641,4682,4705 }, {4311,4333,756 ,468,4793,4731 }, - {379,844,1114 ,2299,4688,2256 }, {2070,1095,614 ,573,1910,1397 }, - {4238,4257,4276 ,4678,698,1446 }, {4083,4129,1459 ,3754,3812,4017 }, - {4129,3477,1459 ,3812,1736,4017 }, {800,4133,1458 ,4676,4732,4489 }, - {1560,800,2001 ,4633,4676,4744 }, {69,25,1319 ,321,2186,322 }, - {118,4051,210 ,1124,437,4592 }, {4315,1450,4337 ,4794,823,4795 }, - {4385,4413,180 ,4778,4798,4777 }, {4413,4455,180 ,4798,4796,4777 }, - {4506,1797,1799 ,4799,4797,4791 }, {4505,4506,1799 ,4790,4799,4791 }, - {573,823,408 ,4800,4801,4781 }, {176,573,408 ,4792,4800,4781 }, - {50,7,408 ,4611,4782,4781 }, {823,50,408 ,4801,4611,4781 }, {2092,4141,191 ,4656,4680,4657 }, - {4193,4121,609 ,4725,4735,4726 }, {934,4234,880 ,131,1197,1483 }, - {4245,4119,4141 ,4654,4697,4680 }, {1926,1079,1832 ,4691,4575,4576 }, - {3985,789,3858 ,4802,3910,4803 }, {66,1211,2697 ,4563,2007,2006 }, - {4085,1368,4376 ,4804,4751,4743 }, {4149,4148,4090 ,1486,2305,1487 }, - {4085,4376,1748 ,4804,4743,4618 }, {4237,4238,4257 ,697,4678,698 }, - {2001,800,1458 ,4744,4676,4489 }, {4276,4356,4355 ,1446,155,1447 }, - {4108,4124,4088 ,2304,2306,4659 }, {7029,2341,3008 ,548,845,546 }, - {3763,771,2707 ,3753,3799,235 }, {1808,1836,380 ,4502,2490,2540 }, - {4337,4338,4385 ,4795,4805,4778 }, {4385,4338,4413 ,4778,4805,4798 }, - {4456,4506,4505 ,4806,4799,4790 }, {4455,4456,4505 ,4796,4806,4790 }, - {4506,895,1797 ,4799,4807,4797 }, {895,573,176 ,4807,4800,4792 }, - {1797,895,176 ,4797,4807,4792 }, {73,50,823 ,4808,4611,4801 }, - {1621,73,823 ,4809,4808,4801 }, {148,651,50 ,4810,3591,4611 }, - {73,148,50 ,4808,4810,4611 }, {212,1208,1942 ,4614,3211,2337 }, - {4251,934,4470 ,132,131,4694 }, {6,0,65 ,4589,4612,4690 }, {884,4059,614 ,2160,363,1397 }, - {1259,4059,4095 ,348,363,349 }, {1306,45,655 ,4653,4714,1122 }, - {1467,1114,4084 ,4535,2256,205 }, {3872,5188,5786 ,4811,4812,4813 }, - {4197,4238,4196 ,82,4678,4747 }, {379,889,844 ,2299,35,4688 }, - {842,1595,979 ,4613,99,267 }, {261,312,756 ,4775,4759,4731 }, - {312,194,756 ,4759,4593,4731 }, {1458,4133,825 ,4489,4732,4752 }, - {4238,4237,4196 ,4678,697,4747 }, {43,739,545 ,304,2233,305 }, - {2650,4031,8096 ,914,3069,1796 }, {4316,4338,4337 ,4814,4805,4795 }, - {1450,4316,4337 ,823,4814,4795 }, {4414,4456,4455 ,4815,4806,4796 }, - {4413,4414,4455 ,4798,4815,4796 }, {4456,4507,4506 ,4806,4816,4799 }, - {4506,4507,895 ,4799,4816,4807 }, {452,1621,823 ,4817,4809,4801 }, - {573,452,823 ,4800,4817,4801 }, {73,2254,148 ,4808,3705,4810 }, - {4373,4347,1851 ,3288,3287,4241 }, {217,6,216 ,4643,4589,4644 }, - {6,65,216 ,4589,4690,4644 }, {4210,2859,4139 ,4704,3451,4668 }, - {4071,4076,4070 ,186,577,4497 }, {4084,2047,1600 ,205,2258,4498 }, - {455,4471,259 ,2205,2187,2203 }, {194,701,756 ,4593,4685,4731 }, - {698,266,121 ,4674,4766,4504 }, {918,416,558 ,4150,556,4151 }, - {4077,4125,4109 ,126,125,576 }, {4144,670,261 ,4761,4760,4775 }, - {670,312,261 ,4760,4759,4775 }, {1114,2047,4084 ,2256,2258,205 }, - {4313,4312,1225 ,4574,467,327 }, {1148,4132,705 ,160,162,70 }, - {259,4471,258 ,2203,2187,3001 }, {1340,4266,1450 ,822,4818,823 }, - {1450,4266,4316 ,823,4818,4814 }, {2254,2995,148 ,3705,2856,4810 }, - {4363,4414,4413 ,4819,4815,4798 }, {4338,4363,4413 ,4805,4819,4798 }, - {4415,4457,4456 ,4820,4821,4806 }, {4414,4415,4456 ,4815,4820,4806 }, - {4456,4457,4507 ,4806,4821,4816 }, {895,452,573 ,4807,4817,4800 }, - {752,2254,73 ,4822,3705,4808 }, {8086,8087,1153 ,4823,385,2245 }, - {4171,659,802 ,399,71,400 }, {4245,345,4119 ,4654,4696,4697 }, - {4135,1259,4179 ,1069,348,251 }, {4159,4280,1833 ,1299,1242,317 }, - {3793,4305,4357 ,3420,4512,4508 }, {664,663,568 ,1755,4773,1723 }, - {4149,4175,4174 ,1486,4500,769 }, {5136,5178,4630 ,1817,524,827 }, - {4089,4088,4069 ,4495,4659,1881 }, {4070,4089,4069 ,4497,4495,1881 }, - {3978,6679,6418 ,4549,4824,3441 }, {4084,4101,1178 ,205,4724,206 }, - {4084,1600,4101 ,205,4498,4724 }, {2,461,443 ,4493,399,920 }, - {660,4192,118 ,387,4601,1124 }, {3615,5681,5660 ,201,2934,3054 }, - {1090,4266,1340 ,2687,4818,822 }, {4266,4317,4316 ,4818,4825,4814 }, - {4317,4363,4338 ,4825,4819,4805 }, {4316,4317,4338 ,4814,4825,4805 }, - {4364,4415,4414 ,4826,4820,4815 }, {4363,4364,4414 ,4819,4826,4815 }, - {4507,1769,895 ,4816,4827,4807 }, {1769,1084,895 ,4827,4828,4807 }, - {1084,246,452 ,4828,4829,4817 }, {895,1084,452 ,4807,4828,4817 }, - {246,1654,1621 ,4829,4830,4809 }, {452,246,1621 ,4817,4829,4809 }, - {1654,73,1621 ,4830,4808,4809 }, {1654,167,73 ,4830,4831,4808 }, - {167,752,73 ,4831,4822,4808 }, {2659,8120,3286 ,3485,906,56 }, - {5182,5181,4631 ,4567,4319,1816 }, {1883,512,4049 ,4625,4665,4682 }, - {4446,2607,1300 ,237,2452,285 }, {4089,4108,4088 ,4495,2304,4659 }, - {5158,5182,4631 ,4832,4567,1816 }, {7,2709,49 ,4782,3523,3367 }, - {3039,2040,1090 ,2686,4833,2687 }, {323,545,46 ,4767,305,2232 }, - {4352,4401,4400 ,4695,4772,4721 }, {2043,11,781 ,4100,299,158 }, - {2040,537,1090 ,4833,4834,2687 }, {537,4267,4266 ,4834,4835,4818 }, - {1090,537,4266 ,2687,4834,4818 }, {4266,4267,4317 ,4818,4835,4825 }, - {4318,4364,4363 ,4836,4826,4819 }, {4317,4318,4363 ,4825,4836,4819 }, - {4457,4523,4507 ,4821,4837,4816 }, {4523,1084,1769 ,4837,4828,4827 }, - {4507,4523,1769 ,4816,4837,4827 }, {1589,167,1654 ,4838,4831,4830 }, - {2276,2254,752 ,4839,3705,4822 }, {167,2276,752 ,4831,4839,4822 }, - {123,48,1049 ,3607,4840,1362 }, {2276,3117,2254 ,4839,3407,3705 }, - {1883,4049,4253 ,4625,4682,4598 }, {8063,8061,8102 ,465,453,253 }, - {130,95,1798 ,2341,3482,4451 }, {642,4280,413 ,1243,1242,351 }, - {699,841,4079 ,4677,4730,4718 }, {825,4133,698 ,4752,4732,4674 }, - {67,118,359 ,1125,1124,4841 }, {67,359,970 ,1125,4841,268 }, - {4133,672,698 ,4732,4662,4674 }, {136,1179,4495 ,1685,4774,4723 }, - {5182,5180,5181 ,4567,1878,4319 }, {5197,1928,4518 ,4842,1282,1281 }, - {4267,4318,4317 ,4835,4836,4825 }, {4415,4458,4457 ,4820,4843,4821 }, - {4458,4477,4457 ,4843,4844,4821 }, {4457,4477,4523 ,4821,4844,4837 }, - {246,641,1654 ,4829,4845,4830 }, {641,1589,1654 ,4845,4838,4830 }, - {354,2276,167 ,4846,4839,4831 }, {2379,3117,2276 ,3238,3407,4839 }, - {354,2379,2276 ,4846,3238,4839 }, {4275,4276,4329 ,699,1446,1247 }, - {1600,24,311 ,4498,247,246 }, {1115,24,1600 ,2257,247,4498 }, - {2314,2407,6467 ,3742,4001,4000 }, {659,1425,1730 ,71,4518,4506 }, - {118,210,359 ,1124,4592,4841 }, {266,841,699 ,4766,4730,4677 }, - {1601,76,476 ,4785,689,4692 }, {1925,1425,659 ,161,4518,71 }, - {76,1632,476 ,689,2241,4692 }, {476,1632,129 ,4692,2241,730 }, - {462,318,695 ,4847,4698,731 }, {4470,661,4182 ,4694,2297,435 }, - {7479,7478,7422 ,4423,1402,1404 }, {537,4268,4267 ,4834,4848,4835 }, - {4267,4268,4318 ,4835,4848,4836 }, {4364,4386,4415 ,4826,4849,4820 }, - {4386,4438,4415 ,4849,4850,4820 }, {4415,4438,4458 ,4820,4850,4843 }, - {4458,4438,4477 ,4843,4850,4844 }, {1084,854,246 ,4828,4851,4829 }, - {854,641,246 ,4851,4845,4829 }, {4451,4452,4498 ,271,2398,88 }, - {4196,4237,4195 ,4747,697,4748 }, {376,842,979 ,379,4613,267 }, - {4216,4237,4256 ,1241,697,3433 }, {4504,208,653 ,4757,4742,318 }, - {323,46,706 ,4767,2232,4784 }, {698,672,266 ,4674,4662,4766 }, - {4073,754,1560 ,4740,4675,4633 }, {8095,7983,8062 ,4362,4361,3272 }, - {753,462,695 ,4749,4847,731 }, {318,462,753 ,4698,4847,4749 }, - {3618,735,3535 ,37,224,442 }, {1245,735,3618 ,36,224,37 }, {4130,1730,175 ,210,4506,211 }, - {4339,4340,4364 ,4852,4853,4826 }, {4318,4339,4364 ,4836,4852,4826 }, - {4340,4386,4364 ,4853,4849,4826 }, {4523,1770,1084 ,4837,4854,4828 }, - {1770,854,1084 ,4854,4851,4828 }, {894,10,641 ,4855,4856,4845 }, - {854,894,641 ,4851,4855,4845 }, {1878,1589,641 ,4857,4838,4845 }, - {10,1878,641 ,4856,4857,4845 }, {1392,167,1589 ,4858,4831,4838 }, - {1878,1392,1589 ,4857,4858,4838 }, {1392,354,167 ,4858,4846,4831 }, - {537,6199,4268 ,4834,4859,4848 }, {214,142,781 ,87,159,158 }, - {8089,8082,8097 ,254,454,1710 }, {46,322,843 ,2232,1250,2423 }, - {4053,1259,4135 ,1371,348,1069 }, {1833,4504,653 ,317,4757,318 }, - {1163,245,2012 ,2211,4488,2212 }, {1424,4116,379 ,2298,2340,2299 }, - {615,614,1095 ,766,1397,1910 }, {4065,4064,4061 ,4717,1880,4490 }, - {148,2995,651 ,4810,2856,3591 }, {4132,1925,659 ,162,161,71 }, - {754,800,1560 ,4675,4676,4633 }, {1808,4111,1872 ,4502,4687,2459 }, - {4268,4269,4318 ,4848,4860,4836 }, {4269,4340,4339 ,4860,4853,4852 }, - {4318,4269,4339 ,4836,4860,4852 }, {4477,1770,4523 ,4844,4854,4837 }, - {1770,1737,4523 ,4854,4861,4837 }, {4523,1737,1770 ,4837,4861,4854 }, - {1737,894,854 ,4861,4855,4851 }, {1770,1737,854 ,4854,4861,4851 }, - {1086,354,1392 ,4862,4846,4858 }, {4163,2379,354 ,4863,3238,4846 }, - {1086,4163,354 ,4862,4863,4846 }, {5334,4887,5376 ,2736,2735,2758 }, - {5950,8074,8066 ,2873,2460,960 }, {4765,4764,4706 ,3983,3982,4786 }, - {4095,4059,884 ,349,363,2160 }, {4182,4051,118 ,435,437,1124 }, - {5182,5221,5180 ,4567,4864,1878 }, {709,653,544 ,316,318,195 }, - {341,632,2193 ,1852,1380,1007 }, {735,1345,3535 ,224,203,442 }, - {72,1368,4085 ,4745,4751,4804 }, {3477,407,1459 ,1736,4018,4017 }, - {4773,4844,4804 ,4865,4866,4867 }, {1835,1871,1870 ,2421,2458,4868 }, - {5377,5411,5376 ,361,4284,2758 }, {4269,4284,4340 ,4860,4869,4853 }, - {4438,4478,4477 ,4850,4870,4844 }, {4477,4478,1770 ,4844,4870,4854 }, - {1770,4478,1737 ,4854,4870,4861 }, {693,1878,10 ,4871,4857,4856 }, - {693,1392,1878 ,4871,4858,4857 }, {213,4163,1086 ,3606,4863,4862 }, - {102,240,260 ,432,1571,1573 }, {4074,2959,4057 ,4607,4608,272 }, - {2012,245,1846 ,2212,4488,204 }, {683,396,196 ,621,153,152 }, - {245,1148,1846 ,4488,160,204 }, {226,111,1653 ,108,1154,106 }, - {379,1467,378 ,2299,4535,4551 }, {4315,1066,1450 ,4794,680,823 }, - {5243,5242,5180 ,3994,3843,1878 }, {6225,4321,5630 ,4872,4873,4874 }, - {701,72,1748 ,4685,4745,4618 }, {72,4085,1748 ,4745,4804,4618 }, - {5814,5815,5831 ,4875,4065,3943 }, {5799,5815,5814 ,4064,4065,4875 }, - {5798,5799,5814 ,4876,4064,4875 }, {5815,5832,5831 ,4065,3904,3943 }, - {3945,3978,6418 ,4550,4549,3441 }, {4229,4284,4269 ,4877,4869,4860 }, - {4387,4439,4438 ,4878,4879,4850 }, {4386,4387,4438 ,4849,4878,4850 }, - {4438,4439,4478 ,4850,4879,4870 }, {942,693,10 ,4880,4871,4856 }, - {894,942,10 ,4855,4880,4856 }, {228,1086,1392 ,4881,4862,4858 }, - {228,213,1086 ,4881,3606,4862 }, {1806,439,802 ,3124,4638,400 }, - {2431,1304,2476 ,2977,2639,2441 }, {5221,5243,5180 ,4864,3994,1878 }, - {4379,4380,4431 ,567,4602,568 }, {5265,5241,5242 ,4882,2120,3843 }, - {4158,802,1346 ,72,400,484 }, {2041,553,1331 ,2737,792,790 }, - {6346,7254,7860 ,4883,450,452 }, {697,113,59 ,3578,677,967 }, - {5243,5265,5242 ,3994,4882,3843 }, {600,4384,131 ,978,4409,2965 }, - {705,4537,1093 ,70,67,66 }, {1846,705,1093 ,204,70,66 }, {4174,4197,4148 ,769,82,2305 }, - {261,756,4333 ,4775,4731,4793 }, {5763,5799,5798 ,4212,4064,4876 }, - {5762,5763,5798 ,4884,4212,4876 }, {1220,875,1920 ,4885,579,581 }, - {7076,1076,7075 ,4886,4887,4420 }, {4284,4341,4340 ,4869,4888,4853 }, - {4341,4387,4386 ,4888,4878,4849 }, {4340,4341,4386 ,4853,4888,4849 }, - {4387,4416,4439 ,4878,4889,4879 }, {1738,942,894 ,4890,4880,4855 }, - {1737,1738,894 ,4861,4890,4855 }, {942,33,693 ,4880,4891,4871 }, - {1856,1392,693 ,4892,4858,4871 }, {33,1856,693 ,4891,4892,4871 }, - {1856,1457,1392 ,4892,4893,4858 }, {1457,228,1392 ,4893,4881,4858 }, - {3447,64,1940 ,3928,297,3925 }, {48,123,213 ,4840,3607,3606 }, - {5287,5286,5241 ,4003,3859,2120 }, {4144,261,1210 ,4761,4775,4739 }, - {1973,4685,4906 ,551,4894,4895 }, {5265,5287,5241 ,4882,4003,2120 }, - {5874,6090,6066 ,4896,4897,1455 }, {2390,1869,940 ,1594,2808,197 }, - {4158,1346,705 ,72,484,70 }, {701,1748,756 ,4685,4618,4731 }, - {3990,3254,4019 ,3231,3233,227 }, {1015,2536,409 ,3368,2793,1480 }, - {3549,588,3369 ,3823,3822,3836 }, {5724,5725,5762 ,4898,3824,4884 }, - {4246,4285,4284 ,3665,4899,4869 }, {4270,4246,4284 ,4900,3665,4869 }, - {4284,4285,4341 ,4869,4899,4888 }, {4341,4365,4387 ,4888,4901,4878 }, - {4387,4365,4416 ,4878,4901,4889 }, {4508,1738,1737 ,4902,4890,4861 }, - {4478,4508,1737 ,4870,4902,4861 }, {1738,986,942 ,4890,4903,4880 }, - {986,1493,942 ,4903,4904,4880 }, {942,1493,33 ,4880,4904,4891 }, - {285,1856,33 ,4905,4892,4891 }, {285,1457,1856 ,4905,4893,4892 }, - {285,228,1457 ,4905,4881,4893 }, {48,213,228 ,4840,3606,4881 }, - {2677,123,1050 ,3033,3607,2282 }, {642,413,739 ,1243,351,2233 }, - {3990,4353,4352 ,3231,4906,4695 }, {4101,209,1178 ,4724,4499,206 }, - {4313,1225,2423 ,4574,327,433 }, {653,208,1259 ,318,4742,348 }, - {1976,4351,2390 ,1180,4606,1594 }, {4351,1976,2390 ,4606,1180,1594 }, - {4351,801,2390 ,4606,4907,1594 }, {2390,801,1869 ,1594,4907,2808 }, - {4352,4353,4401 ,4695,4906,4772 }, {1946,180,131 ,4408,4777,2965 }, - {4539,93,113 ,633,563,677 }, {4835,8126,3148 ,2130,812,814 }, - {588,3368,3369 ,3822,3960,3836 }, {4285,4319,4341 ,4899,4908,4888 }, - {4341,4319,4365 ,4888,4908,4901 }, {4459,4508,4478 ,4909,4902,4870 }, - {4439,4459,4478 ,4879,4909,4870 }, {4508,4509,1738 ,4902,4910,4890 }, - {1738,4509,986 ,4890,4910,4903 }, {1493,598,33 ,4904,4911,4891 }, - {598,285,33 ,4911,4905,4891 }, {285,4143,228 ,4905,4912,4881 }, - {4143,4092,228 ,4912,4913,4881 }, {228,4092,48 ,4881,4913,4840 }, - {47,941,1049 ,4914,2277,1362 }, {48,47,1049 ,4840,4914,1362 }, - {45,2255,195 ,4714,3229,739 }, {1088,1623,1186 ,1604,1709,1605 }, - {142,466,143 ,159,347,157 }, {4367,4343,6225 ,228,1818,4872 }, - {1976,2006,4351 ,1180,1181,4606 }, {1869,363,4427 ,2808,427,426 }, - {2364,3343,2365 ,2513,2515,3351 }, {4243,447,317 ,4764,4651,561 }, - {340,960,730 ,1107,1326,1549 }, {5725,5763,5762 ,3824,4212,4884 }, - {5678,5679,5724 ,3861,2553,4898 }, {5522,5558,5557 ,755,2302,756 }, - {4246,4319,4285 ,3665,4908,4899 }, {4365,4417,4416 ,4901,4915,4889 }, - {4417,4459,4439 ,4915,4909,4879 }, {4416,4417,4439 ,4889,4915,4879 }, - {4460,4509,4508 ,4916,4910,4902 }, {4459,4460,4508 ,4909,4916,4902 }, - {986,599,1493 ,4903,4917,4904 }, {1493,599,598 ,4904,4917,4911 }, - {397,4092,4143 ,4918,4913,4912 }, {285,397,4143 ,4905,4918,4912 }, - {4092,4428,48 ,4913,4919,4840 }, {4428,47,48 ,4919,4914,4840 }, - {1834,1835,1870 ,2422,2421,4868 }, {4082,4081,500 ,4716,4709,4637 }, - {5418,5103,7917 ,3471,77,4920 }, {2255,4350,195 ,3229,740,739 }, - {987,3977,66 ,2950,440,4563 }, {2431,1511,967 ,2977,4921,3668 }, - {136,4495,4450 ,1685,4723,4722 }, {4496,136,4450 ,2220,1685,4722 }, - {4134,4079,658 ,4750,4718,4693 }, {1005,3818,3732 ,3535,1244,3536 }, - {3075,3981,3263 ,2670,915,252 }, {801,415,1869 ,4907,4922,2808 }, - {1869,415,363 ,2808,4922,427 }, {4091,3141,4126 ,123,4701,124 }, - {699,4079,4134 ,4677,4718,4750 }, {913,536,863 ,444,523,284 }, - {1343,4399,1564 ,378,4546,368 }, {443,265,697 ,920,4496,3578 }, - {5217,4763,4797 ,4026,4787,3984 }, {5679,5725,5724 ,2553,3824,4898 }, - {5308,5288,5289 ,3528,3993,80 }, {3837,4320,4319 ,3667,4923,4908 }, - {4246,3837,4319 ,3665,3667,4908 }, {4320,4366,4365 ,4923,4924,4901 }, - {4319,4320,4365 ,4908,4923,4901 }, {4365,4366,4417 ,4901,4924,4915 }, - {4418,4460,4459 ,4925,4916,4909 }, {4417,4418,4459 ,4915,4925,4909 }, - {4509,853,986 ,4910,4926,4903 }, {986,853,599 ,4903,4926,4917 }, - {598,397,285 ,4911,4918,4905 }, {4092,4168,4428 ,4913,4927,4919 }, - {4428,4168,47 ,4919,4927,4914 }, {4062,4082,500 ,4623,4716,4637 }, - {4159,1833,709 ,1299,317,316 }, {1117,5090,6418 ,4928,4929,3441 }, - {658,447,4243 ,4693,4651,4764 }, {223,196,157 ,1985,152,1877 }, - {1179,883,1601 ,4774,119,4785 }, {4399,1922,1564 ,4546,4432,368 }, - {1601,883,76 ,4785,119,689 }, {1307,4203,801 ,4930,4931,4907 }, - {801,4203,415 ,4907,4931,4922 }, {5340,5339,5286 ,4002,2223,3859 }, - {4302,166,4356 ,3727,3729,155 }, {4384,4385,1946 ,4409,4778,4408 }, - {545,739,46 ,305,2233,2232 }, {4110,467,1633 ,372,346,373 }, - {467,513,1633 ,346,377,373 }, {2153,164,3980 ,4181,4932,4933 }, - {3414,4528,2142 ,4934,4935,4936 }, {3837,4286,4320 ,3667,4274,4923 }, - {4366,4418,4417 ,4924,4925,4915 }, {4479,4524,4509 ,4937,4938,4910 }, - {4460,4479,4509 ,4916,4937,4910 }, {4509,4524,853 ,4910,4938,4926 }, - {599,750,598 ,4917,4939,4911 }, {598,750,397 ,4911,4939,4918 }, - {397,4168,4092 ,4918,4927,4913 }, {610,47,4168 ,4940,4914,4927 }, - {4282,941,47 ,4941,2277,4914 }, {610,4282,47 ,4940,4941,4914 }, - {4282,119,941 ,4941,2278,2277 }, {4054,4055,4058 ,3679,3678,4708 }, - {1528,1424,608 ,4559,2298,2300 }, {258,3014,259 ,3001,3568,2203 }, - {2006,1565,1307 ,1181,3737,4930 }, {1307,1565,4203 ,4930,3737,4931 }, - {415,380,363 ,4922,2540,427 }, {5287,5340,5286 ,4003,4002,3859 }, - {4109,4125,4126 ,576,125,124 }, {4058,1253,4065 ,4708,2353,4717 }, - {5103,5412,5378 ,77,360,359 }, {4298,4186,3616 ,3580,683,3974 }, - {4469,2153,3980 ,4060,4181,4933 }, {3009,5702,5701 ,3747,3630,3938 }, - {4366,4388,4418 ,4924,4942,4925 }, {4440,4479,4460 ,4943,4937,4916 }, - {4418,4440,4460 ,4925,4943,4916 }, {853,1563,599 ,4926,4944,4917 }, - {1563,1149,599 ,4944,4945,4917 }, {1149,1924,750 ,4945,4946,4939 }, - {599,1149,750 ,4917,4945,4939 }, {4219,4168,397 ,4947,4927,4918 }, - {657,4282,610 ,4948,4941,4940 }, {657,119,4282 ,4948,2278,4941 }, - {4081,4082,1079 ,4709,4716,4575 }, {4057,2959,2420 ,272,4608,273 }, - {5643,5659,5642 ,4617,3053,526 }, {4471,1653,258 ,2187,106,3001 }, - {1651,200,1609 ,188,244,31 }, {2742,1565,2006 ,2558,3737,1181 }, - {4203,796,415 ,4931,4949,4922 }, {415,796,380 ,4922,4949,2540 }, - {95,4522,1798 ,3482,3481,4451 }, {3604,3626,3654 ,3384,4196,1438 }, - {4451,4498,4497 ,271,88,91 }, {3727,4298,3616 ,3942,3580,3974 }, - {531,4469,3980 ,3829,4060,4933 }, {4320,4342,4366 ,4923,4950,4924 }, - {4342,4389,4388 ,4950,4951,4942 }, {4366,4342,4388 ,4924,4950,4942 }, - {4389,4440,4418 ,4951,4943,4925 }, {4388,4389,4418 ,4942,4951,4925 }, - {4524,1736,853 ,4938,4952,4926 }, {1736,773,853 ,4952,4953,4926 }, - {773,1563,853 ,4953,4944,4926 }, {773,1149,1563 ,4953,4945,4944 }, - {1924,98,397 ,4946,4954,4918 }, {750,1924,397 ,4939,4946,4918 }, - {98,769,397 ,4954,4955,4918 }, {769,4219,397 ,4955,4947,4918 }, - {769,4168,4219 ,4955,4927,4947 }, {656,610,4168 ,4956,4940,4927 }, - {656,657,610 ,4956,4948,4940 }, {2959,2419,2420 ,4608,3353,273 }, - {918,143,416 ,4150,157,556 }, {4019,4300,3990 ,227,231,3231 }, - {3626,3655,3654 ,4196,3936,1438 }, {4300,4301,3990 ,231,167,3231 }, - {1565,1972,4203 ,3737,3034,4931 }, {4203,1972,796 ,4931,3034,4949 }, - {796,1808,380 ,4949,4502,2540 }, {439,1806,1346 ,4638,3124,484 }, - {8088,6837,8100 ,1998,1057,1713 }, {463,360,277 ,1941,86,85 }, - {4301,4354,4353 ,167,376,4906 }, {3990,4301,4353 ,3231,167,4906 }, - {4354,4402,4401 ,376,2190,4772 }, {1869,4427,1839 ,2808,426,1138 }, - {792,4536,4712 ,95,89,3816 }, {4655,4681,4654 ,4957,4958,4348 }, - {5377,4904,5378 ,361,3309,359 }, {34,531,3980 ,3830,3829,4933 }, - {4342,4320,4286 ,4950,4923,4274 }, {3371,1941,3265 ,3708,1034,1033 }, - {4510,4524,4479 ,4959,4938,4937 }, {4510,1719,1736 ,4959,4960,4952 }, - {4524,4510,1736 ,4938,4959,4952 }, {1719,773,1736 ,4960,4953,4952 }, - {1149,98,1924 ,4945,4954,4946 }, {4169,4168,769 ,4961,4927,4955 }, - {4169,605,4168 ,4961,4962,4927 }, {605,656,4168 ,4962,4956,4927 }, - {657,26,119 ,4948,2126,2278 }, {26,460,119 ,2126,1999,2278 }, - {643,2602,546 ,3285,3234,1171 }, {466,4103,604 ,347,4577,486 }, - {66,2697,1211 ,4563,2006,2007 }, {478,613,64 ,2077,298,297 }, - {4353,4354,4401 ,4906,376,4772 }, {1565,511,1972 ,3737,3569,3034 }, - {453,301,82 ,1814,1857,138 }, {1972,1948,796 ,3034,2543,4949 }, - {796,1948,1808 ,4949,2543,4502 }, {915,916,863 ,443,445,284 }, - {4473,4450,4401 ,270,4722,4772 }, {4402,4473,4401 ,2190,270,4772 }, - {6679,1117,6418 ,4824,4928,3441 }, {4298,3727,5832 ,3580,3942,3904 }, - {3673,52,164 ,648,411,4932 }, {3294,3292,3293 ,3895,4067,1988 }, - {4461,4479,4440 ,4963,4937,4943 }, {4461,4511,4510 ,4963,4964,4959 }, - {4479,4461,4510 ,4937,4963,4959 }, {4511,1719,4510 ,4964,4960,4959 }, - {560,98,1149 ,4965,4954,4945 }, {769,1209,4169 ,4955,279,4961 }, - {4169,1209,605 ,4961,279,4962 }, {656,605,657 ,4956,4962,4948 }, - {1347,26,657 ,4966,2126,4948 }, {1427,1971,4740 ,2378,2520,2426 }, - {2504,2461,2583 ,2898,2899,2672 }, {4473,4496,4450 ,270,2220,4722 }, - {1972,1349,1948 ,3034,2519,2543 }, {103,84,2030 ,128,4231,770 }, - {1840,1869,1839 ,198,2808,1138 }, {136,883,1179 ,1685,119,4774 }, - {5679,5697,5725 ,2553,2552,3824 }, {2153,3673,164 ,4181,648,4932 }, - {7648,7697,7647 ,3952,651,4967 }, {4420,4440,4389 ,276,4943,4951 }, - {4419,4420,4389 ,4968,276,4951 }, {4420,4461,4440 ,276,4963,4943 }, - {594,1149,773 ,2453,4945,4953 }, {1149,594,560 ,4945,2453,4965 }, - {1209,769,98 ,279,4955,4954 }, {605,1347,657 ,4962,4966,4948 }, - {1919,1004,1452 ,1779,3452,1606 }, {1832,66,1306 ,4576,4563,4653 }, - {3569,2660,538 ,4381,455,4380 }, {3759,21,2030 ,4233,1231,770 }, - {1948,1427,1808 ,2543,2378,4502 }, {1808,1427,4111 ,4502,2378,4687 }, - {643,546,644 ,3285,1171,1176 }, {4111,1870,1871 ,4687,4868,2458 }, - {4126,4198,4175 ,124,4969,4500 }, {5389,1206,1734 ,4091,2218,2219 }, - {5784,4011,878 ,396,395,398 }, {5814,5831,5830 ,4875,3943,4163 }, - {3892,3905,6166 ,4970,4194,4971 }, {5798,5814,5830 ,4876,4875,4163 }, - {4343,4389,4342 ,1818,4951,4950 }, {4343,4420,4419 ,1818,276,4968 }, - {4389,4343,4419 ,4951,1818,4968 }, {893,773,1719 ,2454,4953,4960 }, - {893,594,773 ,2454,2453,4953 }, {98,1069,1209 ,4954,277,279 }, - {605,44,1347 ,4962,357,4966 }, {1347,70,26 ,4966,323,2126 }, - {66,45,1306 ,4563,4714,4653 }, {3668,959,8070 ,513,1358,941 }, - {4723,1676,4895 ,4972,2343,4973 }, {1049,1050,123 ,1362,2282,3607 }, - {1015,409,89 ,3368,1480,1482 }, {4111,4327,1870 ,4687,2377,4868 }, - {4175,4198,3784 ,4500,4969,2252 }, {2208,3801,5090 ,1257,4974,4929 }, - {1117,2208,5090 ,4928,1257,4929 }, {5389,1734,3113 ,4091,2219,410 }, - {4185,5389,3113 ,409,4091,410 }, {2960,5941,808 ,4975,4976,4734 }, - {4390,4420,4343 ,230,276,1818 }, {4512,4511,4461 ,2279,4964,4963 }, - {4511,4512,1719 ,4964,2279,4960 }, {4512,893,1719 ,2279,2454,4960 }, - {560,971,98 ,4965,356,4954 }, {98,971,1069 ,4954,356,277 }, {4138,44,605 ,278,357,4962 }, - {1209,4138,605 ,279,278,4962 }, {44,1793,1347 ,357,319,4966 }, - {1793,69,1347 ,319,321,4966 }, {1347,69,70 ,4966,321,323 }, {6836,3534,6353 ,852,942,749 }, - {5657,5680,5640 ,48,50,2214 }, {4056,4098,4263 ,1123,353,274 }, - {1846,1148,705 ,204,160,70 }, {844,1115,1114 ,4688,2257,2256 }, - {1115,1600,2047 ,2257,4498,2258 }, {4969,4992,1030 ,4977,4978,1619 }, - {356,1112,4194 ,310,292,293 }, {3346,3617,3375 ,4457,4425,4426 }, - {4329,4380,4379 ,1247,4602,567 }, {1427,4327,4111 ,2378,2377,4687 }, - {4327,4099,1870 ,2377,4533,4868 }, {4197,4196,4148 ,82,4747,2305 }, - {5412,5411,5377 ,360,4284,361 }, {4462,4461,4420 ,1076,4963,276 }, - {4462,4512,4461 ,1076,2279,4963 }, {1057,560,594 ,354,4965,2453 }, - {871,1057,594 ,2106,354,2453 }, {1057,971,560 ,354,356,4965 }, - {4836,137,4783 ,4979,4980,4981 }, {4833,4848,4822 ,4982,4983,4984 }, - {4687,274,4637 ,4985,1819,4986 }, {4176,4127,5163 ,4703,4702,4987 }, - {7374,7373,7348 ,4988,4989,4990 }, {4857,4873,509 ,4991,4992,4993 }, - {4886,1602,361 ,4720,2329,4994 }, {5030,5031,5047 ,2134,4995,4996 }, - {4688,4748,4687 ,4997,4998,4985 }, {574,616,4874 ,2181,4999,5000 }, - {4657,4716,4656 ,5001,1030,5002 }, {3801,3660,7052 ,4974,709,708 }, - {996,3784,4176 ,5003,2252,4703 }, {4614,4692,279 ,3109,2177,2176 }, - {2208,5088,5393 ,1257,5004,5005 }, {4716,4715,4656 ,1030,1029,5002 }, - {4657,4656,4605 ,5001,5002,5006 }, {4751,4880,417 ,5007,5008,5009 }, - {5016,561,4644 ,5010,2379,2425 }, {4644,561,4740 ,2425,2379,2426 }, - {8122,8114,8145 ,384,2286,3376 }, {3801,2208,5393 ,4974,1257,5005 }, - {4614,2322,4692 ,3109,3497,2177 }, {707,669,612 ,2091,2020,5011 }, - {1750,1751,1811 ,745,773,777 }, {1511,4377,967 ,4921,3090,3668 }, - {4935,4936,4973 ,5012,5013,5014 }, {3261,6554,4190 ,5015,3647,3439 }, - {8081,8078,8093 ,1445,1744,2288 }, {4604,4603,4562 ,5016,5017,5018 }, - {811,718,4954 ,557,2407,558 }, {4804,4833,4822 ,4867,4982,4984 }, - {4974,4996,4995 ,5019,5020,5021 }, {1264,1252,3929 ,5022,5023,5024 }, - {8091,8101,8099 ,2167,383,2867 }, {4817,1771,1834 ,2368,2367,2422 }, - {5350,6529,6507 ,1526,5025,2680 }, {4848,4886,417 ,4983,4720,5009 }, - {618,717,677 ,2391,2408,2296 }, {2301,8107,872 ,2132,658,2962 }, - {4749,4810,4785 ,5026,5027,5028 }, {4809,4855,4782 ,4202,4201,5029 }, - {4656,4715,4681 ,5002,1029,4958 }, {4686,4492,4773 ,5030,5031,4865 }, - {7593,7620,7645 ,5032,5033,5034 }, {4683,4647,4643 ,5035,5036,5037 }, - {5049,1928,4859 ,5038,1282,5039 }, {6942,6943,6962 ,521,520,3260 }, - {4871,1834,1870 ,5040,2422,4868 }, {4907,4935,4934 ,2209,5012,5041 }, - {8064,2341,1333 ,3141,845,849 }, {4954,720,812 ,558,2475,559 }, - {8089,2746,8139 ,254,1517,1923 }, {5063,5064,5062 ,5042,5043,5044 }, - {4607,4659,4658 ,5045,5046,5047 }, {4976,4998,4997 ,5048,4713,5049 }, - {4659,319,4658 ,5046,5050,5047 }, {319,367,4717 ,5050,1370,1449 }, - {4658,319,4717 ,5047,5050,1449 }, {8071,8144,3264 ,738,2469,2468 }, - {8127,8142,4106 ,2970,1743,1742 }, {4690,4721,383 ,5051,5052,2087 }, - {4907,576,674 ,2209,2208,2271 }, {717,4938,677 ,2408,5053,2296 }, - {2476,1283,2431 ,2441,2978,2977 }, {5966,1455,4987 ,5054,1917,1491 }, - {1346,2464,1697 ,484,3299,69 }, {1610,1676,749 ,2330,2343,2331 }, - {4934,4972,851 ,5041,2158,2155 }, {1610,1602,4855 ,2330,2329,4201 }, - {6755,6792,6738 ,5055,5056,5057 }, {1536,1581,1508 ,2080,2030,2029 }, - {4951,717,4977 ,5058,2408,4711 }, {6390,6311,6316 ,3868,1097,4435 }, - {565,4869,564 ,1614,5059,3529 }, {4890,4889,564 ,4594,4615,3529 }, - {4869,4890,564 ,5059,4594,3529 }, {417,137,4836 ,5009,4980,4979 }, - {1077,1030,1078 ,2694,1619,5060 }, {4286,3528,4342 ,4274,5061,4950 }, - {361,4751,417 ,4994,5007,5009 }, {5098,5097,5065 ,5062,5063,5064 }, - {1870,4099,4871 ,4868,4533,5040 }, {4918,4967,4966 ,4595,5065,4646 }, - {4931,4964,937 ,5066,783,5067 }, {4930,4931,937 ,5068,5066,5067 }, - {1320,4667,4618 ,2356,5069,5070 }, {2271,6309,6308 ,5071,3690,3474 }, - {4966,4967,978 ,4646,5065,1620 }, {4433,4356,4404 ,4591,155,5072 }, - {1831,1830,1768 ,2221,2110,2109 }, {7185,7184,7159 ,5073,5074,5075 }, - {4795,4432,4433 ,3710,156,4591 }, {1879,1928,5049 ,1283,1282,5038 }, - {4972,4994,949 ,2158,5076,2133 }, {468,469,505 ,1369,988,986 }, - {1024,4686,4647 ,5077,5030,5036 }, {8105,8090,3006 ,3791,412,414 }, - {4967,4991,978 ,5065,1621,1620 }, {446,640,4959 ,501,5078,5079 }, - {7565,7620,7593 ,5080,5033,5032 }, {4951,4977,4976 ,5058,4711,5048 }, - {3609,6159,6144 ,5081,5082,5083 }, {761,845,760 ,1826,1828,3106 }, - {6484,2258,5455 ,685,1198,686 }, {561,4871,4099 ,2379,5040,4533 }, - {4018,2271,6308 ,5084,5071,3474 }, {2808,6606,2454 ,522,5085,1345 }, - {567,568,663 ,1684,1723,4773 }, {2089,2090,2619 ,1325,1324,3035 }, - {7253,7254,6346 ,1855,450,4883 }, {5949,404,5967 ,5086,761,1352 }, - {1164,6386,1298 ,5087,4085,5088 }, {1635,1636,1702 ,989,1036,1039 }, - {5094,4683,1365 ,5089,5035,2085 }, {1699,1752,1751 ,772,946,773 }, - {4615,1566,1635 ,5090,1037,989 }, {1494,4609,1973 ,1083,5091,551 }, - {5017,5292,4144 ,5092,5093,4761 }, {1442,4615,1635 ,990,5090,989 }, - {6322,6897,2249 ,3531,54,3751 }, {4536,4820,4712 ,89,2399,3816 }, - {4452,4536,4498 ,2398,89,88 }, {4989,307,4986 ,5094,5095,5096 }, - {4606,4607,4658 ,5097,5045,5047 }, {2067,2031,2005 ,1592,1560,1593 }, - {1676,4817,4895 ,2343,2368,4973 }, {4782,4667,1397 ,5029,5069,2358 }, - {1028,406,2958 ,1373,2566,1374 }, {6644,5056,4950 ,5098,1300,1302 }, - {1365,1282,1317 ,2085,2097,5099 }, {3534,6686,8121 ,942,750,3466 }, - {1169,4607,4606 ,5100,5045,5097 }, {4647,4773,4661 ,5036,4865,5101 }, - {2015,1994,1995 ,759,5102,757 }, {7287,7310,7286 ,3459,4283,3460 }, - {951,5033,4999 ,2394,5103,4712 }, {2155,875,6353 ,580,579,749 }, - {4874,616,673 ,5000,4999,2210 }, {1602,749,4723 ,2329,2331,4972 }, - {1365,4757,4666 ,2085,5104,5105 }, {7613,7612,7551 ,5106,5107,5108 }, - {2650,8140,3981 ,914,2269,915 }, {8120,6897,3286 ,906,54,56 }, - {4594,4027,5028 ,688,3470,5109 }, {4844,4848,4833 ,4866,4983,4982 }, - {4594,146,4027 ,688,504,3470 }, {4996,4997,5030 ,5020,5049,2134 }, - {5030,5047,5061 ,2134,4996,2135 }, {4594,5028,3249 ,688,5109,5110 }, - {792,147,146 ,95,3469,504 }, {4688,4689,4749 ,4997,5111,5026 }, - {128,4594,4905 ,687,688,5112 }, {5036,128,4905 ,399,687,5112 }, - {1202,366,1040 ,339,4469,1476 }, {4615,1442,4806 ,5090,990,5113 }, - {5127,4801,124 ,5114,5115,2206 }, {128,5036,4905 ,687,399,5112 }, - {3243,128,4905 ,3919,687,5112 }, {616,574,575 ,4999,2181,2180 }, - {7556,6760,4636 ,5116,5117,5118 }, {4997,4998,5018 ,5049,4713,5119 }, - {1105,1202,1040 ,2049,339,1476 }, {7372,7371,7310 ,4373,3748,4283 }, - {1649,1581,1582 ,2031,2030,2081 }, {7204,7241,7203 ,5120,4465,4366 }, - {5910,5838,6343 ,5121,3987,5122 }, {1442,4898,4806 ,990,5123,5113 }, - {1099,3243,4905 ,4350,3919,5112 }, {695,128,3243 ,731,687,3919 }, - {7572,7599,7571 ,5124,5125,5126 }, {4734,4661,4902 ,5127,5101,5128 }, - {135,4637,274 ,2653,4986,1819 }, {4817,1834,4871 ,2368,2422,5040 }, - {7823,7874,7847 ,345,344,3521 }, {7452,7509,7451 ,1875,1874,3963 }, - {137,4762,4843 ,4980,5129,5130 }, {4615,4806,4670 ,5090,5113,5131 }, - {1659,4615,4670 ,5132,5090,5131 }, {8103,1724,8077 ,1291,3880,2078 }, - {5091,5090,7052 ,5133,4929,708 }, {126,197,4659 ,1394,1393,5046 }, - {4607,126,4659 ,5045,1394,5046 }, {4659,197,319 ,5046,1393,5050 }, - {2006,1307,4351 ,1181,4930,4606 }, {4751,4821,4880 ,5007,5134,5008 }, - {4870,4871,5016 ,5135,5040,5010 }, {5061,5093,1317 ,2135,5136,5099 }, - {4838,4808,311 ,245,5137,246 }, {4880,4762,137 ,5008,5129,4980 }, - {760,4970,4920 ,3106,3073,5138 }, {5021,4644,1969 ,2383,2425,2369 }, - {856,811,855 ,5139,557,2392 }, {1768,4735,1831 ,2109,5140,2221 }, - {4869,565,566 ,5059,1614,1613 }, {4843,1718,4783 ,5130,2108,4981 }, - {662,4890,4869 ,5141,4594,5059 }, {4683,4643,4757 ,5035,5037,5104 }, - {324,325,383 ,2090,2088,2087 }, {917,4915,4929 ,4016,64,5142 }, - {4667,4782,4492 ,5069,5029,5031 }, {753,3243,4845 ,4749,3919,3921 }, - {753,462,3243 ,4749,4847,3919 }, {753,695,462 ,4749,731,4847 }, - {280,326,325 ,2175,2152,2088 }, {4976,4977,4998 ,5048,4711,4713 }, - {4566,4571,1168 ,5143,1342,1098 }, {2583,685,3902 ,2672,2674,4437 }, - {5187,4845,1111 ,5144,3921,3920 }, {6689,3285,2405 ,3065,3064,4165 }, - {1790,4183,240 ,4738,1572,1571 }, {1040,1104,1105 ,1476,1473,2049 }, - {4985,4566,1168 ,2703,5143,1098 }, {4643,4818,4734 ,5037,5145,5127 }, - {7815,5439,5440 ,5146,4157,5147 }, {5093,1365,1317 ,5136,2085,5099 }, - {1177,1130,5061 ,5148,2136,2135 }, {4994,5030,5029 ,5076,2134,2159 }, - {4751,4862,4821 ,5007,5149,5134 }, {1517,4780,4846 ,600,5150,4237 }, - {4989,972,4571 ,5094,3277,1342 }, {4984,753,4845 ,5151,4749,3921 }, - {4750,4786,4749 ,5152,5153,5026 }, {4818,4661,4734 ,5145,5101,5127 }, - {4638,4663,4637 ,5154,5155,4986 }, {5750,5739,5775 ,5156,5157,5158 }, - {6463,4989,4566 ,5159,5094,5143 }, {6704,6736,6703 ,5160,1622,5161 }, - {5629,5938,6605 ,5162,5163,5164 }, {383,4811,4786 ,2087,5165,5153 }, - {4690,4689,4639 ,5051,5111,5166 }, {4740,561,1427 ,2426,2379,2378 }, - {4566,4989,4571 ,5143,5094,1342 }, {1024,5071,4686 ,5077,5167,5030 }, - {4997,5031,5030 ,5049,4995,2134 }, {5031,5032,5064 ,4995,5168,5043 }, - {557,82,4801 ,3724,138,5115 }, {7693,3824,8133 ,724,3462,2131 }, - {4824,4812,1602 ,4719,5169,2329 }, {760,4920,663 ,3106,5138,4773 }, - {4973,4974,4995 ,5014,5019,5021 }, {4690,4749,4689 ,5051,5026,5111 }, - {4751,5015,4862 ,5007,5170,5149 }, {1282,1176,1317 ,2097,2096,5099 }, - {4855,4812,4782 ,4201,5169,5029 }, {4850,1931,1903 ,5171,4736,406 }, - {8127,8084,8142 ,2970,1139,1743 }, {2527,2487,3426 ,2637,4427,4438 }, - {4605,4606,4658 ,5006,5097,5047 }, {3762,5044,5442 ,5172,5173,5174 }, - {674,675,4936 ,2271,2294,5013 }, {4331,4984,4845 ,4645,5151,3921 }, - {5083,4331,4845 ,5175,4645,3921 }, {4331,753,4984 ,4645,4749,5151 }, - {5246,6039,5227 ,5176,2728,4097 }, {4862,4850,1831 ,5149,5171,2221 }, - {417,4880,137 ,5009,5008,4980 }, {4811,514,4858 ,5165,2154,5177 }, - {4929,4930,4963 ,5142,5068,5178 }, {5844,1119,1028 ,5179,5180,1373 }, - {7064,7065,2073 ,5181,5182,5183 }, {5056,3319,5005 ,1300,1259,1301 }, - {6570,4554,1263 ,1252,1307,1199 }, {4870,1931,4862 ,5135,4736,5149 }, - {4643,4734,1508 ,5037,5127,2029 }, {1884,1885,1929 ,3567,778,899 }, - {855,951,4977 ,2392,2394,4711 }, {4986,1073,972 ,5096,3741,3277 }, - {1169,4606,4605 ,5100,5097,5006 }, {4689,4688,4638 ,5111,4997,5154 }, - {1252,5999,3929 ,5023,5184,5024 }, {4989,4986,972 ,5094,5096,3277 }, - {4889,4933,4932 ,4615,4596,4580 }, {4688,4687,4638 ,4997,4985,5154 }, - {5096,5097,4912 ,5185,5063,5186 }, {5071,4912,4686 ,5167,5186,5030 }, - {564,4889,4868 ,3529,4615,3969 }, {675,677,4937 ,2294,2296,5187 }, - {5033,5066,5065 ,5103,5188,5064 }, {5034,5033,951 ,2396,5103,2394 }, - {897,898,952 ,2393,2411,2395 }, {1672,1650,1582 ,2083,2082,2081 }, - {4845,5052,5083 ,3921,5189,5175 }, {4118,753,4331 ,4699,4749,4645 }, - {5702,4743,5701 ,3630,3629,3938 }, {4812,4824,4492 ,5169,4719,5031 }, - {673,4934,767 ,2210,5041,2093 }, {1536,4734,1582 ,2080,5127,2081 }, - {17,961,4959 ,5190,500,5079 }, {1659,4670,4685 ,5132,5131,4894 }, - {4644,5021,5019 ,2425,2383,2384 }, {4783,1672,4902 ,4981,2083,5128 }, - {7646,7675,7645 ,5191,5192,5034 }, {1381,1169,4605 ,5193,5100,5006 }, - {5061,1317,1177 ,2135,5099,5148 }, {4933,4966,4965 ,4596,4646,784 }, - {206,3347,1804 ,3932,2098,2902 }, {4888,4889,4932 ,3997,4615,4580 }, - {4932,4933,4965 ,4580,4596,784 }, {4889,4888,4868 ,4615,3997,3969 }, - {4986,5441,42 ,5096,5194,5195 }, {1285,4618,5097 ,1944,5070,5063 }, - {4716,4717,468 ,1030,1449,1369 }, {4997,5018,5031 ,5049,5119,4995 }, - {1073,4986,42 ,3741,5096,5195 }, {1297,4752,1488 ,4048,5196,5197 }, - {280,325,279 ,2175,2088,2176 }, {4817,1676,1720 ,2368,2343,2366 }, - {1213,1197,4983 ,3700,478,480 }, {4331,5083,5052 ,4645,5175,5189 }, - {8132,8141,3900 ,413,3295,884 }, {943,1034,1081 ,1807,1756,3745 }, - {1931,1967,1903 ,4736,404,406 }, {4563,126,4607 ,3024,1394,5045 }, - {1169,4563,4607 ,5100,3024,5045 }, {4969,4970,4992 ,4977,3073,4978 }, - {6686,8070,959 ,750,941,1358 }, {4898,4867,4806 ,5123,5198,5113 }, - {1365,4683,4757 ,2085,5035,5104 }, {3482,4021,8106 ,2494,1712,2438 }, - {977,976,4965 ,3931,782,784 }, {4618,4667,4912 ,5070,5069,5186 }, - {4695,4725,4772 ,5199,5200,5201 }, {4935,4973,4972 ,5012,5014,2158 }, - {509,572,475 ,4993,1947,1884 }, {4938,4976,4975 ,5053,5048,5202 }, - {4848,417,4836 ,4983,5009,4979 }, {4749,4811,4810 ,5026,5165,5027 }, - {4974,4975,4996 ,5019,5202,5020 }, {5033,5065,5064 ,5103,5064,5043 }, - {5032,5033,5064 ,5168,5103,5043 }, {3316,2810,3271 ,2149,1728,1727 }, - {7512,7570,7536 ,5203,5204,5205 }, {4018,6308,6307 ,5084,3474,5206 }, - {1381,4604,4562 ,5193,5016,5018 }, {375,374,320 ,1883,1821,1871 }, - {3824,7714,8131 ,3462,4468,2307 }, {4661,4822,4902 ,5101,4984,5128 }, - {4972,4973,4994 ,2158,5014,5076 }, {4973,4995,4994 ,5014,5021,5076 }, - {7693,8133,8071 ,724,2131,738 }, {4811,4858,4840 ,5165,5177,5207 }, - {2322,281,4692 ,3497,2227,2177 }, {4118,4331,513 ,4699,4645,377 }, - {4810,509,475 ,5027,4993,1884 }, {4640,4691,4690 ,5208,2089,5051 }, - {442,357,589 ,673,672,671 }, {1442,1699,4898 ,990,772,5123 }, - {2219,5000,4982 ,177,286,364 }, {4611,4634,4754 ,5209,5210,5211 }, - {6299,5012,1989 ,760,5212,3016 }, {4782,1469,4809 ,5029,2361,4202 }, - {4619,39,344 ,5213,529,562 }, {4754,4959,4903 ,5211,5079,5214 }, - {4903,4959,640 ,5214,5079,5078 }, {4780,1291,4819 ,5150,5215,5216 }, - {4684,5082,6603 ,5217,5218,3985 }, {5166,5205,5227 ,3427,5219,4097 }, - {1154,1922,4399 ,4545,4432,4546 }, {4858,514,574 ,5177,2154,2181 }, - {3243,462,695 ,3919,4847,731 }, {1635,1702,1699 ,989,1039,772 }, - {4780,1517,5079 ,5150,600,5220 }, {5079,1517,833 ,5220,600,489 }, - {2464,1346,2465 ,3299,484,3181 }, {662,4919,4918 ,5141,5221,4595 }, - {4890,662,4918 ,4594,5141,4595 }, {4919,4968,4967 ,5221,5222,5065 }, - {4918,4919,4967 ,4595,5221,5065 }, {4968,1030,4991 ,5222,1619,1621 }, - {4840,574,4874 ,5207,2181,5000 }, {1136,1042,1043 ,2412,2409,2478 }, - {4967,4968,4991 ,5065,5222,1621 }, {4806,4867,4621 ,5113,5198,5223 }, - {4867,797,4621 ,5198,5224,5223 }, {4749,4785,4748 ,5026,5028,4998 }, - {273,135,274 ,1749,2653,1819 }, {559,4958,4955 ,5225,5226,5227 }, - {4693,559,4955 ,5228,5225,5227 }, {5012,6299,6417 ,5212,760,762 }, - {4840,4858,574 ,5207,5177,2181 }, {4725,4726,4729 ,5200,5229,5230 }, - {4772,4725,4729 ,5201,5200,5230 }, {1291,4772,4819 ,5215,5201,5216 }, - {4812,4855,1602 ,5169,4201,2329 }, {307,6659,4986 ,5095,3577,5096 }, - {17,438,961 ,5190,498,500 }, {4492,4824,4844 ,5031,4719,4866 }, - {1971,1427,1948 ,2520,2378,2543 }, {4898,1698,4867 ,5123,747,5198 }, - {1698,5084,4867 ,747,5231,5198 }, {1810,4698,4894 ,779,1578,746 }, - {1884,1950,1995 ,3567,786,757 }, {4609,4615,1659 ,5091,5090,5132 }, - {2258,2376,1263 ,1198,1251,1199 }, {5093,5094,1365 ,5136,5089,2085 }, - {4785,4810,4748 ,5028,5027,4998 }, {4750,4749,4690 ,5152,5026,5051 }, - {1081,5046,1078 ,3745,5232,5060 }, {4938,4951,4976 ,5053,5058,5048 }, - {5050,1922,1154 ,5233,4432,4545 }, {936,4963,937 ,5234,5178,5067 }, - {4748,375,4687 ,4998,1883,4985 }, {2212,2271,5001 ,476,5071,477 }, - {5944,3562,6037 ,4754,4753,5235 }, {1041,5067,5033 ,2410,1945,5103 }, - {4560,4600,4559 ,5236,4360,5237 }, {579,677,676 ,2324,2296,2295 }, - {7543,7605,7542 ,5238,5239,5240 }, {5412,5418,5411 ,360,3471,4284 }, - {4819,4772,4701 ,5216,5201,5241 }, {2808,1920,6606 ,522,581,5085 }, - {6699,6751,6750 ,630,5242,631 }, {5442,4672,3762 ,5174,2682,5172 }, - {5004,4817,4871 ,5243,2368,5040 }, {197,367,319 ,1393,1370,5050 }, - {5096,4912,1024 ,5185,5186,5077 }, {4723,4895,4751 ,4972,4973,5007 }, - {5016,1931,4870 ,5010,4736,5135 }, {4611,17,4634 ,5209,5190,5210 }, - {4910,4923,4611 ,5244,5245,5209 }, {4923,4945,4611 ,5245,5246,5209 }, - {975,937,976 ,4266,5067,782 }, {833,1517,491 ,489,600,487 }, - {1081,1078,1030 ,3745,5060,1619 }, {4843,4735,1718 ,5130,5140,2108 }, - {4239,4884,85 ,2254,2253,2504 }, {505,5308,5290 ,986,3528,5247 }, - {2322,4614,4590 ,3497,3109,1490 }, {2277,2322,4590 ,3522,3497,1490 }, - {4641,4640,4612 ,5248,5208,5249 }, {4176,4198,4126 ,4703,4969,124 }, - {357,1198,589 ,672,608,671 }, {6570,2376,6562 ,1252,1251,1306 }, - {4670,4621,5073 ,5131,5223,5250 }, {4761,640,4847 ,5251,5078,5252 }, - {5709,5710,6957 ,5253,5254,4315 }, {2224,406,2206 ,2660,2566,176 }, - {2219,4982,4978 ,177,364,178 }, {2814,4922,4636 ,5255,5256,5118 }, - {5067,5066,5033 ,1945,5188,5103 }, {4772,4729,4701 ,5201,5230,5241 }, - {2163,4586,158 ,243,5257,5258 }, {4692,281,280 ,2177,2227,2175 }, - {4727,4667,4492 ,5259,5069,5031 }, {4746,1264,5078 ,5260,5022,5261 }, - {1285,5098,5066 ,1944,5062,5188 }, {4686,4727,4492 ,5030,5259,5031 }, - {951,4999,4977 ,2394,4712,4711 }, {4932,4965,4964 ,4580,784,783 }, - {4948,4962,935 ,5262,5263,5264 }, {1541,1610,4855 ,2363,2330,4201 }, - {2252,3247,144 ,590,1494,853 }, {6342,1749,1492 ,5265,555,1585 }, - {1028,1119,406 ,1373,5180,2566 }, {4923,638,4945 ,5245,495,5246 }, - {7603,7683,7655 ,5266,5267,5268 }, {4647,4686,4773 ,5036,5030,4865 }, - {898,897,811 ,2411,2393,557 }, {4773,4492,4844 ,4865,5031,4866 }, - {4850,4862,1931 ,5171,5149,4736 }, {4661,4804,4822 ,5101,4867,4984 }, - {4762,4735,4843 ,5129,5140,5130 }, {6751,6787,6786 ,5242,5269,4139 }, - {4640,4641,4691 ,5208,5248,2089 }, {281,326,280 ,2227,2152,2175 }, - {2376,3898,6562 ,1251,1400,1306 }, {6349,6358,6357 ,705,5270,5271 }, - {1469,1541,4855 ,2361,2363,4201 }, {4792,4726,5002 ,5272,5229,5273 }, - {5047,5062,5061 ,4996,5044,2135 }, {2093,603,1551 ,553,5274,5275 }, - {897,855,811 ,2393,2392,557 }, {4620,4619,4823 ,5276,5213,5277 }, - {4621,797,4925 ,5223,5224,5278 }, {4749,4748,4688 ,5026,4998,4997 }, - {1990,5520,5059 ,1305,1304,1253 }, {7105,7104,7092 ,5279,5280,3968 }, - {5067,1285,5066 ,1945,1944,5188 }, {4821,4862,4762 ,5134,5149,5129 }, - {4869,566,662 ,5059,1613,5141 }, {4879,4910,4941 ,5281,5244,5282 }, - {4910,4611,4941 ,5244,5209,5282 }, {4726,4725,4700 ,5229,5200,5283 }, - {4867,4789,797 ,5198,5284,5224 }, {4894,4698,4532 ,746,1578,5285 }, - {4945,638,4611 ,5246,495,5209 }, {4844,4833,4804 ,4866,4982,4867 }, - {1566,4615,4609 ,1037,5090,5091 }, {4934,4935,4972 ,5041,5012,2158 }, - {1717,1672,1718 ,2033,2083,2108 }, {4293,6577,8065 ,2732,97,96 }, - {612,4893,707 ,5011,5286,2091 }, {4650,4649,4595 ,5287,5288,5289 }, - {4596,4650,4595 ,1629,5287,5289 }, {4920,4969,4968 ,5138,4977,5222 }, - {4703,4702,4649 ,5290,5291,5288 }, {4690,383,4750 ,5051,2087,5152 }, - {4992,4993,1030 ,4978,5292,1619 }, {7311,7372,7310 ,4334,4373,4283 }, - {4685,4670,4906 ,4894,5131,4895 }, {4787,4729,4792 ,5293,5230,5272 }, - {4608,4925,4585 ,5294,5278,3955 }, {4726,4700,5002 ,5229,5283,5273 }, - {4925,4593,4585 ,5278,5295,3955 }, {4592,4927,4732 ,5296,5297,5298 }, - {4925,4732,4593 ,5278,5298,5295 }, {4761,4619,4620 ,5251,5213,5276 }, - {4789,4592,4732 ,5284,5296,5298 }, {6308,6711,6307 ,3474,3473,5206 }, - {7185,7220,7184 ,5073,4367,5074 }, {833,4695,4772 ,489,5199,5201 }, - {1025,6714,6389 ,5299,5300,5301 }, {4806,4621,4670 ,5113,5223,5131 }, - {5950,8066,8108 ,2873,960,2287 }, {5866,3311,5864 ,5302,5303,5304 }, - {4609,1659,1973 ,5091,5132,551 }, {4611,638,17 ,5209,495,5190 }, - {1494,1566,4609 ,1083,1037,5091 }, {4667,4727,5068 ,5069,5259,5305 }, - {7524,4596,4595 ,1630,1629,5289 }, {4674,4649,4650 ,5306,5288,5287 }, - {4674,4703,4649 ,5306,5290,5288 }, {4848,4783,4822 ,4983,4981,4984 }, - {5062,5064,5094 ,5044,5043,5089 }, {4930,937,4963 ,5068,5067,5178 }, - {3621,4980,158 ,625,241,5258 }, {5082,6744,6603 ,5218,3986,3985 }, - {4670,5073,4608 ,5131,5250,5294 }, {4729,4787,5025 ,5230,5293,5307 }, - {4584,7818,4557 ,5308,5309,5310 }, {3783,4639,4638 ,5311,5166,5154 }, - {616,575,673 ,4999,2180,2210 }, {797,4789,4732 ,5224,5284,5298 }, - {4678,4903,4794 ,5312,5214,5313 }, {4789,4927,4592 ,5284,5297,5296 }, - {4819,4701,4573 ,5216,5241,5314 }, {5068,4727,4686 ,5305,5259,5030 }, - {4800,4700,4725 ,5315,5283,5200 }, {4695,4800,4725 ,5199,5315,5200 }, - {6028,6040,5927 ,5316,5317,5318 }, {4879,4923,4910 ,5281,5245,5244 }, - {6523,5349,5326 ,5319,5320,3714 }, {4800,4923,4879 ,5315,5245,5281 }, - {5090,3801,7052 ,4929,4974,708 }, {4698,559,4532 ,1578,5225,5285 }, - {1698,4894,4789 ,747,746,5284 }, {2154,5474,2273 ,5321,4243,5322 }, - {7698,7746,7697 ,333,332,651 }, {717,4951,4938 ,2408,5058,5053 }, - {4651,4650,4596 ,5323,5287,1629 }, {4576,4651,4596 ,1628,5323,1629 }, - {1519,2544,601 ,2450,2451,3905 }, {4650,4703,4674 ,5287,5290,5306 }, - {674,4936,4935 ,2271,5013,5012 }, {4848,4836,4783 ,4983,4979,4981 }, - {8071,8133,8144 ,738,2131,2469 }, {4663,4687,4637 ,5155,4985,4986 }, - {4643,1508,4666 ,5037,2029,5105 }, {5672,7009,5694 ,5324,5325,5326 }, - {4670,4608,4906 ,5131,5294,4895 }, {4754,4633,4694 ,5211,5327,5328 }, - {4701,4729,5025 ,5241,5230,5307 }, {4633,4632,4694 ,5327,5329,5328 }, - {8091,8099,8083 ,2167,2867,2103 }, {4250,4404,166 ,4161,5072,3729 }, - {4837,4834,4720 ,3990,4304,5330 }, {3600,3578,3623 ,5331,4205,4206 }, - {4929,4963,4948 ,5142,5178,5262 }, {4963,936,4962 ,5178,5234,5263 }, - {917,4929,4948 ,4016,5142,5262 }, {4963,4962,4948 ,5178,5263,5262 }, - {4283,4086,4774 ,1678,3723,5332 }, {4700,4800,4879 ,5283,5315,5281 }, - {682,346,4923 ,448,449,5245 }, {797,4732,4925 ,5224,5298,5278 }, - {5647,6890,6852 ,5333,5334,5335 }, {4958,1995,1994 ,5226,757,5102 }, - {5084,1698,4789 ,5231,747,5284 }, {4894,4532,4789 ,746,5285,5284 }, - {5084,4789,4867 ,5231,5284,5198 }, {2391,328,327 ,3544,2289,2226 }, - {1317,1176,1177 ,5099,2096,5148 }, {5061,5094,5093 ,2135,5089,5136 }, - {137,4843,4783 ,4980,5130,4981 }, {1831,1902,1866 ,2221,2193,2191 }, - {4704,4703,4650 ,4788,5290,5287 }, {4651,4704,4650 ,5323,4788,5287 }, - {665,760,664 ,1754,3106,1755 }, {4936,4974,4973 ,5013,5019,5014 }, - {4907,674,4935 ,2209,2271,5012 }, {4587,4637,135 ,774,4986,2653 }, - {4879,4941,4790 ,5281,5282,5336 }, {4995,4996,5030 ,5021,5020,2134 }, - {4729,4726,4792 ,5230,5229,5272 }, {4810,475,4748 ,5027,1884,4998 }, - {4998,4999,5033 ,4713,4712,5103 }, {4620,4823,343 ,5276,5277,4543 }, - {8079,8104,3286 ,55,1343,56 }, {6613,6650,6649 ,3746,3833,3759 }, - {4880,4821,4762 ,5008,5134,5129 }, {2279,2251,7042 ,5337,3676,5338 }, - {5061,5062,5094 ,2135,5044,5089 }, {1120,6342,1492 ,5339,5265,1585 }, - {4824,4886,4848 ,4719,4720,4983 }, {876,1167,4017 ,5340,5341,5342 }, - {1330,615,654 ,53,766,93 }, {4558,4598,4584 ,4209,5343,5308 }, - {4800,682,4923 ,5315,448,5245 }, {4948,935,4947 ,5262,5264,5344 }, - {82,557,284 ,138,3724,139 }, {4879,4790,4700 ,5281,5336,5283 }, - {4789,4532,838 ,5284,5285,5345 }, {4955,4958,1994 ,5227,5226,5102 }, - {1210,4183,5017 ,4739,1572,5092 }, {4675,4704,4651 ,5346,4788,5323 }, - {4590,3693,2277 ,1490,5347,3522 }, {833,1291,4780 ,489,5215,5150 }, - {1119,2408,406 ,5180,1399,2566 }, {4912,5071,1024 ,5186,5167,5077 }, - {683,1634,396 ,621,768,153 }, {718,620,719 ,2407,2474,2476 }, - {2908,2851,1249 ,3052,3051,2876 }, {4796,1937,4291 ,4756,59,58 }, - {5089,5091,7052 ,3442,5133,708 }, {4621,4925,4608 ,5223,5278,5294 }, - {5073,4621,4608 ,5250,5223,5294 }, {5396,5395,6506 ,3548,5348,3549 }, - {4634,17,4754 ,5210,5190,5211 }, {402,401,7712 ,5349,1387,5350 }, - {7640,4577,4575 ,5351,5352,3128 }, {682,4800,4695 ,448,5315,5199 }, - {4902,1672,1582 ,5128,2083,2081 }, {5326,6524,6523 ,3714,3704,5319 }, - {4927,4789,838 ,5297,5284,5345 }, {4611,4694,4941 ,5209,5328,5282 }, - {559,4698,4958 ,5225,1578,5226 }, {4698,1884,4958 ,1578,3567,5226 }, - {4958,1884,1995 ,5226,3567,757 }, {833,4772,1291 ,489,5201,5215 }, - {1968,1967,1931 ,2309,404,4736 }, {4577,4578,4576 ,5352,5353,1628 }, - {4578,4624,4651 ,5353,5354,5323 }, {4576,4578,4651 ,1628,5353,5323 }, - {4651,4624,4675 ,5323,5354,5346 }, {4579,4578,7641 ,5355,5353,5356 }, - {4757,4643,4666 ,5104,5037,5105 }, {4639,4689,4638 ,5166,5111,5154 }, - {5081,6605,5938 ,1258,5164,5163 }, {4874,673,707 ,5000,2210,2091 }, - {4941,4694,4790 ,5282,5328,5336 }, {6711,6735,7031 ,3473,3472,5357 }, - {4711,4771,5837 ,5358,3622,3621 }, {4926,4796,4291 ,3897,4756,58 }, - {4601,4654,4653 ,5359,4348,4347 }, {4803,4777,4778 ,4776,3917,3916 }, - {3861,3566,2746 ,1147,1146,1517 }, {1602,4723,361 ,2329,4972,4994 }, - {798,4913,5413 ,78,4185,76 }, {4735,1768,1718 ,5140,2109,2108 }, - {5771,8099,8086 ,2868,2867,4823 }, {2000,4740,1971 ,2428,2426,2520 }, - {4562,4602,4561 ,5018,5360,5361 }, {943,4993,4970 ,1807,5292,3073 }, - {943,1081,4993 ,1807,3745,5292 }, {4600,4599,4558 ,4360,4210,4209 }, - {4559,4600,4558 ,5237,4360,4209 }, {559,4693,267 ,5225,5228,5362 }, - {1091,160,4834 ,4597,4295,4304 }, {4638,4687,4663 ,5154,4985,5155 }, - {4624,4704,4675 ,5354,4788,5346 }, {5082,4684,4979 ,5218,5217,5363 }, - {320,4687,375 ,1871,4985,1883 }, {4656,4681,4655 ,5002,4958,4957 }, - {4923,346,638 ,5245,449,495 }, {4667,5068,4912 ,5069,5305,5186 }, - {4829,4852,4865 ,4626,5364,4229 }, {5043,4144,5985 ,4762,4761,5365 }, - {974,975,7335 ,5366,4266,4265 }, {5837,4713,4711 ,3621,4015,5358 }, - {1699,1698,4898 ,772,747,5123 }, {4754,17,4959 ,5211,5190,5079 }, - {4656,4655,4602 ,5002,4957,5360 }, {4604,4656,4602 ,5016,5002,5360 }, - {4603,4604,4602 ,5017,5016,5360 }, {4602,4601,4560 ,5360,5359,5236 }, - {4573,4701,2733 ,5314,5241,5367 }, {4694,4611,4754 ,5328,5209,5211 }, - {4903,640,4761 ,5214,5078,5251 }, {3788,4680,3672 ,4410,5368,4277 }, - {4834,160,1091 ,4304,4295,4597 }, {4720,4834,1091 ,5330,4304,4597 }, - {4680,4720,1091 ,5368,5330,4597 }, {6141,2072,3725 ,2386,1812,3971 }, - {883,146,4594 ,119,504,688 }, {1176,1130,1177 ,2096,2136,5148 }, - {2315,2382,4563 ,3068,3025,3024 }, {2407,1073,2156 ,4001,3741,3631 }, - {4624,4705,4704 ,5354,5369,4788 }, {4705,4706,4704 ,5369,4786,4788 }, - {7186,7185,7168 ,5370,5073,5371 }, {124,196,1423 ,2206,152,151 }, - {3954,8065,8062 ,3463,96,3272 }, {4603,4602,4562 ,5017,5360,5018 }, - {1968,1931,5019 ,2309,4736,2384 }, {640,446,4847 ,5078,501,5252 }, - {678,682,4695 ,446,448,5199 }, {3786,22,1418 ,4074,4066,4619 }, - {4921,4979,2257 ,2079,5363,554 }, {1941,3476,3283 ,1034,3838,262 }, - {4787,4739,4815 ,5293,5372,5373 }, {5025,4787,4815 ,5307,5293,5373 }, - {5768,4713,5804 ,933,4015,3623 }, {4449,4564,4805 ,5374,5375,5376 }, - {4711,4449,4805 ,5358,5374,5376 }, {4564,4646,4645 ,5375,5377,5378 }, - {4805,4564,4645 ,5376,5375,5378 }, {4646,4926,4645 ,5377,3897,5378 }, - {1724,1249,2851 ,3880,2876,3051 }, {4912,5068,4686 ,5186,5305,5030 }, - {976,937,4964 ,782,5067,783 }, {4655,4654,4602 ,4957,4348,5360 }, - {4561,4602,4560 ,5361,5360,5236 }, {2391,327,282 ,3544,2226,3498 }, - {4601,4653,4600 ,5359,4347,4360 }, {675,4937,4936 ,2294,5187,5013 }, - {5095,5096,1024 ,5379,5185,5077 }, {4823,4619,343 ,5277,5213,4543 }, - {1365,4666,1440 ,2085,5105,2063 }, {4619,344,343 ,5213,562,4543 }, - {4761,4847,4619 ,5251,5252,5213 }, {4794,4903,4761 ,5313,5214,5251 }, - {509,4873,572 ,4993,4992,1947 }, {4579,4624,4578 ,5355,5354,5353 }, - {4676,4706,4705 ,5380,4786,5369 }, {4624,4676,4705 ,5354,5380,5369 }, - {4569,4983,2808 ,1344,480,522 }, {2382,127,126 ,3025,1395,1394 }, - {1172,1081,1034 ,1758,3745,1756 }, {1672,1649,1650 ,2083,2031,2082 }, - {4834,5236,1091 ,4304,4301,4597 }, {4847,446,4619 ,5252,501,5213 }, - {446,39,4619 ,501,529,5213 }, {111,110,2962 ,1154,743,3494 }, - {4589,4638,4637 ,776,5154,4986 }, {4571,2162,6311 ,1342,3278,1097 }, - {4176,3784,4198 ,4703,2252,4969 }, {4701,4815,4956 ,5241,5373,5381 }, - {4696,4753,4713 ,5382,5383,4015 }, {5770,4696,4713 ,3949,5382,4015 }, - {4753,4449,4711 ,5383,5374,5358 }, {4713,4753,4711 ,4015,5383,5358 }, - {4939,4926,4646 ,5384,3897,5377 }, {4876,4796,4926 ,5385,4756,3897 }, - {4939,4876,4926 ,5384,5385,3897 }, {4323,4394,4796 ,4045,4044,4756 }, - {4876,4323,4796 ,5385,4045,4756 }, {3975,8064,2812 ,728,3141,1914 }, - {4916,4930,4929 ,2248,5068,5142 }, {4892,343,342 ,5386,4543,4542 }, - {4691,4721,4690 ,2089,5052,5051 }, {468,4803,4779 ,1369,4776,4729 }, - {4822,4783,4902 ,4984,4981,5128 }, {468,4779,4716 ,1369,4729,1030 }, - {5479,6741,6706 ,5387,5388,5389 }, {4601,4600,4560 ,5359,4360,5236 }, - {4994,4995,5030 ,5076,5021,2134 }, {4532,559,838 ,5285,5225,5345 }, - {4754,4903,4678 ,5211,5214,5312 }, {559,267,838 ,5225,5362,5345 }, - {4776,4680,3788 ,5390,5368,4410 }, {4452,4432,4795 ,2398,156,3710 }, - {7101,7128,7114 ,4073,5391,5392 }, {8049,2318,2317 ,5393,3185,3129 }, - {4625,4624,4579 ,5394,5354,5355 }, {4625,4626,4624 ,5394,5395,5354 }, - {4626,4676,4624 ,5395,5380,5354 }, {4998,5033,5032 ,4713,5103,5168 }, - {4717,4716,4657 ,1449,1030,5001 }, {8116,8071,5521 ,172,738,751 }, - {4612,278,4641 ,5249,1489,5248 }, {5031,5064,5063 ,4995,5043,5042 }, - {4721,4691,383 ,5052,2089,2087 }, {4639,4640,4690 ,5166,5208,5051 }, - {1073,42,2156 ,3741,5195,3631 }, {7029,7051,2341 ,548,547,845 }, - {6524,6572,6571 ,3704,3734,4146 }, {1902,1901,1866 ,2193,2192,2191 }, - {6989,5693,6947 ,4586,4075,4587 }, {6968,6967,6916 ,595,4629,596 }, - {6735,3192,2450 ,3472,3063,3444 }, {2733,4701,4956 ,5367,5241,5381 }, - {2407,2156,2258 ,4001,3631,1198 }, {4753,4854,4449 ,5383,5396,5374 }, - {4877,4876,4939 ,5397,5385,5384 }, {4940,4877,4939 ,5398,5397,5384 }, - {4752,4323,4876 ,5196,4045,5385 }, {4877,4752,4876 ,5397,5196,5385 }, - {717,855,4977 ,2408,2392,4711 }, {6711,7031,2450 ,3473,5357,3444 }, - {5520,1516,5059 ,1304,1254,1253 }, {4931,4930,4916 ,5066,5068,2248 }, - {5079,833,4780 ,5220,489,5150 }, {4980,2163,158 ,241,243,5258 }, - {5477,4672,5442 ,5399,2682,5174 }, {1307,801,4351 ,4930,4907,4606 }, - {4846,4780,3139 ,4237,5150,5400 }, {5659,2453,5658 ,3053,42,49 }, - {4633,4754,4678 ,5327,5211,5312 }, {4700,4790,5002 ,5283,5336,5273 }, - {5060,4720,4680 ,5401,5330,5368 }, {4776,5060,4680 ,5390,5401,5368 }, - {5060,4837,4720 ,5401,3990,5330 }, {4937,4975,4974 ,5187,5202,5019 }, - {4626,4625,4579 ,5395,5394,5355 }, {4626,4706,4676 ,5395,4786,5380 }, - {4612,4640,4639 ,5249,5208,5166 }, {4658,4717,4657 ,5047,1449,5001 }, - {677,4938,4937 ,2296,5053,5187 }, {3783,4612,4639 ,5311,5249,5166 }, - {4750,383,4786 ,5152,2087,5153 }, {577,675,674 ,2270,2294,2271 }, - {4893,4874,707 ,5286,5000,2091 }, {4602,4654,4601 ,5360,4348,5359 }, - {5943,6292,6283 ,5402,5403,4298 }, {6523,6524,6571 ,5319,3704,4146 }, - {1167,1120,1492 ,5341,5339,1585 }, {5672,5694,6949 ,5324,5326,4585 }, - {4774,4086,557 ,5332,3723,3724 }, {2156,6464,3898 ,3631,3633,1400 }, - {4701,5025,4815 ,5241,5307,5373 }, {4854,4616,4564 ,5396,5404,5375 }, - {4449,4854,4564 ,5374,5396,5375 }, {4616,4662,4646 ,5404,5405,5377 }, - {4564,4616,4646 ,5375,5404,5377 }, {4940,4939,4646 ,5398,5384,5377 }, - {4662,4940,4646 ,5405,5398,5377 }, {406,2219,2206 ,2566,177,176 }, - {4613,4614,278 ,1488,3109,1489 }, {617,618,677 ,2352,2391,2296 }, - {5064,5096,5095 ,5043,5185,5379 }, {4824,4848,4844 ,4719,4983,4866 }, - {4937,4938,4975 ,5187,5053,5202 }, {5018,5032,5031 ,5119,5168,4995 }, - {4840,4874,4873 ,5207,5000,4992 }, {972,2314,2162 ,3277,3742,3278 }, - {6681,6704,6655 ,5406,5160,5407 }, {4948,4947,917 ,5262,5344,4016 }, - {3358,6393,3357 ,880,1556,883 }, {6342,6555,1749 ,5265,597,555 }, - {4693,4955,4953 ,5228,5227,5408 }, {267,4693,4953 ,5362,5228,5408 }, - {4955,1994,4971 ,5227,5102,5409 }, {4953,4955,4971 ,5408,5227,5409 }, - {4838,5060,4776 ,245,5401,5390 }, {4838,4837,5060 ,245,3990,5401 }, - {4818,4647,4661 ,5145,5036,5101 }, {4683,1024,4647 ,5035,5077,5036 }, - {4580,4626,4579 ,5410,5395,5355 }, {4707,4706,4626 ,5411,4786,5395 }, - {4707,4737,4706 ,5411,5412,4786 }, {4706,4737,4765 ,4786,5412,3983 }, - {4826,5259,4765 ,5413,3794,3983 }, {4658,4657,4605 ,5047,5001,5006 }, - {361,4723,4751 ,4994,4972,5007 }, {4857,509,4810 ,4991,4993,5027 }, - {4873,4874,4893 ,4992,5000,5286 }, {4840,4857,4810 ,5207,4991,5027 }, - {375,4748,475 ,1883,4998,1884 }, {1320,4618,1285 ,2356,5070,1944 }, - {4664,4614,279 ,5414,3109,2176 }, {1583,2621,3683 ,5415,5416,5417 }, - {922,6416,6415 ,117,3440,386 }, {5000,922,6415 ,286,117,386 }, - {6795,5491,5516 ,5418,5419,5420 }, {4922,4608,4585 ,5256,5294,3955 }, - {1073,2407,2314 ,3741,4001,3742 }, {4793,4718,4753 ,5421,5422,5383 }, - {4718,4814,4854 ,5422,5423,5396 }, {4753,4718,4854 ,5383,5422,5396 }, - {4814,4722,4616 ,5423,5424,5404 }, {4854,4814,4616 ,5396,5423,5404 }, - {4722,4665,4662 ,5424,5425,5405 }, {4616,4722,4662 ,5404,5424,5405 }, - {4943,4940,4662 ,5426,5398,5405 }, {4665,4943,4662 ,5425,5426,5405 }, - {1655,2432,68 ,4089,5427,4087 }, {4614,4641,278 ,3109,5248,1489 }, - {4895,4817,5004 ,4973,2368,5243 }, {4975,4976,4997 ,5202,5048,5049 }, - {6417,404,5388 ,762,761,5428 }, {5016,4644,1931 ,5010,2425,4736 }, - {1699,1702,1752 ,772,1039,946 }, {4975,4997,4996 ,5202,5049,5020 }, - {4936,4937,4974 ,5013,5187,5019 }, {4810,4811,4840 ,5027,5165,5207 }, - {6957,5752,5709 ,4315,4374,5253 }, {4866,4865,4852 ,3641,4229,5364 }, - {4734,4902,1582 ,5127,5128,2081 }, {4829,4830,4852 ,4626,3642,5364 }, - {961,446,4959 ,500,501,5079 }, {5015,4870,4862 ,5170,5135,5149 }, - {1702,1636,1703 ,1039,1036,1038 }, {638,15,17 ,495,497,5190 }, - {4842,4838,4776 ,5429,245,5390 }, {24,1375,4837 ,247,325,3990 }, - {4838,24,4837 ,245,247,3990 }, {4919,4920,4968 ,5221,5138,5222 }, - {4581,4627,4626 ,5430,5431,5395 }, {4580,4581,4626 ,5410,5430,5395 }, - {4626,4708,4707 ,5395,5432,5411 }, {4707,4708,4737 ,5411,5432,5412 }, - {4737,4708,4765 ,5412,5432,3983 }, {384,327,328 ,2228,2226,2289 }, - {4751,5004,4871 ,5007,5243,5040 }, {4871,561,5016 ,5040,2379,5010 }, - {4895,5004,4751 ,4973,5243,5007 }, {4857,4840,4873 ,4991,5207,4992 }, - {4782,4812,4492 ,5029,5169,5031 }, {6842,6895,6865 ,5433,5434,5435 }, - {4820,4433,4849 ,2399,4591,5436 }, {4801,82,607 ,5115,138,2207 }, - {935,4962,936 ,5264,5263,5234 }, {7138,7161,7169 ,2560,2559,5437 }, - {1265,6344,4548 ,1273,1450,589 }, {4730,4885,4743 ,5438,5439,3629 }, - {4885,4747,4793 ,5439,5440,5421 }, {4743,4885,4793 ,3629,5439,5421 }, - {4793,4747,4718 ,5421,5440,5422 }, {4742,4877,4940 ,5441,5397,5398 }, - {4943,4742,4940 ,5426,5441,5398 }, {4742,4752,4877 ,5441,5196,5397 }, - {4897,1488,4752 ,5442,5197,5196 }, {410,259,2967 ,2204,2203,2701 }, - {4920,4919,662 ,5138,5221,5141 }, {1041,5034,952 ,2410,2396,2395 }, - {5034,1041,5033 ,2396,2410,5103 }, {2156,42,6783 ,3631,5195,3632 }, - {344,1993,343 ,562,4544,4543 }, {4587,4589,4637 ,774,776,4986 }, - {4787,4792,4816 ,5293,5272,5443 }, {4633,4678,4632 ,5327,5312,5329 }, - {4678,4794,4761 ,5312,5313,5251 }, {4758,4761,4620 ,5444,5251,5276 }, - {4841,4842,4745 ,5445,5429,5446 }, {4745,4776,495 ,5446,5390,4389 }, - {4917,4838,4842 ,5447,245,5429 }, {4841,4917,4842 ,5445,5447,5429 }, - {4258,85,4303 ,84,2504,3728 }, {5095,1024,4683 ,5379,5077,5035 }, - {5094,5095,4683 ,5089,5379,5035 }, {4627,4677,4626 ,5431,5448,5395 }, - {4626,4677,4708 ,5395,5448,5432 }, {4708,4766,4765 ,5432,5449,3983 }, - {4766,4827,4826 ,5449,2734,5413 }, {949,850,851 ,2133,2092,2155 }, - {4886,361,417 ,4720,4994,5009 }, {4580,7672,4581 ,5410,5450,5430 }, - {1397,4667,1320 ,2358,5069,2356 }, {6172,6147,5920 ,5451,5452,5453 }, - {8144,8133,2301 ,2469,2131,2132 }, {7027,7049,7007 ,3175,5454,4628 }, - {3320,6639,2158 ,5455,3699,1160 }, {911,3320,2158 ,1159,5455,1160 }, - {6309,6310,6735 ,3690,3918,3472 }, {1920,2157,6606 ,581,3411,5085 }, - {6686,5105,4544 ,750,5456,748 }, {1332,8123,8143 ,3492,2247,2570 }, - {4730,4731,4747 ,5438,5457,5440 }, {4885,4730,4747 ,5439,5438,5440 }, - {4899,4752,4742 ,5458,5196,5441 }, {4882,4899,4742 ,5459,5458,5441 }, - {3895,4897,4752 ,4455,5442,5196 }, {4899,3895,4752 ,5458,4455,5196 }, - {5065,5097,5096 ,5064,5063,5185 }, {5064,5065,5096 ,5043,5064,5185 }, - {663,4920,662 ,4773,5138,5141 }, {7163,7171,7194 ,5460,4306,1670 }, - {4773,4804,4661 ,4865,4867,5101 }, {4605,4604,1381 ,5006,5016,5193 }, - {1831,4850,1902 ,2221,5171,2193 }, {4968,4969,1030 ,5222,4977,1619 }, - {4906,4608,4922 ,4895,5294,5256 }, {4906,4922,2814 ,4895,5256,5255 }, - {4830,4866,4852 ,3642,3641,5364 }, {4739,4787,4816 ,5372,5293,5443 }, - {1994,2048,3184 ,5102,5461,4453 }, {4971,1994,1460 ,5409,5102,5462 }, - {1460,1994,3184 ,5462,5102,4453 }, {4745,4775,4841 ,5446,4388,5445 }, - {4917,4808,4838 ,5447,5137,245 }, {241,4724,240 ,314,4737,1571 }, - {4581,4628,4627 ,5430,5463,5431 }, {4627,4628,4677 ,5431,5463,5448 }, - {4677,4628,4708 ,5448,5463,5432 }, {4738,4767,4766 ,5464,5465,5449 }, - {4708,4738,4766 ,5432,5464,5449 }, {4766,4828,4827 ,5449,5466,2734 }, - {423,4811,383 ,2086,5165,2087 }, {6744,3350,1116 ,3986,2541,1401 }, - {6415,6416,4424 ,386,3440,3792 }, {6416,5089,4424 ,3440,3442,3792 }, - {5171,5125,5172 ,1804,5467,5468 }, {5105,5040,4544 ,5456,5469,748 }, - {5949,5388,404 ,5086,5428,761 }, {4731,4719,4718 ,5457,5470,5422 }, - {4747,4731,4718 ,5440,5457,5422 }, {4719,4673,4814 ,5470,5471,5423 }, - {4718,4719,4814 ,5422,5470,5423 }, {4673,4781,4722 ,5471,5472,5424 }, - {4814,4673,4722 ,5423,5471,5424 }, {4944,4943,4665 ,5473,5426,5425 }, - {4671,4944,4665 ,5474,5473,5425 }, {4944,4882,4742 ,5473,5459,5441 }, - {4943,4944,4742 ,5426,5473,5441 }, {3247,3777,6430 ,1494,1582,2748 }, - {423,514,4811 ,2086,2154,5165 }, {5018,4998,5032 ,5119,4713,5168 }, - {7927,7976,7952 ,1716,1715,5475 }, {718,811,856 ,2407,557,5139 }, - {8076,8124,2810 ,617,1141,1728 }, {4931,4932,4964 ,5066,4580,783 }, - {1042,898,1043 ,2409,2411,2478 }, {955,4834,4837 ,3991,4304,3990 }, - {4792,5002,4699 ,5272,5273,5476 }, {4802,4841,4775 ,5477,5445,4388 }, - {4917,648,4808 ,5447,4679,5137 }, {4716,4778,4714 ,1030,3916,1031 }, - {4734,1536,1508 ,5127,2080,2029 }, {5047,5031,5062 ,4996,4995,5044 }, - {4993,1081,1030 ,5292,3745,1619 }, {4762,1831,4735 ,5129,2221,5140 }, - {4743,5038,4730 ,3629,3628,5438 }, {4581,4582,4628 ,5430,5478,5463 }, - {4767,4798,4766 ,5465,5479,5449 }, {4766,4798,4828 ,5449,5479,5466 }, - {4828,4887,4827 ,5466,2735,2734 }, {5064,5095,5094 ,5043,5379,5089 }, - {4863,4904,4887 ,5480,3309,2735 }, {8145,8114,6797 ,3376,2286,2246 }, - {1167,1492,4017 ,5341,1585,5342 }, {5946,5991,7083 ,5481,5482,5483 }, - {4445,712,6757 ,3648,3650,3409 }, {5092,4730,4839 ,3953,5438,5484 }, - {7055,1219,7079 ,5485,4102,5486 }, {4635,4591,4731 ,5487,5488,5457 }, - {4730,4635,4731 ,5438,5487,5457 }, {4591,4825,4719 ,5488,5489,5470 }, - {4731,4591,4719 ,5457,5488,5470 }, {4825,4791,4673 ,5489,5490,5471 }, - {4719,4825,4673 ,5470,5489,5471 }, {4791,4728,4781 ,5490,5491,5472 }, - {4673,4791,4781 ,5471,5490,5472 }, {4781,4728,4722 ,5472,5491,5424 }, - {4728,837,4665 ,5491,5492,5425 }, {4722,4728,4665 ,5424,5491,5425 }, - {4665,837,4671 ,5425,5492,5474 }, {837,4946,4944 ,5492,5493,5473 }, - {4671,837,4944 ,5474,5492,5473 }, {4922,3766,4636 ,5256,3954,5118 }, - {4756,3817,5099 ,1190,1189,5494 }, {3817,3800,5099 ,1189,4325,5494 }, - {4682,4756,4736 ,1191,1190,5495 }, {7031,6735,2450 ,5357,3472,3444 }, - {4873,4893,612 ,4992,5286,5011 }, {6704,6703,6655 ,5160,5161,5407 }, - {4816,4792,4699 ,5443,5272,5476 }, {3945,6418,6416 ,4550,3441,3440 }, - {4775,4861,4802 ,4388,3877,5477 }, {4802,4917,4841 ,5477,5447,5445 }, - {4751,4871,5015 ,5007,5040,5170 }, {5031,5063,5062 ,4995,5042,5044 }, - {1790,5017,4183 ,4738,5092,1572 }, {4970,4993,4992 ,3073,5292,4978 }, - {4783,1718,1672 ,4981,2108,2083 }, {4555,4556,4582 ,5496,5497,5478 }, - {79,8104,3421 ,1510,1343,1156 }, {4583,4628,4582 ,5498,5463,5478 }, - {4652,4709,4708 ,5499,4396,5432 }, {4628,4652,4708 ,5463,5499,5432 }, - {4708,4709,4738 ,5432,4396,5464 }, {4767,4768,4798 ,5465,5500,5479 }, - {4798,4768,4828 ,5479,5500,5466 }, {4863,4887,4828 ,5480,2735,5466 }, - {4851,4863,4828 ,5501,5480,5466 }, {311,4808,648 ,246,5137,4679 }, - {673,4907,4934 ,2210,2209,5041 }, {6808,6809,6859 ,3465,712,472 }, - {1583,1606,2621 ,5415,3677,5416 }, {7004,7045,7026 ,5502,5503,5504 }, - {5089,3454,4424 ,3442,710,3792 }, {5844,5812,7073 ,5179,660,662 }, - {1666,4882,4944 ,5505,5459,5473 }, {4946,1666,4944 ,5493,5505,5473 }, - {1666,4899,4882 ,5505,5458,5459 }, {4921,5082,4979 ,2079,5218,5363 }, - {5066,5098,5065 ,5188,5062,5064 }, {4733,5099,4697 ,5506,5494,4327 }, - {4733,4756,5099 ,5506,1190,5494 }, {3634,4741,4813 ,5507,5508,4088 }, - {4733,4736,4756 ,5506,5495,1190 }, {5026,4881,4957 ,4225,2731,2733 }, - {8122,8145,8087 ,384,3376,385 }, {5022,1196,4788 ,4329,4330,3758 }, - {4760,4669,5022 ,5509,3879,4329 }, {4759,4861,4669 ,5510,3877,3879 }, - {4760,4759,4669 ,5509,5510,3879 }, {4892,4917,4802 ,5386,5447,5477 }, - {4892,648,4917 ,5386,4679,5447 }, {675,578,676 ,2294,2293,2295 }, - {718,856,855 ,2407,5139,2392 }, {6348,6349,6357 ,1607,705,5271 }, - {663,662,566 ,4773,5141,1613 }, {668,611,669 ,1949,1948,2020 }, - {4605,4656,4604 ,5006,5002,5016 }, {5217,4703,4704 ,4026,5290,4788 }, - {5067,1041,1135 ,1945,2410,1943 }, {3855,3813,3814 ,1511,1515,5511 }, - {3303,7387,7386 ,1049,3615,5512 }, {4583,4629,4628 ,5498,5513,5463 }, - {4629,4652,4628 ,5513,5499,5463 }, {4709,4768,4767 ,4396,5500,5465 }, - {4738,4709,4767 ,5464,4396,5465 }, {851,767,4934 ,2155,2093,5041 }, - {6153,5040,5105 ,5514,5469,5456 }, {3898,6464,4987 ,1400,3633,1491 }, - {6917,6916,6895 ,5515,596,5434 }, {6757,3702,1990 ,3409,1303,1305 }, - {911,5027,158 ,1159,5516,5258 }, {5027,911,6684 ,5516,1159,1161 }, - {6681,6655,6656 ,5406,5407,5517 }, {5405,6681,6656 ,5518,5406,5517 }, - {5688,5738,6890 ,5519,5520,5334 }, {5738,5750,6890 ,5520,5156,5334 }, - {1460,3184,4899 ,5462,4453,5458 }, {1666,1460,4899 ,5505,5462,5458 }, - {4899,3184,3895 ,5458,4453,4455 }, {4618,4912,5097 ,5070,5186,5063 }, - {8094,8100,8069 ,98,1713,1095 }, {6853,5626,5587 ,2505,1460,1459 }, - {6098,6173,6388 ,1565,3711,3184 }, {2164,2165,3191 ,3583,1041,2903 }, - {7169,7186,7168 ,5437,5370,5371 }, {4741,4815,1655 ,5508,5373,4089 }, - {4813,4741,1655 ,4088,5508,4089 }, {4815,4878,4872 ,5373,5521,5522 }, - {1655,4815,4872 ,4089,5373,5522 }, {4878,4739,4872 ,5521,5372,5522 }, - {4668,4697,4872 ,5523,4327,5522 }, {4739,4668,4872 ,5372,5523,5522 }, - {4668,4733,4697 ,5523,5506,4327 }, {4610,4682,4736 ,3757,1191,5495 }, - {4610,1376,4682 ,3757,1937,1191 }, {5002,4790,4699 ,5273,5336,5476 }, - {4760,5022,4788 ,5509,4329,3758 }, {4660,4760,4788 ,5524,5509,3758 }, - {4759,4802,4861 ,5510,5477,3877 }, {4802,4875,4892 ,5477,5525,5386 }, - {1469,4782,1397 ,2361,5029,2358 }, {707,673,767 ,2091,2210,2093 }, - {4647,4818,4643 ,5036,5145,5037 }, {749,1676,4723 ,2331,2343,4972 }, - {663,566,567 ,4773,1613,1684 }, {4724,4949,1790 ,4737,5526,4738 }, - {1440,4666,1508 ,2063,5105,2029 }, {611,612,669 ,1948,5011,2020 }, - {5098,1285,5097 ,5062,1944,5063 }, {4630,4629,4583 ,827,5513,5498 }, - {4629,4630,4652 ,5513,827,5499 }, {4709,4710,4768 ,4396,4136,5500 }, - {4829,4828,4768 ,4626,5466,5500 }, {4829,4851,4828 ,4626,5501,5466 }, - {2290,7935,7936 ,1982,5527,5528 }, {2376,2156,3898 ,1251,3631,1400 }, - {3609,6195,5920 ,5081,5529,5453 }, {3319,2336,5005 ,1259,1261,1301 }, - {8081,8138,8078 ,1445,2018,1744 }, {5003,4591,4635 ,5530,5488,5487 }, - {4860,5003,4635 ,5531,5530,5487 }, {4591,4909,4825 ,5488,5532,5489 }, - {4909,4791,4825 ,5532,5490,5489 }, {837,4952,4946 ,5492,5533,5493 }, - {4952,1460,1666 ,5533,5462,5505 }, {4946,4952,1666 ,5493,5533,5505 }, - {4698,1885,1884 ,1578,778,3567 }, {4635,4730,5092 ,5487,5438,3953 }, - {7743,7769,7768 ,5534,5535,5536 }, {4741,4956,4815 ,5508,5381,5373 }, - {4815,4739,4878 ,5373,5372,5521 }, {4816,4668,4739 ,5443,5523,5372 }, - {4699,4733,4668 ,5476,5506,5523 }, {4816,4699,4668 ,5443,5476,5523 }, - {4632,4788,4610 ,5329,3758,3757 }, {4891,4632,4610 ,5537,5329,3757 }, - {4632,4660,4788 ,5329,5524,3758 }, {4678,4760,4660 ,5312,5509,5524 }, - {4632,4678,4660 ,5329,5312,5524 }, {4620,4802,4759 ,5276,5477,5510 }, - {4802,4620,4875 ,5477,5276,5525 }, {5015,4871,4870 ,5170,5040,5135 }, - {678,4695,833 ,446,5199,489 }, {4862,1831,4762 ,5149,2221,5129 }, - {4970,4969,4920 ,3073,4977,5138 }, {4749,4786,4811 ,5026,5153,5165 }, - {4641,4664,279 ,5248,5414,2176 }, {557,4883,4774 ,3724,5538,5332 }, - {156,1297,1488 ,5539,4048,5197 }, {557,4801,4883 ,3724,5115,5538 }, - {4264,1488,4897 ,5540,5197,5442 }, {4641,279,4691 ,5248,2176,2089 }, - {4597,4630,4583 ,5541,827,5498 }, {4652,4630,4709 ,5499,827,4396 }, - {4710,4630,5177 ,4136,827,424 }, {4710,4769,4768 ,4136,5542,5500 }, - {4769,4799,4768 ,5542,4627,5500 }, {4768,4799,4829 ,5500,4627,4626 }, - {4829,4864,4863 ,4626,5543,5480 }, {4851,4829,4863 ,5501,4626,5480 }, - {3006,8132,552 ,414,413,3929 }, {6611,5471,6640 ,1391,2051,4224 }, - {1562,4392,7051 ,4649,844,547 }, {4586,911,158 ,5257,1159,5258 }, - {7568,7594,7567 ,5544,4020,5545 }, {7552,7613,7551 ,5546,5106,5108 }, - {4585,4593,5003 ,3955,5295,5530 }, {4860,4585,5003 ,5531,3955,5530 }, - {5003,4593,4591 ,5530,5295,5488 }, {4593,4732,4909 ,5295,5298,5532 }, - {4591,4593,4909 ,5488,5295,5532 }, {4732,4927,4791 ,5298,5297,5490 }, - {4909,4732,4791 ,5532,5298,5490 }, {4927,838,4728 ,5297,5345,5491 }, - {4791,4927,4728 ,5490,5297,5491 }, {267,837,4728 ,5362,5492,5491 }, - {838,267,4728 ,5345,5362,5491 }, {267,4953,4952 ,5362,5408,5533 }, - {837,267,4952 ,5492,5362,5533 }, {7647,7697,7675 ,4967,651,5192 }, - {2000,1971,2002 ,2428,2520,2493 }, {3276,2375,922 ,116,4479,117 }, - {403,1264,3929 ,5547,5022,5024 }, {4832,4736,4733 ,5548,5495,5506 }, - {4699,4832,4733 ,5476,5548,5506 }, {4891,4610,4736 ,5537,3757,5495 }, - {4678,4759,4760 ,5312,5510,5509 }, {4759,4758,4620 ,5510,5444,5276 }, - {4875,4620,4892 ,5525,5276,5386 }, {4850,1903,1902 ,5171,406,2193 }, - {4614,4664,4641 ,3109,5414,5248 }, {7672,7716,4581 ,5450,5549,5430 }, - {1970,4740,2000 ,2427,2426,2428 }, {4724,241,1241 ,4737,314,313 }, - {1241,4283,4774 ,313,1678,5332 }, {4724,1241,4774 ,4737,313,5332 }, - {607,124,4801 ,2207,2206,5115 }, {4491,808,5202 ,107,4734,5550 }, - {6039,5166,5227 ,2728,3427,4097 }, {4331,5052,1154 ,4645,5189,4545 }, - {1154,5052,993 ,4545,5189,5551 }, {4769,4770,4799 ,5542,4345,4627 }, - {4829,4865,4864 ,4626,4229,5543 }, {4864,4865,4863 ,5543,4229,5480 }, - {4865,4913,798 ,4229,4185,78 }, {4863,4865,798 ,5480,4229,78 }, - {3264,8117,8068 ,2468,4119,1784 }, {3626,6534,3627 ,4196,4257,4256 }, - {6418,5091,5089 ,3441,5133,3442 }, {4549,6621,6605 ,877,5552,5164 }, - {5669,5710,5709 ,5553,5254,5253 }, {6389,6714,6868 ,5301,5300,5554 }, - {5092,4585,4860 ,3953,3955,5531 }, {4953,4971,1460 ,5408,5409,5462 }, - {4952,4953,1460 ,5533,5408,5462 }, {185,3777,3247 ,1493,1582,1494 }, - {1166,309,2408 ,2746,4472,1399 }, {4560,4559,7918 ,5236,5237,5555 }, - {922,3945,6416 ,117,4550,3440 }, {2156,2376,2258 ,3631,1251,1198 }, - {4790,4832,4699 ,5336,5548,5476 }, {4790,4736,4832 ,5336,5495,5548 }, - {4694,4891,4736 ,5328,5537,5495 }, {4790,4694,4736 ,5336,5328,5495 }, - {4694,4632,4891 ,5328,5329,5537 }, {4761,4759,4678 ,5251,5510,5312 }, - {4759,4761,4758 ,5510,5251,5444 }, {4620,343,4892 ,5276,4543,5386 }, - {4117,5481,4157 ,4700,3863,3755 }, {206,3815,1606 ,3932,5556,3677 }, - {247,921,2663 ,2569,1922,3593 }, {6044,5934,5980 ,614,616,5557 }, - {3797,3746,3747 ,2061,2708,2925 }, {6211,6246,6245 ,5558,5559,5560 }, - {4443,4422,6212 ,703,5561,5562 }, {1344,1511,3941 ,300,4921,5563 }, - {1268,5995,6105 ,4568,5564,5565 }, {6210,6211,6245 ,5566,5558,5560 }, - {5515,5960,6045 ,5567,5568,935 }, {6157,1017,1426 ,5569,1793,4648 }, - {5140,2094,5130 ,3712,5570,5571 }, {5130,5499,5140 ,5571,5572,3712 }, - {5499,2621,5140 ,5572,5416,3712 }, {1627,3688,1729 ,5573,5574,3666 }, - {6247,6275,1557 ,5575,5576,5577 }, {5340,5379,4916 ,4002,3998,2248 }, - {5339,5340,4916 ,2223,4002,2248 }, {2256,5013,5950 ,2323,684,2873 }, - {6123,5988,4147 ,4221,2516,2517 }, {4392,5130,2094 ,844,5571,5570 }, - {5204,3683,5704 ,5578,5417,5579 }, {5499,5204,5704 ,5572,5578,5579 }, - {6377,6079,5978 ,1347,5580,5581 }, {5978,6082,6377 ,5581,1348,1347 }, - {7948,7994,7947 ,3625,5582,4354 }, {4306,4278,4307 ,4552,5583,4562 }, - {4489,3778,1583 ,5584,5585,5415 }, {6744,5082,5786 ,3986,5218,4813 }, - {5131,5204,5499 ,5586,5578,5572 }, {5130,5131,5499 ,5571,5586,5572 }, - {6390,5950,8114 ,3868,2873,2286 }, {1557,3310,5989 ,5577,5587,5588 }, - {778,1742,5498 ,5589,707,5590 }, {3820,778,5498 ,5591,5589,5590 }, - {313,1562,1742 ,5592,4649,707 }, {778,313,1742 ,5589,5592,707 }, - {313,5132,5130 ,5592,5593,5571 }, {1562,313,5130 ,4649,5592,5571 }, - {5130,5132,5131 ,5571,5593,5586 }, {5132,5141,5204 ,5593,5594,5578 }, - {5131,5132,5204 ,5586,5593,5578 }, {5141,5145,3683 ,5594,5595,5417 }, - {5204,5141,3683 ,5578,5594,5417 }, {5145,1289,1583 ,5595,5596,5415 }, - {3683,5145,1583 ,5417,5595,5415 }, {1289,3952,4489 ,5596,5597,5584 }, - {1583,1289,4489 ,5415,5596,5584 }, {4342,3528,4321 ,4950,5061,4873 }, - {1289,2713,3952 ,5596,4352,5597 }, {5141,1289,5145 ,5594,5596,5595 }, - {1289,3141,2713 ,5596,4701,4352 }, {5231,2375,3276 ,115,4479,116 }, - {5419,3820,3936 ,5598,5591,5599 }, {4024,5419,3936 ,5600,5598,5599 }, - {3798,778,3820 ,5601,5589,5591 }, {5419,3798,3820 ,5598,5601,5591 }, - {3798,4325,313 ,5601,5602,5592 }, {778,3798,313 ,5589,5601,5592 }, - {4325,5133,5132 ,5602,5603,5593 }, {313,4325,5132 ,5592,5602,5593 }, - {5133,533,5141 ,5603,5604,5594 }, {5132,5133,5141 ,5593,5603,5594 }, - {533,1944,5141 ,5604,5605,5594 }, {1944,2270,1289 ,5605,5606,5596 }, - {5141,1944,1289 ,5594,5605,5596 }, {2270,3222,1289 ,5606,5607,5596 }, - {1289,3222,3141 ,5596,5607,4701 }, {5133,1944,533 ,5603,5605,5604 }, - {5163,4127,3141 ,4987,4702,4701 }, {3222,5163,3141 ,5607,4987,4701 }, - {7090,7089,6281 ,4080,5608,4078 }, {4426,1414,4024 ,1056,5609,5600 }, - {3733,4426,4024 ,5610,1056,5600 }, {1414,5422,5419 ,5609,5611,5598 }, - {4024,1414,5419 ,5600,5609,5598 }, {4014,3798,5419 ,5612,5601,5598 }, - {5422,4014,5419 ,5611,5612,5598 }, {4014,3947,4325 ,5612,5613,5602 }, - {3798,4014,4325 ,5601,5612,5602 }, {5133,5561,1944 ,5603,5614,5605 }, - {2270,3002,3222 ,5606,5615,5607 }, {3222,3002,5163 ,5607,5615,4987 }, - {4545,4980,3621 ,586,241,625 }, {3947,5134,5133 ,5613,5616,5603 }, - {4325,3947,5133 ,5602,5613,5603 }, {5133,5134,5561 ,5603,5616,5614 }, - {5134,1786,1944 ,5616,5617,5605 }, {5561,5134,1944 ,5614,5616,5605 }, - {1786,5144,2270 ,5617,5618,5606 }, {1944,1786,2270 ,5605,5617,5606 }, - {5144,996,3002 ,5618,5003,5615 }, {2270,5144,3002 ,5606,5618,5615 }, - {3002,996,5163 ,5615,5003,4987 }, {5163,996,4176 ,4987,5003,4703 }, - {4014,159,3947 ,5612,5619,5613 }, {3947,159,5134 ,5613,5619,5616 }, - {6033,5987,5982 ,5620,5621,4218 }, {4012,1414,4426 ,5622,5609,1056 }, - {3816,4012,4426 ,5623,5622,1056 }, {5268,5422,1414 ,5624,5611,5609 }, - {4012,5268,1414 ,5622,5624,5609 }, {5268,5773,4014 ,5624,5625,5612 }, - {5422,5268,4014 ,5611,5624,5612 }, {5773,3971,4014 ,5625,5626,5612 }, - {3971,2961,159 ,5626,5627,5619 }, {4014,3971,159 ,5612,5626,5619 }, - {2961,5135,5134 ,5627,5628,5616 }, {159,2961,5134 ,5619,5627,5616 }, - {5135,5142,1786 ,5628,5629,5617 }, {5134,5135,1786 ,5616,5628,5617 }, - {1786,5142,5144 ,5617,5629,5618 }, {5142,5311,996 ,5629,5630,5003 }, - {5144,5142,996 ,5618,5629,5003 }, {5311,3784,996 ,5630,2252,5003 }, - {5336,4012,3816 ,5631,5622,5623 }, {5157,3971,5773 ,5632,5626,5625 }, - {5268,5157,5773 ,5624,5632,5625 }, {5447,5426,2140 ,5633,5634,5635 }, - {5157,5268,4012 ,5632,5624,5622 }, {5336,5157,4012 ,5631,5632,5622 }, - {5135,5456,5142 ,5628,5636,5629 }, {6905,5669,5626 ,2506,5553,1460 }, - {5251,5300,5299 ,3802,3793,3800 }, {4097,3816,5445 ,5637,5623,3520 }, - {4293,4097,5445 ,2732,5637,3520 }, {4294,5336,3816 ,5638,5631,5623 }, - {4097,4294,3816 ,5637,5638,5623 }, {4294,3055,5157 ,5638,5639,5632 }, - {5336,4294,5157 ,5631,5638,5632 }, {3055,1391,3971 ,5639,5640,5626 }, - {5157,3055,3971 ,5632,5639,5626 }, {1391,5343,2961 ,5640,5641,5627 }, - {3971,1391,2961 ,5626,5640,5627 }, {5343,5269,5135 ,5641,5642,5628 }, - {2961,5343,5135 ,5627,5641,5628 }, {5269,5310,5456 ,5642,5643,5636 }, - {5135,5269,5456 ,5628,5642,5636 }, {5310,4884,5142 ,5643,2253,5629 }, - {5456,5310,5142 ,5636,5643,5629 }, {5142,4884,5311 ,5629,2253,5630 }, - {5311,4884,3784 ,5630,2253,2252 }, {5343,5310,5269 ,5641,5643,5642 }, - {3100,1552,1590 ,2955,2266,3028 }, {4881,3536,4293 ,2731,5644,2732 }, - {5343,5360,5310 ,5641,5645,5643 }, {5310,5574,4884 ,5643,5646,2253 }, - {5058,3320,2163 ,5647,5455,243 }, {3536,4097,4293 ,5644,5637,2732 }, - {3403,4294,4097 ,5648,5638,5637 }, {3536,3403,4097 ,5644,5648,5637 }, - {3403,1690,3055 ,5648,5649,5639 }, {4294,3403,3055 ,5638,5648,5639 }, - {1690,5164,1391 ,5649,5650,5640 }, {3055,1690,1391 ,5639,5649,5640 }, - {5164,5312,5343 ,5650,5651,5641 }, {1391,5164,5343 ,5640,5650,5641 }, - {5312,5226,5360 ,5651,5652,5645 }, {5343,5312,5360 ,5641,5651,5645 }, - {5226,5601,5310 ,5652,5653,5643 }, {5360,5226,5310 ,5645,5652,5643 }, - {5601,711,5574 ,5653,5654,5646 }, {5310,5601,5574 ,5643,5653,5646 }, - {711,85,4884 ,5654,2504,2253 }, {5574,711,4884 ,5646,5654,2253 }, - {125,5127,124 ,399,5114,2206 }, {5164,5226,5312 ,5650,5652,5651 }, - {5226,711,5601 ,5652,5654,5653 }, {5308,505,5309 ,3528,986,987 }, - {5325,5297,5298 ,5655,3826,3818 }, {5379,4931,4916 ,3998,5066,2248 }, - {5200,5224,4679 ,5656,3850,3852 }, {4558,4631,4598 ,4209,1816,5343 }, - {8090,8080,8132 ,412,1094,413 }, {2320,2319,8049 ,1406,3228,5393 }, - {6256,5609,5953 ,5657,5658,5659 }, {5394,3499,405 ,5660,5661,5662 }, - {758,5361,3525 ,5663,5664,5665 }, {6243,6244,5356 ,5666,5667,4258 }, - {1158,253,249 ,2744,2564,644 }, {5322,5321,5320 ,4297,5668,4464 }, - {6306,5943,6336 ,5669,5402,5670 }, {5122,5717,3507 ,4024,4023,5671 }, - {1661,3611,6111 ,5672,5673,5674 }, {4805,1791,4711 ,5376,5675,5358 }, - {3320,911,2163 ,5455,1159,243 }, {5186,3536,4881 ,5676,5644,2731 }, - {5165,5186,4881 ,4226,5676,2731 }, {4370,3403,3536 ,5677,5648,5644 }, - {5186,4370,3536 ,5676,5677,5644 }, {4370,5156,1690 ,5677,5678,5649 }, - {3403,4370,1690 ,5648,5677,5649 }, {5156,5529,5164 ,5678,5679,5650 }, - {1690,5156,5164 ,5649,5678,5650 }, {5529,1386,5164 ,5679,5680,5650 }, - {1386,5159,5226 ,5680,5681,5652 }, {5164,1386,5226 ,5650,5680,5652 }, - {5159,3840,5226 ,5681,5682,5652 }, {3840,4250,711 ,5682,4161,5654 }, - {5226,3840,711 ,5652,5682,5654 }, {711,4250,85 ,5654,4161,2504 }, - {3499,5394,405 ,5661,5660,5662 }, {6245,6246,6273 ,5560,5559,5683 }, - {6246,6274,6273 ,5559,5684,5683 }, {6111,6063,5575 ,5674,5685,5686 }, - {1451,1538,2954 ,175,0,5687 }, {4490,4273,2954 ,5688,120,5687 }, - {542,1451,2954 ,122,175,5687 }, {5114,2291,2342 ,5689,1115,5690 }, - {1561,407,1525 ,1865,4018,1866 }, {4860,4635,5092 ,5531,5487,3953 }, - {3817,4682,5153 ,1189,1191,3896 }, {5960,5515,6005 ,5568,5567,5691 }, - {747,5782,5781 ,5692,5693,5694 }, {1741,6104,6230 ,5695,5696,2144 }, - {6055,3906,5129 ,3874,5697,5698 }, {2534,368,198 ,2846,1396,1392 }, - {6274,3666,5880 ,5684,5699,5700 }, {5296,5323,5322 ,4296,5701,4297 }, - {5575,202,5958 ,5686,4105,5702 }, {6042,5230,5921 ,5703,5704,5705 }, - {202,5122,5958 ,4105,4024,5702 }, {5898,5653,6115 ,5706,3644,3645 }, - {7487,7516,7540 ,5707,5708,5709 }, {5156,1386,5529 ,5678,5680,5679 }, - {1386,3840,5159 ,5680,5682,5681 }, {5139,5146,5260 ,1939,1075,4174 }, - {6053,5874,5925 ,4463,4896,5710 }, {4153,4374,3953 ,5711,5712,5713 }, - {5891,3822,5602 ,5714,5715,5716 }, {6052,5486,3311 ,5717,5718,5303 }, - {5948,5602,3507 ,5719,5716,5671 }, {5717,5948,3507 ,4023,5719,5671 }, - {5774,5750,5775 ,5720,5156,5158 }, {5808,5807,5774 ,5721,4769,5720 }, - {5775,5808,5774 ,5158,5721,5720 }, {5808,5840,5807 ,5721,4770,4769 }, - {4273,542,2954 ,120,122,5687 }, {4648,1125,1269 ,5722,5723,5724 }, - {7846,7845,7793 ,4162,5725,5726 }, {4859,5501,5165 ,5039,5727,4226 }, - {5026,4859,5165 ,4225,5039,4226 }, {5501,5537,5165 ,5727,5728,4226 }, - {2799,5186,5165 ,5729,5676,4226 }, {5537,2799,5165 ,5728,5729,4226 }, - {2799,5313,4370 ,5729,5730,5677 }, {5186,2799,4370 ,5676,5729,5677 }, - {5313,5358,5156 ,5730,5731,5678 }, {4370,5313,5156 ,5677,5730,5678 }, - {5358,1533,5156 ,5731,5732,5678 }, {1533,3857,1386 ,5732,5733,5680 }, - {5156,1533,1386 ,5678,5732,5680 }, {3857,5270,3840 ,5733,5734,5682 }, - {1386,3857,3840 ,5680,5733,5682 }, {4404,4250,3840 ,5072,4161,5682 }, - {5270,4404,3840 ,5734,5072,5682 }, {5200,4681,5224 ,5656,4958,3850 }, - {4410,6119,5303 ,5735,5736,5737 }, {3845,3497,5319 ,3635,5738,5739 }, - {2238,1272,1268 ,2697,5740,4568 }, {5647,5689,5688 ,5333,5741,5519 }, - {5689,5739,5738 ,5741,5157,5520 }, {5739,5750,5738 ,5157,5156,5520 }, - {5776,5775,5739 ,5742,5158,5157 }, {5809,5808,5775 ,5743,5721,5158 }, - {5776,5809,5775 ,5742,5743,5158 }, {5809,5840,5808 ,5743,4770,5721 }, - {5461,5962,5252 ,5744,5745,5746 }, {2004,1937,4490 ,5747,59,5688 }, - {6235,6165,5703 ,4215,4219,5748 }, {4766,4826,4765 ,5449,5413,3983 }, - {7794,7846,7793 ,5749,4162,5726 }, {3857,4015,5270 ,5733,5750,5734 }, - {4753,4696,4793 ,5383,5382,5421 }, {6418,5090,5091 ,3441,4929,5133 }, - {4653,5182,4599 ,4347,4567,4210 }, {5368,5888,6077 ,5751,5752,5753 }, - {3562,3856,6037 ,4753,5754,5235 }, {6244,6272,5663 ,5667,5755,4259 }, - {6240,6268,6254 ,5756,5757,5758 }, {2048,2015,2049 ,5461,759,758 }, - {5566,5581,5605 ,5759,5760,5761 }, {5647,5664,5689 ,5333,5762,5741 }, - {5841,5840,5809 ,5763,4770,5743 }, {1293,932,532 ,5764,5765,5766 }, - {4271,932,1464 ,5767,5765,5768 }, {1937,4273,4490 ,59,120,5688 }, - {4711,1791,4771 ,5358,5675,3622 }, {1928,5501,4859 ,1282,5727,5039 }, - {5501,2799,5537 ,5727,5729,5728 }, {5313,1533,5358 ,5730,5732,5731 }, - {5260,1868,2217 ,4174,2249,4569 }, {5902,686,6093 ,5769,5770,5771 }, - {3583,5391,5652 ,5772,5773,5774 }, {6046,5713,5686 ,5775,5776,5777 }, - {5935,3560,6218 ,5778,5779,5780 }, {5504,5541,5566 ,5781,5782,5759 }, - {5531,5504,5566 ,5783,5781,5759 }, {5566,5541,5581 ,5759,5782,5760 }, - {5541,5582,5605 ,5782,5784,5761 }, {5581,5541,5605 ,5760,5782,5761 }, - {5582,5622,5647 ,5784,5785,5333 }, {5605,5582,5647 ,5761,5784,5333 }, - {5647,5622,5664 ,5333,5785,5762 }, {5622,5690,5689 ,5785,5786,5741 }, - {5664,5622,5689 ,5762,5785,5741 }, {5690,5740,5739 ,5786,5787,5157 }, - {5689,5690,5739 ,5741,5786,5157 }, {5777,5776,5739 ,5788,5742,5157 }, - {5740,5777,5739 ,5787,5788,5157 }, {5810,5809,5776 ,5789,5743,5742 }, - {5777,5810,5776 ,5788,5789,5742 }, {5842,5841,5809 ,5790,5763,5743 }, - {5810,5842,5809 ,5789,5790,5743 }, {5842,5840,5841 ,5790,4770,5763 }, - {1246,4271,5840 ,5791,5767,4770 }, {5842,1246,5840 ,5790,5791,4770 }, - {532,932,4271 ,5766,5765,5767 }, {1246,532,4271 ,5791,5766,5767 }, - {1689,1937,2004 ,5792,59,5747 }, {4743,5732,5701 ,3629,3940,3938 }, - {489,4326,3761 ,3639,219,218 }, {4744,5049,4859 ,4424,5038,5039 }, - {4096,2799,5501 ,5793,5729,5727 }, {1928,4096,5501 ,1282,5793,5727 }, - {4096,3876,5313 ,5793,5794,5730 }, {2799,4096,5313 ,5729,5793,5730 }, - {3876,5155,1533 ,5794,5795,5732 }, {5313,3876,1533 ,5730,5794,5732 }, - {5155,5620,3857 ,5795,5796,5733 }, {1533,5155,3857 ,5732,5795,5733 }, - {5620,5344,4015 ,5796,5797,5750 }, {3857,5620,4015 ,5733,5796,5750 }, - {5344,4849,5270 ,5797,5436,5734 }, {4015,5344,5270 ,5750,5797,5734 }, - {4849,4433,4404 ,5436,4591,5072 }, {5270,4849,4404 ,5734,5436,5072 }, - {1791,4805,3367 ,5675,5376,5798 }, {5391,3583,3608 ,5773,5772,5799 }, - {3498,5960,6005 ,5800,5568,5691 }, {5652,6046,5686 ,5774,5775,5777 }, - {5463,5505,5504 ,5801,5802,5781 }, {5505,5541,5504 ,5802,5782,5781 }, - {5582,5606,5622 ,5784,5803,5785 }, {5690,5741,5740 ,5786,5804,5787 }, - {5857,1246,5842 ,5805,5791,5790 }, {5155,5344,5620 ,5795,5797,5796 }, - {5290,5308,5289 ,5247,3528,80 }, {4793,5770,5732 ,5421,3949,3940 }, - {4743,4793,5732 ,3629,5421,3940 }, {4797,4765,5259 ,3984,3983,3794 }, - {4715,4714,4681 ,1029,1031,4958 }, {3498,5478,5960 ,5800,5806,5568 }, - {2568,5391,3608 ,5807,5773,5799 }, {5478,6056,6045 ,5806,5808,935 }, - {5880,6137,6136 ,5700,5809,5810 }, {5663,5880,6136 ,4259,5700,5810 }, - {5427,5428,5463 ,5811,5812,5801 }, {5463,5485,5505 ,5801,5813,5802 }, - {5741,5778,5777 ,5804,5814,5788 }, {5740,5741,5777 ,5787,5804,5788 }, - {5778,5810,5777 ,5814,5789,5788 }, {421,1293,746 ,5815,5764,2661 }, - {920,1191,3986 ,57,5816,5817 }, {495,4776,3788 ,4389,5390,4410 }, - {5188,6744,5786 ,4812,3986,4813 }, {3876,4205,5155 ,5794,5818,5795 }, - {3787,5918,5562 ,5819,5820,4193 }, {5224,5267,5244 ,3850,4647,79 }, - {1191,920,1689 ,5816,57,5792 }, {3367,920,3986 ,5798,57,5817 }, - {5960,5478,6045 ,5568,5806,935 }, {5894,2568,3608 ,5821,5807,5799 }, - {6137,3989,4028 ,5809,5822,5823 }, {5391,6046,5652 ,5773,5775,5774 }, - {6136,6137,4028 ,5810,5809,5823 }, {5429,5464,5463 ,5824,5825,5801 }, - {5428,5429,5463 ,5812,5824,5801 }, {5463,5464,5485 ,5801,5825,5813 }, - {5464,5506,5505 ,5825,5826,5802 }, {5485,5464,5505 ,5813,5825,5802 }, - {5506,5542,5541 ,5826,5827,5782 }, {5505,5506,5541 ,5802,5826,5782 }, - {5542,5543,5541 ,5827,5828,5782 }, {5543,5583,5582 ,5828,5829,5784 }, - {5541,5543,5582 ,5782,5828,5784 }, {5582,5583,5606 ,5784,5829,5803 }, - {5583,5623,5622 ,5829,5830,5785 }, {5606,5583,5622 ,5803,5829,5785 }, - {5623,5665,5622 ,5830,5831,5785 }, {5622,5665,5690 ,5785,5831,5786 }, - {5665,5707,5690 ,5831,5832,5786 }, {5690,5707,5741 ,5786,5832,5804 }, - {5707,5779,5778 ,5832,5833,5814 }, {5741,5707,5778 ,5804,5832,5814 }, - {5811,5810,5778 ,5834,5789,5814 }, {5779,5811,5778 ,5833,5834,5814 }, - {5811,5822,5810 ,5834,5835,5789 }, {5843,5842,5810 ,1372,5790,5789 }, - {5822,5843,5810 ,5835,1372,5789 }, {2958,5857,5842 ,1374,5805,5790 }, - {5843,2958,5842 ,1372,1374,5790 }, {1662,1246,5857 ,5836,5791,5805 }, - {2958,1662,5857 ,1374,5836,5805 }, {746,532,1246 ,2661,5766,5791 }, - {1662,746,1246 ,5836,2661,5791 }, {3367,3986,2953 ,5798,5817,5837 }, - {1791,3367,2953 ,5675,5798,5837 }, {556,455,1344 ,4043,2205,300 }, - {994,4096,1928 ,5838,5793,1282 }, {5197,994,1928 ,4842,5838,1282 }, - {994,5421,4096 ,5838,5839,5793 }, {5421,4529,3876 ,5839,5840,5794 }, - {4096,5421,3876 ,5793,5839,5794 }, {4529,3865,4205 ,5840,5841,5818 }, - {3876,4529,4205 ,5794,5840,5818 }, {3865,5357,5155 ,5841,5842,5795 }, - {4205,3865,5155 ,5818,5841,5795 }, {5357,5154,5155 ,5842,5843,5795 }, - {5154,4345,5344 ,5843,5844,5797 }, {5155,5154,5344 ,5795,5843,5797 }, - {4345,4820,4849 ,5844,2399,5436 }, {5344,4345,4849 ,5797,5844,5436 }, - {5337,4914,4866 ,572,65,3641 }, {5290,5289,5244 ,5247,80,79 }, - {3875,3184,2048 ,5845,4453,5461 }, {920,1937,1689 ,57,59,5792 }, - {4028,3989,5193 ,5823,5822,5846 }, {3989,5252,5193 ,5822,5746,5846 }, - {5395,5429,5428 ,5348,5824,5812 }, {5506,5543,5542 ,5826,5828,5827 }, - {5665,5666,5707 ,5831,5847,5832 }, {5811,5843,5822 ,5834,1372,5835 }, - {2958,746,1662 ,1374,2661,5836 }, {3446,5884,3781 ,3718,5848,5849 }, - {6344,4568,4548 ,1450,1492,589 }, {5421,3865,4529 ,5839,5841,5840 }, - {6749,6785,5548 ,4046,4140,1590 }, {5244,5221,5222 ,79,4864,4566 }, - {6056,5883,6080 ,5808,5850,936 }, {5904,1124,5849 ,5851,5852,5853 }, - {5252,5962,4466 ,5746,5745,5854 }, {5121,5167,5120 ,5855,5856,5857 }, - {5167,5190,5166 ,5856,5858,3427 }, {1791,2953,5836 ,5675,5837,5859 }, - {4679,5223,5182 ,3852,3851,4567 }, {5288,5287,5243 ,3993,4003,3994 }, - {4932,4931,5379 ,4580,5066,3998 }, {5515,5898,6115 ,5567,5706,3645 }, - {5117,5515,6115 ,1113,5567,3645 }, {4466,3469,6104 ,5854,5860,5696 }, - {5396,5430,5429 ,3548,5861,5824 }, {5395,5396,5429 ,5348,3548,5824 }, - {5430,5465,5464 ,5861,5862,5825 }, {5429,5430,5464 ,5824,5861,5825 }, - {5465,5507,5506 ,5862,5863,5826 }, {5464,5465,5506 ,5825,5862,5826 }, - {5507,5532,5506 ,5863,5864,5826 }, {5532,5544,5543 ,5864,5865,5828 }, - {5506,5532,5543 ,5826,5864,5828 }, {5544,5584,5583 ,5865,5866,5829 }, - {5543,5544,5583 ,5828,5865,5829 }, {5583,5584,5623 ,5829,5866,5830 }, - {5623,5666,5665 ,5830,5847,5831 }, {5592,746,2224 ,3671,2661,2660 }, - {7538,7573,7602 ,2014,2013,5867 }, {5421,994,3865 ,5839,5838,5841 }, - {4669,4896,4775 ,3879,3878,4388 }, {6045,6056,6080 ,935,5808,936 }, - {5883,5954,5453 ,5850,5868,937 }, {6080,5883,5453 ,936,5850,937 }, - {5954,3657,5923 ,5868,5869,2073 }, {5386,3905,3892 ,5870,4194,4970 }, - {4281,615,1330 ,51,766,53 }, {5167,5205,5190 ,5856,5219,5858 }, - {4771,1791,5836 ,3622,5675,5859 }, {5804,4771,5803 ,3623,3622,5871 }, - {5453,5954,5923 ,937,5868,2073 }, {5461,5984,6113 ,5744,5872,5873 }, - {5894,3608,6113 ,5821,5799,5873 }, {5584,5624,5623 ,5866,5874,5830 }, - {5624,5648,5623 ,5874,5875,5830 }, {5648,5667,5666 ,5875,5876,5847 }, - {5623,5648,5666 ,5830,5875,5847 }, {5667,5708,5707 ,5876,5877,5832 }, - {5666,5667,5707 ,5847,5876,5832 }, {5708,5751,5707 ,5877,5878,5832 }, - {5751,5779,5707 ,5878,5833,5832 }, {5751,5812,5811 ,5878,660,5834 }, - {5779,5751,5811 ,5833,5878,5834 }, {5844,5843,5811 ,5179,1372,5834 }, - {5812,5844,5811 ,660,5179,5834 }, {4724,4908,5245 ,4737,5879,5880 }, - {5984,5894,6113 ,5872,5821,5873 }, {3657,6178,5923 ,5869,5881,2073 }, - {3830,5196,5197 ,5882,5883,4842 }, {4518,3830,5197 ,1281,5882,4842 }, - {4372,994,5197 ,5884,5838,4842 }, {5196,4372,5197 ,5883,5884,4842 }, - {4372,5425,3865 ,5884,5885,5841 }, {994,4372,3865 ,5838,5884,5841 }, - {5425,3083,5357 ,5885,5886,5842 }, {3865,5425,5357 ,5841,5885,5842 }, - {5357,3083,5154 ,5842,5886,5843 }, {3083,1020,4345 ,5886,3817,5844 }, - {5154,3083,4345 ,5843,5886,5844 }, {1020,4712,4820 ,3817,3816,2399 }, - {4345,1020,4820 ,5844,3817,2399 }, {4775,4896,4861 ,4388,3878,3877 }, - {3575,3584,5293 ,5887,5888,5889 }, {3576,5294,5912 ,5890,5891,5892 }, - {2408,309,5231 ,1399,4472,115 }, {4687,320,274 ,4985,1871,1819 }, - {5768,5804,5767 ,933,3623,5893 }, {6178,4901,6162 ,5881,3596,3598 }, - {5923,6178,6162 ,2073,5881,3598 }, {3366,3310,5461 ,5894,5587,5744 }, - {3310,5984,5461 ,5587,5872,5744 }, {7043,2279,7042 ,5895,5337,5338 }, - {5050,3244,1922 ,5233,4433,4432 }, {1196,4669,3266 ,4330,3879,3884 }, - {5989,3310,3366 ,5588,5587,5894 }, {6068,5989,3366 ,5896,5588,5894 }, - {772,1605,713 ,18,17,3 }, {6132,3628,3632 ,5897,4213,5898 }, - {5109,5121,5107 ,4182,5855,4183 }, {5109,5147,5121 ,4182,5899,5855 }, - {5168,5167,5121 ,5900,5856,5855 }, {5147,5168,5121 ,5899,5900,5855 }, - {5206,5205,5167 ,5901,5219,5856 }, {5168,5206,5167 ,5900,5901,5856 }, - {5206,5229,5205 ,5901,5902,5219 }, {7310,7370,7344 ,4283,3750,2749 }, - {5229,4178,5205 ,5902,3825,5219 }, {5305,5306,5572 ,2283,462,2284 }, - {75,1629,2938 ,3962,4207,4320 }, {5976,6028,5927 ,5903,5316,5318 }, - {5364,5397,5396 ,3268,5904,3548 }, {5363,5364,5396 ,3269,3268,3548 }, - {5397,5431,5430 ,5904,5905,5861 }, {5396,5397,5430 ,3548,5904,5861 }, - {5431,5466,5465 ,5905,5906,5862 }, {5430,5431,5465 ,5861,5905,5862 }, - {5466,5467,5465 ,5906,5907,5862 }, {5467,5508,5507 ,5907,5908,5863 }, - {5465,5467,5507 ,5862,5907,5863 }, {5507,5508,5532 ,5863,5908,5864 }, - {5508,5545,5544 ,5908,5909,5865 }, {5532,5508,5544 ,5864,5908,5865 }, - {5545,5585,5584 ,5909,5910,5866 }, {5544,5545,5584 ,5865,5909,5866 }, - {5585,5625,5624 ,5910,5911,5874 }, {5584,5585,5624 ,5866,5910,5874 }, - {5624,5625,5648 ,5874,5911,5875 }, {5625,5668,5667 ,5911,5912,5876 }, - {5648,5625,5667 ,5875,5911,5876 }, {5668,5709,5708 ,5912,5253,5877 }, - {5667,5668,5708 ,5876,5912,5877 }, {5708,5709,5751 ,5877,5253,5878 }, - {1557,5989,6068 ,5577,5588,5896 }, {5812,7038,5823 ,660,3832,661 }, - {3666,1557,6068 ,5699,5577,5896 }, {5115,6060,6281 ,5913,5914,4078 }, - {2279,1313,2251 ,5337,3674,3676 }, {3943,5662,4045 ,4755,5915,5916 }, - {5255,5276,6480 ,3682,1525,1524 }, {3669,1196,3266 ,5917,4330,3884 }, - {6239,6055,6073 ,5918,3874,3873 }, {6238,6239,6073 ,5919,5918,3873 }, - {3469,5651,6104 ,5860,5920,5696 }, {5651,5254,6104 ,5920,4042,5696 }, - {5403,3631,5417 ,5921,5922,5923 }, {5489,5911,5932 ,4244,5924,5925 }, - {5474,5370,5932 ,4243,2171,5925 }, {5804,5803,5767 ,3623,5871,5893 }, - {5108,5107,5106 ,4184,4183,5926 }, {5169,5168,5147 ,5927,5900,5899 }, - {5109,5169,5147 ,4182,5927,5899 }, {5206,4178,5229 ,5901,3825,5902 }, - {2713,3141,4091 ,4352,4701,123 }, {4771,5836,5803 ,3622,5859,5871 }, - {5585,5607,5625 ,5910,5928,5911 }, {5709,5752,5751 ,5253,4374,5878 }, - {6268,1661,3906 ,5757,5672,5697 }, {5261,5538,3830 ,173,5929,5882 }, - {5538,3417,5196 ,5929,5930,5883 }, {3830,5538,5196 ,5882,5929,5883 }, - {5500,4372,5196 ,5931,5884,5883 }, {3417,5500,5196 ,5930,5931,5883 }, - {5500,5821,5425 ,5931,5932,5885 }, {4372,5500,5425 ,5884,5931,5885 }, - {5821,4072,5425 ,5932,5933,5885 }, {4072,1938,3083 ,5933,5934,5886 }, - {5425,4072,3083 ,5885,5933,5886 }, {1938,4027,1020 ,5934,3470,3817 }, - {3083,1938,1020 ,5886,5934,3817 }, {5593,5552,5594 ,5935,5936,5937 }, - {3321,7437,7386 ,2461,5938,5512 }, {3899,1196,3669 ,1938,4330,5917 }, - {5185,3395,6142 ,5939,5940,5941 }, {5579,5564,4565 ,5942,5943,5944 }, - {5169,5206,5168 ,5927,5901,5900 }, {5321,5364,5346 ,5668,3268,3267 }, - {5364,5398,5397 ,3268,5945,5904 }, {5398,5432,5431 ,5945,5946,5905 }, - {5397,5398,5431 ,5904,5945,5905 }, {5432,5467,5466 ,5946,5907,5906 }, - {5431,5432,5466 ,5905,5946,5906 }, {6905,6957,5710 ,2506,4315,5254 }, - {7268,7317,7316 ,3773,5947,5948 }, {8078,8124,8076 ,1744,1141,617 }, - {4572,3693,3638 ,5949,5347,5950 }, {5390,5579,5415 ,3205,5942,5951 }, - {4763,4764,4797 ,4787,3982,3984 }, {5148,5169,5109 ,5952,5927,4182 }, - {5110,5148,5109 ,5953,5952,4182 }, {5207,5206,5169 ,5954,5901,5927 }, - {5148,5207,5169 ,5952,5954,5927 }, {5249,4178,5206 ,5955,3825,5901 }, - {5207,5249,5206 ,5954,5955,5901 }, {5249,5272,4178 ,5955,5956,3825 }, - {5296,5297,5323 ,4296,3826,5701 }, {5347,5321,5322 ,5957,5668,4297 }, - {5323,5347,5322 ,5701,5957,4297 }, {5365,5364,5321 ,5958,3268,5668 }, - {5347,5365,5321 ,5957,5958,5668 }, {5365,5399,5398 ,5958,5959,5945 }, - {5364,5365,5398 ,3268,5958,5945 }, {5399,5433,5432 ,5959,5960,5946 }, - {5398,5399,5432 ,5945,5959,5946 }, {5433,5468,5467 ,5960,5961,5907 }, - {5432,5433,5467 ,5946,5960,5907 }, {5468,5509,5508 ,5961,5962,5908 }, - {5467,5468,5508 ,5907,5961,5908 }, {5509,5546,5545 ,5962,5963,5909 }, - {5508,5509,5545 ,5908,5962,5909 }, {5546,5586,5585 ,5963,1461,5910 }, - {5545,5546,5585 ,5909,5963,5910 }, {5585,5586,5607 ,5910,1461,5928 }, - {5586,5626,5625 ,1461,1460,5911 }, {5607,5586,5625 ,5928,1461,5911 }, - {5625,5626,5668 ,5911,1460,5912 }, {5668,5669,5709 ,5912,5553,5253 }, - {5293,3558,3629 ,5889,5964,5965 }, {5731,5768,5729 ,934,933,200 }, - {5768,5767,5729 ,933,5893,200 }, {5326,6041,5327 ,3714,3801,3702 }, - {5146,3760,1868 ,1075,2250,2249 }, {5731,5729,5730 ,934,200,199 }, - {5731,5730,3615 ,934,199,201 }, {3952,2713,3259 ,5597,4352,407 }, - {1156,5138,5128 ,3100,1940,5966 }, {5500,4072,5821 ,5931,5933,5932 }, - {7837,4897,3895 ,5967,5442,4455 }, {3760,3899,3669 ,2250,1938,5917 }, - {184,4295,4016 ,4052,5968,5969 }, {1064,5579,5390 ,5970,5942,3205 }, - {7166,5110,5109 ,5971,5953,4182 }, {5546,5547,5586 ,5963,5972,1461 }, - {6234,6167,6002 ,5973,5974,5975 }, {5243,5287,5265 ,3994,4003,4882 }, - {3221,5262,5261 ,183,5976,173 }, {5352,3950,3345 ,3502,4530,3476 }, - {5262,5527,5538 ,5976,5977,5929 }, {5261,5262,5538 ,173,5976,5929 }, - {5527,5746,3417 ,5977,5978,5930 }, {5538,5527,3417 ,5929,5977,5930 }, - {5619,5500,3417 ,5979,5931,5930 }, {5746,5619,3417 ,5978,5979,5930 }, - {5619,1671,4072 ,5979,5980,5933 }, {5500,5619,4072 ,5931,5979,5933 }, - {1671,3249,1938 ,5980,5110,5934 }, {4072,1671,1938 ,5933,5980,5934 }, - {572,4873,611 ,1947,4992,1948 }, {6128,1620,6129 ,5981,5982,5983 }, - {4299,1064,5390 ,5984,5970,3205 }, {5446,4299,5390 ,5985,5984,3205 }, - {4299,5579,1064 ,5984,5942,5970 }, {4299,1002,5579 ,5984,2976,5942 }, - {5323,5324,5348 ,5701,5986,5987 }, {5509,5547,5546 ,5962,5972,5963 }, - {4827,5259,4826 ,2734,3794,5413 }, {3249,4905,4594 ,5110,5112,688 }, - {5272,5298,5297 ,5956,3818,3826 }, {5619,5735,1671 ,5979,5988,5980 }, - {6803,5587,5548 ,4169,1459,1590 }, {4863,5378,4904 ,5480,359,3309 }, - {5260,5146,1868 ,4174,1075,2249 }, {5149,5148,5110 ,5989,5952,5953 }, - {5111,5149,5110 ,5990,5989,5953 }, {5208,5207,5148 ,5991,5954,5952 }, - {5149,5208,5148 ,5989,5991,5952 }, {5250,5249,5207 ,5992,5955,5954 }, - {5208,5250,5207 ,5991,5992,5954 }, {5273,5272,5249 ,3819,5956,5955 }, - {5250,5273,5249 ,5992,3819,5955 }, {7683,7704,7682 ,5267,3562,3564 }, - {5348,5347,5323 ,5987,5957,5701 }, {5325,5323,5297 ,5655,5701,3826 }, - {5366,5365,5347 ,5993,5958,5957 }, {5348,5366,5347 ,5987,5993,5957 }, - {5366,5400,5399 ,5993,5994,5959 }, {5365,5366,5399 ,5958,5993,5959 }, - {5400,5434,5433 ,5994,5995,5960 }, {5399,5400,5433 ,5959,5994,5960 }, - {5434,5469,5468 ,5995,5996,5961 }, {5433,5434,5468 ,5960,5995,5961 }, - {5469,5510,5509 ,5996,5997,5962 }, {5468,5469,5509 ,5961,5996,5962 }, - {5510,5511,5509 ,5997,1588,5962 }, {5511,5548,5547 ,1588,1590,5972 }, - {5509,5511,5547 ,5962,1588,5972 }, {5548,5587,5586 ,1590,1459,1461 }, - {5547,5548,5586 ,5972,1590,1461 }, {5860,2321,5951 ,5998,5999,6000 }, - {3620,5991,5946 ,6001,5482,5481 }, {6907,6959,6958 ,6002,6003,4314 }, - {4696,5770,4793 ,5382,3949,5421 }, {6163,5889,6175 ,1453,1587,6004 }, - {5128,2217,5443 ,5966,4569,6005 }, {5266,5243,5221 ,81,3994,4864 }, - {5340,4868,5379 ,4002,3969,3998 }, {5223,5244,5222 ,3851,79,4566 }, - {3221,5527,5262 ,183,5977,5976 }, {3278,8113,1724 ,1158,1157,3880 }, - {5010,2140,5426 ,6006,5635,5634 }, {1166,1119,5844 ,2746,5180,5179 }, - {2375,3945,922 ,4479,4550,117 }, {1116,3350,5497 ,1401,2541,1375 }, - {1488,4264,156 ,5197,5540,5539 }, {3973,4299,5446 ,6007,5984,5985 }, - {5209,5208,5149 ,6008,5991,5989 }, {7566,7621,7565 ,6009,6010,5080 }, - {7621,7647,7620 ,6010,4967,5033 }, {5324,5366,5348 ,5986,5993,5987 }, - {5469,5511,5510 ,5996,1588,5997 }, {6208,6209,6243 ,6011,6012,5666 }, - {5933,3548,5934 ,615,6013,616 }, {3548,5489,5934 ,6013,4244,616 }, - {4278,4260,6138 ,5583,3527,6014 }, {3878,789,3419 ,1248,3910,2012 }, - {1119,1166,2408 ,5180,2746,1399 }, {156,22,1297 ,5539,4066,4048 }, - {5325,5298,6041 ,5655,3818,3801 }, {156,1934,22 ,5539,4620,4066 }, - {1218,3820,5498 ,3255,5591,5590 }, {6736,6754,6703 ,1622,713,5161 }, - {7923,7896,7897 ,816,4355,6015 }, {5772,5746,5527 ,6016,5978,5977 }, - {3984,5772,5527 ,6017,6016,5977 }, {5772,5577,5619 ,6016,6018,5979 }, - {5746,5772,5619 ,5978,6016,5979 }, {5577,4228,5735 ,6018,6019,5988 }, - {5619,5577,5735 ,5979,6018,5988 }, {4228,1099,1671 ,6019,4350,5980 }, - {5735,4228,1671 ,5988,6019,5980 }, {1099,4905,3249 ,4350,5112,5110 }, - {1671,1099,3249 ,5980,4350,5110 }, {3766,7556,4636 ,3954,5116,5118 }, - {3249,5036,4905 ,5110,399,5112 }, {3941,4299,3973 ,5563,5984,6007 }, - {636,3941,3973 ,6020,5563,6007 }, {3941,1511,4299 ,5563,4921,5984 }, - {5158,4631,4599 ,4832,1816,4210 }, {5112,5149,5111 ,6021,5989,5990 }, - {5273,5250,5251 ,3819,5992,3802 }, {2690,303,4296 ,6022,4086,6023 }, - {4191,2690,4296 ,4474,6022,6023 }, {6151,5860,5951 ,6024,5998,6000 }, - {6035,5654,4045 ,6025,6026,5916 }, {1741,6230,5947 ,5695,2144,6027 }, - {5948,5891,5602 ,5719,5714,5716 }, {5979,5929,6132 ,6028,6029,5897 }, - {798,5378,4863 ,78,359,5480 }, {8,1798,4522 ,3341,4451,3481 }, - {5218,5239,5238 ,483,482,4351 }, {5179,5199,5178 ,1879,422,524 }, - {5179,5178,5136 ,1879,524,1817 }, {2797,1935,303 ,6030,4098,4086 }, - {2690,2797,303 ,6022,6030,4086 }, {3150,636,2960 ,6031,6020,4975 }, - {5388,2960,636 ,5428,4975,6020 }, {5150,5149,5112 ,6032,5989,6021 }, - {5113,5150,5112 ,141,6032,6021 }, {5150,5170,5149 ,6032,3683,5989 }, - {5210,5209,5149 ,6033,6008,5989 }, {5170,5210,5149 ,3683,6033,5989 }, - {5210,5208,5209 ,6033,5991,6008 }, {5251,5250,5208 ,3802,5992,5991 }, - {5210,5251,5208 ,6033,3802,5991 }, {3985,3172,1935 ,4802,4155,4098 }, - {2797,3985,1935 ,6030,4802,4098 }, {5349,5324,5325 ,5320,5986,5655 }, - {3482,8106,3449 ,2494,2438,2440 }, {5367,5366,5324 ,6034,5993,5986 }, - {5349,5367,5324 ,5320,6034,5986 }, {5367,5401,5400 ,6034,4145,5994 }, - {5366,5367,5400 ,5993,6034,5994 }, {5401,5435,5434 ,4145,4223,5995 }, - {5400,5401,5434 ,5994,4145,5995 }, {5435,5470,5469 ,4223,6035,5996 }, - {5434,5435,5469 ,5995,4223,5996 }, {5470,5471,5469 ,6035,2051,5996 }, - {5469,5471,5511 ,5996,2051,1588 }, {5652,5686,5651 ,5774,5777,5920 }, - {5651,5747,5254 ,5920,6036,4042 }, {3525,5361,5935 ,5665,5664,5778 }, - {6051,5979,6132 ,6037,6028,5897 }, {6040,6028,5246 ,5317,5316,5176 }, - {5853,5318,6023 ,6038,6039,6040 }, {3731,5922,6075 ,6041,4292,6042 }, - {4654,5200,4679 ,4348,5656,3852 }, {4866,4914,3907 ,3641,65,3883 }, - {4916,4929,4915 ,2248,5142,64 }, {1525,2086,4314 ,1866,1802,1864 }, - {3985,3858,3093 ,4802,4803,4172 }, {3172,3985,3093 ,4155,4802,4172 }, - {5772,4228,5577 ,6016,6019,6018 }, {495,4775,4745 ,4389,4388,5446 }, - {5052,4845,5070 ,5189,3921,6043 }, {789,1156,3858 ,3910,3100,4803 }, - {3858,5128,5119 ,4803,5966,4190 }, {3093,3858,5119 ,4172,4803,4190 }, - {59,145,2689 ,967,810,2821 }, {5435,5471,5470 ,4223,2051,6035 }, - {6246,6247,3666 ,5559,5575,5699 }, {6166,6152,7034 ,4971,6044,6045 }, - {3835,5878,5550 ,6046,2684,6047 }, {6044,5980,5294 ,614,5557,5891 }, - {5889,6339,6034 ,1587,6048,6049 }, {3249,5028,1938 ,5110,5109,5934 }, - {6131,6132,3632 ,6050,5897,5898 }, {6185,5386,3892 ,6051,5870,4970 }, - {5749,5895,3444 ,6052,6053,6054 }, {5490,5749,3444 ,6055,6052,6054 }, - {5325,5326,5349 ,5655,3714,5320 }, {5644,5643,5571 ,4133,4617,4616 }, - {5495,5644,5571 ,4134,4133,4616 }, {5128,5443,5424 ,5966,6005,4227 }, - {3345,4226,835 ,3476,6056,3030 }, {5684,3345,835 ,4683,3476,3030 }, - {4226,1986,3984 ,6056,6057,6017 }, {835,4226,3984 ,3030,6056,6017 }, - {1986,2345,5772 ,6057,6058,6016 }, {3984,1986,5772 ,6017,6057,6016 }, - {2345,5187,4228 ,6058,5144,6019 }, {5772,2345,4228 ,6016,6058,6019 }, - {1111,1099,4228 ,3920,4350,6019 }, {5187,1111,4228 ,5144,3920,6019 }, - {68,2432,3818 ,4087,5427,1244 }, {5119,5128,5424 ,4190,5966,4227 }, - {5443,2217,201 ,6005,4569,4230 }, {5424,5443,201 ,4227,6005,4230 }, - {556,3150,2960 ,4043,6031,4975 }, {556,636,3150 ,4043,6020,6031 }, - {1344,3941,636 ,300,5563,6020 }, {556,1344,636 ,4043,300,6020 }, - {8020,8019,7972 ,1405,1407,6059 }, {2217,3038,2643 ,4569,4342,4232 }, - {201,2217,2643 ,4230,4569,4232 }, {7897,7896,7845 ,6015,4355,5725 }, - {3856,3562,6013 ,5754,4753,6060 }, {6247,1557,3666 ,5575,5577,5699 }, - {6098,6174,6173 ,1565,2381,3711 }, {5790,5813,5104 ,6061,6062,6063 }, - {5755,5790,5104 ,4047,6061,6063 }, {5086,5104,5813 ,6064,6063,6062 }, - {5813,5846,5086 ,6062,6065,6064 }, {5846,4225,257 ,6065,6066,6067 }, - {5714,5715,7028 ,4077,4076,3587 }, {4225,2871,257 ,6066,3649,6067 }, - {5461,3608,5962 ,5744,5799,5745 }, {5644,5660,5643 ,4133,3054,4617 }, - {3038,1341,2634 ,4342,3841,4269 }, {3345,4052,4226 ,3476,6068,6056 }, - {4226,4052,1986 ,6056,6068,6057 }, {1224,2986,1201 ,1508,3500,1477 }, - {3858,1156,5128 ,4803,3100,5966 }, {2643,3038,2634 ,4232,4342,4269 }, - {3788,3672,2634 ,4410,4277,4269 }, {1341,3788,2634 ,3841,4410,4269 }, - {5729,5728,5700 ,200,4486,4501 }, {210,194,262 ,4592,4593,4758 }, - {145,59,113 ,810,967,677 }, {4681,5200,4654 ,4958,5656,4348 }, - {3626,3580,3557 ,4196,6069,6070 }, {4894,1750,1810 ,746,745,779 }, - {4764,4763,4706 ,3982,4787,4786 }, {284,4086,4283 ,139,3723,1678 }, - {5211,5210,5170 ,6071,6033,3683 }, {7873,7923,7897 ,817,816,6015 }, - {5957,202,6063 ,4054,4105,5685 }, {8109,8116,5521 ,2938,172,751 }, - {1700,807,3563 ,6072,6073,6074 }, {3568,1941,3529 ,3839,1034,3837 }, - {5694,5716,5715 ,5326,6075,4076 }, {5716,5756,5755 ,6075,6076,4047 }, - {5715,5716,5755 ,4076,6075,4047 }, {5755,5756,5790 ,4047,6076,6061 }, - {5756,5791,5813 ,6076,6077,6062 }, {5790,5756,5813 ,6061,6076,6062 }, - {5791,5847,5846 ,6077,6078,6065 }, {5813,5791,5846 ,6062,6077,6065 }, - {5847,32,4225 ,6078,6079,6066 }, {5846,5847,4225 ,6065,6078,6066 }, - {32,181,2871 ,6079,6080,3649 }, {4225,32,2871 ,6066,6079,3649 }, - {5151,5125,5171 ,1803,5467,1804 }, {181,712,2871 ,6080,3650,3649 }, - {6242,6270,6269 ,6081,6082,6083 }, {1191,1689,1195 ,5816,5792,725 }, - {1689,4490,4347 ,5792,5688,3287 }, {1586,1191,1195 ,943,5816,725 }, - {612,611,4873 ,5011,1948,4992 }, {3615,5729,5700 ,201,200,4501 }, - {5295,556,808 ,2188,4043,4734 }, {2953,212,5835 ,5837,4614,4573 }, - {5836,2953,5835 ,5859,5837,4573 }, {4599,5182,5158 ,4210,4567,4832 }, - {4166,1016,1251 ,6084,6085,4604 }, {5788,5579,1002 ,6086,5942,2976 }, - {5316,5588,5550 ,6087,6088,6047 }, {6184,1170,1620 ,6089,4103,5982 }, - {6989,5694,5693 ,4586,5326,4075 }, {5716,5744,5756 ,6075,6090,6076 }, - {4106,5684,835 ,1742,4683,3030 }, {5924,6042,5865 ,6091,5703,6092 }, - {5649,5924,5865 ,6093,6091,6092 }, {6000,5851,3870 ,6094,6095,6096 }, - {4490,2954,3867 ,5688,5687,4507 }, {4347,4490,3867 ,3287,5688,4507 }, - {6644,4950,4981 ,5098,1302,1350 }, {3915,3939,4307 ,1575,3539,4562 }, - {3950,3799,4052 ,4530,4531,6068 }, {3345,3950,4052 ,3476,4530,6068 }, - {3799,3282,1986 ,4531,6097,6057 }, {4052,3799,1986 ,6068,4531,6057 }, - {3282,3769,2345 ,6097,6098,6058 }, {1986,3282,2345 ,6057,6097,6058 }, - {3769,5070,5187 ,6098,6043,5144 }, {2345,3769,5187 ,6058,6098,5144 }, - {4681,4714,5224 ,4958,1031,3850 }, {1005,68,3818 ,3535,4087,1244 }, - {5138,5260,5128 ,1940,4174,5966 }, {5767,5766,5728 ,5893,4487,4486 }, - {5729,5767,5728 ,200,5893,4486 }, {5143,1416,297 ,6099,6100,1918 }, - {1416,1455,140 ,6100,1917,1919 }, {4519,5202,1455 ,4746,5550,1917 }, - {1416,4519,1455 ,6100,4746,1917 }, {4519,4491,5202 ,4746,107,5550 }, - {4491,4472,808 ,107,2189,4734 }, {4710,4770,4769 ,4136,4345,5542 }, - {3580,3626,3605 ,6069,4196,3383 }, {5966,297,1455 ,5054,1918,1917 }, - {7745,7795,7744 ,650,3804,6101 }, {6255,6256,6275 ,6102,5657,5576 }, - {6247,6255,6275 ,5575,6102,5576 }, {5782,3836,3385 ,5693,6103,6104 }, - {2990,1519,601 ,3646,2450,3905 }, {6256,5953,1557 ,5657,5659,5577 }, - {6275,6256,1557 ,5576,5657,5577 }, {5756,5792,5791 ,6076,6105,6077 }, - {5852,2213,32 ,6106,6107,6079 }, {5847,5852,32 ,6078,6106,6079 }, - {4322,181,32 ,6108,6080,6079 }, {2213,4322,32 ,6107,6108,6079 }, - {5851,5881,3870 ,6095,6109,6096 }, {1700,3563,2896 ,6072,6074,6110 }, - {4770,5263,4830 ,4345,4302,3642 }, {309,2375,5231 ,4472,4479,115 }, - {4697,5099,3800 ,4327,5494,4325 }, {882,8117,3264 ,3846,4119,2468 }, - {3769,5736,5070 ,6098,6111,6043 }, {1937,4796,4273 ,59,4756,120 }, - {5441,5143,297 ,5194,6099,1918 }, {4447,5143,3399 ,717,6099,715 }, - {670,262,312 ,4760,4758,4759 }, {6158,6284,6034 ,6112,6113,6049 }, - {543,3266,495 ,3840,3884,4389 }, {7073,1166,5844 ,662,2746,5179 }, - {1689,2004,4490 ,5792,5747,5688 }, {5767,5803,5766 ,5893,5871,4487 }, - {5803,5802,5766 ,5871,4681,4487 }, {5819,5818,5802 ,6114,4640,4681 }, - {5803,5819,5802 ,5871,6114,4681 }, {5819,5836,5835 ,6114,5859,4573 }, - {5818,5819,5835 ,4640,6114,4573 }, {2953,3986,1208 ,5837,5817,3211 }, - {212,2953,1208 ,4614,5837,3211 }, {1191,1586,1208 ,5816,943,3211 }, - {3986,1191,1208 ,5817,5816,3211 }, {5953,3870,3310 ,5659,6096,5587 }, - {1557,5953,3310 ,5577,5659,5587 }, {5946,3415,5907 ,5481,6115,6116 }, - {3217,5008,2342 ,6117,6118,5690 }, {3870,3686,5984 ,6096,6119,5872 }, - {3310,3870,5984 ,5587,6096,5872 }, {3686,5915,5894 ,6119,6120,5821 }, - {5984,3686,5894 ,5872,6119,5821 }, {6091,5328,5384 ,2173,2172,6121 }, - {6003,6004,5871 ,6122,6123,4124 }, {5328,5301,5384 ,2172,2698,6121 }, - {3715,3018,5851 ,6124,6125,6095 }, {5718,5757,5756 ,6126,6127,6076 }, - {5943,5514,6009 ,5402,6128,6129 }, {5757,5793,5792 ,6127,6130,6105 }, - {5756,5757,5792 ,6076,6127,6105 }, {5793,5791,5792 ,6130,6077,6105 }, - {5793,5825,5847 ,6130,6131,6078 }, {5791,5793,5847 ,6077,6130,6078 }, - {5847,5825,5852 ,6078,6131,6106 }, {5825,445,2213 ,6131,6132,6107 }, - {5852,5825,2213 ,6106,6131,6107 }, {1456,4322,2213 ,6133,6108,6107 }, - {445,1456,2213 ,6132,6133,6107 }, {1456,181,4322 ,6133,6080,6108 }, - {852,712,181 ,6134,3650,6080 }, {1456,852,181 ,6133,6134,6080 }, - {852,4230,712 ,6134,6135,3650 }, {4249,3702,712 ,6136,1303,3650 }, - {4230,4249,712 ,6135,6136,3650 }, {3606,3607,4164 ,6137,6138,6139 }, - {7873,7846,7847 ,817,4162,3521 }, {5477,5789,6036 ,5399,6140,6141 }, - {5905,5528,5820 ,6142,6143,6144 }, {1538,1101,3867 ,0,2,4507 }, - {4805,4645,3367 ,5376,5378,5798 }, {6950,6644,4981 ,1349,5098,1350 }, - {5274,5300,5251 ,6145,3793,3802 }, {2158,6639,4983 ,1160,3699,480 }, - {6300,6301,6708 ,6146,6147,6148 }, {5342,5143,4447 ,6149,6099,717 }, - {5685,1416,5143 ,6150,6100,6099 }, {5036,3249,4905 ,399,5110,5112 }, - {4830,4829,4770 ,3642,4626,4345 }, {5615,3001,3274 ,3171,3210,3172 }, - {6223,6254,6055 ,6151,5758,3874 }, {5898,5662,5653 ,5706,5915,3644 }, - {6243,6271,6270 ,5666,6152,6082 }, {5610,5609,6248 ,6153,5658,6154 }, - {1028,5843,5844 ,1373,1372,5179 }, {5915,6072,2568 ,6120,6155,5807 }, - {5894,5915,2568 ,5821,6120,5807 }, {6207,6208,6242 ,6156,6011,6081 }, - {7621,7620,7565 ,6010,5033,5080 }, {5718,5719,5757 ,6126,6157,6127 }, - {4231,4249,4230 ,6158,6136,6135 }, {852,4231,4230 ,6134,6158,6135 }, - {7648,7647,7621 ,3952,4967,6010 }, {4231,1185,4249 ,6158,6159,6136 }, - {5915,5905,5820 ,6120,6142,6144 }, {5528,5712,5975 ,6143,6160,6161 }, - {1700,6266,3563 ,6072,399,6074 }, {180,8,131 ,4777,3341,2965 }, - {4400,637,3299 ,4721,3805,3232 }, {5975,5391,2568 ,6161,5773,5807 }, - {1410,5540,3893 ,3911,6162,3789 }, {6072,5975,2568 ,6155,6161,5807 }, - {5253,6046,5391 ,6163,5775,5773 }, {5353,1342,3799 ,851,6164,4531 }, - {5352,5353,3799 ,3502,851,4531 }, {1342,3255,3282 ,6164,6165,6097 }, - {3799,1342,3282 ,4531,6164,6097 }, {3255,1527,3877 ,6165,6166,6167 }, - {3282,3255,3877 ,6097,6165,6167 }, {3255,3282,3877 ,6165,6097,6167 }, - {1527,3255,3877 ,6166,6165,6167 }, {3255,4013,3769 ,6165,6168,6098 }, - {3282,3255,3769 ,6097,6165,6098 }, {4013,4220,5736 ,6168,6169,6111 }, - {3769,4013,5736 ,6098,6168,6111 }, {4220,5052,5070 ,6169,5189,6043 }, - {5736,4220,5070 ,6111,6169,6043 }, {3669,3266,1783 ,5917,3884,2251 }, - {3800,1248,1907 ,4325,2850,1245 }, {1524,3800,1907 ,4326,4325,1245 }, - {5685,774,1416 ,6150,767,6100 }, {5222,5221,5182 ,4566,4864,4567 }, - {2432,1524,3818 ,5427,4326,1244 }, {5128,5260,2217 ,5966,4174,4569 }, - {4883,4801,5127 ,5538,5115,5114 }, {1195,1689,4347 ,725,5792,3287 }, - {4550,5563,4447 ,716,4605,717 }, {5482,5342,4447 ,3565,6149,717 }, - {5126,5482,4447 ,6170,3565,717 }, {5423,5143,5342 ,6171,6099,6149 }, - {5482,5423,5342 ,3565,6171,6149 }, {1634,5685,5143 ,768,6150,6099 }, - {5423,1634,5143 ,6171,768,6099 }, {1416,774,104 ,6100,767,4765 }, - {8052,3638,8051 ,4122,5950,6172 }, {2659,601,2622 ,3485,3905,2840 }, - {3800,3817,1248 ,4325,1189,2850 }, {4872,4697,1524 ,5522,4327,4326 }, - {2954,1538,3867 ,5687,0,4507 }, {5356,5909,4167 ,4258,4260,6173 }, - {5654,6188,5916 ,6026,6174,6175 }, {5975,5253,5391 ,6161,6163,5773 }, - {2342,5008,2273 ,5690,6118,5322 }, {5896,5713,6046 ,6176,5776,5775 }, - {5253,5896,6046 ,6163,6176,5775 }, {564,5309,507 ,3529,987,1523 }, - {5611,5634,5633 ,6177,6178,6179 }, {6949,5634,5672 ,4585,6178,5324 }, - {5633,5634,6949 ,6179,6178,4585 }, {6088,6082,6069 ,3670,1348,6180 }, - {5672,5719,5718 ,5324,6157,6126 }, {5848,2994,445 ,6181,6182,6132 }, - {5825,5848,445 ,6131,6181,6132 }, {2994,1456,445 ,6182,6133,6132 }, - {3703,1185,4231 ,6183,6159,6158 }, {5820,5528,5975 ,6144,6143,6161 }, - {6532,3547,3494 ,6184,803,736 }, {1516,4233,3177 ,1254,6185,1255 }, - {3494,3495,6532 ,736,735,6184 }, {7422,7478,7450 ,1404,1402,399 }, - {5160,3524,5969 ,6186,6187,6188 }, {3018,5530,5851 ,6125,6189,6095 }, - {5965,5329,6076 ,6190,6191,4217 }, {5886,6087,6084 ,6192,6193,6194 }, - {3217,2342,2273 ,6117,5690,5322 }, {3829,3217,2273 ,6195,6117,5322 }, - {5713,5896,4648 ,5776,6176,5722 }, {3562,3943,6013 ,4753,4755,6060 }, - {5353,5733,1342 ,851,1584,6164 }, {1342,1527,3255 ,6164,6166,6165 }, - {4013,3255,1527 ,6168,6165,6166 }, {5244,5266,5221 ,79,81,4864 }, - {3817,1207,1248 ,1189,1074,2850 }, {5685,1634,774 ,6150,768,767 }, - {7509,7508,7479 ,1874,6196,4423 }, {1251,5126,5563 ,4604,6170,4605 }, - {2661,5126,1251 ,4684,6170,4604 }, {5482,1634,5423 ,3565,768,6171 }, - {3816,6577,5445 ,5623,97,3520 }, {3244,5050,993 ,4433,5233,5551 }, - {1376,4788,1196 ,1937,3758,4330 }, {1700,81,323 ,6072,4673,4767 }, - {3939,4361,4307 ,3539,4584,4562 }, {4321,4343,4342 ,4873,1818,4950 }, - {5980,6091,6010 ,5557,2173,6197 }, {1426,1017,3452 ,4648,1793,1794 }, - {6175,3620,6163 ,6004,6001,1453 }, {5331,5371,5350 ,6198,3558,1526 }, - {5331,5372,5371 ,6198,6199,3558 }, {5372,5406,5405 ,6199,6200,5518 }, - {5371,5372,5405 ,3558,6199,5518 }, {5406,5436,5405 ,6200,6201,5518 }, - {5008,2342,2273 ,6118,5690,5322 }, {5594,5612,5611 ,5937,6202,6177 }, - {5593,5594,5611 ,5935,5937,6177 }, {5612,5635,5634 ,6202,6203,6178 }, - {5611,5612,5634 ,6177,6202,6178 }, {5635,5673,5672 ,6203,6204,5324 }, - {5634,5635,5672 ,6178,6203,5324 }, {5673,5674,5672 ,6204,6205,5324 }, - {5674,5720,5719 ,6205,6206,6157 }, {5672,5674,5719 ,5324,6205,6157 }, - {5720,5758,5757 ,6206,6207,6127 }, {5719,5720,5757 ,6157,6206,6127 }, - {5758,5794,5793 ,6207,6208,6130 }, {5757,5758,5793 ,6127,6207,6130 }, - {5794,5826,5825 ,6208,6209,6131 }, {5793,5794,5825 ,6130,6208,6131 }, - {5825,5826,5848 ,6131,6209,6181 }, {5826,3145,2994 ,6209,6210,6182 }, - {5848,5826,2994 ,6181,6209,6182 }, {3940,1456,2994 ,6211,6133,6182 }, - {3145,3940,2994 ,6210,6211,6182 }, {1598,852,1456 ,6212,6134,6133 }, - {3940,1598,1456 ,6211,6212,6133 }, {3928,4231,852 ,6213,6158,6134 }, - {1598,3928,852 ,6212,6213,6134 }, {3587,3703,4231 ,6214,6183,6158 }, - {3928,3587,4231 ,6213,6214,6158 }, {2861,1185,3703 ,6215,6159,6183 }, - {3587,2861,3703 ,6214,6215,6183 }, {1988,1516,1185 ,6216,1254,6159 }, - {2861,1988,1185 ,6215,6216,6159 }, {4295,4233,1516 ,5968,6185,1254 }, - {1988,4295,1516 ,6216,5968,1254 }, {4295,4324,4233 ,5968,6217,6185 }, - {733,1026,4233 ,4051,6218,6185 }, {4324,733,4233 ,6217,4051,6185 }, - {7220,7239,7219 ,4367,1527,1529 }, {7186,7203,7185 ,5370,4366,5073 }, - {3781,5884,5451 ,5849,5848,6219 }, {5879,5987,6033 ,6220,5621,5620 }, - {5969,5965,6076 ,6188,6190,4217 }, {6001,6095,6081 ,6221,6222,6223 }, - {5869,5886,6084 ,6224,6192,6194 }, {4094,4642,5670 ,6225,6226,6227 }, - {3497,747,5319 ,5738,5692,5739 }, {6010,6016,5692 ,6197,6228,6229 }, - {5734,4467,1342 ,6230,6231,6164 }, {5733,5734,1342 ,1584,6230,6164 }, - {4467,602,1527 ,6231,6232,6166 }, {1342,4467,1527 ,6164,6231,6166 }, - {4220,4013,1527 ,6169,6168,6166 }, {602,4220,1527 ,6232,6169,6166 }, - {1537,1745,4191 ,4473,6233,4474 }, {1251,306,4166 ,4604,6234,6084 }, - {2661,5482,5126 ,4684,3565,6170 }, {3266,4669,4775 ,3884,3879,4388 }, - {1745,1444,4191 ,6233,4035,4474 }, {6242,6243,6270 ,6081,5666,6082 }, - {5171,5195,6114 ,1804,6235,1805 }, {5278,5277,5232 ,6236,6237,6238 }, - {5533,4010,6172 ,6239,4343,5451 }, {4465,4444,6210 ,257,582,5566 }, - {5845,6234,6174 ,143,5973,2381 }, {3943,5860,5956 ,4755,5998,6240 }, - {5636,5674,5673 ,6241,6205,6204 }, {5635,5636,5673 ,6203,6241,6204 }, - {5720,5759,5758 ,6206,6242,6207 }, {5758,5759,5794 ,6207,6242,6208 }, - {3942,3928,1598 ,6243,6213,6212 }, {3942,3587,3928 ,6243,6214,6213 }, - {184,733,4324 ,4052,4051,6217 }, {4295,184,4324 ,5968,4052,6217 }, - {7462,7435,7409 ,4310,6244,6245 }, {5973,6110,6081 ,6246,6247,6223 }, - {5711,5879,6033 ,6248,6220,5620 }, {2837,75,930 ,2511,3962,3594 }, - {6001,5996,6156 ,6221,6249,6250 }, {6001,6181,5705 ,6221,6251,4127 }, - {6081,3395,5185 ,6223,5940,5939 }, {5927,6040,5227 ,5318,5317,4097 }, - {6197,6223,6222 ,6252,6151,6253 }, {4026,4467,5734 ,6254,6231,6230 }, - {4261,4026,5734 ,1583,6254,6230 }, {4467,4026,602 ,6231,6254,6232 }, - {5459,4220,602 ,6255,6169,6232 }, {5459,993,5052 ,6255,5551,5189 }, - {4220,5459,5052 ,6169,6255,5189 }, {4908,4724,4774 ,5879,4737,5332 }, - {252,5526,966 ,2743,6256,2565 }, {3838,1016,4166 ,6257,6085,6084 }, - {5127,2661,1251 ,5114,4684,4604 }, {1016,5127,1251 ,6085,5114,4604 }, - {5127,124,2661 ,5114,2206,4684 }, {125,124,5127 ,399,2206,5114 }, - {1790,4949,5245 ,4738,5526,5880 }, {1444,3318,2690 ,4035,4036,6022 }, - {4191,1444,2690 ,4474,4035,6022 }, {3318,3419,2797 ,4036,2012,6030 }, - {2659,2622,2901 ,3485,2840,3468 }, {5609,6135,5953 ,5658,6258,5659 }, - {5278,5331,5277 ,6236,6198,6237 }, {5406,5437,5436 ,6200,6259,6201 }, - {5516,5552,5551 ,5420,5936,6260 }, {5612,5636,5635 ,6202,6241,6203 }, - {5720,5745,5759 ,6206,6261,6242 }, {1151,3587,3942 ,6262,6214,6243 }, - {2861,4295,1988 ,6215,5968,6216 }, {4016,4295,4348 ,5969,5968,6263 }, - {5898,6038,6035 ,5706,6264,6025 }, {6001,5705,5996 ,6221,4127,6249 }, - {3395,5854,6142 ,5940,6265,5941 }, {3583,5651,6067 ,5772,5920,6266 }, - {75,3510,1629 ,3962,6267,4207 }, {5654,5916,4425 ,6026,6175,6268 }, - {5987,5451,5608 ,5621,6219,4356 }, {5662,3943,5944 ,5915,4755,4754 }, - {5653,5662,5944 ,3644,5915,4754 }, {4209,4290,3777 ,6269,6270,1582 }, - {789,3985,2797 ,3910,4802,6030 }, {2690,3318,2797 ,6022,4036,6030 }, - {5803,5836,5819 ,5871,5859,6114 }, {7128,7160,7159 ,5391,6271,5075 }, - {993,5050,1154 ,5551,5233,4545 }, {5214,5213,5171 ,6272,428,1804 }, - {5172,5214,5171 ,5468,6272,1804 }, {5234,5233,5213 ,6273,429,428 }, - {5256,5232,5233 ,6274,6238,429 }, {5234,5256,5233 ,6273,6274,429 }, - {5279,5278,5232 ,6275,6236,6238 }, {5256,5279,5232 ,6274,6275,6238 }, - {5332,5331,5278 ,6276,6198,6236 }, {5279,5332,5278 ,6275,6276,6236 }, - {5332,5373,5372 ,6276,6277,6199 }, {5331,5332,5372 ,6198,6276,6199 }, - {5373,5407,5406 ,6277,6278,6200 }, {5372,5373,5406 ,6199,6277,6200 }, - {5407,5408,5406 ,6278,6279,6200 }, {5408,5438,5437 ,6279,4156,6259 }, - {5406,5408,5437 ,6200,6279,6259 }, {5479,5517,5516 ,5387,6280,5420 }, - {5517,5553,5552 ,6280,6281,5936 }, {5516,5517,5552 ,5420,6280,5936 }, - {5553,5554,5552 ,6281,6282,5936 }, {5554,5595,5594 ,6282,6283,5937 }, - {5552,5554,5594 ,5936,6282,5937 }, {5594,5595,5612 ,5937,6283,6202 }, - {5595,5637,5636 ,6283,6284,6241 }, {5612,5595,5636 ,6202,6283,6241 }, - {5637,5675,5674 ,6284,6285,6205 }, {5636,5637,5674 ,6241,6284,6205 }, - {5675,5721,5720 ,6285,6286,6206 }, {5674,5675,5720 ,6205,6285,6206 }, - {5721,5722,5745 ,6286,6287,6261 }, {5720,5721,5745 ,6206,6286,6261 }, - {5722,5760,5759 ,6287,6288,6242 }, {5745,5722,5759 ,6261,6287,6242 }, - {5760,5795,5794 ,6288,6289,6208 }, {5759,5760,5794 ,6242,6288,6208 }, - {5795,5827,5826 ,6289,6290,6209 }, {5794,5795,5826 ,6208,6289,6209 }, - {5827,5828,3145 ,6290,6291,6210 }, {5826,5827,3145 ,6209,6290,6210 }, - {5828,4288,3145 ,6291,6292,6210 }, {4288,4287,3145 ,6292,6293,6210 }, - {3480,3940,3145 ,6294,6211,6210 }, {4287,3480,3145 ,6293,6294,6210 }, - {995,1598,3940 ,6295,6212,6211 }, {3480,995,3940 ,6294,6295,6211 }, - {3983,3942,1598 ,6296,6243,6212 }, {995,3983,1598 ,6295,6296,6212 }, - {1522,1151,3942 ,6297,6262,6243 }, {3983,1522,3942 ,6296,6297,6243 }, - {1522,3587,1151 ,6297,6214,6262 }, {1732,2861,3587 ,6298,6215,6214 }, - {1522,1732,3587 ,6297,6298,6214 }, {4232,4295,2861 ,6299,5968,6215 }, - {1732,4232,2861 ,6298,6299,6215 }, {4232,4348,4295 ,6299,6263,5968 }, - {4321,3528,5630 ,4873,5061,4874 }, {4017,4016,4232 ,5342,5969,6299 }, - {5982,5924,5649 ,4218,6091,6093 }, {5705,6181,5992 ,4127,6251,4197 }, - {6130,6132,6131 ,6300,5897,6050 }, {5472,3443,5869 ,6301,6302,6224 }, - {7168,7185,7160 ,5371,5073,6271 }, {1555,4290,4209 ,6303,6270,6269 }, - {1554,1555,4209 ,6304,6303,6269 }, {1555,4261,4290 ,6303,1583,6270 }, - {3771,4026,4261 ,6305,6254,1583 }, {1555,3771,4261 ,6303,6305,1583 }, - {3010,602,4026 ,6306,6232,6254 }, {3771,3010,4026 ,6305,6306,6254 }, - {3242,5459,602 ,6307,6255,6232 }, {3010,3242,602 ,6306,6307,6232 }, - {3242,3244,993 ,6307,4433,5551 }, {5459,3242,993 ,6255,6307,5551 }, - {1207,3817,5153 ,1074,1189,3896 }, {6749,5548,5512 ,4046,1590,1589 }, - {5457,5387,1252 ,6308,6309,5023 }, {5387,3838,3839 ,6309,6257,6310 }, - {1388,1016,3838 ,6311,6085,6257 }, {5387,1388,3838 ,6309,6311,6257 }, - {5617,5127,1016 ,6312,5114,6085 }, {2621,1606,3815 ,5416,3677,5556 }, - {5321,5346,5320 ,5668,3267,4464 }, {5172,5215,5214 ,5468,6313,6272 }, - {5234,5279,5256 ,6273,6275,6274 }, {5332,5374,5373 ,6276,6314,6277 }, - {5374,5408,5407 ,6314,6279,6278 }, {5373,5374,5407 ,6277,6314,6278 }, - {7371,7370,7310 ,3748,3750,4283 }, {5479,5492,5517 ,5387,6315,6280 }, - {5517,5518,5553 ,6280,6316,6281 }, {5796,5828,5827 ,6317,6291,6290 }, - {5795,5796,5827 ,6289,6317,6290 }, {3665,3480,4287 ,6318,6294,6293 }, - {4288,3665,4287 ,6292,6318,6293 }, {1491,1732,1522 ,6319,6298,6297 }, - {4348,4232,4016 ,6263,6299,5969 }, {4921,1551,5082 ,2079,5275,5218 }, - {5786,5082,3872 ,4813,5218,4811 }, {6081,5185,5992 ,6223,5939,4197 }, - {6181,6081,5992 ,6251,6223,4197 }, {3726,3771,1555 ,6320,6305,6303 }, - {3726,3010,3771 ,6320,6306,6305 }, {4834,955,5787 ,4304,3991,4305 }, - {5387,3839,1252 ,6309,6310,5023 }, {4241,5387,5457 ,6321,6309,6308 }, - {5225,1388,5387 ,6322,6311,6309 }, {4883,5617,1016 ,5538,6312,6085 }, - {1388,4883,1016 ,6311,5538,6085 }, {5617,4883,5127 ,6312,5538,5114 }, - {3760,3669,1783 ,2250,5917,2251 }, {5267,5290,5244 ,4647,5247,79 }, - {5215,5172,5216 ,6313,5468,6323 }, {4842,4776,4745 ,5429,5390,5446 }, - {5492,5518,5517 ,6315,6316,6280 }, {5518,5554,5553 ,6316,6282,6281 }, - {5696,5722,5721 ,6324,6287,6286 }, {5675,5696,5721 ,6285,6324,6286 }, - {5760,5796,5795 ,6288,6317,6289 }, {4188,995,3480 ,6325,6295,6294 }, - {3665,4188,3480 ,6318,6325,6294 }, {2957,603,2093 ,6326,5274,553 }, - {5189,5188,3872 ,6327,4812,4811 }, {803,101,6204 ,144,5,4050 }, - {248,1554,4530 ,4114,6304,1376 }, {3118,3010,3726 ,6328,6306,6320 }, - {3118,3242,3010 ,6328,6307,6306 }, {455,556,4471 ,2205,4043,2187 }, - {5205,5228,5227 ,5219,4095,4097 }, {4649,5152,5125 ,5288,6329,5467 }, - {4702,5173,5125 ,5291,6330,5467 }, {5152,4702,5125 ,6329,5291,5467 }, - {4702,5172,5173 ,5291,5468,6330 }, {4702,5216,5172 ,5291,6323,5468 }, - {5257,5234,5214 ,6331,6273,6272 }, {5280,5279,5234 ,6332,6275,6273 }, - {5257,5280,5234 ,6331,6332,6273 }, {5333,5332,5279 ,6333,6276,6275 }, - {5280,5333,5279 ,6332,6333,6275 }, {5375,5374,5332 ,6334,6314,6276 }, - {5333,5375,5332 ,6333,6334,6276 }, {5375,5409,5408 ,6334,6335,6279 }, - {5374,5375,5408 ,6314,6334,6279 }, {5409,5439,5438 ,6335,4157,4156 }, - {5408,5409,5438 ,6279,6335,4156 }, {7160,7138,7168 ,6271,2560,5371 }, - {5493,5519,5518 ,6336,6337,6316 }, {5479,5493,5492 ,5387,6336,6315 }, - {5519,5555,5554 ,6337,6338,6282 }, {5518,5519,5554 ,6316,6337,6282 }, - {5555,5596,5595 ,6338,6339,6283 }, {5554,5555,5595 ,6282,6338,6283 }, - {5596,5638,5637 ,6339,6340,6284 }, {5595,5596,5637 ,6283,6339,6284 }, - {5638,5676,5675 ,6340,6341,6285 }, {5637,5638,5675 ,6284,6340,6285 }, - {5676,5677,5696 ,6341,6342,6324 }, {5675,5676,5696 ,6285,6341,6324 }, - {5677,5723,5722 ,6342,6343,6287 }, {5696,5677,5722 ,6324,6342,6287 }, - {5723,5761,5760 ,6343,6344,6288 }, {5722,5723,5760 ,6287,6343,6288 }, - {5761,5783,5760 ,6344,6345,6288 }, {5783,5797,5796 ,6345,6346,6317 }, - {5760,5783,5796 ,6288,6345,6317 }, {5797,5829,5828 ,6346,6347,6291 }, - {5796,5797,5828 ,6317,6346,6291 }, {5829,1667,4288 ,6347,6348,6292 }, - {5828,5829,4288 ,6291,6347,6292 }, {1667,1019,3665 ,6348,6349,6318 }, - {4288,1667,3665 ,6292,6348,6318 }, {1540,4188,3665 ,6350,6325,6318 }, - {1019,1540,3665 ,6349,6350,6318 }, {1540,995,4188 ,6350,6295,6325 }, - {2499,3983,995 ,6351,6296,6295 }, {1540,2499,995 ,6350,6351,6295 }, - {2499,3988,3983 ,6351,6352,6296 }, {3974,1522,3983 ,6353,6297,6296 }, - {3988,3974,3983 ,6352,6353,6296 }, {218,1491,1522 ,6354,6319,6297 }, - {3974,218,1522 ,6353,6354,6297 }, {218,1732,1491 ,6354,6298,6319 }, - {2809,4232,1732 ,6355,6299,6298 }, {218,2809,1732 ,6354,6355,6298 }, - {2809,4208,4232 ,6355,6356,6299 }, {7129,7138,7160 ,1026,2560,6271 }, - {7138,7169,7168 ,2560,5437,5371 }, {876,5859,1120 ,5340,6357,5339 }, - {5859,37,1120 ,6357,6358,5339 }, {2957,1120,37 ,6326,5339,6358 }, - {37,555,2957 ,6358,6359,6326 }, {555,551,603 ,6359,6360,5274 }, - {2957,555,603 ,6326,6359,5274 }, {1523,1551,603 ,6361,5275,5274 }, - {551,1523,603 ,6360,6361,5274 }, {1108,3872,1551 ,6362,4811,5275 }, - {1523,1108,1551 ,6361,6362,5275 }, {3361,5189,3872 ,6363,6327,4811 }, - {1108,3361,3872 ,6362,6363,4811 }, {3361,5188,5189 ,6363,4812,6327 }, - {1861,3350,5188 ,6364,2541,4812 }, {3361,1861,5188 ,6363,6364,4812 }, - {1861,5856,3350 ,6364,6365,2541 }, {5856,5806,3350 ,6365,4113,2541 }, - {3418,248,5806 ,6366,4114,4113 }, {3418,5341,1554 ,6366,6367,6304 }, - {4025,1555,1554 ,6368,6303,6304 }, {5341,4025,1554 ,6367,6368,6304 }, - {3774,3726,1555 ,6369,6320,6303 }, {4025,3774,1555 ,6368,6369,6303 }, - {2991,3118,3726 ,6370,6328,6320 }, {3774,2991,3726 ,6369,6370,6320 }, - {5201,3242,3118 ,6371,6307,6328 }, {2991,5201,3118 ,6370,6371,6328 }, - {5201,5174,3242 ,6371,6372,6307 }, {4397,3244,3242 ,4434,4433,6307 }, - {5174,4397,3242 ,6372,4434,6307 }, {1253,3778,4068 ,2353,5585,408 }, - {5020,4272,4241 ,6373,6374,6321 }, {5245,5387,4241 ,5880,6309,6321 }, - {4272,5245,4241 ,6374,5880,6321 }, {5245,4908,5387 ,5880,5879,6309 }, - {4908,5161,5225 ,5879,6375,6322 }, {5387,4908,5225 ,6309,5879,6322 }, - {5161,4774,1388 ,6375,5332,6311 }, {5225,5161,1388 ,6322,6375,6311 }, - {5153,4682,3899 ,3896,1191,1938 }, {4702,5152,4649 ,5291,6329,5288 }, - {1922,4397,1085 ,4432,4434,369 }, {5519,5535,5555 ,6337,3512,6338 }, - {5596,5613,5638 ,6339,6376,6340 }, {5638,5677,5676 ,6340,6342,6341 }, - {2499,3974,3988 ,6351,6353,6352 }, {4208,2809,876 ,6356,6355,5340 }, - {876,37,5859 ,5340,6358,6357 }, {2913,414,551 ,6377,6378,6360 }, - {555,2913,551 ,6359,6377,6360 }, {671,1523,551 ,6379,6361,6360 }, - {414,671,551 ,6378,6379,6360 }, {4309,1108,1523 ,6380,6362,6361 }, - {671,4309,1523 ,6379,6380,6361 }, {3630,5806,5856 ,6381,4113,6365 }, - {1861,3630,5856 ,6364,6381,6365 }, {3287,4025,5341 ,6382,6368,6367 }, - {3418,3287,5341 ,6366,6382,6367 }, {4025,5661,3774 ,6368,6383,6369 }, - {5174,4117,4397 ,6372,4700,4434 }, {6785,6803,5548 ,4140,4169,1590 }, - {5292,4272,5175 ,5093,6374,6384 }, {4908,4774,5161 ,5879,5332,6375 }, - {5224,4714,5267 ,3850,1031,4647 }, {3732,2785,3419 ,3536,1246,2012 }, - {3318,3732,3419 ,4036,3536,2012 }, {5235,5280,5257 ,6385,6332,6331 }, - {5439,5410,5440 ,4157,4285,5147 }, {5104,2246,5755 ,6063,591,4047 }, - {6697,5512,5471 ,3866,1589,2051 }, {6680,6697,5471 ,3834,3866,2051 }, - {5590,6173,6002 ,6386,3711,5975 }, {5555,5568,5596 ,6338,6387,6339 }, - {5638,5655,5677 ,6340,6388,6342 }, {1585,3974,2499 ,6389,6353,6351 }, - {876,4346,37 ,5340,6390,6358 }, {37,2913,555 ,6358,6377,6359 }, - {4309,3361,1108 ,6380,6363,6362 }, {1384,3418,5806 ,6391,6366,4113 }, - {3630,1384,5806 ,6381,6391,4113 }, {4025,3287,5661 ,6368,6382,6383 }, - {3775,2991,3774 ,6392,6370,6369 }, {5661,3775,3774 ,6383,6392,6369 }, - {4397,4117,1859 ,4434,4700,4480 }, {4272,5020,5175 ,6374,6373,6384 }, - {6697,6749,5512 ,3866,4046,1589 }, {3367,4645,4926 ,5798,5378,3897 }, - {1416,104,4519 ,6100,4765,4746 }, {5217,5216,4702 ,4026,6323,5291 }, - {4703,5217,4702 ,5290,4026,5291 }, {5217,5235,5216 ,4026,6385,6323 }, - {5217,5258,5235 ,4026,1193,6385 }, {5281,5280,5235 ,1195,6332,6385 }, - {5258,5281,5235 ,1193,1195,6385 }, {5281,5282,5280 ,1195,1194,6332 }, - {5282,5334,5333 ,1194,2736,6333 }, {5280,5282,5333 ,6332,1194,6333 }, - {5334,5376,5375 ,2736,2758,6334 }, {5333,5334,5375 ,6333,2736,6334 }, - {5410,5409,5375 ,4285,6335,6334 }, {5376,5410,5375 ,2758,4285,6334 }, - {5409,5410,5439 ,6335,4285,4157 }, {5172,5125,5173 ,5468,5467,6330 }, - {1353,1395,1352 ,1205,1164,1262 }, {5556,5557,5568 ,3511,756,6387 }, - {5555,5556,5568 ,6338,3511,6387 }, {5557,5597,5596 ,756,6393,6339 }, - {5568,5557,5596 ,6387,756,6339 }, {5557,5598,5597 ,756,2216,6393 }, - {5596,5597,5613 ,6339,6393,6376 }, {5598,5639,5638 ,2216,2215,6340 }, - {5613,5598,5638 ,6376,2216,6340 }, {5639,5656,5655 ,2215,3864,6388 }, - {5638,5639,5655 ,6340,2215,6388 }, {5656,5678,5677 ,3864,3861,6342 }, - {5655,5656,5677 ,6388,3864,6342 }, {5678,5724,5723 ,3861,4898,6343 }, - {5677,5678,5723 ,6342,3861,6343 }, {5724,5762,5761 ,4898,4884,6344 }, - {5723,5724,5761 ,6343,4898,6344 }, {5761,5762,5783 ,6344,4884,6345 }, - {5762,5798,5797 ,4884,4876,6346 }, {5783,5762,5797 ,6345,4884,6346 }, - {5798,5830,5829 ,4876,4163,6347 }, {5797,5798,5829 ,6346,4876,6347 }, - {1794,1667,5829 ,4129,6348,6347 }, {5830,1794,5829 ,4163,4129,6347 }, - {1794,2795,1019 ,4129,3975,6349 }, {1667,1794,1019 ,6348,4129,6349 }, - {1607,1540,1019 ,3941,6350,6349 }, {2795,1607,1019 ,3975,3941,6349 }, - {2477,2499,1540 ,642,6351,6350 }, {1607,2477,1540 ,3941,642,6350 }, - {87,1585,2499 ,641,6389,6351 }, {2477,87,2499 ,642,641,6351 }, - {87,3974,1585 ,641,6353,6389 }, {1587,218,3974 ,837,6354,6353 }, - {87,1587,3974 ,641,837,6353 }, {96,2809,218 ,836,6355,6354 }, - {1587,96,218 ,837,836,6354 }, {96,3257,876 ,836,4010,5340 }, - {2809,96,876 ,6355,836,5340 }, {876,3257,4346 ,5340,4010,6390 }, - {3257,5737,37 ,4010,6394,6358 }, {4346,3257,37 ,6390,4010,6358 }, - {5737,1974,37 ,6394,3862,6358 }, {1974,62,2913 ,3862,3831,6377 }, - {37,1974,2913 ,6358,3862,6377 }, {34,414,2913 ,3830,6378,6377 }, - {62,34,2913 ,3831,3830,6377 }, {3980,671,414 ,4933,6379,6378 }, - {34,3980,414 ,3830,4933,6378 }, {164,4309,671 ,4932,6380,6379 }, - {3980,164,671 ,4933,4932,6379 }, {52,3361,4309 ,411,6363,6380 }, - {164,52,4309 ,4932,411,6380 }, {3113,1861,3361 ,410,6364,6363 }, - {52,3113,3361 ,411,410,6363 }, {3113,269,1861 ,410,3813,6364 }, - {1734,3630,1861 ,2219,6381,6364 }, {269,1734,1861 ,3813,2219,6364 }, - {878,1384,3630 ,398,6391,6381 }, {1734,878,3630 ,2219,398,6381 }, - {878,3418,1384 ,398,6366,6391 }, {4011,3287,3418 ,395,6382,6366 }, - {878,4011,3418 ,398,395,6366 }, {4011,3662,5661 ,395,1942,6383 }, - {3287,4011,5661 ,6382,395,6383 }, {5304,3775,5661 ,654,6392,6383 }, - {3662,5304,5661 ,1942,654,6383 }, {5304,2991,3775 ,654,6370,6392 }, - {5481,5201,2991 ,3863,6371,6370 }, {5304,5481,2991 ,654,3863,6370 }, - {5481,4117,5201 ,3863,4700,6371 }, {4117,5174,5201 ,4700,6372,6371 }, - {104,1150,4519 ,4765,741,4746 }, {3899,1376,1196 ,1938,1937,4330 }, - {7410,7462,7409 ,3766,4310,6245 }, {7033,6152,5945 ,6395,6044,6396 }, - {5562,5945,6152 ,4193,6396,6044 }, {1790,4272,5292 ,4738,6374,5093 }, - {5017,1790,5292 ,5092,4738,5093 }, {4272,1790,5245 ,6374,4738,5880 }, - {3419,789,2797 ,2012,3910,6030 }, {5153,3899,5146 ,3896,1938,1075 }, - {4502,1859,4117 ,4650,4480,4700 }, {6648,6680,6647 ,1390,3834,2050 }, - {6648,6647,6611 ,1390,2050,1391 }, {5557,8043,5598 ,756,6397,2216 }, - {6530,1990,1217 ,6398,1305,6399 }, {5613,5597,5598 ,6376,6393,2216 }, - {1539,1587,87 ,835,837,641 }, {96,3909,3257 ,836,4164,4010 }, - {3257,1974,5737 ,4010,3862,6394 }, {3688,4292,4153 ,5574,6400,5711 }, - {3470,6003,5917 ,6401,6122,6402 }, {350,5653,1273 ,1114,3644,6403 }, - {4286,5580,3528 ,4274,6404,5061 }, {5392,5947,5717 ,4022,6027,4023 }, - {2044,465,501 ,4031,4578,4313 }, {670,5043,5985 ,4760,4762,5365 }, - {7960,100,2306 ,3505,2823,6405 }, {5882,3674,3728 ,4397,4286,4251 }, - {5575,5958,6112 ,5686,5702,6406 }, {8023,8038,8022 ,4582,4121,4123 }, - {4284,4229,4270 ,4869,4877,4900 }, {3778,1253,1583 ,5585,2353,5415 }, - {6267,3607,3606 ,6407,6138,6137 }, {6012,5963,6004 ,6408,6409,6123 }, - {6241,6242,6269 ,6410,6081,6083 }, {5129,5293,5314 ,5698,5889,6411 }, - {3659,5129,5314 ,3875,5698,6411 }, {6141,6122,2072 ,2386,1797,1812 }, - {3559,5567,5897 ,6412,6413,6414 }, {4058,206,4054 ,4708,3932,3679 }, - {5650,5981,3905 ,2713,6415,4194 }, {6227,5906,5462 ,6416,6417,6418 }, - {3813,3758,5926 ,1515,1789,6419 }, {5662,6035,4045 ,5915,6025,5916 }, - {5687,5048,5101 ,6420,6421,6422 }, {5361,6227,5462 ,5664,6416,6418 }, - {206,4054,4055 ,3932,3679,3678 }, {5488,3518,5473 ,2730,4338,3429 }, - {3528,5580,5630 ,5061,6404,4874 }, {6113,3608,5461 ,5873,5799,5744 }, - {6057,5994,5893 ,6423,6424,6425 }, {5994,5524,1008 ,6424,6426,6427 }, - {3599,6057,5893 ,6428,6423,6425 }, {4153,3688,3953 ,5711,5574,5713 }, - {5893,5994,1008 ,6425,6424,6427 }, {6096,2357,4043 ,4092,3933,419 }, - {2142,6031,5706 ,4936,6429,3796 }, {3007,6070,3582 ,818,820,1378 }, - {7437,7436,7386 ,5938,4245,5512 }, {6168,5646,5316 ,6430,6431,6087 }, - {5524,5646,1008 ,6426,6431,6427 }, {5646,5743,5316 ,6431,6432,6087 }, - {5346,6260,5320 ,3267,3397,4464 }, {8095,8062,8090 ,4362,3272,412 }, - {6128,6129,5123 ,5981,5983,6433 }, {5646,6168,1008 ,6431,6430,6427 }, - {6023,5646,5524 ,6040,6431,6426 }, {5875,3797,5490 ,6434,2061,6055 }, - {5550,5878,5549 ,6047,2684,6435 }, {5452,5650,3905 ,2714,2713,4194 }, - {3803,3720,3804 ,6436,6437,4324 }, {6001,6003,6095 ,6221,6122,6222 }, - {5345,6057,3599 ,6438,6423,6428 }, {5392,1741,5947 ,4022,5695,6027 }, - {187,2159,1171 ,6439,6440,6441 }, {3804,3720,5882 ,4324,6437,4397 }, - {3720,6160,3674 ,6437,6442,4286 }, {5882,3720,3674 ,4397,6437,4286 }, - {5254,5576,3436 ,4042,4039,2145 }, {7688,7689,7712 ,6443,6444,5350 }, - {4528,5550,5549 ,4935,6047,6435 }, {2159,4528,5549 ,6440,4935,6435 }, - {6230,6104,3436 ,2144,5696,2145 }, {5303,2636,5315 ,5737,2712,6445 }, - {3688,4153,3953 ,5574,5711,5713 }, {5880,3666,6137 ,5700,5699,5809 }, - {6059,3679,5906 ,6446,6447,6417 }, {6094,5977,5742 ,692,809,6448 }, - {3373,6094,5742 ,693,692,6448 }, {4807,5426,5970 ,6449,5634,3518 }, - {381,3522,1627 ,6450,6451,5573 }, {2636,5303,5650 ,2712,5737,2713 }, - {5862,3893,4623 ,3790,3789,6452 }, {3893,5861,4623 ,3789,6453,6452 }, - {5609,5851,6135 ,5658,6095,6258 }, {5297,4178,5272 ,3826,3825,5956 }, - {5044,5192,5303 ,5173,6454,5737 }, {5922,6149,3445 ,4292,732,1791 }, - {7089,7103,5115 ,5608,6455,5913 }, {4433,4820,4795 ,4591,2399,3710 }, - {5462,5906,5961 ,6418,6417,6456 }, {5192,4410,6251 ,6454,5735,6457 }, - {6224,6248,6213 ,6458,6154,6459 }, {2636,5452,5386 ,2712,2714,5870 }, - {6010,5384,6016 ,6197,6121,6228 }, {6058,5345,5416 ,6460,6438,6461 }, - {5384,3631,5403 ,6121,5922,5921 }, {5235,5257,5214 ,6385,6331,6272 }, - {6254,3906,6055 ,5758,5697,3874 }, {3411,5193,1741 ,4280,5846,5695 }, - {6003,5973,6095 ,6122,6246,6222 }, {3415,7082,6186 ,6115,6462,4365 }, - {6205,6206,6240 ,6463,6464,5756 }, {5213,5195,5171 ,428,6235,1804 }, - {5888,5902,6093 ,5752,5769,5771 }, {7423,7479,7422 ,3749,4423,1404 }, - {5322,5320,5695 ,4297,4464,6465 }, {5874,5976,5925 ,4896,5903,5710 }, - {7690,449,448 ,6466,1169,1172 }, {5958,5122,3507 ,5702,4024,5671 }, - {3930,1627,4247 ,6467,5573,6468 }, {3628,6235,5703 ,4213,4215,5748 }, - {5567,5526,5897 ,6413,6256,6414 }, {5205,5248,5247 ,5219,6469,4096 }, - {6254,6268,3906 ,5758,5757,5697 }, {5609,6256,6213 ,5658,5657,6459 }, - {6102,3868,3879 ,2464,970,2549 }, {5055,3979,1261 ,6470,6471,6472 }, - {4247,4246,381 ,6468,3665,6450 }, {381,1627,3930 ,6450,5573,6467 }, - {7293,7248,7322 ,6473,73,75 }, {5926,3758,3714 ,6419,1789,3970 }, - {6004,6003,5974 ,6123,6122,6474 }, {5993,3953,5580 ,6475,5713,6404 }, - {7423,7422,7370 ,3749,1404,3750 }, {1701,1949,216 ,6476,3637,4644 }, - {5851,5530,5881 ,6095,6189,6109 }, {4574,6062,5974 ,6477,6478,6474 }, - {1532,1051,217 ,4771,4588,4643 }, {6075,5922,5908 ,6042,4292,4293 }, - {5662,5898,6035 ,5915,5706,6025 }, {1605,6206,6205 ,17,6464,6463 }, - {5971,5903,5902 ,6479,6480,5769 }, {5902,5903,686 ,5769,6480,5770 }, - {5753,5055,5916 ,6481,6470,6175 }, {3522,6227,758 ,6451,6416,5663 }, - {6024,3410,5486 ,6482,6483,5718 }, {6225,5610,6248 ,4872,6153,6154 }, - {4517,6058,5416 ,6484,6460,6461 }, {5923,5591,3979 ,2073,3597,6471 }, - {1854,635,5971 ,2184,2183,6479 }, {4540,4526,4515 ,19,187,30 }, - {5318,3360,6023 ,6039,6485,6040 }, {5972,5988,4147 ,399,2516,2517 }, - {6225,6248,6224 ,4872,6154,6458 }, {1661,6179,3906 ,5672,6486,5697 }, - {6070,4486,3582 ,820,819,1378 }, {6240,6241,1661 ,5756,6410,5672 }, - {3717,3715,5630 ,6487,6124,4874 }, {3902,4807,5970 ,4437,6449,3518 }, - {3051,5474,5877 ,6488,4243,4242 }, {5388,5446,6317 ,5428,5985,3207 }, - {6032,5472,5869 ,6489,6301,6224 }, {5472,3409,6032 ,6301,6490,6489 }, - {3360,3386,5472 ,6485,6491,6301 }, {3409,5472,6032 ,6490,6301,6489 }, - {20,2657,3506 ,3961,2185,6492 }, {6018,4304,1747 ,340,4579,266 }, - {5185,6142,3632 ,5939,5941,5898 }, {5887,5888,6087 ,6493,5752,6193 }, - {6089,6050,6087 ,6494,4094,6193 }, {6023,6024,5646 ,6040,6482,6431 }, - {5055,5476,5916 ,6470,6495,6175 }, {5906,6006,3560 ,6417,6496,5779 }, - {5630,5610,5609 ,4874,6153,5658 }, {5888,6093,6050 ,5752,5771,4094 }, - {5319,747,5781 ,5739,5692,5694 }, {4229,4246,4270 ,4877,3665,4900 }, - {3680,3499,405 ,6497,5661,5662 }, {6084,3499,3680 ,6194,5661,6497 }, - {5961,5906,3560 ,6456,6417,5779 }, {6006,6043,3560 ,6496,6498,5779 }, - {5866,5867,4094 ,5302,6499,6225 }, {3560,6043,5318 ,5779,6498,6039 }, - {5867,5869,5866 ,6499,6224,5302 }, {5273,5298,5272 ,3819,3818,5956 }, - {5513,6123,4147 ,6500,4221,2517 }, {1417,3522,381 ,6501,6451,6450 }, - {3638,278,8051 ,5950,1489,6172 }, {5866,4094,4410 ,5302,6225,5735 }, - {5192,5866,4410 ,6454,5302,5735 }, {3525,5935,5885 ,5665,5778,6502 }, - {6168,5316,1008 ,6430,6087,6427 }, {3517,1729,5580 ,6503,3666,6404 }, - {6052,3311,3762 ,5717,5303,5172 }, {5303,5981,5650 ,5737,6415,2713 }, - {5303,5315,5044 ,5737,6445,5173 }, {1700,706,807 ,6072,4784,6073 }, - {3581,3508,6017 ,6504,6505,6506 }, {3508,5964,6017 ,6505,6507,6506 }, - {3879,5317,6102 ,2549,6508,2464 }, {5317,5382,3831 ,6508,6509,2321 }, - {6102,5317,3831 ,2464,6508,2321 }, {5382,4154,3803 ,6509,6510,6436 }, - {3831,5382,3803 ,2321,6509,6436 }, {1606,4054,206 ,3677,3679,3932 }, - {3953,3018,6124 ,5713,6125,6511 }, {5567,3559,5955 ,6413,6412,6512 }, - {5351,3386,5318 ,6513,6491,6039 }, {3443,6077,5887 ,6302,5753,6493 }, - {5988,20,4147 ,2516,3961,2517 }, {6145,5247,4023 ,6514,4096,3827 }, - {6087,6050,5394 ,6193,4094,5660 }, {5416,5345,5671 ,6461,6438,6515 }, - {507,565,564 ,1523,1614,3529 }, {3576,5912,6017 ,5890,5892,6506 }, - {807,3606,3563 ,6073,6137,6074 }, {5747,6030,5254 ,6036,4037,4042 }, - {6118,5923,3979 ,2074,2073,6471 }, {5753,6118,3979 ,6481,2074,6471 }, - {1729,5993,5580 ,3666,6475,6404 }, {6093,686,6086 ,5771,5770,6516 }, - {4260,6139,6138 ,3527,2059,6014 }, {5867,5869,4094 ,6499,6224,6225 }, - {3522,758,1627 ,6451,5663,5573 }, {5909,6136,5824 ,4260,5810,6517 }, - {5630,3715,5610 ,4874,6124,6153 }, {4147,3506,3384 ,2517,6492,6518 }, - {5888,6089,6087 ,5752,6494,6193 }, {6124,3018,3715 ,6511,6125,6124 }, - {3829,2273,3051 ,6195,5322,6488 }, {4517,5416,3018 ,6484,6461,6125 }, - {5853,3560,5318 ,6038,5779,6039 }, {3509,6128,5123 ,6519,5981,6433 }, - {4443,6212,6211 ,703,5562,5558 }, {5490,3747,5749 ,6055,2925,6052 }, - {5296,4023,5297 ,4296,3827,3826 }, {4055,4054,206 ,3678,3679,3932 }, - {6103,6123,5897 ,4220,4221,6414 }, {4486,3454,3582 ,819,710,1378 }, - {2204,6032,5867 ,6520,6489,6499 }, {5869,5867,5866 ,6224,6499,5302 }, - {6032,5869,5867 ,6489,6224,6499 }, {3658,6023,5524 ,6521,6040,6426 }, - {3584,6078,3558 ,5888,6522,5964 }, {3506,5368,3409 ,6492,5751,6490 }, - {5315,2636,5477 ,6445,2712,5399 }, {3680,405,4642 ,6497,5662,6226 }, - {6119,4410,5670 ,5736,5735,6227 }, {4374,4517,3018 ,5712,6484,6125 }, - {5299,5300,6041 ,3800,3793,3801 }, {3018,5416,5905 ,6125,6461,6142 }, - {5293,3584,3558 ,5889,5888,5964 }, {6218,3658,5935 ,5780,6521,5778 }, - {5246,5227,6040 ,5176,4097,5317 }, {3405,8086,1153 ,1798,4823,2245 }, - {3563,3606,1510 ,6074,6137,3788 }, {3905,5562,6152 ,4194,4193,6044 }, - {6163,3620,3860 ,1453,6001,6523 }, {5928,3904,3903 ,4072,1264,296 }, - {5882,3772,3804 ,4397,4250,4324 }, {3905,6152,6166 ,4194,6044,4971 }, - {5192,6251,5303 ,6454,6457,5737 }, {1417,381,4229 ,6501,6450,4877 }, - {635,5534,5971 ,2183,6524,6479 }, {6226,5981,5562 ,4192,6415,4193 }, - {1629,3510,1518 ,4207,6267,3978 }, {4367,6225,6224 ,228,4872,6458 }, - {3360,5472,5450 ,6485,6301,6525 }, {6244,5663,5356 ,5667,4259,4258 }, - {6006,5351,6043 ,6496,6513,6498 }, {3384,3506,3409 ,6518,6492,6490 }, - {5368,6077,3443 ,5751,5753,6302 }, {3409,5368,3443 ,6490,5751,6302 }, - {6077,5888,5887 ,5753,5752,6493 }, {4623,5861,5939 ,6452,6453,4276 }, - {6119,5670,5303 ,5736,6227,5737 }, {7973,7972,7948 ,3624,6059,3625 }, - {5567,2040,3039 ,6413,4833,2686 }, {6270,3780,3611 ,6082,6526,5673 }, - {5868,3720,3803 ,6527,6437,6436 }, {3525,4292,3688 ,5665,6400,5574 }, - {3337,5123,3951 ,4125,6433,6528 }, {970,5997,6018 ,268,6529,340 }, - {4154,5868,3803 ,6510,6527,6436 }, {6251,4410,5303 ,6457,5735,5737 }, - {5671,5345,3599 ,6515,6438,6428 }, {4286,3517,5580 ,4274,6503,6404 }, - {6161,6160,3720 ,6530,6442,6437 }, {5868,6161,3720 ,6527,6530,6437 }, - {6161,6187,6160 ,6530,6531,6442 }, {2896,3497,3845 ,6110,5738,3635 }, - {5903,2357,686 ,6480,3933,5770 }, {5906,3679,6006 ,6417,6447,6496 }, - {6227,3522,5906 ,6416,6451,6417 }, {4528,5316,5550 ,4935,6087,6047 }, - {3953,3717,5580 ,5713,6487,6404 }, {6139,5875,6250 ,2059,6434,6532 }, - {5390,6317,5446 ,3205,3207,5985 }, {4293,3954,4957 ,2732,3463,2733 }, - {5417,5451,5987 ,5923,6219,5621 }, {6207,6242,6241 ,6156,6081,6410 }, - {41,5037,5390 ,6533,3206,3205 }, {5116,3337,3951 ,4126,4125,6528 }, - {6306,6336,6335 ,5669,5670,6534 }, {1729,4153,5993 ,3666,5711,6475 }, - {249,6103,1158 ,644,4220,2744 }, {6103,249,5988 ,4220,644,2516 }, - {4642,6022,5670 ,6226,6535,6227 }, {5533,6172,6195 ,6239,5451,5529 }, - {6239,6223,6055 ,5918,6151,3874 }, {2960,5388,5949 ,4975,5428,5086 }, - {6043,5351,5318 ,6498,6513,6039 }, {5318,3386,3360 ,6039,6491,6485 }, - {3386,3409,5472 ,6491,6490,6301 }, {297,1416,140 ,1918,6100,1919 }, - {3902,685,3935 ,4437,2674,4346 }, {5631,5453,5863 ,6536,937,6537 }, - {6045,5453,5631 ,935,937,6536 }, {4515,6207,6206 ,30,6156,6464 }, - {5879,5417,5987 ,6220,5923,5621 }, {6050,6086,6096 ,4094,6516,4092 }, - {101,6196,6204 ,5,4,4050 }, {253,6228,751 ,2564,1366,1365 }, - {3679,5351,6006 ,6447,6513,6496 }, {3715,5851,5609 ,6124,6095,5658 }, - {3360,5450,3410 ,6485,6525,6483 }, {3410,5450,2204 ,6483,6525,6520 }, - {5450,6032,2204 ,6525,6489,6520 }, {3608,3583,6067 ,5799,5772,6266 }, - {6206,6241,6240 ,6464,6410,5756 }, {6024,6023,3410 ,6482,6040,6483 }, - {3411,1741,5392 ,4280,5695,4022 }, {1700,323,706 ,6072,4767,4784 }, - {6212,6213,6247 ,5562,6459,5575 }, {1022,793,1051 ,4198,4200,4588 }, - {6195,6172,5920 ,5529,5451,5453 }, {3658,5853,6023 ,6521,6038,6040 }, - {5928,6236,3879 ,4072,6538,2549 }, {6213,6256,6255 ,6459,5657,6102 }, - {6247,6213,6255 ,5575,6459,6102 }, {5515,6045,6038 ,5567,935,6264 }, - {6038,6045,5631 ,6264,935,6536 }, {6210,6245,6244 ,5566,5560,5667 }, - {4540,4515,6206 ,19,30,6464 }, {3797,5875,6139 ,2061,6434,2059 }, - {5893,1008,3414 ,6425,6427,4934 }, {6897,8112,8079 ,54,3530,55 }, - {5294,6010,5692 ,5891,6197,6229 }, {4278,4306,4277 ,5583,4552,4532 }, - {3563,1510,3497 ,6074,3788,5738 }, {2896,3563,3497 ,6110,6074,5738 }, - {5415,41,5390 ,5951,6533,3205 }, {4422,4391,6212 ,5561,992,5562 }, - {6074,3515,501 ,6539,1357,4313 }, {3470,5917,3079 ,6401,6402,6540 }, - {2657,1854,3506 ,2185,2184,6492 }, {7719,7697,7744 ,6541,651,6101 }, - {3879,6236,5317 ,2549,6538,6508 }, {3410,2204,5486 ,6483,6520,5718 }, - {3597,3546,3598 ,1810,2557,802 }, {5486,2204,3311 ,5718,6520,5303 }, - {262,5997,970 ,4758,6529,268 }, {359,262,970 ,4841,4758,268 }, - {5997,6019,6018 ,6529,6542,340 }, {6019,4304,6018 ,6542,4579,340 }, - {2318,8049,2319 ,3185,5393,3228 }, {959,3515,535 ,1358,1357,2001 }, - {5940,5926,3714 ,1625,6419,3970 }, {6224,6213,4391 ,6458,6459,992 }, - {1158,6103,252 ,2744,4220,2743 }, {5489,5474,5911 ,4244,4243,5924 }, - {6005,5515,5117 ,5691,5567,1113 }, {6209,6210,6244 ,6012,5566,5667 }, - {6245,6273,6272 ,5560,5683,5755 }, {6243,5356,6271 ,5666,4258,6152 }, - {6206,6207,6241 ,6464,6156,6410 }, {6204,6196,6203 ,4050,4,1249 }, - {5449,5314,3523 ,6543,6411,6544 }, {5951,2321,3509 ,6000,5999,6519 }, - {5934,5370,6091 ,616,2171,2173 }, {1510,5862,747 ,3788,3790,5692 }, - {3497,1510,747 ,5738,3788,5692 }, {949,5029,1083 ,2133,2159,2095 }, - {6138,6139,6250 ,6014,2059,6532 }, {808,556,2960 ,4734,4043,4975 }, - {4292,4517,4374 ,6400,6484,5712 }, {5416,3599,5302 ,6461,6428,3795 }, - {4144,5175,5985 ,4761,6384,5365 }, {5953,6000,3870 ,5659,6094,6096 }, - {7856,7855,7803 ,4635,6545,4636 }, {6061,465,4304 ,6546,4578,4579 }, - {5988,249,20 ,2516,644,3961 }, {6061,501,465 ,6546,4313,4578 }, - {5934,6091,5980 ,616,2173,5557 }, {1729,3517,4286 ,3666,6503,4274 }, - {5213,5214,5234 ,428,6272,6273 }, {6005,5117,186 ,5691,1113,1265 }, - {6244,6245,6272 ,5667,5560,5755 }, {6273,5880,5663 ,5683,5700,4259 }, - {6272,6273,5663 ,5755,5683,4259 }, {5956,6151,5951 ,6240,6024,6000 }, - {6203,6196,6239 ,1249,4,5918 }, {3629,3524,5160 ,5965,6187,6186 }, - {3523,3629,5160 ,6544,5965,6186 }, {5329,5711,6033 ,6191,6248,5620 }, - {6076,5329,6033 ,4217,6191,5620 }, {5576,5475,5876 ,4039,4038,2146 }, - {5530,5915,3870 ,6189,6120,6096 }, {5924,1696,6042 ,6091,6547,5703 }, - {3436,5576,5876 ,2145,4039,2146 }, {5475,5489,5876 ,4038,4244,2146 }, - {843,706,46 ,2423,4784,2232 }, {5302,3599,5706 ,3795,6428,3796 }, - {5895,5749,3731 ,6053,6052,6041 }, {6145,5925,5899 ,6514,5710,6548 }, - {5195,5213,5212 ,6235,428,430 }, {6004,5963,5871 ,6123,6409,4124 }, - {1125,2142,4528 ,5723,4936,4935 }, {706,806,807 ,4784,4783,6073 }, - {882,3396,3271 ,3846,3867,1727 }, {262,5998,5997 ,4758,6549,6529 }, - {5998,6020,6019 ,6549,6550,6542 }, {5997,5998,6019 ,6529,6549,6542 }, - {6020,6021,4304 ,6550,6551,4579 }, {6019,6020,4304 ,6542,6550,4579 }, - {6048,6061,4304 ,6552,6546,4579 }, {6021,6048,4304 ,6551,6552,4579 }, - {6074,501,6061 ,6539,4313,6546 }, {6048,6074,6061 ,6552,6539,6546 }, - {3632,3628,5703 ,5898,4213,5748 }, {6118,5753,5863 ,2074,6481,6537 }, - {5861,5870,5939 ,6453,4275,4276 }, {5453,6118,5863 ,937,2074,6537 }, - {3829,5475,3217 ,6195,4038,6117 }, {6012,6013,5963 ,6408,6060,6409 }, - {6129,6130,3951 ,5983,6300,6528 }, {5123,6129,3951 ,6433,5983,6528 }, - {5789,5386,6258 ,6140,5870,6553 }, {6217,5355,5703 ,6554,6555,5748 }, - {5881,5530,3870 ,6109,6189,6096 }, {6174,6234,6002 ,2381,5973,5975 }, - {1701,1700,2896 ,6476,6072,6110 }, {5875,5490,3444 ,6434,6055,6054 }, - {5528,5416,5302 ,6143,6461,3795 }, {5749,5922,3731 ,6052,4292,6041 }, - {5891,5876,5933 ,5714,2146,615 }, {938,803,322 ,983,144,1250 }, - {5869,3680,4094 ,6224,6497,6225 }, {5903,2912,2357 ,6480,3934,3933 }, - {1153,3012,2624 ,2245,3491,3132 }, {3599,5893,5706 ,6428,6425,3796 }, - {6222,6223,6239 ,6253,6151,5918 }, {6229,5987,5608 ,6556,5621,4356 }, - {4094,3680,4642 ,6225,6497,6226 }, {6577,3816,4426 ,97,5623,1056 }, - {262,670,5998 ,4758,4760,6549 }, {6048,3515,6074 ,6552,1357,6539 }, - {6035,6038,5654 ,6025,6264,6026 }, {5974,6003,3470 ,6474,6122,6401 }, - {5631,5863,6188 ,6536,6537,6174 }, {5654,5631,6188 ,6026,6536,6174 }, - {4292,3525,6058 ,6400,5665,6460 }, {6013,5956,5963 ,6060,6240,6409 }, - {5872,6051,6130 ,6557,6037,6300 }, {6129,5872,6130 ,5983,6557,6300 }, - {5530,5905,5915 ,6189,6142,6120 }, {1293,532,746 ,5764,5766,2661 }, - {6250,5875,3444 ,6532,6434,6054 }, {5953,6135,6000 ,5659,6258,6094 }, - {3446,3781,5487 ,3718,5849,6558 }, {5301,3631,5384 ,2698,5922,6121 }, - {686,2357,6086 ,5770,3933,6516 }, {5749,3747,6249 ,6052,2925,4032 }, - {6227,5361,758 ,6416,5664,5663 }, {7745,7744,7697 ,650,6101,651 }, - {670,5985,5998 ,4760,5365,6549 }, {6021,6020,5998 ,6551,6550,6549 }, - {6048,6085,3515 ,6552,6559,1357 }, {5628,4642,405 ,6560,6226,5662 }, - {7886,2295,2263 ,6561,3160,3080 }, {6164,6165,7062 ,6562,4219,6563 }, - {3856,5995,1268 ,5754,5564,4568 }, {3856,6013,6012 ,5754,6060,6408 }, - {5995,3856,6012 ,5564,5754,6408 }, {1121,5979,6051 ,6564,6028,6037 }, - {5872,1121,6051 ,6557,6564,6037 }, {3606,4164,1410 ,6137,6139,3911 }, - {5216,5235,5215 ,6323,6385,6313 }, {5475,3829,5877 ,4038,6195,4242 }, - {5686,5747,5651 ,5777,6036,5920 }, {5253,5302,3779 ,6163,3795,6565 }, - {2142,3779,6031 ,4936,6565,6429 }, {1608,421,746 ,4128,5815,2661 }, - {7802,7826,7801 ,6566,1616,1618 }, {3973,5388,636 ,6007,5428,6020 }, - {3989,3366,5252 ,5822,5894,5746 }, {1608,1293,421 ,4128,5764,5815 }, - {6086,2357,6096 ,6516,3933,4092 }, {3822,6044,3576 ,5715,614,5890 }, - {1153,8123,1332 ,2245,2247,3492 }, {3758,3712,3714 ,1789,1439,3970 }, - {5670,6022,3787 ,6227,6535,5819 }, {6135,5851,6000 ,6258,6095,6094 }, - {6172,5124,6146 ,5451,6567,6568 }, {4045,5654,4425 ,5916,6026,6268 }, - {3926,3970,3925 ,3125,3225,3227 }, {5175,5998,5985 ,6384,6549,5365 }, - {5175,5494,5998 ,6384,6569,6549 }, {5494,6021,5998 ,6569,6551,6549 }, - {6049,6048,6021 ,6570,6552,6551 }, {2260,6049,6021 ,6571,6570,6551 }, - {6085,6100,3515 ,6559,6572,1357 }, {3515,6100,535 ,1357,6572,2001 }, - {3548,5876,5489 ,6013,2146,4244 }, {5898,5515,6038 ,5706,5567,6264 }, - {1272,3856,1268 ,5740,5754,4568 }, {4164,5449,5540 ,6139,6543,6162 }, - {1661,6269,3611 ,5672,6083,5673 }, {3039,5526,5567 ,2686,6256,6413 }, - {6209,6244,6243 ,6012,5667,5666 }, {2621,5704,3683 ,5416,5579,5417 }, - {5323,5325,5324 ,5701,5655,5986 }, {4528,2159,1125 ,4935,6440,5723 }, - {3953,6124,3715 ,5713,6511,6124 }, {3891,3855,6847 ,3820,1511,4004 }, - {5494,5175,5020 ,6569,6384,6373 }, {1214,6085,6048 ,6573,6559,6552 }, - {1214,6101,6100 ,6573,6574,6572 }, {6085,1214,6100 ,6559,6573,6572 }, - {6101,6121,535 ,6574,6575,2001 }, {6100,6101,535 ,6572,6574,2001 }, - {6140,6153,535 ,2333,5514,2001 }, {6121,6140,535 ,6575,2333,2001 }, - {6140,3704,5040 ,2333,2332,5469 }, {6196,713,6197 ,4,3,6252 }, - {3584,6112,6078 ,5888,6406,6522 }, {6017,5912,3581 ,6506,5892,6504 }, - {5934,5489,5932 ,616,4244,5925 }, {1410,4164,5540 ,3911,6139,6162 }, - {5610,5630,5609 ,6153,4874,5658 }, {4167,5957,6063 ,6173,4054,5685 }, - {6136,4028,5824 ,5810,5823,6517 }, {3328,3288,3307 ,3973,2058,2057 }, - {6104,5858,3436 ,5696,4041,2145 }, {5976,5927,5925 ,5903,5318,5710 }, - {6228,253,2663 ,1366,2564,3593 }, {5905,5416,5528 ,6142,6461,6143 }, - {6008,5706,3779 ,3797,3796,6565 }, {5706,3414,2142 ,3796,4934,4936 }, - {5931,5928,3915 ,6576,4072,1575 }, {4308,5931,3915 ,6577,6576,1575 }, - {5931,6237,6236 ,6576,6578,6538 }, {6003,6001,5917 ,6122,6221,6402 }, - {758,3525,3688 ,5663,5665,5574 }, {1627,758,3688 ,5573,5663,5574 }, - {5929,5045,3628 ,6029,4214,4213 }, {7240,7239,7220 ,4312,1527,4367 }, - {6153,6140,5040 ,5514,2333,5469 }, {5979,1121,6125 ,6028,6564,4395 }, - {6078,6112,3508 ,6522,6406,6505 }, {5904,6189,3621 ,5851,6579,625 }, - {5849,5578,6189 ,5853,587,6579 }, {5904,5849,6189 ,5851,5853,6579 }, - {3583,5652,5651 ,5772,5774,5920 }, {5166,5120,5167 ,3427,5857,5856 }, - {5608,3472,3007 ,4356,3155,818 }, {5982,6229,5608 ,4218,6556,4356 }, - {5193,5252,4466 ,5846,5746,5854 }, {5326,5325,6041 ,3714,5655,3801 }, - {5322,5695,6145 ,4297,6465,6514 }, {4465,6210,6209 ,257,5566,6012 }, - {5928,5931,6236 ,4072,6576,6538 }, {3561,5317,6236 ,6580,6508,6538 }, - {6237,3561,6236 ,6578,6580,6538 }, {4260,4278,4277 ,3527,5583,4532 }, - {5384,5403,6016 ,6121,5921,6228 }, {5846,257,5086 ,6065,6067,6064 }, - {5303,5670,5981 ,5737,6227,6415 }, {3525,5885,5345 ,5665,6502,6438 }, - {5942,5382,5317 ,6581,6509,6508 }, {3561,5942,5317 ,6580,6581,6508 }, - {4488,4154,5382 ,6582,6510,6509 }, {3007,1696,5924 ,818,6547,6091 }, - {1811,1810,1750 ,777,779,745 }, {6621,5629,6605 ,5552,5162,5164 }, - {6058,3525,5345 ,6460,5665,6438 }, {5961,3560,5935 ,6456,5779,5778 }, - {5487,3781,5417 ,6558,5849,5923 }, {5904,3621,4200 ,5851,625,6583 }, - {7128,7129,7160 ,5391,1026,6271 }, {5302,6008,3779 ,3795,3797,6565 }, - {3472,4486,3007 ,3155,819,818 }, {5962,3469,4466 ,5745,5860,5854 }, - {3659,5314,5449 ,3875,6411,6543 }, {5314,3629,3523 ,6411,5965,6544 }, - {4164,3659,5449 ,6139,3875,6543 }, {6001,6081,6181 ,6221,6223,6251 }, - {5942,4488,5382 ,6581,6582,6509 }, {6026,5868,4154 ,6584,6527,6510 }, - {4488,6026,4154 ,6582,6584,6510 }, {3386,168,3409 ,6491,6585,6490 }, - {6148,6161,5868 ,6586,6530,6527 }, {4153,3953,5993 ,5711,5713,6475 }, - {7351,7403,7402 ,6587,6588,6589 }, {1,1022,6202 ,4622,4198,6590 }, - {2896,3845,1949 ,6110,3635,3637 }, {5963,5956,3337 ,6409,6240,4125 }, - {5933,6044,3822 ,615,614,5715 }, {5890,5686,5713 ,6591,5777,5776 }, - {5947,6230,5876 ,6027,2144,2146 }, {6014,6083,6015 ,6592,3989,3988 }, - {7129,7128,7101 ,1026,5391,4073 }, {6196,6222,6239 ,4,6253,5918 }, - {3409,3443,5472 ,6490,6302,6301 }, {3701,6149,5922 ,733,732,4292 }, - {6132,5929,3628 ,5897,6029,4213 }, {7370,7343,7344 ,3750,2750,2749 }, - {5930,7058,5979 ,6593,6594,6028 }, {3666,6068,6137 ,5699,5896,5809 }, - {5939,5649,5865 ,4276,6093,6092 }, {3836,5939,5865 ,6103,4276,6092 }, - {5608,3007,5924 ,4356,818,6091 }, {5982,5608,5924 ,4218,4356,6091 }, - {601,3286,2990 ,3905,56,3646 }, {5663,6136,5909 ,4259,5810,4260 }, - {5952,5991,3620 ,6595,5482,6001 }, {4147,20,3506 ,2517,3961,6492 }, - {6034,5952,3620 ,6049,6595,6001 }, {3012,1153,1332 ,3491,2245,3492 }, - {6026,6148,5868 ,6584,6586,6527 }, {249,348,20 ,644,643,3961 }, - {6161,6599,6187 ,6530,6596,6531 }, {5910,6354,5590 ,5121,6597,6386 }, - {6249,3701,5922 ,4032,733,4292 }, {5915,5975,6072 ,6120,6161,6155 }, - {3804,3832,3831 ,4324,2322,2321 }, {3831,3803,3804 ,2321,6436,4324 }, - {3929,5999,4166 ,5024,5184,6084 }, {3838,5999,1252 ,6257,5184,5023 }, - {6140,6101,6122 ,2333,6574,1797 }, {6295,6553,3283 ,1290,780,262 }, - {6219,6191,6220 ,6598,6599,6600 }, {6660,2138,6219 ,6601,6602,6598 }, - {5185,3632,5703 ,5939,5898,5748 }, {5355,5185,5703 ,6555,5939,5748 }, - {7909,7886,2263 ,6603,6561,3080 }, {3834,1298,6386 ,4083,5088,4085 }, - {5621,5560,1164 ,6604,6605,5087 }, {1298,5621,1164 ,5088,6604,5087 }, - {5913,5076,5560 ,6606,6607,6605 }, {5621,5913,5560 ,6604,6606,6605 }, - {5913,5919,5904 ,6606,6608,5851 }, {5076,5913,5904 ,6607,6606,5851 }, - {5919,5369,5904 ,6608,6609,5851 }, {5320,6053,6145 ,4464,4463,6514 }, - {4623,5939,3836 ,6452,4276,6103 }, {5782,4623,3836 ,5693,6452,6103 }, - {6248,5609,6213 ,6154,5658,6459 }, {3787,6159,5918 ,5819,5082,5820 }, - {1696,3007,3582 ,6547,818,1378 }, {3607,6073,4164 ,6138,3873,6139 }, - {5962,3608,3469 ,5745,5799,5860 }, {6034,3620,6175 ,6049,6001,6004 }, - {5602,3822,5964 ,5716,5715,6507 }, {5964,3576,6017 ,6507,5890,6506 }, - {5706,5893,3414 ,3796,6425,4934 }, {5247,6145,5899 ,4096,6514,6548 }, - {5253,3779,5896 ,6163,6565,6176 }, {5896,3779,4648 ,6176,6565,5722 }, - {3292,3294,3308 ,4067,3895,3894 }, {4485,6209,6208 ,32,6012,6011 }, - {6169,6191,6190 ,2334,6599,6610 }, {6190,6191,6219 ,6610,6599,6598 }, - {3522,6059,5906 ,6451,6446,6417 }, {5452,3905,5386 ,2714,4194,5870 }, - {5449,3523,3893 ,6543,6544,3789 }, {5540,5449,3893 ,6162,6543,3789 }, - {3523,5160,5861 ,6544,6186,6453 }, {3893,3523,5861 ,3789,6544,6453 }, - {7286,7344,7285 ,3460,2749,2751 }, {747,5862,5782 ,5692,3790,5693 }, - {5862,4623,5782 ,3790,6452,5693 }, {6159,3609,5918 ,5082,5081,5820 }, - {806,6073,3607 ,4783,3873,6138 }, {6203,6239,6238 ,1249,5918,5919 }, - {6034,6175,5889 ,6049,6004,1587 }, {6179,3575,3906 ,6486,5887,5697 }, - {5205,4178,5248 ,5219,3825,6469 }, {7973,8020,7972 ,3624,1405,6059 }, - {6170,3725,3537 ,3719,3971,1735 }, {7568,7567,7508 ,5544,5545,6196 }, - {187,1171,3498 ,6439,6441,5800 }, {7311,7310,7287 ,4334,4283,3459 }, - {6076,3248,5870 ,4217,4216,4275 }, {5969,6076,5870 ,6188,4217,4275 }, - {5969,5870,5861 ,6188,4275,6453 }, {5160,5969,5861 ,6186,6188,6453 }, - {5937,1298,3834 ,6611,5088,4083 }, {4044,5937,3834 ,4322,6611,4083 }, - {5937,1382,1298 ,6611,6612,5088 }, {1298,1382,5621 ,5088,6612,6604 }, - {1382,6047,5913 ,6612,6613,6606 }, {5621,1382,5913 ,6604,6612,6606 }, - {6047,5603,5913 ,6613,6614,6606 }, {5913,5603,5919 ,6606,6614,6608 }, - {5402,5369,5919 ,6615,6609,6608 }, {5603,5402,5919 ,6614,6615,6608 }, - {5687,6065,5369 ,6420,6616,6609 }, {5402,5687,5369 ,6615,6420,6609 }, - {2912,5903,1379 ,3934,6480,4137 }, {3620,5907,3860 ,6001,6116,6523 }, - {5703,6165,1464 ,5748,4219,5768 }, {5602,5964,3508 ,5716,6507,6505 }, - {3507,5602,3508 ,5671,5716,6505 }, {3773,3812,3811 ,4279,1513,4323 }, - {537,5567,5955 ,4834,6413,6512 }, {5610,3715,5609 ,6153,6124,5658 }, - {6292,6060,6282 ,5403,5914,6617 }, {7509,7568,7508 ,1874,5544,6196 }, - {381,3930,4247 ,6450,6467,6468 }, {6154,6182,6169 ,2387,6618,2334 }, - {6169,6182,6191 ,2334,6618,6599 }, {5072,4044,6261 ,6619,4322,4321 }, - {3527,5687,5402 ,6620,6420,6615 }, {158,4200,3621 ,5258,6583,625 }, - {2582,1017,3451 ,873,1793,1720 }, {6089,5888,6050 ,6494,5752,4094 }, - {6165,6164,1464 ,4219,6562,5768 }, {6073,3659,4164 ,3873,3875,6139 }, - {2160,5328,5370 ,6621,2172,2171 }, {5956,5860,6151 ,6240,5998,6024 }, - {6038,5631,5654 ,6264,6536,6026 }, {6147,6172,6146 ,5452,5451,6568 }, - {6013,3943,5956 ,6060,4755,6240 }, {422,1701,216 ,4689,6476,4644 }, - {5126,4447,5563 ,6170,717,4605 }, {3018,5905,5530 ,6125,6142,6189 }, - {5294,5692,5912 ,5891,6229,5892 }, {6056,5478,5883 ,5808,5806,5850 }, - {4278,4308,4307 ,5583,6577,4562 }, {5878,5892,5549 ,2684,2683,6435 }, - {5462,5961,5935 ,6418,6456,5778 }, {3725,6170,6182 ,3971,3719,6618 }, - {6154,3725,6182 ,2387,3971,6618 }, {6170,6192,6191 ,3719,6622,6599 }, - {6182,6170,6191 ,6618,3719,6599 }, {6192,6200,6191 ,6622,6623,6599 }, - {6191,6200,6220 ,6599,6623,6600 }, {6200,6231,6220 ,6623,6624,6600 }, - {7851,7850,7825 ,6625,3769,3768 }, {6047,1382,5603 ,6613,6612,6614 }, - {5247,5899,5227 ,4096,6548,4097 }, {5703,1464,932 ,5748,5768,5765 }, - {5246,6134,6039 ,5176,2729,2728 }, {5980,6010,5294 ,5557,6197,5891 }, - {6028,6029,3860 ,5316,1454,6523 }, {5958,3507,3508 ,5702,5671,6505 }, - {6112,5958,3508 ,6406,5702,6505 }, {3631,5487,5417 ,5922,6558,5923 }, - {1723,5476,1261 ,6626,6495,6472 }, {4307,4308,3915 ,4562,6577,1575 }, - {2321,3262,3509 ,5999,6627,6519 }, {3471,5627,3262 ,4104,6628,6627 }, - {6177,3471,3262 ,6629,4104,6627 }, {6246,3666,6274 ,5559,5699,5684 }, - {5947,5948,5717 ,6027,5719,4023 }, {5876,3548,5933 ,2146,6013,615 }, - {4541,3631,3079 ,6630,5922,6540 }, {6192,6170,6200 ,6622,3719,6623 }, - {6231,6262,5072 ,6624,6631,6619 }, {3982,4044,5072 ,6632,4322,6619 }, - {6262,3982,5072 ,6631,6632,6619 }, {4044,3982,5937 ,4322,6632,6611 }, - {3982,1007,1382 ,6632,6633,6612 }, {5937,3982,1382 ,6611,6632,6612 }, - {5484,5603,1382 ,6634,6614,6612 }, {1007,5484,1382 ,6633,6634,6612 }, - {6106,5402,5603 ,6635,6615,6614 }, {5484,6106,5603 ,6634,6635,6614 }, - {5748,3527,5402 ,6636,6620,6615 }, {6106,5748,5402 ,6635,6636,6615 }, - {4653,4600,4679 ,4347,4360,3852 }, {6523,5367,5349 ,5319,6034,5320 }, - {6057,5935,5524 ,6423,5778,6426 }, {966,5526,3039 ,2565,6256,2686 }, - {806,3607,6267 ,4783,6138,6407 }, {5588,3835,5550 ,6088,6046,6047 }, - {1293,6217,932 ,5764,6554,5765 }, {3415,5488,5246 ,6115,2730,5176 }, - {5911,5474,5932 ,5924,4243,5925 }, {1661,6111,6179 ,5672,5674,6486 }, - {635,2938,5534 ,2183,4320,6524 }, {6050,3765,5394 ,4094,4093,5660 }, - {4425,6177,3262 ,6268,6629,6627 }, {2321,4425,3262 ,5999,6268,6627 }, - {5534,1629,5971 ,6524,4207,6479 }, {2938,1629,5534 ,4320,4207,6524 }, - {2204,5867,5866 ,6520,6499,5302 }, {7291,7268,7316 ,3774,3773,5948 }, - {6213,6212,4391 ,6459,5562,992 }, {3631,4541,5487 ,5922,6630,6558 }, - {6170,6193,6200 ,3719,6637,6623 }, {6262,6231,3982 ,6631,6624,6632 }, - {3982,3667,1007 ,6632,6638,6633 }, {6011,5484,1007 ,6639,6634,6633 }, - {5484,5748,6106 ,6634,6636,6635 }, {5451,3446,5608 ,6219,3718,4356 }, - {6217,5703,932 ,6554,5748,5765 }, {3415,6186,5488 ,6115,4365,2730 }, - {5899,5925,5227 ,6548,5710,4097 }, {3560,5853,3658 ,5779,6038,6521 }, - {4153,4292,4374 ,5711,6400,5712 }, {5559,5687,3527 ,6640,6420,6620 }, - {1741,4466,6104 ,5695,5854,5696 }, {955,377,5787 ,3991,4311,4305 }, - {5302,5253,5975 ,3795,6163,6161 }, {5860,4045,2321 ,5998,5916,5999 }, - {3248,5982,5649 ,4216,4218,6093 }, {1261,3979,5591 ,6472,6471,3597 }, - {1629,1379,5971 ,4207,4137,6479 }, {3575,6179,3584 ,5887,6486,5888 }, - {5886,5887,6087 ,6192,6493,6193 }, {2645,3041,3535 ,4418,3182,442 }, - {3451,6183,6170 ,1720,6641,3719 }, {6183,6193,6170 ,6641,6637,3719 }, - {6193,6221,6200 ,6637,6642,6623 }, {6200,6221,6231 ,6623,6642,6624 }, - {3982,6127,3667 ,6632,6643,6638 }, {6127,1058,1007 ,6643,6644,6633 }, - {3667,6127,1007 ,6638,6643,6633 }, {6097,6011,1007 ,6645,6639,6633 }, - {1058,6097,1007 ,6644,6645,6633 }, {5460,5484,6011 ,6646,6634,6639 }, - {6097,5460,6011 ,6645,6646,6639 }, {1608,5992,1293 ,4128,4197,5764 }, - {5355,6217,1293 ,6555,6554,5764 }, {3558,6078,3581 ,5964,6522,6504 }, - {5957,5824,4105 ,4054,6517,4053 }, {5627,6184,6128 ,6628,6089,5981 }, - {4045,4425,2321 ,5916,6268,5999 }, {6104,5254,5858 ,5696,4042,4041 }, - {5824,4028,3411 ,6517,5823,4280 }, {5455,6509,5013 ,686,1452,684 }, - {5322,6145,4023 ,4297,6514,3827 }, {5971,1379,5903 ,6479,4137,6480 }, - {5627,6128,3509 ,6628,5981,6519 }, {3262,5627,3509 ,6627,6628,6519 }, - {6044,5294,3576 ,614,5891,5890 }, {572,571,475 ,1947,1885,1884 }, - {1605,6197,713 ,17,6252,3 }, {3041,3618,3535 ,3182,37,442 }, - {3451,6194,6193 ,1720,6647,6637 }, {6183,3451,6193 ,6641,1720,6637 }, - {6194,6201,6221 ,6647,6648,6642 }, {6193,6194,6221 ,6637,6647,6642 }, - {6232,6231,6221 ,6649,6624,6642 }, {6201,6232,6221 ,6648,6649,6642 }, - {6232,1746,3982 ,6649,6650,6632 }, {6231,6232,3982 ,6624,6649,6632 }, - {3982,1746,6127 ,6632,6650,6643 }, {6025,5748,5484 ,6651,6636,6634 }, - {5460,6025,5484 ,6646,6651,6634 }, {3716,5559,5748 ,6652,6640,6636 }, - {6025,3716,5748 ,6651,6652,6636 }, {5629,5048,5559 ,5162,6421,6640 }, - {3716,5629,5559 ,6652,5162,6640 }, {5992,5355,1293 ,4197,6555,5764 }, - {5580,3717,5630 ,6404,6487,4874 }, {5403,5417,5879 ,5921,5923,6220 }, - {6016,5403,5879 ,6228,5921,6220 }, {6150,1723,7053 ,6653,6626,6654 }, - {5909,5824,4167 ,4260,6517,6173 }, {6270,6271,3780 ,6082,6152,6526 }, - {6142,5854,3632 ,5941,6265,5898 }, {1605,6205,6223 ,17,6463,6151 }, - {6223,6205,6254 ,6151,6463,5758 }, {6055,5129,3659 ,3874,5698,3875 }, - {5705,5592,4567 ,4127,3671,6655 }, {5228,5205,5247 ,4095,5219,4096 }, - {5291,6148,6026 ,6656,6586,6584 }, {5232,5277,5255 ,6238,6237,3682 }, - {4444,6211,6210 ,582,5558,5566 }, {5011,5457,1252 ,6657,6308,5023 }, - {3443,5886,5869 ,6302,6192,6224 }, {3943,4045,5860 ,4755,5916,5998 }, - {3845,5319,6216 ,3635,5739,6658 }, {3953,4374,3018 ,5713,5712,6125 }, - {2291,350,2342 ,1115,1114,5690 }, {35,6228,2663 ,1338,1366,3593 }, - {3451,6171,6194 ,1720,6659,6647 }, {5912,5692,5329 ,5892,6229,6191 }, - {5632,5912,5329 ,6660,5892,6191 }, {5965,5632,5329 ,6190,6660,6191 }, - {3629,3581,3524 ,5965,6504,6187 }, {3471,6150,1219 ,4104,6653,4102 }, - {5854,6131,3632 ,6265,6050,5898 }, {6197,1605,6223 ,6252,17,6151 }, - {1605,4540,6206 ,17,19,6464 }, {6196,6197,6222 ,4,6252,6253 }, - {2636,5386,5789 ,2712,5870,6140 }, {5457,5020,4241 ,6308,6373,6321 }, - {5020,5457,5011 ,6373,6308,6657 }, {5973,5871,6110 ,6246,4124,6247 }, - {42,297,6783 ,5195,1918,3632 }, {5907,3415,5246 ,6116,6115,5176 }, - {5925,5927,5227 ,5710,5318,4097 }, {4572,3638,8038 ,5949,5950,4121 }, - {5987,6229,5982 ,5621,6556,4218 }, {6188,5863,5916 ,6174,6537,6175 }, - {6093,6086,6050 ,5771,6516,4094 }, {3443,5887,5886 ,6302,6493,6192 }, - {6171,3451,1017 ,6659,1720,1793 }, {6201,6194,6171 ,6648,6647,6659 }, - {6263,873,1746 ,6661,6662,6650 }, {6232,6263,1746 ,6649,6661,6650 }, - {873,6109,6127 ,6662,6663,6643 }, {1746,873,6127 ,6650,6662,6643 }, - {6109,4046,1058 ,6663,6664,6644 }, {6127,6109,1058 ,6643,6663,6644 }, - {3045,6097,1058 ,6665,6645,6644 }, {4046,3045,1058 ,6664,6665,6644 }, - {5900,5460,6097 ,6666,6646,6645 }, {3045,5900,6097 ,6665,6666,6645 }, - {5900,5448,5460 ,6666,6667,6646 }, {5381,6025,5460 ,6668,6651,6646 }, - {5448,5381,5460 ,6667,6668,6646 }, {7976,7975,7952 ,1715,6669,5475 }, - {5251,6041,5273 ,3802,3801,3819 }, {5692,6016,5879 ,6229,6228,6220 }, - {5329,5692,5879 ,6191,6229,6220 }, {6090,5874,6053 ,4897,4896,4463 }, - {6029,5976,6066 ,1454,5903,1455 }, {5996,5705,4567 ,6249,4127,6655 }, - {3582,3660,5362 ,1378,709,6670 }, {6205,6240,6254 ,6463,5756,5758 }, - {5863,5753,5916 ,6537,6481,6175 }, {5849,1124,5578 ,5853,5852,587 }, - {6212,6247,6246 ,5562,5575,5559 }, {6211,6212,6246 ,5558,5562,5559 }, - {5567,537,2040 ,6413,4834,4833 }, {4484,4465,6209 ,258,257,6012 }, - {262,359,210 ,4758,4841,4592 }, {1455,5202,808 ,1917,5550,4734 }, - {2140,4565,5447 ,5635,5944,5633 }, {6149,3648,3445 ,732,734,1791 }, - {3385,3836,5921 ,6104,6103,5705 }, {6269,6270,3611 ,6083,6082,5673 }, - {1854,5971,5368 ,2184,6479,5751 }, {5124,3970,6146 ,6567,3225,6568 }, - {3611,6063,6111 ,5673,5685,5674 }, {6157,6171,1017 ,5569,6659,1793 }, - {6157,4063,6171 ,5569,4733,6659 }, {6202,6201,6171 ,6590,6648,6659 }, - {4063,6202,6171 ,4733,6590,6659 }, {6202,6233,6232 ,6590,6671,6649 }, - {6201,6202,6232 ,6648,6590,6649 }, {6232,6233,6263 ,6649,6671,6661 }, - {5183,3716,6025 ,6672,6652,6651 }, {5381,5183,6025 ,6668,6672,6651 }, - {5691,5629,3716 ,6673,5162,6652 }, {5183,5691,3716 ,6672,6673,6652 }, - {5691,5938,5629 ,6673,5163,5162 }, {6078,3508,3581 ,6522,6505,6504 }, - {6203,6238,806 ,1249,5919,4783 }, {7203,7220,7185 ,4366,4367,5073 }, - {3620,5946,5907 ,6001,5481,6116 }, {5533,6195,3609 ,6239,5529,5081 }, - {5992,5185,5355 ,4197,5939,6555 }, {3611,3780,6063 ,5673,6526,5685 }, - {3829,3051,5877 ,6195,6488,4242 }, {6024,5743,5646 ,6482,6432,6431 }, - {5526,252,5897 ,6256,2743,6414 }, {5368,5971,5901 ,5751,6479,6674 }, - {5368,5901,5888 ,5751,6674,5752 }, {808,4987,1455 ,4734,1491,1917 }, - {3606,1410,1510 ,6137,3911,3788 }, {5749,6249,5922 ,6052,4032,4292 }, - {2204,5866,5864 ,6520,5302,5304 }, {3780,4167,6063 ,6526,6173,5685 }, - {5884,3446,5451 ,5848,3718,6219 }, {4269,6199,4229 ,4860,4859,4877 }, - {1426,4063,6157 ,4648,4733,5569 }, {1,6202,4063 ,4622,6590,4733 }, - {8049,8035,8018 ,5393,6675,6676 }, {843,6203,806 ,2423,1249,4783 }, - {3581,5632,5965 ,6504,6660,6190 }, {3524,3581,5965 ,6187,6504,6190 }, - {5824,5957,4167 ,6517,4054,6173 }, {6179,6111,5575 ,6486,5674,5686 }, - {4485,4484,6209 ,32,258,6012 }, {5489,5475,5877 ,4244,4038,4242 }, - {7511,7510,7453 ,6677,1873,1187 }, {1700,422,81 ,6072,4689,4673 }, - {3900,552,8132 ,884,3929,413 }, {5129,3906,3575 ,5698,5697,5887 }, - {6037,3856,1272 ,5235,5754,5740 }, {75,107,930 ,3962,2548,3594 }, - {3688,4153,1729 ,5574,5711,3666 }, {253,1664,249 ,2564,2268,644 }, - {808,5941,4987 ,4734,4976,1491 }, {5941,5967,4987 ,4976,1352,1491 }, - {5876,5891,5948 ,2146,5714,5719 }, {5947,5876,5948 ,6027,2146,5719 }, - {3584,5575,6112 ,5888,5686,6406 }, {6057,5524,5994 ,6423,6426,6424 }, - {3801,5362,3660 ,4974,6670,709 }, {4147,3384,3409 ,2517,6518,6490 }, - {5986,306,1251 ,4603,6234,4604 }, {6202,6252,6233 ,6590,6678,6671 }, - {6233,6252,6263 ,6671,6678,6661 }, {6252,1484,873 ,6678,6679,6662 }, - {6263,6252,873 ,6661,6678,6662 }, {1484,5525,6109 ,6679,6680,6663 }, - {873,1484,6109 ,6662,6679,6663 }, {5525,5589,4046 ,6680,6681,6664 }, - {6109,5525,4046 ,6663,6680,6664 }, {1242,3045,4046 ,6682,6665,6664 }, - {5589,1242,4046 ,6681,6682,6664 }, {5539,5900,3045 ,6683,6666,6665 }, - {1242,5539,3045 ,6682,6683,6665 }, {5539,5448,5900 ,6683,6667,6666 }, - {5271,5381,5448 ,6684,6668,6667 }, {5539,5271,5448 ,6683,6684,6667 }, - {5271,5183,5381 ,6684,6672,6668 }, {5938,5502,5081 ,5163,1256,1258 }, - {806,6238,6073 ,4783,5919,3873 }, {6066,5976,5874 ,1455,5903,4896 }, - {5632,3581,5912 ,6660,6504,5892 }, {1696,3582,5362 ,6547,1378,6670 }, - {3524,5965,5969 ,6187,6190,6188 }, {6273,6274,5880 ,5683,5684,5700 }, - {3499,5394,5628 ,5661,5660,6560 }, {3547,3598,3546 ,803,802,2557 }, - {3879,3904,5928 ,2549,1264,4072 }, {6063,202,5575 ,5685,4105,5686 }, - {5981,6226,3905 ,6415,4192,4194 }, {3087,3131,3130 ,3573,3732,3414 }, - {5943,6283,7088 ,5402,4298,4299 }, {3629,3558,3581 ,5965,5964,6504 }, - {5316,3835,5588 ,6087,6046,6088 }, {3248,5649,5939 ,4216,6093,4276 }, - {7333,7332,3304 ,4353,6685,1050 }, {7208,7226,7225 ,1671,6686,1672 }, - {5949,5967,2960 ,5086,1352,4975 }, {2960,5967,5941 ,4975,1352,4976 }, - {6179,5575,3584 ,6486,5686,5888 }, {5345,5885,6057 ,6438,6502,6423 }, - {253,751,6228 ,2564,1365,1366 }, {168,4147,3409 ,6585,2517,6490 }, - {1022,1,969 ,4198,4622,4199 }, {3515,3719,501 ,1357,1356,4313 }, - {58,1332,8143 ,2156,3492,2570 }, {6202,1022,6252 ,6590,4198,6678 }, - {5176,5183,5271 ,6687,6672,6684 }, {6064,5691,5183 ,6688,6673,6672 }, - {5176,6064,5183 ,6687,6688,6672 }, {5502,5938,5691 ,1256,5163,6673 }, - {6064,5502,5691 ,6688,1256,6673 }, {6218,3560,3658 ,5780,5779,6521 }, - {5351,168,3386 ,6513,6585,6491 }, {4268,6199,4269 ,4848,4859,4860 }, - {6084,6087,3499 ,6194,6193,5661 }, {5361,5462,5935 ,5664,6418,5778 }, - {6087,5394,3499 ,6193,5660,5661 }, {3822,3576,5964 ,5715,5890,6507 }, - {3456,8083,5771 ,1145,2103,2868 }, {2263,2262,7909 ,3080,3359,6603 }, - {5824,3411,4105 ,6517,4280,4053 }, {5351,5513,168 ,6513,6500,6585 }, - {2206,5592,2224 ,176,3671,2660 }, {807,806,6267 ,6073,4783,6407 }, - {5513,4147,168 ,6500,2517,6585 }, {7923,7948,7896 ,816,3625,4355 }, - {2204,5864,3311 ,6520,5304,5303 }, {5129,3575,5293 ,5698,5887,5889 }, - {2663,783,35 ,3593,679,1338 }, {6252,6264,1484 ,6678,6689,6679 }, - {5754,5271,5539 ,6690,6684,6683 }, {5502,6064,5176 ,1256,6688,6687 }, - {5854,3951,6130 ,6265,6528,6300 }, {6051,6132,6130 ,6037,5897,6300 }, - {5211,5191,6433 ,6071,2900,6691 }, {5695,5320,6145 ,6465,4464,6514 }, - {2573,2660,3569 ,3253,455,4381 }, {4485,6208,6207 ,32,6011,6156 }, - {4517,4292,6058 ,6484,6400,6460 }, {6266,1700,3563 ,399,6072,6074 }, - {3870,5915,3686 ,6096,6120,6119 }, {5932,5370,5934 ,5925,2171,616 }, - {422,1700,1701 ,4689,6072,6476 }, {4321,6225,4343 ,4873,4872,1818 }, - {4356,166,4404 ,155,3729,5072 }, {5978,6114,5195 ,5581,1805,6235 }, - {5212,5978,5195 ,430,5581,6235 }, {4246,4247,1729 ,3665,6468,3666 }, - {5314,5293,3629 ,6411,5889,5965 }, {5528,5302,5712 ,6143,3795,6160 }, - {3797,3747,5490 ,2061,2925,6055 }, {4515,4485,6207 ,30,32,6156 }, - {5915,5820,5975 ,6120,6144,6161 }, {3679,5990,5351 ,6447,6692,6513 }, - {807,6267,3606 ,6073,6407,6137 }, {1022,6253,6252 ,4198,6693,6678 }, - {6253,6265,6264 ,6693,6694,6689 }, {6252,6253,6264 ,6678,6693,6689 }, - {6265,4189,1484 ,6694,6695,6679 }, {6264,6265,1484 ,6689,6694,6679 }, - {4189,5184,5525 ,6695,6696,6680 }, {1484,4189,5525 ,6679,6695,6680 }, - {5184,3874,5589 ,6696,6697,6681 }, {5525,5184,5589 ,6680,6696,6681 }, - {3908,1242,5589 ,6698,6682,6681 }, {3874,3908,5589 ,6697,6698,6681 }, - {3776,5539,1242 ,6699,6683,6682 }, {3908,3776,1242 ,6698,6699,6682 }, - {5780,5754,5539 ,6700,6690,6683 }, {3776,5780,5539 ,6699,6700,6683 }, - {4344,5271,5754 ,6701,6684,6690 }, {5780,4344,5754 ,6700,6701,6690 }, - {5968,5176,5271 ,6702,6687,6684 }, {4344,5968,5271 ,6701,6702,6684 }, - {5088,5502,5176 ,5004,1256,6687 }, {5968,5088,5176 ,6702,5004,6687 }, - {6240,1661,6268 ,5756,5672,5757 }, {1723,6150,3471 ,6626,6653,4104 }, - {5476,1723,3471 ,6495,6626,4104 }, {4367,6224,4391 ,228,6458,992 }, - {5233,5978,5212 ,429,5581,430 }, {1204,4499,4500 ,338,4510,4523 }, - {6014,6015,5838 ,6592,3988,3987 }, {5910,6014,5838 ,5121,6592,3987 }, - {3408,3435,3434 ,3484,6703,737 }, {6076,6033,5982 ,4217,5620,4218 }, - {1008,5316,3414 ,6427,6087,4934 }, {1252,3839,3838 ,5023,6310,6257 }, - {6059,3559,3679 ,6446,6412,6447 }, {5897,5990,3679 ,6414,6692,6447 }, - {5316,4528,3414 ,6087,4935,4934 }, {1629,931,1379 ,4207,3944,4137 }, - {6123,5513,5351 ,4221,6500,6513 }, {5981,6007,5562 ,6415,6704,4193 }, - {6137,6068,3989 ,5809,5896,5822 }, {1022,1051,6253 ,4198,4588,6693 }, - {3395,5116,5854 ,5940,4126,6265 }, {3780,5356,4167 ,6526,4258,6173 }, - {5192,5044,3762 ,6454,5173,5172 }, {5916,5476,6177 ,6175,6495,6629 }, - {6052,3762,3835 ,5717,5172,6046 }, {5477,2636,5789 ,5399,2712,6140 }, - {8080,8141,8132 ,1094,3295,413 }, {4299,1511,2431 ,5984,4921,2977 }, - {5486,6052,3835 ,5718,5717,6046 }, {4028,5193,3411 ,5823,5846,4280 }, - {7532,7565,7507 ,6705,5080,6706 }, {5901,5971,5888 ,6674,6479,5752 }, - {5971,5902,5888 ,6479,5769,5752 }, {3506,1854,5368 ,6492,2184,5751 }, - {5990,6123,5351 ,6692,4221,6513 }, {3559,5897,3679 ,6412,6414,6447 }, - {6145,6053,5925 ,6514,4463,5710 }, {5869,6084,3680 ,6224,6194,6497 }, - {3366,5461,5252 ,5894,5744,5746 }, {3908,3874,3776 ,6698,6697,6699 }, - {5116,3951,5854 ,4126,6528,6265 }, {2208,5502,5088 ,1257,1256,5004 }, - {5450,5472,6032 ,6525,6301,6489 }, {5246,5488,6134 ,5176,2730,2729 }, - {2159,5549,1171 ,6440,6435,6441 }, {3836,5865,5921 ,6103,6092,5705 }, - {5892,3498,1171 ,2683,5800,6441 }, {6042,1696,5230 ,5703,6547,5704 }, - {4247,1627,1729 ,6468,5573,3666 }, {4425,5916,6177 ,6268,6175,6629 }, - {5549,5892,1171 ,6435,2683,6441 }, {4278,6138,5931 ,5583,6014,6576 }, - {4308,4278,5931 ,6577,5583,6576 }, {6138,6250,6237 ,6014,6532,6578 }, - {5316,5743,3835 ,6087,6432,6046 }, {5233,5232,5978 ,429,6238,5581 }, - {5983,6082,5232 ,6707,1348,6238 }, {5590,6014,5910 ,6386,6592,5121 }, - {5931,6138,6237 ,6576,6014,6578 }, {6250,3444,3561 ,6532,6054,6580 }, - {3559,6059,3522 ,6412,6446,6451 }, {1696,5362,5230 ,6547,6670,5704 }, - {1701,2896,1949 ,6476,6110,3637 }, {5865,6042,5921 ,6092,5703,5705 }, - {6036,5789,5883 ,6141,6140,5850 }, {5478,6036,5883 ,5806,6141,5850 }, - {6237,6250,3561 ,6578,6532,6580 }, {1620,5872,6129 ,5982,6557,5983 }, - {5245,4949,4724 ,5880,5526,4737 }, {3469,3608,6067 ,5860,5799,6266 }, - {5891,5933,3822 ,5714,615,5715 }, {1051,1858,217 ,4588,4590,4643 }, - {1051,1532,6253 ,4588,4771,6693 }, {6253,1532,6265 ,6693,4771,6694 }, - {1532,5275,4189 ,4771,6708,6695 }, {6265,1532,4189 ,6694,4771,6695 }, - {4349,5184,4189 ,6709,6696,6695 }, {5275,4349,4189 ,6708,6709,6695 }, - {3927,3874,5184 ,6710,6697,6696 }, {4349,3927,5184 ,6709,6710,6696 }, - {3927,6117,3874 ,6710,6711,6697 }, {5959,3776,3874 ,6712,6699,6697 }, - {6117,5959,3874 ,6711,6712,6697 }, {5565,5780,3776 ,6713,6700,6699 }, - {5959,5565,3776 ,6712,6713,6699 }, {5565,3610,4344 ,6713,6714,6701 }, - {5780,5565,4344 ,6700,6713,6701 }, {5873,5968,4344 ,6715,6702,6701 }, - {3610,5873,4344 ,6714,6715,6701 }, {5393,5088,5968 ,5005,5004,6702 }, - {5873,5393,5968 ,6715,5005,6702 }, {6110,5871,3395 ,6247,4124,5940 }, - {6105,6062,1268 ,5565,6478,4568 }, {7370,7422,7396 ,3750,1404,6716 }, - {2343,6563,2210 ,2685,464,2510 }, {5995,6012,5974 ,5564,6408,6474 }, - {5789,6258,5954 ,6140,6553,5868 }, {5883,5789,5954 ,5850,6140,5868 }, - {6258,5386,5954 ,6553,5870,5868 }, {5476,3471,6177 ,6495,4104,6629 }, - {5954,5386,3657 ,5868,5870,5869 }, {5983,5232,5255 ,6707,6238,3682 }, - {6241,6269,1661 ,6410,6083,5672 }, {5895,5942,3561 ,6053,6581,6580 }, - {5743,5486,3835 ,6432,5718,6046 }, {5386,6185,6178 ,5870,6051,5881 }, - {3657,5386,6178 ,5869,5870,5881 }, {5232,6082,5978 ,6238,1348,5581 }, - {6271,5356,3780 ,6152,4258,6526 }, {3444,5895,3561 ,6054,6053,6580 }, - {3731,4488,5942 ,6041,6582,6581 }, {3559,3522,1417 ,6412,6451,6501 }, - {5955,3559,1417 ,6512,6412,6501 }, {3717,3953,3715 ,6487,5713,6124 }, - {5630,5610,6225 ,4874,6153,4872 }, {6185,3892,6178 ,6051,4970,5881 }, - {5956,5951,3337 ,6240,6000,4125 }, {5712,5302,5975 ,6160,3795,6161 }, - {5417,3781,5451 ,5923,5849,6219 }, {5895,3731,5942 ,6053,6041,6581 }, - {6174,6002,6173 ,2381,5975,3711 }, {5935,3658,5524 ,5778,6521,6426 }, - {5426,5447,5970 ,5634,5633,3518 }, {537,5955,1417 ,4834,6512,6501 }, - {5743,6024,5486 ,6432,6482,5718 }, {6007,3787,5562 ,6704,5819,4193 }, - {252,6103,5897 ,2743,4220,6414 }, {5885,5935,6057 ,6502,5778,6423 }, - {4574,5301,1268 ,6477,2698,4568 }, {5974,3470,3079 ,6474,6401,6540 }, - {5995,5974,6062 ,5564,6474,6478 }, {5781,5782,3385 ,5694,5693,6104 }, - {6568,5395,5427 ,6717,5348,5811 }, {6075,6026,4488 ,6042,6584,6582 }, - {3731,6075,4488 ,6041,6042,6582 }, {5628,3609,6144 ,6560,5081,5083 }, - {6091,5384,6010 ,2173,6121,6197 }, {6069,6082,5983 ,6180,1348,6707 }, - {5255,6069,5983 ,3682,6180,6707 }, {58,8143,8128 ,2156,2570,959 }, - {4170,5447,5579 ,3731,5633,5942 }, {1002,1283,5788 ,2976,2978,6086 }, - {3844,4170,5579 ,2443,3731,5942 }, {5788,3844,5579 ,6086,2443,5942 }, - {4299,2431,1002 ,5984,2977,2976 }, {6075,5291,6026 ,6042,6656,6584 }, - {5908,6148,5291 ,4293,6586,6656 }, {6023,3360,3410 ,6040,6485,6483 }, - {6095,5973,6081 ,6222,6246,6223 }, {6081,6110,3395 ,6223,6247,5940 }, - {5981,3787,6007 ,6415,5819,6704 }, {5562,5918,5945 ,4193,5820,6396 }, - {5996,4567,6156 ,6249,6655,6250 }, {7743,7744,7769 ,5534,6101,5535 }, - {5329,5879,5711 ,6191,6220,6248 }, {5393,5362,3801 ,5005,6670,4974 }, - {5871,5963,3337 ,4124,6409,4125 }, {6105,5995,6062 ,5565,5564,6478 }, - {3217,5475,6030 ,6117,4038,4037 }, {4410,4094,5670 ,5735,6225,6227 }, - {6075,5908,5291 ,6042,4293,6656 }, {5559,3527,5748 ,6640,6620,6636 }, - {1121,5936,6125 ,6564,4393,4395 }, {6167,6259,5590 ,5974,6718,6386 }, - {6002,6167,5590 ,5975,5974,6386 }, {6003,5871,5973 ,6122,4124,6246 }, - {5871,5116,3395 ,4124,4126,5940 }, {5671,3599,5416 ,6515,6428,6461 }, - {6199,537,4229 ,4859,4834,4877 }, {537,1417,4229 ,4834,6501,4877 }, - {5670,3787,5981 ,6227,5819,6415 }, {6012,6004,5974 ,6408,6123,6474 }, - {6068,3366,3989 ,5896,5894,5822 }, {1620,1122,5872 ,5982,6719,6557 }, - {6215,5275,1532 ,3636,6708,4771 }, {1949,6215,1532 ,3637,3636,4771 }, - {3845,4349,5275 ,3635,6709,6708 }, {6215,3845,5275 ,3636,3635,6708 }, - {3845,3927,4349 ,3635,6710,6709 }, {3845,6216,3927 ,3635,6658,6710 }, - {6216,5319,6117 ,6658,5739,6711 }, {3927,6216,6117 ,6710,6658,6711 }, - {6117,5319,5959 ,6711,5739,6712 }, {5319,5781,5959 ,5739,5694,6712 }, - {5781,3385,5565 ,5694,6104,6713 }, {5959,5781,5565 ,6712,5694,6713 }, - {5565,3385,3610 ,6713,6104,6714 }, {3385,5921,3610 ,6104,5705,6714 }, - {5230,5873,3610 ,5704,6715,6714 }, {5921,5230,3610 ,5705,5704,6714 }, - {5362,5393,5873 ,6670,5005,6715 }, {5230,5362,5873 ,5704,6670,6715 }, - {8131,8105,8075 ,2307,3791,2308 }, {5897,6123,5990 ,6414,4221,6692 }, - {5951,3509,5123 ,6000,6519,6433 }, {3337,5951,5123 ,4125,6000,6433 }, - {6208,6243,6242 ,6011,5666,6081 }, {3469,6067,5651 ,5860,6266,5920 }, - {3498,6036,5478 ,5800,6141,5806 }, {5193,4466,1741 ,5846,5854,5695 }, - {4444,4443,6211 ,582,703,5558 }, {5854,6130,6131 ,6265,6300,6050 }, - {3902,3935,4807 ,4437,4346,6449 }, {7082,3415,5946 ,6462,6115,5481 }, - {7873,7897,7846 ,817,6015,4162 }, {8086,8099,8087 ,4823,2867,385 }, - {5520,1185,1516 ,1304,6159,1254 }, {257,3284,1380 ,6067,6720,6721 }, - {5706,6031,3779 ,3796,6429,6565 }, {1313,2373,1947 ,3674,6722,6723 }, - {7089,7115,7103 ,5608,1024,6455 }, {2220,1072,6709 ,6724,6725,6726 }, - {5085,1313,1947 ,3675,3674,6723 }, {2872,4204,784 ,311,38,4211 }, - {4542,6378,6481 ,6727,6728,6729 }, {5069,257,255 ,6730,6067,6731 }, - {352,351,255 ,593,592,6731 }, {5578,3621,6189 ,587,625,6579 }, - {6965,6964,6944 ,6732,6733,2633 }, {7005,7046,7004 ,6734,6735,5502 }, - {6914,6945,6913 ,3532,2632,2634 }, {6945,6965,6944 ,2632,6732,2633 }, - {2406,6530,1217 ,6736,6398,6399 }, {1215,6644,6950 ,3937,5098,1349 }, - {7719,7744,7743 ,6541,6101,5534 }, {4986,3399,5441 ,5096,715,5194 }, - {4831,4486,3472 ,3154,819,3155 }, {144,6430,5353 ,853,2748,851 }, - {7005,7004,6964 ,6734,5502,6733 }, {6965,7005,6964 ,6732,6734,6733 }, - {7046,7045,7004 ,6735,5503,5502 }, {2335,2284,7045 ,6737,6738,5503 }, - {7046,2335,7045 ,6735,6737,5503 }, {3609,5920,6990 ,5081,5453,6739 }, - {6858,6859,6910 ,6740,472,6741 }, {6158,7087,7086 ,6112,6742,6743 }, - {5978,6079,6114 ,5581,5580,1805 }, {3598,6598,3597 ,802,804,1810 }, - {6598,5908,3597 ,804,4293,1810 }, {4988,5020,5011 ,6744,6373,6657 }, - {6569,4988,5011 ,6745,6744,6657 }, {1118,4853,2284 ,6746,6747,6738 }, - {2335,1118,2284 ,6737,6746,6738 }, {6284,7086,5952 ,6113,6743,6595 }, - {3445,3597,5908 ,1791,1810,4293 }, {7062,1464,6164 ,6563,5768,6562 }, - {1380,6313,6312 ,6721,6748,6749 }, {879,4122,3397 ,1155,137,136 }, - {6859,6911,6910 ,472,474,6741 }, {255,257,1380 ,6731,6067,6721 }, - {6532,3496,6556 ,6184,3105,4273 }, {6557,6599,6598 ,6750,6596,804 }, - {6556,6557,6598 ,4273,6750,804 }, {6148,5908,6598 ,6586,4293,804 }, - {6599,6148,6598 ,6596,6586,804 }, {7453,7452,7424 ,1187,1875,1188 }, - {4568,5074,185 ,1492,6751,1493 }, {7736,2451,450 ,6752,2102,1653 }, - {3496,6557,6556 ,3105,6750,4273 }, {3733,4021,4426 ,5610,1712,1056 }, - {6690,7022,3649 ,6753,6754,6755 }, {5363,5383,6506 ,3269,3547,3549 }, - {2304,3302,2303 ,6756,6757,6758 }, {6571,5367,6523 ,4146,6034,5319 }, - {6468,6510,3496 ,6759,6760,3105 }, {3464,6468,3496 ,3151,6759,3105 }, - {6510,6558,6557 ,6760,6761,6750 }, {3496,6510,6557 ,3105,6760,6750 }, - {6558,6559,6557 ,6761,6762,6750 }, {6559,6600,6599 ,6762,6763,6596 }, - {6557,6559,6599 ,6750,6762,6596 }, {6600,6187,6599 ,6763,6531,6596 }, - {5823,7038,7073 ,661,3832,662 }, {6808,6807,6753 ,3465,6764,6765 }, - {3421,2851,3278 ,1156,3051,1158 }, {6703,6754,6701 ,5161,713,6766 }, - {6754,6789,6753 ,713,6767,6765 }, {7451,7509,7479 ,3963,1874,4423 }, - {3358,3357,3383 ,880,883,882 }, {5694,5715,5693 ,5326,4076,4075 }, - {3408,6468,3435 ,3484,6759,6703 }, {6533,6559,6558 ,6768,6762,6761 }, - {6510,6533,6558 ,6760,6768,6761 }, {6190,6219,2138 ,6610,6598,6602 }, - {6808,6859,6858 ,3465,472,6740 }, {6789,6808,6753 ,6767,3465,6765 }, - {5086,257,5069 ,6064,6067,6730 }, {7267,7291,7266 ,4331,3774,6769 }, - {5027,2272,4755 ,5516,1201,6770 }, {3936,3733,4024 ,5599,5610,5600 }, - {5693,7028,6988 ,4075,3587,6771 }, {5694,6989,6949 ,5326,4586,4585 }, - {5367,6571,5401 ,6034,4146,4145 }, {6393,6439,3408 ,1556,6772,3484 }, - {3357,6393,3408 ,883,1556,3484 }, {6439,6469,6468 ,6772,6773,6759 }, - {3408,6439,6468 ,3484,6772,6759 }, {6469,6511,6510 ,6773,6774,6760 }, - {6468,6469,6510 ,6759,6773,6760 }, {6510,6511,6533 ,6760,6774,6768 }, - {6511,6560,6559 ,6774,6775,6762 }, {6533,6511,6559 ,6768,6774,6762 }, - {6601,6600,6559 ,6776,6763,6762 }, {6560,6601,6559 ,6775,6776,6762 }, - {6601,6099,6187 ,6776,6777,6531 }, {6600,6601,6187 ,6763,6776,6531 }, - {297,6464,6783 ,1918,3633,3632 }, {6919,6918,6895 ,6778,6779,5434 }, - {2211,4988,1270 ,6780,6744,6781 }, {4988,6569,1270 ,6744,6745,6781 }, - {6948,6947,6920 ,6782,4587,6783 }, {6525,6526,6573 ,3703,6784,3733 }, - {6614,6651,6650 ,3886,6785,3833 }, {5300,6526,6525 ,3793,6784,3703 }, - {6866,6896,6842 ,6786,6787,5433 }, {6318,6319,5151 ,6788,6789,1803 }, - {7064,7048,7007 ,5181,6790,4628 }, {5415,5579,4565 ,5951,5942,5944 }, - {6393,6419,6439 ,1556,6791,6772 }, {6469,6485,6511 ,6773,6792,6774 }, - {3449,3478,3482 ,2440,885,2494 }, {6910,6911,6941 ,6741,474,6793 }, - {2271,3281,6309 ,5071,6794,3690 }, {5742,3815,3373 ,6448,5556,693 }, - {2244,6660,4570 ,6795,6601,4082 }, {5087,1117,6679 ,6796,4928,4824 }, - {2340,2303,2308 ,6797,6758,6798 }, {6389,6868,5041 ,5301,5554,6799 }, - {5559,5048,5687 ,6640,6421,6420 }, {2093,6342,2957 ,553,5265,6326 }, - {2303,3302,2308 ,6758,6757,6798 }, {6158,7086,6284 ,6112,6743,6113 }, - {7083,5991,5952 ,5483,5482,6595 }, {6318,5151,6356 ,6788,1803,3787 }, - {7453,7510,7452 ,1187,1873,1875 }, {2095,5081,1117 ,6800,1258,4928 }, - {7924,7974,7923 ,815,4171,816 }, {2237,2236,2373 ,6801,6802,6722 }, - {7087,5514,7088 ,6742,6128,4299 }, {6090,6053,6260 ,4897,4463,3397 }, - {5009,6391,6463 ,6803,6804,5159 }, {4575,7585,7640 ,3128,6805,5351 }, - {5514,7087,6158 ,6128,6742,6112 }, {5447,5564,5579 ,5633,5943,5942 }, - {5751,5752,7038 ,5878,4374,3832 }, {3359,6420,6419 ,824,6806,6791 }, - {6393,3359,6419 ,1556,824,6791 }, {6419,6420,6439 ,6791,6806,6772 }, - {6420,6470,6469 ,6806,6807,6773 }, {6439,6420,6469 ,6772,6806,6773 }, - {6470,6471,6485 ,6807,6808,6792 }, {6469,6470,6485 ,6773,6807,6792 }, - {6471,6512,6511 ,6808,6809,6774 }, {6485,6471,6511 ,6792,6808,6774 }, - {6561,6560,6511 ,6810,6775,6774 }, {6512,6561,6511 ,6809,6810,6774 }, - {6561,6180,6601 ,6810,6811,6776 }, {6560,6561,6601 ,6775,6810,6776 }, - {6601,6180,6099 ,6776,6811,6777 }, {3674,6160,6099 ,4286,6442,6777 }, - {6180,3674,6099 ,6811,4286,6777 }, {7033,7034,6152 ,6395,6045,6044 }, - {6682,5087,6679 ,6812,6796,4824 }, {184,4016,4017 ,4052,5969,5342 }, - {6942,6962,6961 ,521,3260,6813 }, {7000,7001,7024 ,6814,6815,6816 }, - {6160,6187,6099 ,6442,6531,6777 }, {7649,7648,7621 ,3950,3952,6010 }, - {5454,6682,3978 ,6817,6812,4549 }, {6711,2450,5014 ,3473,3444,6818 }, - {6554,3261,6521 ,3647,5015,6819 }, {350,5117,6115 ,1114,1113,3645 }, - {6713,6644,1215 ,6820,5098,3937 }, {6713,5056,6644 ,6820,1300,5098 }, - {3261,4190,2384 ,5015,3439,6821 }, {6844,6896,6866 ,6822,6787,6786 }, - {7105,7130,7104 ,5279,6823,5280 }, {7220,7219,7184 ,4367,1529,5074 }, - {6962,7001,7000 ,3260,6815,6814 }, {7025,7043,7042 ,6824,5895,5338 }, - {6319,5118,5125 ,6789,6825,5467 }, {3359,6394,6420 ,824,6826,6806 }, - {6420,6471,6470 ,6806,6808,6807 }, {6602,6180,6561 ,6827,6811,6810 }, - {6918,6946,6919 ,6779,594,6778 }, {1025,6657,6714 ,5299,6828,5300 }, - {2337,2405,5578 ,6829,4165,587 }, {2245,6359,6344 ,1260,6830,1450 }, - {5512,5511,5471 ,1589,1588,2051 }, {6379,6380,6394 ,6831,6832,6826 }, - {3359,6379,6394 ,824,6831,6826 }, {6380,6421,6420 ,6832,6833,6806 }, - {6394,6380,6420 ,6826,6832,6806 }, {6421,6472,6471 ,6833,6834,6808 }, - {6420,6421,6471 ,6806,6833,6808 }, {6472,6513,6512 ,6834,6835,6809 }, - {6471,6472,6512 ,6808,6834,6809 }, {6513,3600,6561 ,6835,5331,6810 }, - {6512,6513,6561 ,6809,6835,6810 }, {3623,6602,6561 ,4206,6827,6810 }, - {3600,3623,6561 ,5331,4206,6810 }, {6602,3623,6180 ,6827,4206,6811 }, - {6359,5074,4568 ,6830,6751,1492 }, {6344,6359,4568 ,1450,6830,1492 }, - {6739,6738,5437 ,6836,5057,6259 }, {6754,6753,6701 ,713,6765,6766 }, - {1990,5059,1217 ,1305,1253,6399 }, {7042,2251,7077 ,5338,3676,6837 }, - {7041,7042,7077 ,6838,5338,6837 }, {2251,5085,7077 ,3676,3675,6837 }, - {5085,4142,7077 ,3675,6839,6837 }, {6966,7006,6965 ,6840,6841,6732 }, - {2406,1217,6814 ,6736,6399,6842 }, {6421,6440,6472 ,6833,6843,6834 }, - {5527,3221,835 ,5977,183,3030 }, {2320,8049,8018 ,1406,5393,6676 }, - {6573,6574,6613 ,3733,3885,3746 }, {6342,2093,6555 ,5265,553,597 }, - {6854,6893,6906 ,3344,6844,4294 }, {6088,6069,5255 ,3670,6180,3682 }, - {6389,5041,5102 ,5301,6799,6845 }, {6688,6389,5102 ,6846,5301,6845 }, - {5054,5053,6688 ,6847,6848,6846 }, {5053,6389,6688 ,6848,5301,6846 }, - {6708,5053,5054 ,6148,6848,6847 }, {6696,6708,5054 ,6849,6148,6847 }, - {6442,6300,6708 ,6850,6146,6148 }, {2237,2308,6297 ,6801,6798,6851 }, - {6297,6300,6442 ,6851,6146,6850 }, {2308,6300,6297 ,6798,6146,6851 }, - {2409,2340,2237 ,6852,6797,6801 }, {3326,6380,6379 ,826,6832,6831 }, - {7047,7046,7005 ,6853,6735,6734 }, {7006,7047,7005 ,6841,6853,6734 }, - {2455,5001,4018 ,475,477,5084 }, {6613,6614,6650 ,3746,3886,3833 }, - {2340,2409,1075 ,6797,6852,6854 }, {2340,2308,2237 ,6797,6798,6801 }, - {4853,2340,1075 ,6747,6797,6854 }, {6959,6998,6997 ,6003,6855,4368 }, - {8019,8018,7972 ,1407,6676,6059 }, {5436,6681,5405 ,6201,5406,5518 }, - {5331,5330,5277 ,6198,3345,6237 }, {4960,306,5986 ,6856,6234,4603 }, - {4191,4296,3802 ,4474,6023,4475 }, {6737,6736,6704 ,6857,1622,5160 }, - {6681,6737,6704 ,5406,6857,5160 }, {2284,2248,7044 ,6738,6858,6859 }, - {7045,7044,7002 ,5503,6859,1047 }, {7006,7005,6965 ,6841,6734,6732 }, - {6941,6942,6961 ,6793,521,6813 }, {6966,6965,6914 ,6840,6732,3532 }, - {6141,6140,6122 ,2386,2333,1797 }, {6347,6381,6380 ,451,6860,6832 }, - {3326,6347,6380 ,826,451,6832 }, {6381,6422,6421 ,6860,6861,6833 }, - {6380,6381,6421 ,6832,6860,6833 }, {6422,6441,6440 ,6861,6862,6843 }, - {6421,6422,6440 ,6833,6861,6843 }, {6441,6473,6472 ,6862,6863,6834 }, - {6440,6441,6472 ,6843,6862,6834 }, {3550,6513,6472 ,4179,6835,6834 }, - {6473,3550,6472 ,6863,4179,6834 }, {6513,3550,3600 ,6835,4179,5331 }, - {6742,6746,4784 ,3422,6864,3423 }, {6864,6863,6839 ,6865,6866,6867 }, - {6840,6864,6839 ,6868,6865,6867 }, {7045,2284,7044 ,5503,6738,6859 }, - {4853,1075,2248 ,6747,6854,6858 }, {2284,4853,2248 ,6738,6747,6858 }, - {4746,6302,2210 ,5260,6869,2510 }, {2373,2236,2235 ,6722,6802,6870 }, - {7241,7287,7240 ,4465,3459,4312 }, {5140,1936,2094 ,3712,848,5570 }, - {7026,7045,7002 ,5504,5503,1047 }, {7026,7002,7003 ,5504,1047,1046 }, - {6915,6966,6914 ,6871,6840,3532 }, {7049,7064,7007 ,5454,5181,4628 }, - {6571,6572,6611 ,4146,3734,1391 }, {6840,6839,6792 ,6868,6867,5056 }, - {6812,6840,6792 ,6872,6868,5056 }, {6912,6913,6943 ,519,2634,520 }, - {1118,2304,2340 ,6746,6756,6797 }, {7002,7044,7043 ,1047,6859,5895 }, - {6291,6690,6027 ,6873,6753,6874 }, {6690,6687,6027 ,6753,6875,6874 }, - {455,456,1344 ,2205,301,300 }, {6351,8077,8079 ,1568,2078,55 }, - {3495,3496,6532 ,735,3105,6184 }, {6690,3649,4549 ,6753,6755,877 }, - {6687,6690,4549 ,6875,6753,877 }, {2236,6291,6027 ,6802,6873,6874 }, - {1947,2373,2235 ,6723,6722,6870 }, {2235,2236,6027 ,6870,6802,6874 }, - {3649,6661,6621 ,6755,6876,5552 }, {4549,3649,6621 ,877,6755,5552 }, - {5028,4027,1938 ,5109,3470,5934 }, {6661,5048,5629 ,6876,6421,5162 }, - {7004,7026,7003 ,5502,5504,1046 }, {206,3373,3815 ,3932,693,5556 }, - {7004,7003,6963 ,5502,1046,1048 }, {6915,6914,6862 ,6871,3532,6877 }, - {6312,6313,6747 ,6749,6748,6878 }, {7048,7047,7006 ,6790,6853,6841 }, - {6812,6792,6793 ,6872,5056,6879 }, {6794,6812,6793 ,6880,6872,6879 }, - {6911,6942,6941 ,474,521,6793 }, {6861,6913,6912 ,3533,2634,519 }, - {6860,6861,6912 ,473,3533,519 }, {6754,6808,6789 ,713,3465,6767 }, - {6687,4549,5077 ,6875,877,876 }, {6617,6616,6576 ,6881,6882,6883 }, - {6617,6655,6616 ,6881,5407,6882 }, {6655,6654,6616 ,5407,6884,6882 }, - {3556,3557,3580 ,3385,6070,6069 }, {4010,7030,4043 ,4343,6885,419 }, - {4009,4010,4043 ,3870,4343,419 }, {7030,3765,6096 ,6885,4093,4092 }, - {6685,6687,5077 ,6886,6875,876 }, {6621,6661,5629 ,5552,6876,5162 }, - {5404,6617,6576 ,3559,6881,6883 }, {6964,7004,6963 ,6733,5502,1048 }, - {6894,6915,6862 ,6887,6871,6877 }, {6894,6862,6863 ,6887,6877,6866 }, - {6348,6382,6381 ,1607,6888,6860 }, {6347,6348,6381 ,451,1607,6860 }, - {6382,6423,6422 ,6888,6889,6861 }, {6381,6382,6422 ,6860,6888,6861 }, - {6423,3465,6441 ,6889,6890,6862 }, {6422,6423,6441 ,6861,6889,6862 }, - {3465,3500,6473 ,6890,4177,6863 }, {6441,3465,6473 ,6862,6890,6863 }, - {6473,3500,3550 ,6863,4177,4179 }, {6794,6793,6755 ,6880,6879,5055 }, - {6756,6794,6755 ,6891,6880,5055 }, {6913,6944,6943 ,2634,2633,520 }, - {6480,5350,6507 ,1524,1526,2680 }, {7007,7048,7006 ,4628,6790,6841 }, - {5930,6125,6143 ,6593,4395,4394 }, {6140,6121,6101 ,2333,6575,6574 }, - {6893,6856,6906 ,6844,6892,4294 }, {4981,4950,1216 ,1350,1302,6893 }, - {5011,1264,4746 ,6657,5022,5260 }, {2279,2248,1313 ,5337,6858,3674 }, - {6964,6963,6943 ,6733,1048,520 }, {6864,6894,6863 ,6865,6887,6866 }, - {6741,6740,6705 ,5388,6894,4158 }, {6310,6746,6742 ,3918,6864,3422 }, - {5907,5246,3860 ,6116,5176,6523 }, {6382,3465,6423 ,6888,6890,6889 }, - {7102,7101,7088 ,1240,4073,4299 }, {4567,6155,6156 ,6655,3726,6250 }, - {3399,5143,5441 ,715,6099,5194 }, {6756,6755,6740 ,6891,5055,6894 }, - {3973,5446,5388 ,6007,5985,5428 }, {2235,6027,2139 ,6870,6874,6895 }, - {6737,6790,6736 ,6857,711,1622 }, {6619,6554,6521 ,1272,3647,6819 }, - {7076,7075,7039 ,4886,4420,4376 }, {1026,4981,1216 ,6218,1350,6893 }, - {1072,1026,1216 ,6725,6218,6893 }, {6172,4010,5124 ,5451,4343,6567 }, - {5686,5890,5747 ,5777,6591,6036 }, {4261,3777,4290 ,1583,1582,6270 }, - {6750,6751,6786 ,631,5242,4139 }, {6961,7000,6960 ,6813,6814,6896 }, - {7000,7042,7041 ,6814,5338,6838 }, {6999,7000,7041 ,6897,6814,6838 }, - {6909,6910,6960 ,6898,6741,6896 }, {7000,6999,6960 ,6814,6897,6896 }, - {6858,6910,6857 ,6740,6741,6899 }, {6910,6961,6960 ,6741,6813,6896 }, - {6944,6964,6943 ,2633,6733,520 }, {6738,6791,6737 ,5057,6900,6857 }, - {6348,6357,6382 ,1607,5271,6888 }, {6383,3437,3465 ,6901,4142,6890 }, - {6382,6383,3465 ,6888,6901,6890 }, {5694,7009,5716 ,5326,5325,6075 }, - {351,5069,255 ,592,6730,6731 }, {3418,1554,248 ,6366,6304,4114 }, - {5491,5479,5516 ,5419,5387,5420 }, {6741,6756,6740 ,5388,6891,6894 }, - {2221,2291,5114 ,6902,1115,5689 }, {1264,5011,1252 ,5022,6657,5023 }, - {7025,7002,7043 ,6824,1047,5895 }, {6862,6914,6861 ,6877,3532,3533 }, - {6998,7040,7039 ,6855,6903,4376 }, {7040,7076,7039 ,6903,4886,4376 }, - {6910,6909,6857 ,6741,6898,6899 }, {6838,6858,6806 ,6904,6740,6905 }, - {6807,6838,6806 ,6764,6904,6905 }, {6858,6857,6806 ,6740,6899,6905 }, - {3435,3464,3434 ,6703,3151,737 }, {4780,4819,3139 ,5150,5216,5400 }, - {6532,6556,3547 ,6184,4273,803 }, {6146,3970,3926 ,6568,3225,3125 }, - {6899,6146,3926 ,4005,6568,3125 }, {3787,6022,6159 ,5819,6535,5082 }, - {5533,5628,3765 ,6239,6560,4093 }, {7030,5533,3765 ,6885,6239,4093 }, - {4835,4021,3936 ,2130,1712,5599 }, {6753,6752,6700 ,6765,6906,6907 }, - {4547,5058,2163 ,242,5647,243 }, {6071,5590,6354 ,1346,6386,6597 }, - {7675,7697,7719 ,5192,651,6541 }, {6755,6738,6739 ,5055,5057,6836 }, - {6358,6383,6382 ,5270,6901,6888 }, {6357,6358,6382 ,5271,5270,6888 }, - {5628,5533,3609 ,6560,6239,5081 }, {6740,6755,6739 ,6894,5055,6836 }, - {1882,4547,4543 ,894,242,3002 }, {6810,6861,6860 ,6908,3533,473 }, - {6809,6810,6860 ,712,6908,473 }, {6807,6806,6752 ,6764,6905,6906 }, - {3464,3435,6468 ,3151,6703,6759 }, {4043,4007,4009 ,419,3909,3870 }, - {4987,6464,5966 ,1491,3633,5054 }, {5059,3177,4233 ,1253,1255,6185 }, - {4950,5005,4115 ,1302,1301,6909 }, {6862,6861,6810 ,6877,3533,6908 }, - {6701,6753,6700 ,6766,6765,6907 }, {6302,5078,1074 ,6869,5261,2715 }, - {6618,6656,6617 ,6910,5517,6881 }, {6791,6790,6737 ,6900,711,6857 }, - {7744,7795,7794 ,6101,3804,5749 }, {5437,6738,6681 ,6259,5057,5406 }, - {6840,6894,6864 ,6868,6887,6865 }, {6740,6739,5437 ,6894,6836,6259 }, - {342,209,4892 ,4542,4499,5386 }, {6844,6843,6795 ,6822,6911,5418 }, - {5693,6988,6947 ,4075,6771,4587 }, {6810,6809,6790 ,6908,712,711 }, - {6864,6915,6894 ,6865,6871,6887 }, {7620,7647,7675 ,5033,4967,5192 }, - {5950,5013,8108 ,2873,684,2287 }, {6753,6807,6752 ,6765,6764,6906 }, - {7769,7794,7768 ,5535,5749,5536 }, {1170,5627,3471 ,4103,6628,4104 }, - {6847,6900,6899 ,4004,6912,4005 }, {4043,7030,6096 ,419,6885,4092 }, - {3408,3382,3383 ,3484,870,882 }, {6752,6806,6788 ,6906,6905,6913 }, - {6701,6700,6652 ,6766,6907,6914 }, {6653,6701,6652 ,6915,6766,6914 }, - {6656,6655,6617 ,5517,5407,6881 }, {6738,6737,6681 ,5057,6857,5406 }, - {1076,4617,7075 ,4887,4431,4420 }, {5477,5442,5315 ,5399,5174,6445 }, - {6843,6842,6813 ,6911,5433,6916 }, {6350,3362,6358 ,704,1200,5270 }, - {6349,6350,6358 ,705,704,5270 }, {3362,6384,6383 ,1200,1786,6901 }, - {6358,3362,6383 ,5270,1200,6901 }, {6384,3387,6383 ,1786,1787,6901 }, - {6383,3387,3437 ,6901,1787,4142 }, {6791,6810,6790 ,6900,6908,711 }, - {5910,6079,6354 ,5121,5580,6597 }, {6987,7007,6966 ,6917,4628,6840 }, - {6844,6795,5551 ,6822,5418,6260 }, {3814,6799,3855 ,5511,6918,1511 }, - {6799,6761,3855 ,6918,6919,1511 }, {6761,6848,6847 ,6919,6920,4004 }, - {3855,6761,6847 ,1511,6919,4004 }, {6848,6901,6900 ,6920,6921,6912 }, - {6847,6848,6900 ,4004,6920,6912 }, {6901,6899,6900 ,6921,4005,6912 }, - {6147,6146,6899 ,5452,6568,4005 }, {6901,6147,6899 ,6921,5452,4005 }, - {6744,5188,3350 ,3986,4812,2541 }, {7900,7926,7899 ,6922,6923,4116 }, - {3277,8098,2901 ,961,907,3468 }, {6144,4642,5628 ,5083,6226,6560 }, - {2160,5474,2154 ,6621,4243,5321 }, {6616,6653,6615 ,6882,6915,6924 }, - {6297,6696,6694 ,6851,6849,6925 }, {6534,6578,3656 ,4257,6926,4195 }, - {973,6465,2141 ,2017,6927,2015 }, {5593,6920,6896 ,5935,6783,6787 }, - {6795,6843,6813 ,5418,6911,6916 }, {3504,3441,3505 ,2986,2987,6928 }, - {3556,3521,3504 ,3385,4307,2986 }, {1285,1226,1320 ,1944,2354,2356 }, - {3605,3626,3604 ,3383,4196,3384 }, {6572,6612,6611 ,3734,1389,1391 }, - {6125,5930,5979 ,4395,6593,6028 }, {5404,5371,5405 ,3559,3558,5518 }, - {6715,6761,6799 ,6929,6919,6918 }, {3814,6715,6799 ,5511,6929,6918 }, - {1936,2341,2094 ,848,845,5570 }, {1590,1552,1656 ,3028,2266,1166 }, - {3605,3556,3580 ,3383,3385,6069 }, {6159,4642,6144 ,5082,6226,5083 }, - {5087,5077,2095 ,6796,876,6800 }, {6466,6758,973 ,6930,6931,2017 }, - {6909,6908,6857 ,6898,6932,6899 }, {5437,6681,5436 ,6259,5406,6201 }, - {2957,6342,1120 ,6326,5265,5339 }, {6564,6508,6639 ,6933,6934,3699 }, - {3320,6564,6639 ,5455,6933,3699 }, {3192,4784,6387 ,3063,3423,6935 }, - {3656,6578,3714 ,4195,6926,3970 }, {7148,7147,7120 ,6936,6937,6938 }, - {5405,6618,5404 ,5518,6910,3559 }, {5473,7096,5120 ,3429,4337,5857 }, - {6022,4642,6159 ,6535,6226,5082 }, {7286,7285,7261 ,3460,2751,1528 }, - {2139,6685,6682 ,6895,6886,6812 }, {3714,3655,3656 ,3970,3936,4195 }, - {1809,6605,5081 ,878,5164,1258 }, {6682,6685,5087 ,6812,6886,6796 }, - {2095,1809,5081 ,6800,878,1258 }, {5077,1809,2095 ,876,878,6800 }, - {6685,5077,5087 ,6886,876,6796 }, {5359,3815,5977 ,3713,5556,809 }, - {1074,6466,973 ,2715,6930,2017 }, {6466,6465,6758 ,6930,6927,6931 }, - {6653,6652,6615 ,6915,6914,6924 }, {6576,6616,6575 ,6883,6882,6939 }, - {6354,6079,6377 ,6597,5580,1347 }, {1562,5130,4392 ,4649,5571,844 }, - {4856,2244,4570 ,4081,6795,4082 }, {3288,3328,3362 ,2058,3973,1200 }, - {6321,3288,3362 ,706,2058,1200 }, {5441,297,42 ,5194,1918,5195 }, - {6001,6156,5917 ,6221,6250,6402 }, {6443,6486,3557 ,6940,6941,6070 }, - {3504,6443,3557 ,2986,6940,6070 }, {6486,6534,3626 ,6941,4257,4196 }, - {3557,6486,3626 ,6070,6941,4196 }, {5747,5890,6214 ,6036,6591,6942 }, - {6578,6092,3714 ,6926,1623,3970 }, {5742,5977,3815 ,6448,809,5556 }, - {6302,1074,2210 ,6869,2715,2510 }, {2342,5008,2221 ,5690,6118,6902 }, - {6640,5435,6611 ,4224,4223,1391 }, {6176,6716,6715 ,1624,6943,6929 }, - {7232,7231,7196 ,2124,6944,2401 }, {6716,6762,6761 ,6943,6945,6919 }, - {6715,6716,6761 ,6929,6943,6919 }, {6762,6815,6761 ,6945,6946,6919 }, - {6761,6815,6848 ,6919,6946,6920 }, {6902,6901,6848 ,6947,6921,6920 }, - {6815,6902,6848 ,6946,6947,6920 }, {6952,6147,6901 ,6948,5452,6921 }, - {6902,6952,6901 ,6947,6948,6921 }, {6952,6990,5920 ,6948,6739,5453 }, - {6147,6952,5920 ,5452,6948,5453 }, {7001,7002,7025 ,6815,1047,6824 }, - {6652,6700,6699 ,6914,6907,630 }, {2234,2139,5454 ,6949,6895,6817 }, - {2241,2234,5454 ,6950,6949,6817 }, {5454,2139,6682 ,6817,6895,6812 }, - {5300,5327,6041 ,3793,3702,3801 }, {4207,1444,1745 ,4247,4035,6233 }, - {5498,1742,1218 ,5590,707,3255 }, {6616,6615,6575 ,6882,6924,6939 }, - {6844,6866,6843 ,6822,6786,6911 }, {1380,3284,6313 ,6721,6720,6748 }, - {5593,6896,6867 ,5935,6787,6951 }, {6896,6919,6895 ,6787,6778,5434 }, - {5024,2138,6660 ,6952,6602,6601 }, {5087,2095,1117 ,6796,6800,4928 }, - {6486,6487,6534 ,6941,6953,4257 }, {6717,6763,6762 ,6954,6955,6945 }, - {6716,6717,6762 ,6943,6954,6945 }, {6763,6816,6815 ,6955,6956,6946 }, - {6762,6763,6815 ,6945,6955,6946 }, {6903,6902,6815 ,6957,6947,6946 }, - {6816,6903,6815 ,6956,6957,6946 }, {3393,3365,3394 ,4441,4240,6958 }, - {5111,5110,7166 ,5990,5953,5971 }, {6805,6855,6854 ,3343,6959,3344 }, - {6391,4550,6659 ,6804,716,3577 }, {6642,6652,6651 ,6960,6914,6785 }, - {6958,6959,6997 ,4314,6003,4368 }, {6575,6615,6574 ,6939,6924,3885 }, - {6651,6652,6699 ,6785,6914,630 }, {6752,6751,6699 ,6906,5242,630 }, - {6641,6642,6651 ,6961,6960,6785 }, {2260,6021,5494 ,6571,6551,6569 }, - {7239,7286,7261 ,1527,3460,1528 }, {6466,6315,6465 ,6930,6962,6927 }, - {6315,6392,306 ,6962,6963,6234 }, {6528,6576,6527 ,6964,6883,6965 }, - {5086,351,2246 ,6064,592,591 }, {6313,4445,6747 ,6748,3648,6878 }, - {2336,6521,5496 ,1261,6819,6966 }, {6228,1664,253 ,1366,2268,2564 }, - {7050,7067,7028 ,6967,3585,3587 }, {6443,3441,3442 ,6940,2987,4460 }, - {6708,6710,5053 ,6148,6968,6848 }, {6443,6487,6486 ,6940,6953,6941 }, - {6565,6579,6578 ,6969,6970,6926 }, {6534,6565,6578 ,4257,6969,6926 }, - {6579,6092,6578 ,6970,1623,6926 }, {6691,6717,6716 ,6971,6954,6943 }, - {6176,6691,6716 ,1624,6971,6943 }, {6903,6953,6952 ,6957,6972,6948 }, - {6902,6903,6952 ,6947,6957,6948 }, {6991,6990,6952 ,6973,6739,6948 }, - {6953,6991,6952 ,6972,6973,6948 }, {6991,7032,5918 ,6973,6974,5820 }, - {6990,6991,5918 ,6739,6973,5820 }, {1275,6108,1221 ,1688,6975,1759 }, - {6642,6641,6614 ,6960,6961,3886 }, {6615,6642,6614 ,6924,6960,3886 }, - {6615,6614,6574 ,6924,3886,3885 }, {3311,5192,3762 ,5303,6454,5172 }, - {6999,6998,6959 ,6897,6855,6003 }, {6315,306,4960 ,6962,6234,6856 }, - {6909,6960,6908 ,6898,6896,6932 }, {6576,6575,6527 ,6883,6939,6965 }, - {5104,5086,2246 ,6063,6064,591 }, {3284,4445,6313 ,6720,3648,6748 }, - {5438,6705,5437 ,4156,4158,6259 }, {5251,5210,6433 ,3802,6033,6691 }, - {6444,6488,6487 ,6976,6977,6953 }, {6443,6444,6487 ,6940,6976,6953 }, - {6488,6535,6534 ,6977,6978,4257 }, {6487,6488,6534 ,6953,6977,4257 }, - {6534,6535,6565 ,4257,6978,6969 }, {6535,6580,6579 ,6978,6979,6970 }, - {6565,6535,6579 ,6969,6978,6970 }, {6622,6092,6579 ,6980,1623,6970 }, - {6580,6622,6579 ,6979,6980,6970 }, {6622,6662,6176 ,6980,6981,1624 }, - {6092,6622,6176 ,1623,6980,1624 }, {6176,6662,6691 ,1624,6981,6971 }, - {6662,6718,6717 ,6981,6982,6954 }, {6691,6662,6717 ,6971,6981,6954 }, - {6718,6764,6763 ,6982,6983,6955 }, {6717,6718,6763 ,6954,6982,6955 }, - {6817,6816,6763 ,6984,6956,6955 }, {6764,6817,6763 ,6983,6984,6955 }, - {6871,6903,6816 ,6985,6957,6956 }, {6817,6871,6816 ,6984,6985,6956 }, - {6871,6954,6953 ,6985,6986,6972 }, {6903,6871,6953 ,6957,6985,6972 }, - {6992,6991,6953 ,6987,6973,6972 }, {6954,6992,6953 ,6986,6987,6972 }, - {6992,5945,7032 ,6987,6396,6974 }, {6991,6992,7032 ,6973,6987,6974 }, - {5945,5918,7032 ,6396,5820,6974 }, {2808,1987,1920 ,522,3614,581 }, - {6315,5009,6465 ,6962,6803,6927 }, {3425,1724,8103 ,1859,3880,1291 }, - {6960,6999,6959 ,6896,6897,6003 }, {7974,7973,7923 ,4171,3624,816 }, - {3359,3326,6379 ,824,826,6831 }, {6071,6354,6377 ,1346,6597,1347 }, - {5633,6949,5611 ,6179,4585,6177 }, {405,3499,5628 ,5662,5661,6560 }, - {6661,6688,5048 ,6876,6846,6421 }, {7027,7007,7008 ,3175,4628,3176 }, - {2406,1990,6530 ,6736,1305,6398 }, {3442,6444,6443 ,4460,6976,6940 }, - {6706,7814,5479 ,5389,6988,5387 }, {7092,7104,7091 ,3968,5280,4153 }, - {1879,5049,4744 ,1283,5038,4424 }, {6856,6907,6906 ,6892,6002,4294 }, - {7041,7040,6998 ,6838,6903,6855 }, {1394,2074,1027 ,6989,6990,6991 }, - {6793,6792,6755 ,6879,5056,5055 }, {2304,2303,2340 ,6756,6758,6797 }, - {3609,6990,5918 ,5081,6739,5820 }, {6345,4595,5118 ,191,5289,6825 }, - {6444,6474,6488 ,6976,6992,6977 }, {6488,6514,6535 ,6977,6993,6978 }, - {6999,7041,6998 ,6897,6838,6855 }, {6960,6959,6907 ,6896,6003,6002 }, - {4900,2274,4545 ,585,893,586 }, {6614,6641,6651 ,3886,6961,6785 }, - {6793,6811,6792 ,6879,399,5056 }, {7566,7565,7532 ,6009,5080,6705 }, - {3394,6395,3442 ,6958,6994,4460 }, {3393,3394,3442 ,4441,6958,4460 }, - {6395,6445,6444 ,6994,6995,6976 }, {3442,6395,6444 ,4460,6994,6976 }, - {6445,6446,6474 ,6995,6996,6992 }, {6444,6445,6474 ,6976,6995,6992 }, - {6446,6489,6488 ,6996,6997,6977 }, {6474,6446,6488 ,6992,6996,6977 }, - {6489,6490,6514 ,6997,6998,6993 }, {6488,6489,6514 ,6977,6997,6993 }, - {6490,6536,6535 ,6998,6999,6978 }, {6514,6490,6535 ,6993,6998,6978 }, - {6536,6581,6580 ,6999,7000,6979 }, {6535,6536,6580 ,6978,6999,6979 }, - {6623,6622,6580 ,7001,6980,6979 }, {6581,6623,6580 ,7000,7001,6979 }, - {6623,6663,6662 ,7001,7002,6981 }, {6622,6623,6662 ,6980,7001,6981 }, - {6663,6719,6718 ,7002,7003,6982 }, {6662,6663,6718 ,6981,7002,6982 }, - {6719,6765,6764 ,7003,7004,6983 }, {6718,6719,6764 ,6982,7003,6983 }, - {6765,6766,6764 ,7004,7005,6983 }, {6766,6818,6817 ,7005,7006,6984 }, - {6764,6766,6817 ,6983,7005,6984 }, {6818,6849,6817 ,7006,7007,6984 }, - {6872,6871,6817 ,7008,6985,6984 }, {6849,6872,6817 ,7007,7008,6984 }, - {6872,6955,6954 ,7008,7009,6986 }, {6871,6872,6954 ,6985,7008,6986 }, - {6955,6993,6992 ,7009,7010,6987 }, {6954,6955,6992 ,6986,7009,6987 }, - {6993,7033,5945 ,7010,6395,6396 }, {6992,6993,5945 ,6987,7010,6396 }, - {3970,5124,3969 ,3225,6567,3226 }, {4845,5187,5070 ,3921,5144,6043 }, - {5878,3835,3762 ,2684,6046,5172 }, {4672,5878,3762 ,2682,2684,5172 }, - {6908,6960,6907 ,6932,6896,6002 }, {7041,7077,7076 ,6838,6837,4886 }, - {7048,2074,7047 ,6790,6990,6853 }, {2222,4746,2210 ,2509,5260,2510 }, - {6479,6528,6478 ,2659,6964,7011 }, {6963,7002,7001 ,1048,1047,6815 }, - {248,4530,3350 ,4114,1376,2541 }, {4489,4068,3778 ,5584,408,5585 }, - {6301,6710,6708 ,6147,6968,6148 }, {6811,6839,6792 ,399,6867,5056 }, - {5926,5940,6715 ,6419,1625,6929 }, {5081,2208,1117 ,1258,1257,4928 }, - {6014,5590,6259 ,6592,6386,6718 }, {3394,6396,6395 ,6958,7012,6994 }, - {6396,6446,6445 ,7012,6996,6995 }, {6395,6396,6445 ,6994,7012,6995 }, - {6663,6720,6719 ,7002,7013,7003 }, {6720,6766,6765 ,7013,7005,7004 }, - {6719,6720,6765 ,7003,7013,7004 }, {6873,6872,6849 ,7014,7008,7007 }, - {6818,6873,6849 ,7006,7014,7007 }, {6955,6922,6993 ,7009,7015,7010 }, - {6855,6856,6805 ,6959,6892,3343 }, {3291,3293,3292 ,1203,1988,4067 }, - {4704,4763,5217 ,4788,4787,4026 }, {1987,1220,1920 ,3614,4885,581 }, - {7040,7041,7076 ,6903,6838,4886 }, {6392,6315,6466 ,6963,6962,6930 }, - {6528,6527,6478 ,6964,6965,7011 }, {6388,6436,6435 ,3184,3681,2658 }, - {2138,3704,6190 ,6602,2332,6610 }, {5315,5442,5044 ,6445,5174,5173 }, - {3394,6385,6396 ,6958,7016,7012 }, {6446,6490,6489 ,6996,6998,6997 }, - {6663,6692,6720 ,7002,7017,7013 }, {6873,6922,6872 ,7014,7015,7008 }, - {6872,6922,6955 ,7008,7015,7009 }, {6994,6993,6922 ,7018,7010,7015 }, - {6994,7034,7033 ,7018,6045,6395 }, {6993,6994,7033 ,7010,7018,6395 }, - {4672,5477,6036 ,2682,5399,6141 }, {5744,5716,7009 ,6090,6075,5325 }, - {685,2629,794 ,2674,2673,3392 }, {2336,6619,6521 ,1261,1272,6819 }, - {6619,1265,4190 ,1272,1273,3439 }, {6908,6907,6856 ,6932,6002,6892 }, - {5005,2336,5496 ,1301,1261,6966 }, {6857,6908,6856 ,6899,6932,6892 }, - {3600,3550,3578 ,5331,4179,4205 }, {6951,2211,6870 ,2615,6780,2616 }, - {1264,403,5078 ,5022,5547,5261 }, {2409,2237,2373 ,6852,6801,6722 }, - {5075,1215,184 ,1586,3937,4052 }, {7068,6166,7034 ,7019,4971,6045 }, - {6324,6360,3394 ,4239,7020,6958 }, {3365,6324,3394 ,4240,4239,6958 }, - {6360,6361,6385 ,7020,7021,7016 }, {3394,6360,6385 ,6958,7020,7016 }, - {6361,6397,6396 ,7021,7022,7012 }, {6385,6361,6396 ,7016,7021,7012 }, - {6397,6447,6446 ,7022,7023,6996 }, {6396,6397,6446 ,7012,7022,6996 }, - {6447,6475,6446 ,7023,7024,6996 }, {6475,6491,6490 ,7024,7025,6998 }, - {6446,6475,6490 ,6996,7024,6998 }, {6491,6537,6536 ,7025,7026,6999 }, - {6490,6491,6536 ,6998,7025,6999 }, {6537,6582,6581 ,7026,7027,7000 }, - {6536,6537,6581 ,6999,7026,7000 }, {6624,6623,6581 ,7028,7001,7000 }, - {6582,6624,6581 ,7027,7028,7000 }, {6624,6664,6663 ,7028,7029,7002 }, - {6623,6624,6663 ,7001,7028,7002 }, {6663,6664,6692 ,7002,7029,7017 }, - {6664,6721,6720 ,7029,7030,7013 }, {6692,6664,6720 ,7017,7029,7013 }, - {6721,6767,6766 ,7030,7031,7005 }, {6720,6721,6766 ,7013,7030,7005 }, - {6767,6819,6818 ,7031,7032,7006 }, {6766,6767,6818 ,7005,7031,7006 }, - {6874,6873,6818 ,7033,7014,7006 }, {6819,6874,6818 ,7032,7033,7006 }, - {6874,6923,6922 ,7033,7034,7015 }, {6873,6874,6922 ,7014,7033,7015 }, - {6971,6994,6922 ,7035,7018,7015 }, {6923,6971,6922 ,7034,7035,7015 }, - {6971,7035,7034 ,7035,7036,6045 }, {6994,6971,7034 ,7018,7035,6045 }, - {3311,5866,5192 ,5303,5302,6454 }, {7035,7068,7034 ,7036,7019,6045 }, - {2357,2798,4043 ,3933,420,419 }, {8019,2320,8018 ,1407,1406,6676 }, - {1204,1205,4499 ,338,3187,4510 }, {5076,5904,4200 ,6607,5851,6583 }, - {6687,6685,2139 ,6875,6886,6895 }, {6027,6687,2139 ,6874,6875,6895 }, - {2374,2455,4018 ,7037,475,5084 }, {1551,4921,2093 ,5275,2079,553 }, - {3952,4068,4489 ,5597,408,5584 }, {6036,5892,4672 ,6141,2683,2682 }, - {535,6153,5105 ,2001,5514,5456 }, {2455,2374,1027 ,475,7037,6991 }, - {5274,5251,6433 ,6145,3802,6691 }, {6805,6856,6855 ,3343,6892,6959 }, - {6434,6479,6478 ,3127,2659,7011 }, {6433,6434,6478 ,6691,3127,7011 }, - {7161,7186,7169 ,2559,5370,5437 }, {912,2209,2240 ,4471,7038,4478 }, - {4445,6748,6747 ,3648,3408,6878 }, {5647,5688,6890 ,5333,5519,5334 }, - {7533,7509,7510 ,7039,1874,1873 }, {6836,5353,8111 ,852,851,4359 }, - {2211,2222,6870 ,6780,2509,2616 }, {4017,5075,184 ,5342,1586,4052 }, - {6324,6361,6360 ,4239,7021,7020 }, {2290,7936,2292 ,1982,5528,1983 }, - {5394,3765,5628 ,5660,4093,6560 }, {2074,1071,1027 ,6990,3382,6991 }, - {2248,2279,7043 ,6858,5337,5895 }, {6997,6998,7039 ,4368,6855,4376 }, - {6758,6465,973 ,6931,6927,2017 }, {2205,6563,6898 ,2874,464,1946 }, - {6690,6694,7022 ,6753,6925,6754 }, {6696,5054,3649 ,6849,6847,6755 }, - {6173,6071,6088 ,3711,1346,3670 }, {7972,8018,7994 ,6059,6676,5582 }, - {2211,1270,2222 ,6780,6781,2509 }, {1749,6713,1215 ,555,6820,3937 }, - {6566,6583,6582 ,7040,7041,7027 }, {6537,6566,6582 ,7026,7040,7027 }, - {6583,6624,6582 ,7041,7028,7027 }, {4550,4960,5986 ,716,6856,4603 }, - {5009,6315,6391 ,6803,6962,6804 }, {6315,4960,6391 ,6962,6856,6804 }, - {6391,4960,4550 ,6804,6856,716 }, {3217,6030,5747 ,6117,4037,6036 }, - {5006,4981,1026 ,1351,1350,6218 }, {5503,5463,5504 ,7042,5801,5781 }, - {6569,5011,4746 ,6745,6657,5260 }, {3936,3820,4835 ,5599,5591,2130 }, - {6148,6599,6161 ,6586,6596,6530 }, {5191,6434,6433 ,2900,3127,6691 }, - {6291,6297,6690 ,6873,6851,6753 }, {6694,6696,7022 ,6925,6849,6754 }, - {7795,7846,7794 ,3804,4162,5749 }, {5075,1749,1215 ,1586,555,3937 }, - {6116,6325,6324 ,4170,7043,4239 }, {3336,6116,6324 ,3922,4170,4239 }, - {6325,6362,6361 ,7043,7044,7021 }, {6324,6325,6361 ,4239,7043,7021 }, - {6362,6398,6397 ,7044,7045,7022 }, {6361,6362,6397 ,7021,7044,7022 }, - {6398,6448,6447 ,7045,7046,7023 }, {6397,6398,6447 ,7022,7045,7023 }, - {6447,6448,6475 ,7023,7046,7024 }, {6448,6492,6491 ,7046,7047,7025 }, - {6475,6448,6491 ,7024,7046,7025 }, {6492,6538,6537 ,7047,7048,7026 }, - {6491,6492,6537 ,7025,7047,7026 }, {6537,6538,6566 ,7026,7048,7040 }, - {6538,6584,6583 ,7048,7049,7041 }, {6566,6538,6583 ,7040,7048,7041 }, - {6625,6624,6583 ,7050,7028,7041 }, {6584,6625,6583 ,7049,7050,7041 }, - {6625,6665,6664 ,7050,7051,7029 }, {6624,6625,6664 ,7028,7050,7029 }, - {6665,6722,6721 ,7051,7052,7030 }, {6664,6665,6721 ,7029,7051,7030 }, - {6722,6768,6767 ,7052,7053,7031 }, {6721,6722,6767 ,7030,7052,7031 }, - {6768,6820,6819 ,7053,7054,7032 }, {6767,6768,6819 ,7031,7053,7032 }, - {6875,6874,6819 ,7055,7033,7032 }, {6820,6875,6819 ,7054,7055,7032 }, - {6875,6924,6923 ,7055,7056,7034 }, {6874,6875,6923 ,7033,7055,7034 }, - {6924,6972,6971 ,7056,7057,7035 }, {6923,6924,6971 ,7034,7056,7035 }, - {7036,7035,6971 ,7058,7036,7035 }, {6972,7036,6971 ,7057,7058,7035 }, - {7036,7069,7068 ,7058,7059,7019 }, {7035,7036,7068 ,7036,7058,7019 }, - {4901,3892,7068 ,3596,4970,7019 }, {7069,4901,7068 ,7059,3596,7019 }, - {6527,6575,6526 ,6965,6939,6784 }, {6575,6574,6526 ,6939,3885,6784 }, - {6478,6527,5300 ,7011,6965,3793 }, {6527,6526,5300 ,6965,6784,3793 }, - {6433,6478,5300 ,6691,7011,3793 }, {5274,6433,5300 ,6145,6691,3793 }, - {1269,1125,2159 ,5724,5723,6440 }, {187,1269,2159 ,6439,5724,6440 }, - {4391,4422,4443 ,992,5561,703 }, {6702,6701,6653 ,7060,6766,6915 }, - {6654,6702,6653 ,6884,7060,6915 }, {6297,6694,6690 ,6851,6925,6753 }, - {6465,4985,2141 ,6927,2703,2015 }, {3156,1658,1657 ,3164,1782,1781 }, - {2257,5056,6713 ,554,1300,6820 }, {949,4994,5029 ,2133,5076,2159 }, - {6788,6787,6751 ,6913,5269,5242 }, {6700,6752,6699 ,6907,6906,630 }, - {6806,6805,6787 ,6905,3343,5269 }, {6752,6788,6751 ,6906,6913,5242 }, - {6788,6806,6787 ,6913,6905,5269 }, {6857,6855,6805 ,6899,6959,3343 }, - {6857,6856,6855 ,6899,6892,6959 }, {6806,6857,6805 ,6905,6899,3343 }, - {3454,5089,7052 ,710,3442,708 }, {3926,3891,6899 ,3125,3820,4005 }, - {4978,4567,5592 ,178,6655,3671 }, {2236,2237,6291 ,6802,6801,6873 }, - {5590,6071,6173 ,6386,1346,3711 }, {6918,6917,6895 ,6779,5515,5434 }, - {1749,2257,6713 ,555,554,6820 }, {4979,3319,5056 ,5363,1259,1300 }, - {6492,6515,6538 ,7047,7061,7048 }, {6768,6821,6820 ,7053,7062,7054 }, - {6821,6876,6875 ,7062,7063,7055 }, {6820,6821,6875 ,7054,7062,7055 }, - {6876,6925,6924 ,7063,7064,7056 }, {6875,6876,6924 ,7055,7063,7056 }, - {6973,6972,6924 ,7065,7057,7056 }, {6925,6973,6924 ,7064,7065,7056 }, - {6973,7036,6972 ,7065,7058,7057 }, {7030,4010,5533 ,6885,4343,6239 }, - {1881,2234,2241 ,7066,6949,6950 }, {2209,1881,2241 ,7038,7066,6950 }, - {1881,2209,1076 ,7066,7038,4887 }, {4142,1881,1076 ,6839,7066,4887 }, - {7077,4142,1076 ,6837,6839,4887 }, {5009,6463,4985 ,6803,5159,2703 }, - {7076,7077,1076 ,4886,6837,4887 }, {5926,6715,3814 ,6419,6929,5511 }, - {6108,1172,1221 ,6975,1758,1759 }, {7436,7412,7386 ,4245,3765,5512 }, - {3441,6443,3505 ,2987,6940,6928 }, {5370,5474,2160 ,2171,4243,6621 }, - {2257,4979,5056 ,554,5363,1300 }, {6286,6326,6325 ,4349,7067,7043 }, - {6116,6286,6325 ,4170,4349,7043 }, {6326,6363,6362 ,7067,7068,7044 }, - {6325,6326,6362 ,7043,7067,7044 }, {6363,6399,6398 ,7068,7069,7045 }, - {6362,6363,6398 ,7044,7068,7045 }, {6399,6449,6448 ,7069,7070,7046 }, - {6398,6399,6448 ,7045,7069,7046 }, {6449,6493,6492 ,7070,7071,7047 }, - {6448,6449,6492 ,7046,7070,7047 }, {6493,6516,6515 ,7071,7072,7061 }, - {6492,6493,6515 ,7047,7071,7061 }, {6516,6539,6538 ,7072,7073,7048 }, - {6515,6516,6538 ,7061,7072,7048 }, {6539,6585,6584 ,7073,7074,7049 }, - {6538,6539,6584 ,7048,7073,7049 }, {6626,6625,6584 ,7075,7050,7049 }, - {6585,6626,6584 ,7074,7075,7049 }, {6626,6666,6665 ,7075,7076,7051 }, - {6625,6626,6665 ,7050,7075,7051 }, {6666,6723,6722 ,7076,7077,7052 }, - {6665,6666,6722 ,7051,7076,7052 }, {6769,6768,6722 ,7078,7053,7052 }, - {6723,6769,6722 ,7077,7078,7052 }, {6769,6822,6821 ,7078,7079,7062 }, - {6768,6769,6821 ,7053,7078,7062 }, {6822,6877,6876 ,7079,7080,7063 }, - {6821,6822,6876 ,7062,7079,7063 }, {6877,6926,6925 ,7080,7081,7064 }, - {6876,6877,6925 ,7063,7080,7064 }, {6974,6973,6925 ,7082,7065,7064 }, - {6926,6974,6925 ,7081,7082,7064 }, {6974,7010,6973 ,7082,7083,7065 }, - {7010,7036,6973 ,7083,7058,7065 }, {7010,7070,7069 ,7083,7084,7059 }, - {7036,7010,7069 ,7058,7083,7059 }, {3813,5926,3814 ,1515,6419,5511 }, - {7972,7994,7948 ,6059,5582,3625 }, {4082,1426,3452 ,4716,4648,1794 }, - {2235,2234,1881 ,6870,6949,7066 }, {307,4989,6463 ,5095,5094,5159 }, - {2209,912,4617 ,7038,4471,4431 }, {7044,2248,7043 ,6859,6858,5895 }, - {2248,1075,1313 ,6858,6854,3674 }, {186,187,1171 ,1265,6439,6441 }, - {3133,1269,187 ,7085,5724,6439 }, {186,3133,187 ,1265,7085,6439 }, - {5890,4648,1269 ,6591,5722,5724 }, {3133,5890,1269 ,7085,6591,5724 }, - {1126,6037,1272 ,7086,5235,5740 }, {2237,6297,6291 ,6801,6851,6873 }, - {6748,1990,2406 ,3408,1305,6736 }, {6747,6748,2406 ,6878,3408,6736 }, - {4684,2245,3319 ,5217,1260,1259 }, {4979,4684,3319 ,5363,5217,1259 }, - {6305,6327,6326 ,7087,7088,7067 }, {6286,6305,6326 ,4349,7087,7067 }, - {6326,6327,6363 ,7067,7088,7068 }, {6769,6770,6822 ,7078,7089,7079 }, - {4901,7069,7070 ,3596,7059,7084 }, {4900,6378,2274 ,585,6728,893 }, - {6689,2405,2337 ,3065,4165,6829 }, {6378,1882,2274 ,6728,894,893 }, - {3556,3504,3557 ,3385,2986,6070 }, {4570,5072,6261 ,4082,6619,4321 }, - {5444,4544,5040 ,3410,748,5469 }, {7533,7568,7509 ,7039,5544,1874 }, - {6666,6724,6723 ,7076,7090,7077 }, {6724,6770,6769 ,7090,7089,7078 }, - {6723,6724,6769 ,7077,7090,7078 }, {6787,6805,6804 ,5269,3343,3342 }, - {978,977,4965 ,1620,3931,784 }, {6615,6652,6642 ,6924,6914,6960 }, - {3786,3400,1451 ,4074,3659,175 }, {6005,186,1171 ,5691,1265,6441 }, - {1026,733,5006 ,6218,4051,1351 }, {6507,6529,6479 ,2680,5025,2659 }, - {4988,5494,5020 ,6744,6569,6373 }, {8109,8127,8119 ,2938,2970,184 }, - {2246,2452,7066 ,591,7091,3586 }, {4684,6603,6359 ,5217,3985,6830 }, - {2245,4684,6359 ,1260,5217,6830 }, {6286,6287,6305 ,4349,4377,7087 }, - {6287,6328,6327 ,4377,7092,7088 }, {6305,6287,6327 ,7087,4377,7088 }, - {6328,6364,6363 ,7092,7093,7068 }, {6327,6328,6363 ,7088,7092,7068 }, - {6364,6400,6399 ,7093,7094,7069 }, {6363,6364,6399 ,7068,7093,7069 }, - {6400,6424,6399 ,7094,7095,7069 }, {6424,6450,6449 ,7095,7096,7070 }, - {6399,6424,6449 ,7069,7095,7070 }, {6450,6494,6493 ,7096,7097,7071 }, - {6449,6450,6493 ,7070,7096,7071 }, {6495,6516,6493 ,7098,7072,7071 }, - {6494,6495,6493 ,7097,7098,7071 }, {6540,6539,6516 ,7099,7073,7072 }, - {6495,6540,6516 ,7098,7099,7072 }, {6586,6585,6539 ,7100,7074,7073 }, - {6540,6586,6539 ,7099,7100,7073 }, {6586,6627,6626 ,7100,7101,7075 }, - {6585,6586,6626 ,7074,7100,7075 }, {6627,6667,6666 ,7101,7102,7076 }, - {6626,6627,6666 ,7075,7101,7076 }, {6667,6668,6666 ,7102,7103,7076 }, - {6668,6725,6724 ,7103,7104,7090 }, {6666,6668,6724 ,7076,7103,7090 }, - {6725,6771,6770 ,7104,7105,7089 }, {6724,6725,6770 ,7090,7104,7089 }, - {6771,6823,6822 ,7105,7106,7079 }, {6770,6771,6822 ,7089,7105,7079 }, - {6823,6878,6877 ,7106,7107,7080 }, {6822,6823,6877 ,7079,7106,7080 }, - {6927,6926,6877 ,7108,7081,7080 }, {6878,6927,6877 ,7107,7108,7080 }, - {6975,6974,6926 ,7109,7082,7081 }, {6927,6975,6926 ,7108,7109,7081 }, - {6975,7011,7010 ,7109,7110,7083 }, {6974,6975,7010 ,7082,7109,7083 }, - {7011,7071,7070 ,7110,7111,7084 }, {7010,7011,7070 ,7083,7110,7084 }, - {7071,1261,7070 ,7111,6472,7084 }, {1261,5591,7070 ,6472,3597,7084 }, - {4986,6659,3399 ,5096,3577,715 }, {6854,6855,6893 ,3344,6959,6844 }, - {1076,2209,4617 ,4887,7038,4431 }, {4746,5078,6302 ,5260,5261,6869 }, - {2291,2221,3133 ,1115,6902,7085 }, {186,2291,3133 ,1265,1115,7085 }, - {2221,6214,5890 ,6902,6942,6591 }, {3133,2221,5890 ,7085,6902,6591 }, - {4950,4115,1216 ,1302,6909,6893 }, {5072,6220,6231 ,6619,6600,6624 }, - {2260,5494,4988 ,6571,6569,6744 }, {2211,2260,4988 ,6780,6571,6744 }, - {5444,5040,5024 ,3410,5469,6952 }, {2157,5444,5024 ,3411,3410,6952 }, - {5591,4901,7070 ,3597,3596,7084 }, {6627,6668,6667 ,7101,7103,7102 }, - {5330,5331,5350 ,3345,6198,1526 }, {5611,6920,5593 ,6177,6783,5935 }, - {6234,6259,6167 ,5973,6718,5974 }, {2717,819,728 ,2676,2244,1266 }, - {2025,2000,2027 ,2430,2428,2492 }, {2342,2221,5114 ,5690,6902,5689 }, - {5435,5401,6611 ,4223,4145,1391 }, {6529,6576,6528 ,5025,6883,6964 }, - {6870,2222,2205 ,2616,2509,2874 }, {6603,1116,5074 ,3985,1401,6751 }, - {6359,6603,5074 ,6830,3985,6751 }, {6476,6495,6494 ,7112,7098,7097 }, - {6450,6476,6494 ,7096,7112,7097 }, {6586,6628,6627 ,7100,7113,7101 }, - {6627,6628,6668 ,7101,7113,7103 }, {6163,3860,6029 ,1453,6523,1454 }, - {5059,7081,2220 ,1253,7114,6724 }, {1171,187,3498 ,6441,6439,5800 }, - {7022,6696,3649 ,6754,6849,6755 }, {2260,2211,6951 ,6571,6780,2615 }, - {2157,5024,2244 ,3411,6952,6795 }, {6278,6288,6287 ,3967,7115,4377 }, - {6277,6278,6287 ,4387,3967,4377 }, {6288,6329,6328 ,7115,7116,7092 }, - {6287,6288,6328 ,4377,7115,7092 }, {6329,6365,6364 ,7116,7117,7093 }, - {6328,6329,6364 ,7092,7116,7093 }, {6365,6401,6400 ,7117,7118,7094 }, - {6364,6365,6400 ,7093,7117,7094 }, {6401,6425,6424 ,7118,7119,7095 }, - {6400,6401,6424 ,7094,7118,7095 }, {6425,6451,6450 ,7119,7120,7096 }, - {6424,6425,6450 ,7095,7119,7096 }, {6450,6451,6476 ,7096,7120,7112 }, - {6451,6496,6495 ,7120,7121,7098 }, {6476,6451,6495 ,7112,7120,7098 }, - {6496,6541,6540 ,7121,7122,7099 }, {6495,6496,6540 ,7098,7121,7099 }, - {6541,6587,6586 ,7122,7123,7100 }, {6540,6541,6586 ,7099,7122,7100 }, - {6587,6607,6586 ,7123,7124,7100 }, {6607,6629,6628 ,7124,7125,7113 }, - {6586,6607,6628 ,7100,7124,7113 }, {6629,6669,6668 ,7125,7126,7103 }, - {6628,6629,6668 ,7113,7125,7103 }, {6669,6726,6725 ,7126,7127,7104 }, - {6668,6669,6725 ,7103,7126,7104 }, {6772,6771,6725 ,7128,7105,7104 }, - {6726,6772,6725 ,7127,7128,7104 }, {6772,6824,6823 ,7128,7129,7106 }, - {6771,6772,6823 ,7105,7128,7106 }, {6824,6879,6878 ,7129,7130,7107 }, - {6823,6824,6878 ,7106,7129,7107 }, {6879,6880,6878 ,7130,7131,7107 }, - {6880,6928,6927 ,7131,7132,7108 }, {6878,6880,6927 ,7107,7131,7108 }, - {6976,6975,6927 ,7133,7109,7108 }, {6928,6976,6927 ,7132,7133,7108 }, - {6976,7012,7011 ,7133,7134,7110 }, {6975,6976,7011 ,7109,7133,7110 }, - {7053,7071,7011 ,6654,7111,7110 }, {7012,7053,7011 ,7134,6654,7110 }, - {1723,1261,7071 ,6626,6472,7111 }, {7053,1723,7071 ,6654,6626,7111 }, - {8127,3221,8119 ,2970,183,184 }, {6792,6839,6810 ,5056,6867,6908 }, - {7533,7595,7568 ,7039,4019,5544 }, {3979,5055,5753 ,6471,6470,6481 }, - {5008,3217,6214 ,6118,6117,6942 }, {2221,5008,6214 ,6902,6118,6942 }, - {6214,3217,5747 ,6942,6117,6036 }, {6654,6653,6616 ,6884,6915,6882 }, - {6529,6528,6479 ,5025,6964,2659 }, {8038,3638,8052 ,4121,5950,4122 }, - {6049,2260,6951 ,6570,6571,2615 }, {6606,2157,2244 ,5085,3411,6795 }, - {4990,1124,6065 ,7135,5852,6616 }, {1116,2239,185 ,1401,1377,1493 }, - {5074,1116,185 ,6751,1401,1493 }, {6824,6880,6879 ,7129,7131,7130 }, - {6880,6929,6928 ,7131,7136,7132 }, {6929,6976,6928 ,7136,7133,7132 }, - {6977,7013,7012 ,7137,7138,7134 }, {6976,6977,7012 ,7133,7137,7134 }, - {7013,7053,7012 ,7138,6654,7134 }, {7570,7625,7598 ,5204,7139,7140 }, - {6910,6941,6961 ,6741,6793,6813 }, {7000,7024,7042 ,6814,6816,5338 }, - {5328,2160,2238 ,2172,6621,2697 }, {5045,7061,6165 ,4214,7141,4219 }, - {4649,5125,5118 ,5288,5467,6825 }, {1214,6049,6951 ,6573,6570,2615 }, - {6606,2244,4856 ,5085,6795,4081 }, {3040,8072,8076 ,619,511,617 }, - {6824,6850,6880 ,7129,7142,7131 }, {6929,6977,6976 ,7136,7137,7133 }, - {7054,7053,7013 ,7143,6654,7138 }, {7081,4233,2220 ,7114,6185,6724 }, - {5124,4010,3969 ,6567,4343,3226 }, {7454,7511,7453 ,3996,6677,1187 }, - {5057,1214,6951 ,1795,6573,2615 }, {2454,6606,4856 ,1345,5085,4081 }, - {4209,3777,185 ,6269,1582,1493 }, {2239,4209,185 ,1377,6269,1493 }, - {6279,6289,6288 ,3966,7144,7115 }, {6278,6279,6288 ,3967,3966,7115 }, - {6289,6330,6329 ,7144,7145,7116 }, {6288,6289,6329 ,7115,7144,7116 }, - {6366,6365,6329 ,7146,7117,7116 }, {6330,6366,6329 ,7145,7146,7116 }, - {6366,6402,6401 ,7146,7147,7118 }, {6365,6366,6401 ,7117,7146,7118 }, - {6402,6403,6425 ,7147,7148,7119 }, {6401,6402,6425 ,7118,7147,7119 }, - {6403,6452,6451 ,7148,7149,7120 }, {6425,6403,6451 ,7119,7148,7120 }, - {6452,6497,6496 ,7149,7150,7121 }, {6451,6452,6496 ,7120,7149,7121 }, - {6497,6542,6541 ,7150,7151,7122 }, {6496,6497,6541 ,7121,7150,7122 }, - {6542,6588,6587 ,7151,7152,7123 }, {6541,6542,6587 ,7122,7151,7123 }, - {6588,6589,6607 ,7152,7153,7124 }, {6587,6588,6607 ,7123,7152,7124 }, - {6589,6630,6629 ,7153,7154,7125 }, {6607,6589,6629 ,7124,7153,7125 }, - {6630,6670,6669 ,7154,7155,7126 }, {6629,6630,6669 ,7125,7154,7126 }, - {6727,6726,6669 ,7156,7127,7126 }, {6670,6727,6669 ,7155,7156,7126 }, - {6773,6772,6726 ,7157,7128,7127 }, {6727,6773,6726 ,7156,7157,7127 }, - {6773,6825,6824 ,7157,7158,7129 }, {6772,6773,6824 ,7128,7157,7129 }, - {6825,6826,6850 ,7158,7159,7142 }, {6824,6825,6850 ,7129,7158,7142 }, - {6826,6881,6880 ,7159,7160,7131 }, {6850,6826,6880 ,7142,7159,7131 }, - {6881,6930,6929 ,7160,7161,7136 }, {6880,6881,6929 ,7131,7160,7136 }, - {6930,6978,6977 ,7161,7162,7137 }, {6929,6930,6977 ,7136,7161,7137 }, - {6978,7014,7013 ,7162,7163,7138 }, {6977,6978,7013 ,7137,7162,7138 }, - {7055,7054,7013 ,5485,7143,7138 }, {7014,7055,7013 ,7163,5485,7138 }, - {7055,7053,7054 ,5485,6654,7143 }, {7055,7079,7053 ,5485,5486,6654 }, - {6618,6617,5404 ,6910,6881,3559 }, {2273,2342,350 ,5322,5690,1114 }, - {1273,2273,350 ,6403,5322,1114 }, {5254,6030,5576 ,4042,4037,4039 }, - {1214,5057,6122 ,6573,1795,1797 }, {6101,1214,6122 ,6574,6573,1797 }, - {2272,2454,6386 ,1201,1345,4085 }, {4853,1118,2340 ,6747,6746,6797 }, - {875,2252,6836 ,579,590,852 }, {7053,7079,6150 ,6654,5486,6653 }, - {6366,6403,6402 ,7146,7148,7147 }, {6542,6589,6588 ,7151,7153,7152 }, - {1219,6150,7079 ,4102,6653,5486 }, {6916,6967,6915 ,596,4629,6871 }, - {6841,6840,6812 ,7164,6868,6872 }, {6967,6987,6966 ,4629,6917,6840 }, - {6794,6841,6812 ,6880,7164,6872 }, {6864,6894,6840 ,6865,6887,6868 }, - {6651,6699,6698 ,6785,630,629 }, {6967,6966,6915 ,4629,6840,6871 }, - {5944,1273,5653 ,4754,6403,3644 }, {4465,4483,4444 ,257,549,582 }, - {6392,3929,306 ,6963,5024,6234 }, {3302,6301,6300 ,6757,6147,6146 }, - {4755,2272,1164 ,6770,1201,5087 }, {2454,4856,6386 ,1345,4081,4085 }, - {6682,6679,3978 ,6812,4824,4549 }, {2252,144,6836 ,590,853,852 }, - {6542,6567,6589 ,7151,7165,7153 }, {6773,6826,6825 ,7157,7159,7158 }, - {5838,6355,6079 ,3987,3786,5580 }, {6650,6651,6698 ,3833,6785,629 }, - {7450,7478,7422 ,399,1402,1404 }, {5944,1126,1273 ,4754,7086,6403 }, - {1074,973,8073 ,2715,2017,2567 }, {3929,4166,306 ,5024,6084,6234 }, - {3675,3674,6180 ,4300,4286,6811 }, {2272,6386,1164 ,1201,4085,5087 }, - {6961,6962,7000 ,6813,3260,6814 }, {1220,1271,875 ,4885,588,579 }, - {6280,6290,6289 ,4079,7166,7144 }, {6279,6280,6289 ,3966,4079,7144 }, - {6290,6331,6330 ,7166,7167,7145 }, {6289,6290,6330 ,7144,7166,7145 }, - {6331,6367,6366 ,7167,7168,7146 }, {6330,6331,6366 ,7145,7167,7146 }, - {6367,6404,6403 ,7168,7169,7148 }, {6366,6367,6403 ,7146,7168,7148 }, - {6404,6426,6403 ,7169,7170,7148 }, {6426,6453,6452 ,7170,7171,7149 }, - {6403,6426,6452 ,7148,7170,7149 }, {6498,6497,6452 ,7172,7150,7149 }, - {6453,6498,6452 ,7171,7172,7149 }, {6498,6543,6542 ,7172,7173,7151 }, - {6497,6498,6542 ,7150,7172,7151 }, {6543,6544,6567 ,7173,7174,7165 }, - {6542,6543,6567 ,7151,7173,7165 }, {6544,6590,6589 ,7174,7175,7153 }, - {6567,6544,6589 ,7165,7174,7153 }, {6590,6631,6630 ,7175,7176,7154 }, - {6589,6590,6630 ,7153,7175,7154 }, {6631,6671,6670 ,7176,7177,7155 }, - {6630,6631,6670 ,7154,7176,7155 }, {6728,6727,6670 ,7178,7156,7155 }, - {6671,6728,6670 ,7177,7178,7155 }, {6728,6774,6773 ,7178,7179,7157 }, - {6727,6728,6773 ,7156,7178,7157 }, {6774,6775,6773 ,7179,7180,7157 }, - {6775,6827,6826 ,7180,7181,7159 }, {6773,6775,6826 ,7157,7180,7159 }, - {6827,6882,6881 ,7181,7182,7160 }, {6826,6827,6881 ,7159,7181,7160 }, - {6882,6931,6930 ,7182,7183,7161 }, {6881,6882,6930 ,7160,7182,7161 }, - {6931,6979,6978 ,7183,7184,7162 }, {6930,6931,6978 ,7161,7183,7162 }, - {6979,7015,7014 ,7184,7185,7163 }, {6978,6979,7014 ,7162,7184,7163 }, - {7056,7055,7014 ,7186,5485,7163 }, {7015,7056,7014 ,7185,7186,7163 }, - {1170,1219,7055 ,4103,4102,5485 }, {7056,1170,7055 ,7186,4103,5485 }, - {5499,5704,2621 ,5572,5579,5416 }, {6660,6220,5072 ,6601,6600,6619 }, - {4570,6660,5072 ,4082,6601,6619 }, {1121,5872,1122 ,6564,6557,6719 }, - {6786,6787,6804 ,4139,5269,3342 }, {3834,4570,4044 ,4083,4082,4322 }, - {5426,4807,5010 ,5634,6449,6006 }, {4803,5290,5267 ,4776,5247,4647 }, - {2154,2273,1273 ,5321,5322,6403 }, {1126,2154,1273 ,7086,5321,6403 }, - {5516,5551,6795 ,5420,6260,5418 }, {403,3929,6466 ,5547,5024,6930 }, - {5054,6688,6661 ,6847,6846,6876 }, {2015,2048,1994 ,759,5461,5102 }, - {7001,7025,7024 ,6815,6824,6816 }, {7048,7064,2074 ,6790,5181,6990 }, - {1271,2252,875 ,588,590,579 }, {7064,2073,2074 ,5181,5183,6990 }, - {6498,6544,6543 ,7172,7174,7173 }, {6728,6775,6774 ,7178,7180,7179 }, - {6660,6219,6220 ,6601,6598,6600 }, {4486,3340,3454 ,819,114,710 }, - {6526,6574,6573 ,6784,3885,3733 }, {5738,5688,5689 ,5520,5519,5741 }, - {307,6391,6659 ,5095,6804,3577 }, {3929,6392,6466 ,5024,6963,6930 }, - {5113,5914,5150 ,141,1566,6032 }, {6435,6436,6480 ,2658,3681,1524 }, - {3649,5054,6661 ,6755,6847,6876 }, {7067,2246,7066 ,3585,591,3586 }, - {1197,2384,1987 ,478,6821,3614 }, {4190,1271,1220 ,3439,588,4885 }, - {7007,7006,6966 ,4628,6841,6840 }, {6631,6672,6671 ,7176,7187,7177 }, - {6672,6728,6671 ,7187,7178,7177 }, {6807,6808,6858 ,6764,3465,6740 }, - {6703,6701,6702 ,5161,6766,7060 }, {2337,5578,1124 ,6829,587,5852 }, - {4990,2337,1124 ,7135,6829,5852 }, {1025,2450,6657 ,5299,3444,6828 }, - {6689,2337,4990 ,3065,6829,7135 }, {1608,746,5592 ,4128,2661,3671 }, - {5277,5330,5276 ,6237,3345,1525 }, {7068,3892,6166 ,7019,4970,4971 }, - {6034,6284,5952 ,6049,6113,6595 }, {403,6466,1074 ,5547,6930,2715 }, - {5078,403,1074 ,5261,5547,2715 }, {6807,6858,6838 ,6764,6740,6904 }, - {158,4755,5560 ,5258,6770,6605 }, {5076,158,5560 ,6607,5258,6605 }, - {1213,3261,1197 ,3700,5015,478 }, {1987,4190,1220 ,3614,3439,4885 }, - {1620,6128,6184 ,5982,5981,6089 }, {6281,3526,6290 ,4078,7188,7166 }, - {6280,6281,6290 ,4079,4078,7166 }, {3526,6332,6331 ,7188,7189,7167 }, - {6290,3526,6331 ,7166,7188,7167 }, {6368,6367,6331 ,7190,7168,7167 }, - {6332,6368,6331 ,7189,7190,7167 }, {6368,6405,6404 ,7190,7191,7169 }, - {6367,6368,6404 ,7168,7190,7169 }, {6405,6427,6426 ,7191,7192,7170 }, - {6404,6405,6426 ,7169,7191,7170 }, {6427,6454,6453 ,7192,7193,7171 }, - {6426,6427,6453 ,7170,7192,7171 }, {6454,6499,6498 ,7193,7194,7172 }, - {6453,6454,6498 ,7171,7193,7172 }, {6499,6517,6498 ,7194,7195,7172 }, - {6517,6545,6544 ,7195,7196,7174 }, {6498,6517,6544 ,7172,7195,7174 }, - {6545,6591,6590 ,7196,7197,7175 }, {6544,6545,6590 ,7174,7196,7175 }, - {6632,6631,6590 ,7198,7176,7175 }, {6591,6632,6590 ,7197,7198,7175 }, - {6632,6673,6672 ,7198,7199,7187 }, {6631,6632,6672 ,7176,7198,7187 }, - {6729,6728,6672 ,7200,7178,7187 }, {6673,6729,6672 ,7199,7200,7187 }, - {6729,6776,6775 ,7200,7201,7180 }, {6728,6729,6775 ,7178,7200,7180 }, - {6776,6828,6827 ,7201,7202,7181 }, {6775,6776,6827 ,7180,7201,7181 }, - {6828,6883,6882 ,7202,7203,7182 }, {6827,6828,6882 ,7181,7202,7182 }, - {6883,6932,6931 ,7203,7204,7183 }, {6882,6883,6931 ,7182,7203,7183 }, - {6932,6980,6979 ,7204,7205,7184 }, {6931,6932,6979 ,7183,7204,7184 }, - {6980,7016,7015 ,7205,7206,7185 }, {6979,6980,7015 ,7184,7205,7185 }, - {7057,7056,7015 ,7207,7186,7185 }, {7016,7057,7015 ,7206,7207,7185 }, - {1122,1170,7056 ,6719,4103,7186 }, {7057,1122,7056 ,7207,6719,7186 }, - {1170,1122,1620 ,4103,6719,5982 }, {6655,6703,6654 ,5407,5161,6884 }, - {6430,5733,5353 ,2748,1584,851 }, {4023,5248,4178 ,3827,6469,3825 }, - {6319,6345,5118 ,6789,191,6825 }, {5734,5733,4261 ,6230,1584,1583 }, - {2450,6689,6657 ,3444,3065,6828 }, {2621,3815,5359 ,5416,5556,3713 }, - {7196,7231,7212 ,2401,6944,7208 }, {2160,2154,1126 ,6621,5321,7086 }, - {1272,2160,1126 ,5740,6621,7086 }, {7024,7025,7042 ,6816,6824,5338 }, - {4755,1164,5560 ,6770,5087,6605 }, {2384,4190,1987 ,6821,3439,3614 }, - {7998,7997,7950 ,7209,7210,7211 }, {5514,6158,6293 ,6128,6112,7212 }, - {6703,6702,6654 ,5161,7060,6884 }, {6307,6301,3302 ,5206,6147,6757 }, - {4018,6307,3302 ,5084,5206,6757 }, {6657,6689,4990 ,6828,3065,7135 }, - {6521,3261,6639 ,6819,5015,3699 }, {5496,6521,6564 ,6966,6819,6933 }, - {6521,6639,6508 ,6819,3699,6934 }, {6741,6794,6756 ,5388,6880,6891 }, - {6896,6895,6842 ,6787,5434,5433 }, {5005,5496,4115 ,1301,6966,6909 }, - {6792,6810,6791 ,5056,6908,6900 }, {1075,2409,2373 ,6854,6852,6722 }, - {5057,6951,6796 ,1795,2615,2617 }, {6345,6319,3533 ,191,6789,192 }, - {6521,6508,6564 ,6819,6934,6933 }, {3261,2384,1197 ,5015,6821,478 }, - {5369,1124,5904 ,6609,5852,5851 }, {5566,5605,5604 ,5759,5761,7213 }, - {5140,2621,5359 ,3712,5416,3713 }, {3505,6443,3504 ,6928,6940,2986 }, - {5496,6564,3320 ,6966,6933,5455 }, {5514,5943,7088 ,6128,5402,4299 }, - {7065,7064,7049 ,5182,5181,5454 }, {3261,1213,6639 ,5015,3700,3699 }, - {5496,3320,5058 ,6966,5455,5647 }, {6867,6844,5551 ,6951,6822,6260 }, - {4926,920,3367 ,3897,57,5798 }, {5014,2450,1025 ,6818,3444,5299 }, - {2238,2160,1272 ,2697,6621,5740 }, {6906,6907,6958 ,4294,6002,4314 }, - {876,4232,4208 ,5340,6299,6356 }, {6711,6710,6301 ,3473,6968,6147 }, - {1216,4115,4547 ,6893,6909,242 }, {7387,3303,3322 ,3615,1049,1182 }, - {5552,5593,6867 ,5936,5935,6951 }, {1124,5369,6065 ,5852,6609,6616 }, - {3526,6281,6060 ,7188,4078,5914 }, {6060,6333,6332 ,5914,7214,7189 }, - {3526,6060,6332 ,7188,5914,7189 }, {6369,6368,6332 ,7215,7190,7189 }, - {6333,6369,6332 ,7214,7215,7189 }, {6406,6405,6368 ,7216,7191,7190 }, - {6369,6406,6368 ,7215,7216,7190 }, {6428,6427,6405 ,7217,7192,7191 }, - {6406,6428,6405 ,7216,7217,7191 }, {6455,6454,6427 ,7218,7193,7192 }, - {6428,6455,6427 ,7217,7218,7192 }, {6455,6500,6499 ,7218,7219,7194 }, - {6454,6455,6499 ,7193,7218,7194 }, {6500,6518,6517 ,7219,7220,7195 }, - {6499,6500,6517 ,7194,7219,7195 }, {6518,6546,6545 ,7220,7221,7196 }, - {6517,6518,6545 ,7195,7220,7196 }, {6546,6592,6591 ,7221,7222,7197 }, - {6545,6546,6591 ,7196,7221,7197 }, {6592,6633,6632 ,7222,7223,7198 }, - {6591,6592,6632 ,7197,7222,7198 }, {6633,6674,6673 ,7223,7224,7199 }, - {6632,6633,6673 ,7198,7223,7199 }, {6730,6729,6673 ,7225,7200,7199 }, - {6674,6730,6673 ,7224,7225,7199 }, {6730,6777,6776 ,7225,7226,7201 }, - {6729,6730,6776 ,7200,7225,7201 }, {6777,6829,6828 ,7226,7227,7202 }, - {6776,6777,6828 ,7201,7226,7202 }, {6829,6884,6883 ,7227,7228,7203 }, - {6828,6829,6883 ,7202,7227,7203 }, {6884,6933,6932 ,7228,7229,7204 }, - {6883,6884,6932 ,7203,7228,7204 }, {6933,6981,6980 ,7229,7230,7205 }, - {6932,6933,6980 ,7204,7229,7205 }, {6981,6126,7016 ,7230,7231,7206 }, - {6980,6981,7016 ,7205,7230,7206 }, {6126,6107,7016 ,7231,7232,7206 }, - {7016,6107,7057 ,7206,7232,7207 }, {5693,5714,7028 ,4075,4077,3587 }, - {1122,7057,5936 ,6719,7207,4393 }, {4554,1989,6323 ,1307,3016,1451 }, - {3860,5246,6028 ,6523,5176,5316 }, {4115,5058,4547 ,6909,5647,242 }, - {6319,6318,6304 ,6789,6788,7233 }, {1121,1122,5936 ,6564,6719,4393 }, - {4115,5496,5058 ,6909,6966,5647 }, {1882,1072,4547 ,894,6725,242 }, - {6711,5014,1025 ,3473,6818,5299 }, {6178,3892,4901 ,5881,4970,3596 }, - {6867,5551,5552 ,6951,6260,5936 }, {7370,7396,7343 ,3750,6716,2750 }, - {6307,6711,6301 ,5206,3473,6147 }, {2343,8067,8097 ,2685,2168,1710 }, - {4784,4542,3285 ,3423,6727,3064 }, {4542,6481,4900 ,6727,6729,585 }, - {7197,5112,5111 ,7234,6021,5990 }, {6387,4784,3285 ,6935,3423,3064 }, - {3285,4542,4900 ,3064,6727,585 }, {6633,6645,6674 ,7223,7235,7224 }, - {6995,6107,6126 ,7236,7232,7231 }, {6981,6995,6126 ,7230,7236,7231 }, - {5503,5504,5531 ,7042,5781,5783 }, {5713,4648,5890 ,5776,5722,6591 }, - {2374,2304,1118 ,7037,6756,6746 }, {1027,2374,1118 ,6991,7037,6746 }, - {5838,6318,6355 ,3987,6788,3786 }, {6378,2220,1882 ,6728,6724,894 }, - {6709,1072,1882 ,6726,6725,894 }, {2244,5024,6660 ,6795,6952,6601 }, - {6710,6711,1025 ,6968,3473,5299 }, {1524,1655,4872 ,4326,4089,5522 }, - {6839,6862,6810 ,6867,6877,6908 }, {7650,7699,7649 ,7237,3951,3950 }, - {7595,7594,7568 ,4019,4020,5544 }, {5970,4170,4146 ,3518,3731,3730 }, - {2374,4018,3302 ,7037,5084,6757 }, {4144,5292,5175 ,4761,5093,6384 }, - {1217,2220,6378 ,6399,6724,6728 }, {1072,1216,4547 ,6725,6893,242 }, - {5024,5040,2138 ,6952,5469,6602 }, {5040,3704,2138 ,5469,2332,6602 }, - {5111,7166,7197 ,5990,5971,7234 }, {6234,5845,7255 ,5973,143,7238 }, - {5112,7197,6120 ,6021,7234,142 }, {6281,7089,5115 ,4078,5608,5913 }, - {6829,6851,6884 ,7227,7239,7228 }, {6885,6934,6933 ,7240,7241,7229 }, - {6884,6885,6933 ,7228,7240,7229 }, {6934,6982,6981 ,7241,7242,7230 }, - {6933,6934,6981 ,7229,7241,7230 }, {6981,6982,6995 ,7230,7242,7236 }, - {6982,7017,6107 ,7242,7243,7232 }, {6995,6982,6107 ,7236,7242,7232 }, - {7017,5930,6143 ,7243,6593,4394 }, {6107,7017,6143 ,7232,7243,4394 }, - {7424,7451,7423 ,1188,3963,3749 }, {4835,1218,8118 ,2130,3255,2129 }, - {7650,7649,7595 ,7237,3950,4019 }, {2209,2241,2240 ,7038,6950,4478 }, - {1394,1027,1118 ,6989,6991,6746 }, {2335,1394,1118 ,6737,6989,6746 }, - {4784,2406,4542 ,3423,6736,6727 }, {6814,1217,4542 ,6842,6399,6727 }, - {4530,1554,4209 ,1376,6304,6269 }, {4574,1268,6062 ,6477,4568,6478 }, - {2220,6709,1882 ,6724,6726,894 }, {5166,5473,5120 ,3427,3429,5857 }, - {1655,1524,2432 ,4089,4326,5427 }, {5427,5395,5428 ,5811,5348,5812 }, - {8093,8076,8072 ,2288,617,511 }, {6569,4746,2222 ,6745,5260,2509 }, - {5277,5276,5255 ,6237,1525,3682 }, {6180,3623,3675 ,6811,4206,4300 }, - {6868,6657,5041 ,5554,6828,6799 }, {2304,2374,3302 ,6756,7037,6757 }, - {6318,6356,6355 ,6788,3787,3786 }, {6746,6747,4784 ,6864,6878,3423 }, - {4542,1217,6378 ,6727,6399,6728 }, {7160,7185,7159 ,6271,5073,5075 }, - {7267,7246,7291 ,4331,3772,3774 }, {4552,1309,3371 ,7244,3709,3708 }, - {3265,4552,3371 ,1033,7244,3708 }, {7127,7128,7159 ,7245,5391,5075 }, - {6292,6334,6333 ,5403,7246,7214 }, {6060,6292,6333 ,5914,5403,7214 }, - {6334,6335,6333 ,7246,6534,7214 }, {6370,6369,6333 ,7247,7215,7214 }, - {6335,6370,6333 ,6534,7247,7214 }, {6407,6406,6369 ,7248,7216,7215 }, - {6370,6407,6369 ,7247,7248,7215 }, {6429,6428,6406 ,7249,7217,7216 }, - {6407,6429,6406 ,7248,7249,7216 }, {6429,6456,6455 ,7249,7250,7218 }, - {6428,6429,6455 ,7217,7249,7218 }, {6456,6501,6500 ,7250,7251,7219 }, - {6455,6456,6500 ,7218,7250,7219 }, {6519,6518,6500 ,7252,7220,7219 }, - {6501,6519,6500 ,7251,7252,7219 }, {6547,6546,6518 ,7253,7221,7220 }, - {6519,6547,6518 ,7252,7253,7220 }, {6547,6593,6592 ,7253,7254,7222 }, - {6546,6547,6592 ,7221,7253,7222 }, {6593,6634,6633 ,7254,7255,7223 }, - {6592,6593,6633 ,7222,7254,7223 }, {6633,6634,6645 ,7223,7255,7235 }, - {6634,6675,6674 ,7255,7256,7224 }, {6645,6634,6674 ,7235,7255,7224 }, - {6675,6731,6730 ,7256,7257,7225 }, {6674,6675,6730 ,7224,7256,7225 }, - {6731,6778,6777 ,7257,7258,7226 }, {6730,6731,6777 ,7225,7257,7226 }, - {6778,6830,6829 ,7258,7259,7227 }, {6777,6778,6829 ,7226,7258,7227 }, - {6829,6830,6851 ,7227,7259,7239 }, {6830,6885,6884 ,7259,7240,7228 }, - {6851,6830,6884 ,7239,7259,7228 }, {6935,6934,6885 ,7260,7241,7240 }, - {6934,6935,6982 ,7241,7260,7242 }, {1664,6228,751 ,2268,1366,1365 }, - {7047,2335,7046 ,6853,6737,6735 }, {5053,1025,6389 ,6848,5299,5301 }, - {6714,6657,6868 ,5300,6828,5554 }, {3872,5082,1551 ,4811,5218,5275 }, - {2406,6814,4542 ,6736,6842,6727 }, {6312,6747,6746 ,6749,6878,6864 }, - {3510,75,2837 ,6267,3962,2511 }, {2837,1518,3510 ,2511,3978,6267 }, - {6114,6355,5151 ,1805,3786,1803 }, {5085,1947,1881 ,3675,6723,7066 }, - {5041,6065,5687 ,6799,6616,6420 }, {3336,3309,6285 ,3922,3892,3923 }, - {4831,3340,4486 ,3154,114,819 }, {6318,5838,6303 ,6788,3987,7261 }, - {6303,6304,6318 ,7261,7233,6788 }, {7116,7115,7089 ,7262,1024,5608 }, - {6432,6553,3265 ,1032,780,1033 }, {5914,5170,5150 ,1566,3683,6032 }, - {7149,7173,7165 ,7263,7264,7265 }, {6292,6335,6334 ,5403,6534,7246 }, - {6371,6370,6335 ,7266,7247,6534 }, {6370,6371,6407 ,7247,7266,7248 }, - {6593,6608,6634 ,7254,7267,7255 }, {6688,5102,5101 ,6846,6845,6422 }, - {5491,6795,6741 ,5419,5418,5388 }, {1380,6312,6310 ,6721,6749,3918 }, - {6747,2406,4784 ,6878,6736,3423 }, {6310,6312,6746 ,3918,6749,6864 }, - {1126,5944,6037 ,7086,4754,5235 }, {4574,3079,5301 ,6477,6540,2698 }, - {209,648,4892 ,4499,4679,5386 }, {3079,3631,5301 ,6540,5922,2698 }, - {4233,1026,1072 ,6185,6218,6725 }, {5102,5041,5007 ,6845,6799,7268 }, - {5007,5041,5687 ,7268,6799,6420 }, {7047,1394,2335 ,6853,6989,6737 }, - {5479,5491,6741 ,5387,5419,5388 }, {6795,6794,6741 ,5418,6880,5388 }, - {255,1380,256 ,6731,6721,7269 }, {3277,2567,227 ,961,2842,2157 }, - {6083,6303,5838 ,3989,7261,3987 }, {7797,7875,7848 ,3506,4118,343 }, - {6620,3265,6553 ,7270,1033,780 }, {1309,4552,3935 ,3709,7244,4346 }, - {6079,6343,5838 ,5580,5122,3987 }, {6895,6916,6864 ,5434,596,6865 }, - {6962,6963,7001 ,3260,1048,6815 }, {1170,6184,5627 ,4103,6089,6628 }, - {4588,4587,8020 ,775,774,1405 }, {6292,6306,6335 ,5403,5669,6534 }, - {6608,6635,6634 ,7267,7271,7255 }, {6676,6675,6634 ,7272,7256,7255 }, - {6635,6676,6634 ,7271,7272,7255 }, {6676,6732,6731 ,7272,7273,7257 }, - {6675,6676,6731 ,7256,7272,7257 }, {6732,6779,6778 ,7273,7274,7258 }, - {6731,6732,6778 ,7257,7273,7258 }, {6779,6800,6778 ,7274,7275,7258 }, - {6800,6831,6830 ,7275,7276,7259 }, {6778,6800,6830 ,7258,7275,7259 }, - {6831,6886,6885 ,7276,7277,7240 }, {6830,6831,6885 ,7259,7276,7240 }, - {6936,6935,6885 ,7278,7260,7240 }, {6886,6936,6885 ,7277,7278,7240 }, - {6936,6983,6982 ,7278,7279,7242 }, {6935,6936,6982 ,7260,7278,7242 }, - {6983,7018,7017 ,7279,7280,7243 }, {6982,6983,7017 ,7242,7279,7243 }, - {7058,5930,7017 ,6594,6593,7243 }, {7018,7058,7017 ,7280,6594,7243 }, - {1120,1167,876 ,5339,5341,5340 }, {3498,6005,1171 ,5800,5691,6441 }, - {5101,5007,5687 ,6422,7268,6420 }, {2240,2241,3978 ,4478,6950,4549 }, - {6795,6813,6794 ,5418,6916,6880 }, {3281,1380,6310 ,6794,6721,3918 }, - {6688,5101,5048 ,6846,6422,6421 }, {352,255,256 ,593,6731,7269 }, - {353,352,256 ,7281,593,7269 }, {6842,6841,6794 ,5433,7164,6880 }, - {6813,6842,6794 ,6916,5433,6880 }, {5101,5102,5007 ,6422,6845,7268 }, - {6865,6840,6841 ,5435,6868,7164 }, {6842,6865,6841 ,5433,5435,7164 }, - {7500,4595,6345 ,326,5289,191 }, {7271,7320,7270 ,2554,7282,2555 }, - {7898,7874,7848 ,4117,344,343 }, {6314,6553,6646 ,1132,780,1133 }, - {7539,7515,7538 ,1080,1079,2014 }, {5051,6620,6553 ,7283,7270,780 }, - {6314,5051,6553 ,1132,7283,780 }, {5051,3265,6620 ,7283,1033,7270 }, - {6798,4552,3265 ,7284,7244,1033 }, {5051,6798,3265 ,7283,7284,1033 }, - {5010,4807,4552 ,6006,6449,7244 }, {6798,5010,4552 ,7284,6006,7244 }, - {5943,6306,6292 ,5402,5669,5403 }, {2247,2452,353 ,7285,7091,7281 }, - {1380,3281,256 ,6721,6794,7269 }, {4588,8020,7995 ,775,1405,4135 }, - {6048,6049,1214 ,6552,6570,6573 }, {3820,1218,4835 ,5591,3255,2130 }, - {6372,6371,6335 ,7286,7266,6534 }, {6336,6372,6335 ,5670,7286,6534 }, - {6372,6408,6407 ,7286,7287,7248 }, {6371,6372,6407 ,7266,7286,7248 }, - {6408,6429,6407 ,7287,7249,7248 }, {6457,6456,6429 ,7288,7250,7249 }, - {6408,6457,6429 ,7287,7288,7249 }, {6502,6501,6456 ,7289,7251,7250 }, - {6457,6502,6456 ,7288,7289,7250 }, {6520,6519,6501 ,7290,7252,7251 }, - {6502,6520,6501 ,7289,7290,7251 }, {6520,6548,6547 ,7290,7291,7253 }, - {6519,6520,6547 ,7252,7290,7253 }, {6548,6594,6593 ,7291,7292,7254 }, - {6547,6548,6593 ,7253,7291,7254 }, {6609,6608,6593 ,7293,7267,7254 }, - {6594,6609,6593 ,7292,7293,7254 }, {6609,6635,6608 ,7293,7271,7267 }, - {7058,5929,5979 ,6594,6029,6028 }, {5359,5977,1936 ,3713,809,848 }, - {6914,6965,6945 ,3532,6732,2632 }, {7066,2452,7065 ,3586,7091,5182 }, - {6895,6864,6840 ,5434,6865,6868 }, {5404,6576,6529 ,3559,6883,5025 }, - {5350,5404,6529 ,1526,3559,5025 }, {5205,5166,5190 ,5219,3427,5858 }, - {6855,6856,6893 ,6959,6892,6844 }, {2308,3302,6300 ,6798,6757,6146 }, - {6297,6442,6696 ,6851,6850,6849 }, {6865,6895,6840 ,5435,5434,6868 }, - {6916,6915,6864 ,596,6871,6865 }, {7028,7066,7027 ,3587,3586,3175 }, - {1492,5075,4017 ,1585,1586,5342 }, {876,4017,4232 ,5340,5342,6299 }, - {7875,7898,7848 ,4118,4117,343 }, {7925,7924,7874 ,7294,815,344 }, - {7023,6314,2259 ,7295,1132,1131 }, {5645,6798,5051 ,7296,7284,7283 }, - {2140,5010,6798 ,5635,6006,7284 }, {5645,2140,6798 ,7296,5635,7284 }, - {7846,7897,7845 ,4162,6015,5725 }, {2452,352,353 ,7091,593,7281 }, - {6114,6079,6355 ,1805,5580,3786 }, {5248,4023,5247 ,6469,3827,4096 }, - {6502,6548,6520 ,7289,7291,7290 }, {6594,6635,6609 ,7292,7271,7293 }, - {2452,2247,7065 ,7091,7285,5182 }, {7028,7027,6968 ,3587,3175,595 }, - {5917,4541,3079 ,6402,6630,6540 }, {1283,3844,5788 ,2978,2443,6086 }, - {6464,297,5966 ,3633,1918,5054 }, {1071,2455,1027 ,3382,475,6991 }, - {6442,6708,6696 ,6850,6148,6849 }, {6320,3533,7439 ,190,192,7297 }, - {7925,7974,7924 ,7294,4171,815 }, {3426,2566,2527 ,4438,2635,2637 }, - {7023,5051,6314 ,7295,7283,1132 }, {5892,6036,3498 ,2683,6141,5800 }, - {4170,5970,5447 ,3731,3518,5633 }, {6947,6988,6946 ,4587,6771,594 }, - {7066,7065,7027 ,3586,5182,3175 }, {5363,5396,5383 ,3269,3548,3547 }, - {6458,6457,6408 ,7298,7288,7287 }, {6503,6502,6457 ,7299,7289,7288 }, - {6458,6503,6457 ,7298,7299,7288 }, {6549,6548,6502 ,7300,7291,7289 }, - {6503,6549,6502 ,7299,7300,7289 }, {6595,6594,6548 ,7301,7292,7291 }, - {6549,6595,6548 ,7300,7301,7291 }, {6636,6635,6594 ,7302,7271,7292 }, - {6595,6636,6594 ,7301,7302,7292 }, {6677,6676,6635 ,7303,7272,7271 }, - {6636,6677,6635 ,7302,7303,7271 }, {6733,6732,6676 ,7304,7273,7272 }, - {6677,6733,6676 ,7303,7304,7272 }, {6780,6779,6732 ,7305,7274,7273 }, - {6733,6780,6732 ,7304,7305,7273 }, {6801,6800,6779 ,7306,7275,7274 }, - {6780,6801,6779 ,7305,7306,7274 }, {6801,6832,6831 ,7306,7307,7276 }, - {6800,6801,6831 ,7275,7306,7276 }, {6887,6886,6831 ,7308,7277,7276 }, - {6832,6887,6831 ,7307,7308,7276 }, {6937,6936,6886 ,7309,7278,7277 }, - {6887,6937,6886 ,7308,7309,7277 }, {6937,6984,6983 ,7309,7310,7279 }, - {6936,6937,6983 ,7278,7309,7279 }, {7019,7018,6983 ,7311,7280,7279 }, - {6984,7019,6983 ,7310,7311,7279 }, {7019,7059,7058 ,7311,7312,6594 }, - {7018,7019,7058 ,7280,7311,6594 }, {7059,5045,5929 ,7312,4214,6029 }, - {7058,7059,5929 ,6594,7312,6029 }, {6967,7007,6987 ,4629,4628,6917 }, - {6988,7028,6968 ,6771,3587,595 }, {6920,6947,6919 ,6783,4587,6778 }, - {6863,6862,6839 ,6866,6877,6867 }, {6169,6190,3704 ,2334,6610,2332 }, - {5476,5055,1261 ,6495,6470,6472 }, {4595,4649,5118 ,5289,5288,6825 }, - {6920,6919,6896 ,6783,6778,6787 }, {4597,4583,7788 ,5541,5498,7313 }, - {7534,7533,7511 ,7314,7039,6677 }, {7115,7102,7103 ,1024,1240,6455 }, - {4553,2259,6351 ,7315,1131,1568 }, {6322,4553,6351 ,3531,7315,1568 }, - {4553,6296,2259 ,7315,7316,1131 }, {6298,7023,2259 ,7317,7295,1131 }, - {6296,6298,2259 ,7316,7317,1131 }, {5100,5051,7023 ,7318,7283,7295 }, - {6298,5100,7023 ,7317,7318,7295 }, {5100,7078,5051 ,7318,7319,7283 }, - {1262,5645,5051 ,7320,7296,7283 }, {7078,1262,5051 ,7319,7320,7283 }, - {4565,2140,5645 ,5944,5635,7296 }, {1262,4565,5645 ,7320,5944,7296 }, - {6463,4566,4985 ,5159,5143,2703 }, {6009,6337,6336 ,6129,7321,5670 }, - {5943,6009,6336 ,5402,6129,5670 }, {6337,6373,6372 ,7321,7322,7286 }, - {6336,6337,6372 ,5670,7321,7286 }, {6373,6409,6408 ,7322,7323,7287 }, - {6372,6373,6408 ,7286,7322,7287 }, {6459,6458,6408 ,7324,7298,7287 }, - {6409,6459,6408 ,7323,7324,7287 }, {6550,6549,6503 ,7325,7300,7299 }, - {6637,6636,6595 ,7326,7302,7301 }, {6780,6832,6801 ,7305,7307,7306 }, - {6988,6968,6946 ,6771,595,594 }, {6947,6946,6918 ,4587,594,6779 }, - {6792,6839,6811 ,5056,6867,399 }, {6156,1165,5917 ,6250,3153,6402 }, - {2241,5454,3978 ,6950,6817,4549 }, {2234,2235,2139 ,6949,6870,6895 }, - {3192,6387,3285 ,3063,6935,3064 }, {1313,1075,2373 ,3674,6854,6722 }, - {8037,8036,7996 ,4528,7327,7328 }, {5115,7103,6282 ,5913,6455,6617 }, - {41,1262,7078 ,6533,7320,7319 }, {5100,41,7078 ,7318,6533,7319 }, - {6029,6028,5976 ,1454,5316,5903 }, {1270,6569,2222 ,6781,6745,2509 }, - {6867,6896,6844 ,6951,6787,6822 }, {3838,4166,5999 ,6257,6084,5184 }, - {6637,6677,6636 ,7326,7303,7302 }, {6780,6801,6832 ,7305,7306,7307 }, - {7059,7072,5045 ,7312,7329,4214 }, {4577,4576,4575 ,5352,1628,3128 }, - {6792,6811,6793 ,5056,399,6879 }, {5447,4565,5564 ,5633,5944,5943 }, - {6947,6918,6919 ,4587,6779,6778 }, {3437,3500,3465 ,4142,4177,6890 }, - {3500,3551,3550 ,4177,4180,4179 }, {3670,4326,489 ,281,219,3639 }, - {3051,2273,5474 ,6488,5322,4243 }, {5415,4565,41 ,5951,5944,6533 }, - {6866,6842,6843 ,6786,5433,6911 }, {7818,4584,4598 ,5309,5308,5343 }, - {7187,7186,7161 ,7330,5370,2559 }, {1634,5482,1423 ,768,3565,151 }, - {4553,6298,6296 ,7315,7317,7316 }, {1262,41,4565 ,7320,6533,5944 }, - {6391,307,6463 ,6804,5095,5159 }, {2247,353,1071 ,7285,7281,3382 }, - {1215,5006,184 ,3937,1351,4052 }, {6293,6338,6337 ,7212,7331,7321 }, - {6009,6293,6337 ,6129,7212,7321 }, {6338,6374,6373 ,7331,7332,7322 }, - {6337,6338,6373 ,7321,7331,7322 }, {6410,6409,6373 ,7333,7323,7322 }, - {6374,6410,6373 ,7332,7333,7322 }, {6460,6459,6409 ,7334,7324,7323 }, - {6410,6460,6409 ,7333,7334,7323 }, {6460,6458,6459 ,7334,7298,7324 }, - {6504,6503,6458 ,7335,7299,7298 }, {6460,6504,6458 ,7334,7335,7298 }, - {6551,6550,6503 ,7336,7325,7299 }, {6504,6551,6503 ,7335,7336,7299 }, - {6551,6549,6550 ,7336,7300,7325 }, {6596,6595,6549 ,7337,7301,7300 }, - {6551,6596,6549 ,7336,7337,7300 }, {6638,6637,6595 ,7338,7326,7301 }, - {6596,6638,6595 ,7337,7338,7301 }, {6678,6677,6637 ,7339,7303,7326 }, - {6638,6678,6637 ,7338,7339,7326 }, {6678,6693,6677 ,7339,7340,7303 }, - {6734,6733,6677 ,7341,7304,7303 }, {6693,6734,6677 ,7340,7341,7303 }, - {6781,6780,6733 ,7342,7305,7304 }, {6734,6781,6733 ,7341,7342,7304 }, - {6781,6801,6780 ,7342,7306,7305 }, {6833,6832,6801 ,7343,7307,7306 }, - {6781,6833,6801 ,7342,7343,7306 }, {6888,6887,6832 ,7344,7308,7307 }, - {6833,6888,6832 ,7343,7344,7307 }, {6888,6938,6937 ,7344,7345,7309 }, - {6887,6888,6937 ,7308,7344,7309 }, {6938,6985,6984 ,7345,7346,7310 }, - {6937,6938,6984 ,7309,7345,7310 }, {7020,7019,6984 ,7347,7311,7310 }, - {6985,7020,6984 ,7346,7347,7310 }, {7020,7060,7059 ,7347,7348,7312 }, - {7019,7020,7059 ,7311,7347,7312 }, {7060,7061,7072 ,7348,7141,7329 }, - {7059,7060,7072 ,7312,7348,7329 }, {7072,7061,5045 ,7329,7141,4214 }, - {5672,5744,7009 ,5324,6090,5325 }, {2074,2247,1071 ,6990,7285,3382 }, - {1071,353,3661 ,3382,7281,789 }, {1165,4541,5917 ,3153,6630,6402 }, - {1165,3446,5487 ,3153,3718,6558 }, {4541,1165,5487 ,6630,3153,6558 }, - {6319,5125,5151 ,6789,5467,1803 }, {4597,5136,4630 ,5541,1817,827 }, - {4598,4631,5137 ,5343,1816,1815 }, {7705,7754,7704 ,7349,7350,3562 }, - {3352,7438,3321 ,2724,7351,2461 }, {2249,6352,6322 ,3751,7352,3531 }, - {3176,4553,6322 ,7353,7315,3531 }, {6352,3176,6322 ,7352,7353,3531 }, - {6376,6298,4553 ,7354,7317,7315 }, {3176,6376,4553 ,7353,7354,7315 }, - {6438,5100,6298 ,7355,7318,7317 }, {6376,6438,6298 ,7354,7355,7317 }, - {5037,41,5100 ,3206,6533,7318 }, {6438,5037,5100 ,7355,3206,7318 }, - {1809,4549,6605 ,878,877,5164 }, {6505,6504,6460 ,7356,7335,7334 }, - {6597,6596,6551 ,7357,7337,7336 }, {7020,7061,7060 ,7347,7141,7348 }, - {5211,5170,5191 ,6071,3683,2900 }, {2452,2246,352 ,7091,591,593 }, - {6919,6946,6918 ,6778,594,6779 }, {351,5086,5069 ,592,6064,6730 }, - {6969,1165,6156 ,7358,3153,6250 }, {5001,2271,4018 ,477,5071,5084 }, - {3336,6324,3335 ,3922,4239,4222 }, {4445,6757,6748 ,3648,3409,3408 }, - {2220,4233,1072 ,6724,6185,6725 }, {7818,4598,5137 ,5309,5343,1815 }, - {7204,7203,7186 ,5120,4366,5370 }, {535,5105,6686 ,2001,5456,750 }, - {7227,7247,7269 ,7359,7360,7361 }, {6956,6376,3176 ,7362,7354,7353 }, - {5137,4597,7788 ,1815,5541,7313 }, {4142,5085,1881 ,6839,3675,7066 }, - {7065,2247,2073 ,5182,7285,5183 }, {7027,7065,7049 ,3175,5182,5454 }, - {6505,6551,6504 ,7356,7336,7335 }, {6597,6638,6596 ,7357,7338,7337 }, - {6678,6734,6693 ,7339,7341,7340 }, {6834,6833,6781 ,7363,7343,7342 }, - {7020,7037,7061 ,7347,7364,7141 }, {5751,7038,5812 ,5878,3832,660 }, - {6949,6947,6948 ,4585,4587,6782 }, {5059,4233,7081 ,1253,6185,7114 }, - {1125,3779,2142 ,5723,6565,4936 }, {4068,3952,3259 ,408,5597,407 }, - {7998,8021,7997 ,7209,7365,7210 }, {5910,6343,6079 ,5121,5122,5580 }, - {6710,1025,5053 ,6968,5299,6848 }, {3281,6310,6309 ,6794,3918,3690 }, - {6481,6378,4900 ,6729,6728,585 }, {7818,5137,7788 ,5309,1815,7313 }, - {7187,7204,7186 ,7330,5120,5370 }, {7908,7907,7858 ,7366,7367,7368 }, - {227,8128,3277 ,2157,959,961 }, {6956,6438,6376 ,7362,7355,7354 }, - {6158,6034,6293 ,6112,6049,7212 }, {6034,6339,6338 ,6049,6048,7331 }, - {6293,6034,6338 ,7212,6049,7331 }, {6339,6375,6374 ,6048,7369,7332 }, - {6338,6339,6374 ,7331,6048,7332 }, {6411,6410,6374 ,7370,7333,7332 }, - {6375,6411,6374 ,7369,7370,7332 }, {6461,6460,6410 ,7371,7334,7333 }, - {6411,6461,6410 ,7370,7371,7333 }, {6506,6505,6460 ,3549,7356,7334 }, - {6461,6506,6460 ,7371,3549,7334 }, {5395,6551,6505 ,5348,7336,7356 }, - {6506,5395,6505 ,3549,5348,7356 }, {5395,6568,6551 ,5348,6717,7336 }, - {5427,6597,6551 ,5811,7357,7336 }, {6568,5427,6551 ,6717,5811,7336 }, - {5463,6638,6597 ,5801,7338,7357 }, {5427,5463,6597 ,5811,5801,7357 }, - {5463,5503,6638 ,5801,7042,7338 }, {5531,6678,6638 ,5783,7339,7338 }, - {5503,5531,6638 ,7042,5783,7338 }, {5566,6734,6678 ,5759,7341,7339 }, - {5531,5566,6678 ,5783,5759,7339 }, {6782,6781,6734 ,7372,7342,7341 }, - {5566,6782,6734 ,5759,7372,7341 }, {6835,6834,6781 ,7373,7363,7342 }, - {6782,6835,6781 ,7372,7373,7342 }, {6835,6833,6834 ,7373,7343,7363 }, - {6889,6888,6833 ,7374,7344,7343 }, {6835,6889,6833 ,7373,7374,7343 }, - {6889,6904,6888 ,7374,7375,7344 }, {6939,6938,6888 ,7376,7345,7344 }, - {6904,6939,6888 ,7375,7376,7344 }, {6939,6940,6938 ,7376,7377,7345 }, - {6986,6985,6938 ,7378,7346,7345 }, {6940,6986,6938 ,7377,7378,7345 }, - {6986,7021,7020 ,7378,7379,7347 }, {6985,6986,7020 ,7346,7378,7347 }, - {7020,7021,7037 ,7347,7379,7364 }, {7021,7062,7061 ,7379,6563,7141 }, - {7037,7021,7061 ,7364,7379,7141 }, {4752,1297,4323 ,5196,4048,4045 }, - {712,3702,6757 ,3650,1303,3409 }, {4010,4009,3968 ,4343,3870,3848 }, - {3529,1941,3371 ,3837,1034,3708 }, {6155,6970,6969 ,3726,3688,7358 }, - {6156,6155,6969 ,6250,3726,7358 }, {6970,4831,1165 ,3688,3154,3153 }, - {6969,6970,1165 ,7358,3688,3153 }, {978,4965,4966 ,1620,784,4646 }, - {1217,5059,2220 ,6399,1253,6724 }, {3281,2271,2212 ,6794,5071,476 }, - {2073,2247,2074 ,5183,7285,6990 }, {5027,6684,2272 ,5516,1161,1201 }, - {5136,4597,5137 ,1817,5541,1815 }, {4803,468,505 ,4776,1369,986 }, - {7103,7102,6283 ,6455,1240,4298 }, {6323,2249,6531 ,1451,3751,2280 }, - {4551,6352,2249 ,7380,7352,3751 }, {6323,4551,2249 ,1451,7380,3751 }, - {1989,3176,6352 ,3016,7353,7352 }, {4551,1989,6352 ,7380,3016,7352 }, - {5012,6956,3176 ,5212,7362,7353 }, {1989,5012,3176 ,3016,5212,7353 }, - {6417,6438,6956 ,762,7355,7362 }, {5012,6417,6956 ,5212,762,7362 }, - {6417,5388,5037 ,762,5428,3206 }, {6438,6417,5037 ,7355,762,3206 }, - {5037,5388,6317 ,3206,5428,3207 }, {353,256,2212 ,7281,7269,476 }, - {5211,6433,5210 ,6071,6691,6033 }, {6165,7061,7062 ,4219,7141,6563 }, - {5604,6782,5566 ,7213,7372,5759 }, {6940,6939,6904 ,7377,7376,7375 }, - {6889,6940,6904 ,7374,7377,7375 }, {835,3984,5527 ,3030,6017,5977 }, - {4545,2274,4980 ,586,893,241 }, {3661,353,2212 ,789,7281,476 }, - {256,3281,2212 ,7269,6794,476 }, {6465,5009,4985 ,6927,6803,2703 }, - {6968,7008,6967 ,595,3176,4629 }, {5940,6176,6715 ,1625,1624,6929 }, - {3321,3353,3352 ,2461,2424,2724 }, {2074,1394,7047 ,6990,6989,6853 }, - {5974,3079,4574 ,6474,6540,6477 }, {7660,7707,7659 ,7381,7382,7383 }, - {6792,6791,6738 ,5056,6900,5057 }, {6009,5514,6293 ,6129,6128,7212 }, - {5744,5718,5756 ,6090,6126,6076 }, {6531,6509,6323 ,2280,1452,1451 }, - {4586,2163,911 ,5257,243,1159 }, {6946,6916,6917 ,594,596,5515 }, - {6411,6462,6461 ,7370,7384,7371 }, {6462,6506,6461 ,7384,3549,7371 }, - {5715,7050,7028 ,4076,6967,3587 }, {3779,1125,4648 ,6565,5723,5722 }, - {2871,3284,257 ,3649,6720,6067 }, {5106,5120,7096 ,5926,5857,4337 }, - {4392,2094,2341 ,844,5570,845 }, {5041,4990,6065 ,6799,7135,6616 }, - {4803,5267,4777 ,4776,4647,3917 }, {5604,6835,6782 ,7213,7373,7372 }, - {5669,6905,5710 ,5553,2506,5254 }, {2343,2210,1074 ,2685,2510,2715 }, - {158,5027,4755 ,5258,5516,6770 }, {8007,2250,7957 ,3854,3716,7385 }, - {7050,5715,5755 ,6967,4076,4047 }, {1947,2235,1881 ,6723,6870,7066 }, - {5405,6656,6618 ,5518,5517,6910 }, {4552,4807,3935 ,7244,6449,4346 }, - {6657,4990,5041 ,6828,7135,6799 }, {4043,2956,2798 ,419,399,420 }, - {5611,6949,6920 ,6177,4585,6783 }, {7262,7287,7241 ,4335,3459,4465 }, - {7769,7744,7794 ,5535,6101,5749 }, {4021,3733,3936 ,1712,5610,5599 }, - {6323,1989,4551 ,1451,3016,7380 }, {4983,4569,2158 ,480,1344,1160 }, - {6949,6948,6920 ,4585,6782,6783 }, {6918,6946,6917 ,6779,594,5515 }, - {4229,381,4246 ,4877,6450,3665 }, {6092,5940,3714 ,1623,1625,3970 }, - {6483,2164,4961 ,3584,3583,2905 }, {5889,6066,6375 ,1587,1455,7369 }, - {6339,5889,6375 ,6048,1587,7369 }, {6090,6411,6375 ,4897,7370,7369 }, - {6066,6090,6375 ,1455,4897,7369 }, {6090,6260,6462 ,4897,3397,7384 }, - {6411,6090,6462 ,7370,4897,7384 }, {5363,6506,6462 ,3269,3549,7384 }, - {6260,5363,6462 ,3397,3269,7384 }, {4530,4209,2239 ,1376,6269,1377 }, - {5120,5106,5121 ,5857,5926,5855 }, {5605,5647,5604 ,5761,5333,7213 }, - {5647,6835,5604 ,5333,7373,7213 }, {5647,6852,6835 ,5333,5335,7373 }, - {6890,6889,6835 ,5334,7374,7373 }, {6852,6890,6835 ,5335,5334,7373 }, - {5750,6940,6889 ,5156,7377,7374 }, {6890,5750,6889 ,5334,5156,7374 }, - {5774,6986,6940 ,5720,7378,7377 }, {5750,5774,6940 ,5156,5720,7377 }, - {5807,7021,6986 ,4769,7379,7378 }, {5774,5807,6986 ,5720,4769,7378 }, - {7021,5807,7062 ,7379,4769,6563 }, {5807,5839,7062 ,4769,4768,6563 }, - {5839,5840,7062 ,4768,4770,6563 }, {5840,4271,1464 ,4770,5767,5768 }, - {7062,5840,1464 ,6563,4770,5768 }, {5668,5626,5669 ,5912,1460,5553 }, - {5076,4200,158 ,6607,6583,5258 }, {4983,6341,2808 ,480,479,522 }, - {7050,5755,7067 ,6967,4047,3585 }, {4978,6413,6155 ,178,112,3726 }, - {4567,4978,6155 ,6655,178,3726 }, {6413,3340,6970 ,112,114,3688 }, - {7733,7758,7707 ,7386,7387,7382 }, {7708,7733,7707 ,7388,7386,7382 }, - {7733,7780,7758 ,7386,7389,7387 }, {7834,7884,7833 ,7390,7391,7392 }, - {7523,7581,7522 ,7393,7394,7395 }, {7518,7546,7545 ,7396,7397,7398 }, - {7629,7684,7683 ,7399,7400,5267 }, {7656,7629,7683 ,7401,7399,5267 }, - {2328,2282,2283 ,3664,3663,3687 }, {2281,2280,8054 ,3626,3613,7402 }, - {2278,2277,4572 ,3495,3522,5949 }, {7956,8004,7981 ,7403,7404,4252 }, - {7173,7172,7165 ,7264,7405,7265 }, {7574,7656,7603 ,7406,7401,5266 }, - {2250,8006,7957 ,3716,7407,7385 }, {7907,7932,7906 ,7367,7408,7409 }, - {4803,505,5290 ,4776,986,5247 }, {7827,7878,7826 ,7410,7411,1616 }, - {7852,7901,7851 ,7412,7413,6625 }, {7116,7141,7140 ,7262,7414,7415 }, - {7263,7312,7262 ,627,4333,4335 }, {402,7690,448 ,5349,6466,1172 }, - {7540,7574,7603 ,5709,7406,5266 }, {7629,7656,7574 ,7399,7401,7406 }, - {8021,8037,7997 ,7365,4528,7210 }, {7604,7605,7657 ,7416,5239,7417 }, - {7726,7774,7725 ,7418,7419,7420 }, {3351,7497,7438 ,1444,7421,7351 }, - {3352,3351,7438 ,2724,1444,7351 }, {7297,7273,7274 ,7422,3467,7423 }, - {3298,3830,4518 ,7424,5882,1281 }, {7678,7677,7623 ,7425,7426,7427 }, - {7399,7425,7398 ,7428,3995,7429 }, {7379,7378,7319 ,7430,7431,7432 }, - {7252,7297,7274 ,3437,7422,7423 }, {7327,7326,7273 ,7433,7434,3467 }, - {7297,7327,7273 ,7422,7433,3467 }, {7327,7355,7326 ,7433,7435,7434 }, - {7403,7457,7486 ,6588,1078,7436 }, {7457,7539,7538 ,1078,1080,2014 }, - {7856,7905,7855 ,4635,7437,6545 }, {7626,7625,7624 ,7438,7139,7439 }, - {7405,7461,7460 ,7440,7441,7442 }, {7431,7405,7460 ,7443,7440,7442 }, - {7461,7489,7460 ,7441,7444,7442 }, {7489,7519,7518 ,7444,7445,7396 }, - {7460,7489,7518 ,7442,7444,7396 }, {7757,7758,7779 ,7446,7387,7447 }, - {7833,7832,7809 ,7392,7448,7449 }, {7707,7758,7757 ,7382,7387,7446 }, - {7732,7707,7757 ,7450,7382,7446 }, {4022,3534,6836 ,3503,942,852 }, - {7320,7380,7379 ,7282,7451,7430 }, {7833,7883,7832 ,7392,7452,7448 }, - {7519,7547,7546 ,7445,7453,7397 }, {7518,7519,7546 ,7396,7445,7397 }, - {7771,7770,7721 ,4336,4272,7454 }, {7547,7607,7546 ,7453,7455,7397 }, - {7661,7660,7607 ,7456,7381,7455 }, {7606,7659,7633 ,7457,7383,7458 }, - {7726,7725,7681 ,7418,7420,7459 }, {7622,7676,7650 ,7460,7461,7237 }, - {7606,7633,7578 ,7457,7458,7462 }, {7661,7708,7660 ,7456,7388,7381 }, - {7480,7511,7454 ,7463,6677,3996 }, {7781,7780,7733 ,7464,7389,7386 }, - {7325,7382,7381 ,7465,7466,7467 }, {7885,7884,7834 ,7468,7391,7390 }, - {6322,8112,6897 ,3531,3530,54 }, {2048,2096,3875 ,5461,788,5845 }, - {7885,7909,7884 ,7468,6603,7391 }, {2262,7936,7884 ,3359,5528,7391 }, - {7909,2262,7884 ,6603,3359,7391 }, {7382,7405,7431 ,7466,7440,7443 }, - {7582,7581,7523 ,7469,7394,7393 }, {7438,7497,7437 ,7351,7421,5938 }, - {7273,7250,7251 ,3467,3418,2671 }, {7497,7496,7437 ,7421,7470,5938 }, - {2526,2525,2485 ,2636,2937,2815 }, {7273,7296,7250 ,3467,7471,3418 }, - {7684,7705,7683 ,7400,7349,5267 }, {7705,7704,7683 ,7349,3562,5267 }, - {6784,2278,4572 ,7472,3495,5949 }, {7110,7133,7108 ,1990,1989,4111 }, - {7355,7405,7382 ,7435,7440,7466 }, {7582,7637,7581 ,7469,7473,7394 }, - {7714,4744,7983 ,4468,4424,4361 }, {5026,8062,7983 ,4225,3272,4361 }, - {5643,5660,5659 ,4617,3054,3053 }, {7698,7720,7747 ,333,4271,331 }, - {7613,7634,7612 ,5106,7474,5107 }, {7516,7575,7574 ,5708,7475,7406 }, - {6784,4572,8039 ,7472,5949,7476 }, {7274,7273,7252 ,7423,3467,3437 }, - {3824,4744,7714 ,3462,4424,4468 }, {3824,1879,4744 ,3462,1283,4424 }, - {3976,3830,3298 ,919,5882,7424 }, {7398,7425,7397 ,7429,3995,1186 }, - {7253,7297,7252 ,1855,7422,3437 }, {7356,7355,7327 ,7477,7435,7433 }, - {2487,2486,7615 ,4427,2814,2816 }, {6316,6311,2162 ,4435,1097,3278 }, - {3824,3298,1879 ,3462,7424,1283 }, {7935,2290,7960 ,5527,1982,3505 }, - {7461,7490,7489 ,7441,7478,7444 }, {7489,7490,7519 ,7444,7478,7445 }, - {7608,7607,7547 ,7479,7455,7453 }, {2250,2285,8006 ,3716,3701,7407 }, - {7881,7907,7906 ,7480,7367,7409 }, {7709,7708,7661 ,7481,7388,7456 }, - {7262,7311,7287 ,4335,4334,3459 }, {7693,3298,3824 ,724,7424,3462 }, - {3298,7693,3976 ,7424,724,919 }, {2292,7936,2262 ,1983,5528,3359 }, - {7734,7733,7708 ,7482,7386,7388 }, {7709,7734,7708 ,7481,7482,7388 }, - {7835,7834,7780 ,7483,7390,7389 }, {7781,7835,7780 ,7464,7483,7389 }, - {7229,7270,7247 ,2556,2555,7360 }, {1788,145,113 ,676,810,677 }, - {3290,3289,7196 ,1204,2056,2401 }, {7517,7516,7459 ,7484,5708,7485 }, - {7883,7934,7882 ,7452,7486,7487 }, {3294,3293,7110 ,3895,1988,1990 }, - {7150,7149,3293 ,7488,7263,1988 }, {7150,7173,7149 ,7488,7264,7263 }, - {7637,7713,7692 ,7473,7489,7490 }, {7251,7250,3288 ,2671,3418,2058 }, - {7960,2290,162 ,3505,1982,2822 }, {7224,7223,7189 ,7491,7492,7493 }, - {6276,7107,6277 ,4316,7494,4387 }, {6282,7103,6283 ,6617,6455,4298 }, - {7713,7736,7692 ,7489,6752,7490 }, {7809,7832,7808 ,7449,7448,7495 }, - {7266,7315,7265 ,6769,7496,7497 }, {7230,7229,7210 ,7498,2556,7499 }, - {7211,7210,7173 ,7500,7499,7264 }, {7211,7230,7210 ,7500,7498,7499 }, - {7321,7353,7320 ,7501,7502,7282 }, {7188,7187,7161 ,7503,7330,2559 }, - {7631,7658,7605 ,7504,7505,5239 }, {7997,8037,7996 ,7210,4528,7328 }, - {7266,7265,7245 ,6769,7497,7506 }, {7935,7960,7933 ,5527,3505,7507 }, - {7931,7981,7930 ,7508,4252,4278 }, {7804,7803,7775 ,4634,4636,7509 }, - {7753,7804,7775 ,3643,4634,7509 }, {7779,7809,7808 ,7447,7449,7495 }, - {7757,7779,7808 ,7446,7447,7495 }, {7727,7775,7726 ,3563,7509,7418 }, - {7934,7933,7882 ,7486,7507,7487 }, {8025,8024,7980 ,7510,7511,4253 }, - {7383,7355,7382 ,7512,7435,7466 }, {7321,7320,7271 ,7501,7282,2554 }, - {7980,8003,7955 ,4253,3776,4254 }, {7855,7904,7854 ,6545,7513,7514 }, - {7353,7380,7320 ,7502,7451,7282 }, {7541,7516,7517 ,7515,5708,7484 }, - {7541,7575,7516 ,7515,7475,5708 }, {7934,7935,7933 ,7486,5527,7507 }, - {7713,2451,7736 ,7489,2102,6752 }, {7732,7757,7731 ,7450,7446,7516 }, - {8116,3976,8129 ,172,919,723 }, {7707,7732,7731 ,7382,7450,7516 }, - {7535,7534,7480 ,7517,7314,7463 }, {7685,7707,7731 ,7518,7382,7516 }, - {7755,7805,7754 ,7519,7520,7350 }, {7707,7685,7659 ,7382,7518,7383 }, - {1274,6108,1275 ,1687,6975,1688 }, {7980,8024,8003 ,4253,7511,3776 }, - {2281,2326,2280 ,3626,3588,3613 }, {7164,7195,7171 ,7521,7522,4306 }, - {7209,7228,7227 ,7523,7524,7359 }, {7228,7247,7227 ,7524,7360,7359 }, - {7855,7854,7803 ,6545,7514,4636 }, {7574,7575,7629 ,7406,7475,7399 }, - {7805,7804,7754 ,7520,4634,7350 }, {7578,7633,7577 ,7462,7458,7525 }, - {7325,7381,7354 ,7465,7467,7526 }, {7755,7754,7705 ,7519,7350,7349 }, - {8005,8004,7956 ,7527,7404,7403 }, {7540,7603,7628 ,5709,5266,7528 }, - {7798,7825,7771 ,4728,3768,4336 }, {7093,7107,6276 ,4318,7494,4316 }, - {7093,7119,7107 ,4318,7529,7494 }, {7119,7147,7146 ,7529,6937,7530 }, - {7683,7682,7655 ,5267,3564,5268 }, {7880,7879,7857 ,7531,7532,7533 }, - {7604,7657,7630 ,7416,7417,7534 }, {7275,7253,7254 ,1854,1855,450 }, - {7298,7297,7253 ,7535,7422,1855 }, {2285,2283,8004 ,3701,3687,7404 }, - {8005,2285,8004 ,7527,3701,7404 }, {7254,7253,6348 ,450,1855,1607 }, - {5558,5569,5599 ,2302,2075,2213 }, {7603,7655,7628 ,5266,5268,7528 }, - {7427,7426,7399 ,7536,7537,7428 }, {7275,7298,7253 ,1854,7535,1855 }, - {7298,7327,7297 ,7535,7433,7422 }, {7406,7405,7355 ,7538,7440,7435 }, - {7356,7406,7355 ,7477,7538,7435 }, {7490,7547,7519 ,7478,7453,7445 }, - {7662,7661,7607 ,7539,7456,7455 }, {7608,7662,7607 ,7479,7539,7455 }, - {1314,7638,1315 ,1409,7540,1627 }, {1877,3802,3948 ,282,4475,280 }, - {3948,3802,4296 ,280,4475,6023 }, {7720,7698,7648 ,4271,333,3952 }, - {7655,7682,7628 ,5268,3564,7528 }, {68,4368,3530 ,4087,4148,7541 }, - {7481,7535,7480 ,7542,7517,7463 }, {7734,7781,7733 ,7482,7464,7386 }, - {7537,7601,7572 ,7543,7544,5124 }, {7886,7885,7834 ,6561,7468,7390 }, - {7835,7886,7834 ,7483,6561,7390 }, {7886,7909,7885 ,6561,6603,7468 }, - {7884,7935,7883 ,7391,5527,7452 }, {7221,7241,7204 ,7545,4465,5120 }, - {3976,8116,5483 ,919,172,171 }, {7900,7951,7926 ,6922,7546,6923 }, - {1877,3825,3802 ,282,7547,4475 }, {59,2553,395 ,967,2716,966 }, - {7901,7900,7851 ,7413,6922,6625 }, {2283,8041,8004 ,3687,7548,7404 }, - {7753,7775,7727 ,3643,7509,3563 }, {7497,7523,7496 ,7421,7393,7470 }, - {7878,7877,7826 ,7411,7549,1616 }, {7459,7516,7458 ,7485,5708,7550 }, - {7900,7899,7849 ,6922,4116,7551 }, {7515,7487,7540 ,1079,5707,5709 }, - {7648,7699,7720 ,3952,3951,4271 }, {7149,7165,7133 ,7263,7265,1989 }, - {8107,2731,872 ,658,659,2962 }, {2410,3400,1877 ,1,3659,282 }, - {1315,1355,1314 ,1627,1408,1409 }, {7907,7958,7932 ,7367,3855,7408 }, - {7454,7453,7397 ,3996,1187,1186 }, {59,2689,2553 ,967,2821,2716 }, - {209,342,1178 ,4499,4542,206 }, {7328,7327,7298 ,7552,7433,7535 }, - {7275,7328,7298 ,1854,7552,7535 }, {7686,7659,7685 ,7553,7383,7518 }, - {7328,7356,7327 ,7552,7477,7433 }, {7432,7405,7406 ,7554,7440,7538 }, - {7633,7659,7632 ,7458,7383,7555 }, {7659,7686,7632 ,7383,7553,7555 }, - {7537,7572,7514 ,7543,5124,3610 }, {7601,7600,7572 ,7544,7556,5124 }, - {7432,7461,7405 ,7554,7441,7440 }, {7548,7547,7490 ,7557,7453,7478 }, - {7609,7608,7547 ,7558,7479,7453 }, {7548,7609,7547 ,7557,7558,7453 }, - {7663,7662,7608 ,7559,7539,7479 }, {7609,7663,7608 ,7558,7559,7479 }, - {7663,7661,7662 ,7559,7456,7539 }, {7710,7709,7661 ,7560,7481,7456 }, - {7663,7710,7661 ,7559,7560,7456 }, {7735,7734,7709 ,7561,7482,7481 }, - {7710,7735,7709 ,7560,7561,7481 }, {7295,7325,7354 ,7562,7465,7526 }, - {2410,1877,3670 ,1,282,281 }, {3400,1538,1451 ,3659,0,175 }, - {3400,3786,1877 ,3659,4074,282 }, {1877,3786,3825 ,282,4074,7547 }, - {3802,3825,1537 ,4475,7547,4473 }, {976,977,1029 ,782,3931,3930 }, - {7849,7899,7875 ,7551,4116,4118 }, {7782,7781,7734 ,7563,7464,7482 }, - {7836,7835,7781 ,7564,7483,7464 }, {7782,7836,7781 ,7563,7564,7464 }, - {7296,7295,7250 ,7471,7562,3418 }, {7836,7886,7835 ,7564,6561,7483 }, - {7721,7720,7676 ,7454,4271,7461 }, {2263,2295,2294 ,3080,3160,3081 }, - {7883,7882,7832 ,7452,7487,7448 }, {3296,3295,2265 ,4159,7565,2662 }, - {7637,7666,7636 ,7473,7566,7567 }, {7229,7247,7210 ,2556,7360,7499 }, - {7801,7853,7800 ,1618,1617,7568 }, {7110,7108,7109 ,1990,4111,4112 }, - {7802,7801,7751 ,6566,1618,4332 }, {7479,7508,7478 ,4423,6196,1402 }, - {3786,1934,3825 ,4074,4620,7547 }, {1934,3514,1537 ,4620,7569,4473 }, - {3825,1934,1537 ,7547,4620,4473 }, {3514,7764,1537 ,7569,7570,4473 }, - {1537,7764,1745 ,4473,7570,6233 }, {7764,7739,4207 ,7570,7571,4247 }, - {1745,7764,4207 ,6233,7570,4247 }, {4961,2164,3191 ,2905,3583,2903 }, - {7620,7646,7645 ,5033,5191,5034 }, {7457,7487,7515 ,1078,5707,1079 }, - {7429,7487,7457 ,7572,5707,1078 }, {3351,7523,7497 ,1444,7393,7421 }, - {2283,2282,2281 ,3687,3663,3626 }, {7296,7325,7295 ,7471,7465,7562 }, - {7106,7105,7092 ,7573,5279,3968 }, {7879,7905,7856 ,7532,7437,4635 }, - {7484,7483,7427 ,3612,7574,7536 }, {7289,7347,7288 ,7575,7576,7577 }, - {7513,7512,7483 ,3611,5203,7574 }, {7373,7399,7347 ,4989,7428,7576 }, - {7456,7455,7400 ,7578,7579,7580 }, {7754,7804,7753 ,7350,4634,3643 }, - {7320,7379,7319 ,7282,7430,7432 }, {7465,7464,7436 ,7581,4246,4245 }, - {7627,7626,7572 ,7582,7438,5124 }, {7313,7346,7312 ,7583,7584,4333 }, - {7488,7517,7459 ,7585,7484,7485 }, {3514,1934,7764 ,7569,4620,7570 }, - {937,975,974 ,5067,4266,5366 }, {8035,2275,8034 ,6675,3152,7586 }, - {7430,7429,7457 ,7587,7572,1078 }, {7209,7227,7246 ,7523,7359,3772 }, - {7429,7430,7457 ,7572,7587,1078 }, {7221,7263,7241 ,7545,627,4465 }, - {7345,7397,7372 ,7588,1186,4373 }, {7736,450,7691 ,6752,1653,4419 }, - {7582,7667,7637 ,7469,7589,7473 }, {7667,7668,7637 ,7589,7590,7473 }, - {7996,7995,7949 ,7328,4135,7591 }, {7377,7430,7429 ,7592,7587,7572 }, - {7318,7292,7352 ,7593,7594,7595 }, {7268,7292,7318 ,3773,7594,7593 }, - {7227,7269,7268 ,7359,7361,3773 }, {7246,7227,7268 ,3772,7359,3773 }, - {7269,7292,7268 ,7361,7594,3773 }, {7637,7636,7580 ,7473,7567,7596 }, - {7581,7637,7580 ,7394,7473,7596 }, {7230,7271,7229 ,7498,2554,2556 }, - {6346,7275,7253 ,4883,1854,1855 }, {7357,7356,7328 ,7597,7477,7552 }, - {7832,7882,7859 ,7448,7487,7598 }, {7646,7620,7675 ,5191,5033,5192 }, - {1934,2350,7764 ,4620,7599,7570 }, {7764,2350,7739 ,7570,7599,7571 }, - {3338,3530,4368 ,4147,7541,4148 }, {4445,3284,2871 ,3648,6720,3649 }, - {7422,7477,7449 ,1404,1403,7600 }, {7778,7731,7807 ,7601,7516,7602 }, - {7832,7859,7831 ,7448,7598,7603 }, {7731,7757,7807 ,7516,7446,7602 }, - {7357,7406,7356 ,7597,7538,7477 }, {7491,7490,7461 ,7604,7478,7441 }, - {7432,7491,7461 ,7554,7604,7441 }, {7549,7548,7490 ,7605,7557,7478 }, - {7610,7609,7548 ,7606,7558,7557 }, {7549,7610,7548 ,7605,7606,7557 }, - {7960,7959,7933 ,3505,7607,7507 }, {7516,7574,7540 ,5708,7406,5709 }, - {7689,7690,402 ,6444,6466,5349 }, {7225,7245,7207 ,1672,7506,7608 }, - {7225,7207,7194 ,1672,7608,1670 }, {7291,7315,7266 ,3774,7496,6769 }, - {7291,7349,7315 ,3774,7609,7496 }, {7163,7164,7171 ,5460,7521,4306 }, - {7174,7173,7150 ,7610,7264,7488 }, {7996,8036,7995 ,7328,7327,4135 }, - {7664,7663,7609 ,7611,7559,7558 }, {7610,7664,7609 ,7606,7611,7558 }, - {7806,7805,7755 ,7612,7520,7519 }, {6796,6898,8063 ,2617,1946,465 }, - {2350,7813,7739 ,7599,7613,7571 }, {7813,3338,7739 ,7613,4147,7571 }, - {4741,3634,3530 ,5508,5507,7541 }, {7808,7832,7831 ,7495,7448,7603 }, - {7806,7829,7805 ,7612,7614,7520 }, {7633,7632,7576 ,7458,7555,7615 }, - {3297,7734,7735 ,4203,7482,7561 }, {7710,3297,7735 ,7560,4203,7561 }, - {7783,7782,7734 ,7616,7563,7482 }, {3297,7783,7734 ,4203,7616,7482 }, - {7295,7354,7324 ,7562,7526,7617 }, {2265,7836,7782 ,2662,7564,7563 }, - {7316,7317,7350 ,5948,5947,7618 }, {7629,7657,7705 ,7399,7417,7349 }, - {7959,7960,2306 ,7607,3505,6405 }, {8039,4572,8038 ,7476,5949,4121 }, - {7401,7456,7400 ,7619,7578,7580 }, {7245,7265,7244 ,7506,7497,7620 }, - {7245,7244,7207 ,7506,7620,7608 }, {7132,7164,7163 ,7621,7521,5460 }, - {7148,7132,7163 ,6936,7621,5460 }, {7783,2265,7782 ,7616,2662,7563 }, - {7250,7295,7249 ,3418,7562,7622 }, {7849,7875,7797 ,7551,4118,3506 }, - {7932,7931,7906 ,7408,7508,7409 }, {156,3691,1934 ,5539,7623,4620 }, - {1934,3691,2350 ,4620,7623,7599 }, {7763,7838,3338 ,7624,7625,4147 }, - {7813,7763,3338 ,7613,7624,4147 }, {4911,4741,3530 ,7626,5508,7541 }, - {936,937,974 ,5234,5067,5366 }, {7289,7288,7242 ,7575,7577,7627 }, - {7829,7857,7805 ,7614,7533,7520 }, {2265,7886,7836 ,2662,6561,7564 }, - {2907,3791,2941 ,111,3739,109 }, {7668,7713,7637 ,7590,7489,7473 }, - {7604,7575,7541 ,7416,7475,7515 }, {7575,7604,7629 ,7475,7416,7399 }, - {7604,7630,7629 ,7416,7534,7399 }, {7630,7657,7629 ,7534,7417,7399 }, - {7118,7119,7145 ,7628,7529,7629 }, {7386,7412,7385 ,5512,3765,7630 }, - {7206,7243,7224 ,7631,7632,7491 }, {7206,7224,7190 ,7631,7491,7633 }, - {7191,7206,7190 ,7634,7631,7633 }, {7290,7289,7243 ,7635,7575,7632 }, - {7290,7348,7289 ,7635,4990,7575 }, {7538,7537,7485 ,2014,7543,7636 }, - {7654,7653,7601 ,7637,7638,7544 }, {8036,8037,4589 ,7327,4528,776 }, - {156,3740,3691 ,5539,7639,7623 }, {3691,3740,2350 ,7623,7639,7599 }, - {3740,7763,7813 ,7639,7624,7613 }, {2350,3740,7813 ,7599,7639,7613 }, - {7763,7122,7838 ,7624,7640,7625 }, {7838,7122,3338 ,7625,7640,4147 }, - {7122,8046,3530 ,7640,7641,7541 }, {3338,7122,3530 ,4147,7640,7541 }, - {3737,1350,791 ,7642,509,7643 }, {7957,7956,7931 ,7385,7403,7508 }, - {7748,7771,7722 ,7644,4336,7645 }, {7932,7957,7931 ,7408,7385,7508 }, - {7577,7633,7576 ,7525,7458,7615 }, {7995,8036,4588 ,4135,7327,775 }, - {7581,7580,7522 ,7394,7596,7395 }, {8041,2283,2281 ,7548,3687,3626 }, - {7905,7904,7855 ,7437,7513,6545 }, {7690,7689,7613 ,6466,6444,5106 }, - {7635,7690,7613 ,7646,6466,5106 }, {7193,7192,7162 ,7647,7648,7649 }, - {7147,7193,7162 ,6937,7647,7649 }, {7222,7263,7221 ,628,627,7545 }, - {7117,7116,7089 ,7650,7262,5608 }, {7090,7117,7089 ,4080,7650,5608 }, - {7143,7170,7190 ,7651,7652,7633 }, {7170,7191,7190 ,7652,7634,7633 }, - {7144,7170,7143 ,7653,7652,7651 }, {7131,7144,7143 ,7654,7653,7651 }, - {7130,7131,7143 ,6823,7654,7651 }, {7119,7118,7107 ,7529,7628,7494 }, - {7553,7579,7552 ,7655,7656,5546 }, {7553,7613,7579 ,7655,5106,7656 }, - {7193,7194,7192 ,7647,1670,7648 }, {7981,8004,7980 ,4252,7404,4253 }, - {7521,7580,7520 ,7657,7596,7658 }, {3740,1413,7763 ,7639,7659,7624 }, - {7122,3423,8046 ,7640,7660,7641 }, {3423,8046,3530 ,7660,7641,7541 }, - {8046,3423,3530 ,7641,7660,7541 }, {8046,3633,4911 ,7641,7661,7626 }, - {3530,8046,4911 ,7541,7641,7626 }, {6869,4741,4911 ,7662,5508,7626 }, - {3633,6869,4911 ,7661,7662,7626 }, {1350,3737,5571 ,509,7642,4616 }, - {6869,4956,4741 ,7662,5381,5508 }, {7162,7192,7170 ,7649,7648,7652 }, - {7749,7748,7723 ,7663,7644,7664 }, {7748,7799,7771 ,7644,4727,4336 }, - {2281,8054,8024 ,3626,7402,7511 }, {6658,5570,3121 ,7665,508,2076 }, - {7272,7293,7322 ,7666,6473,75 }, {7654,7703,7653 ,7637,7667,7638 }, - {7774,7773,7725 ,7419,7668,7420 }, {7207,7206,7191 ,7608,7631,7634 }, - {7346,7345,7312 ,7584,7588,4333 }, {3615,5700,5681 ,201,4501,2934 }, - {3530,3634,68 ,7541,5507,4087 }, {7522,7580,7521 ,7395,7596,7657 }, - {7148,7163,7147 ,6936,5460,6937 }, {7171,7195,7209 ,4306,7522,7523 }, - {7851,7900,7850 ,6625,6922,3769 }, {7248,7293,7272 ,73,6473,7666 }, - {7205,7204,7188 ,7669,5120,7503 }, {7602,7628,7601 ,5867,7528,7544 }, - {7428,7427,7373 ,7670,7536,4989 }, {7374,7428,7373 ,4988,7670,4989 }, - {7194,7207,7192 ,1670,7608,7648 }, {7465,7521,7464 ,7581,7657,4246 }, - {7854,7878,7827 ,7514,7411,7410 }, {7580,7553,7520 ,7596,7655,7658 }, - {7579,7613,7552 ,7656,5106,5546 }, {3740,156,4264 ,7639,5539,5540 }, - {1413,6477,7763 ,7659,7671,7624 }, {7763,6477,7122 ,7624,7671,7640 }, - {7122,6477,3423 ,7640,7671,7660 }, {3423,3633,8046 ,7660,7661,7641 }, - {5039,6869,3633 ,7672,7662,7661 }, {2733,4956,6869 ,5367,5381,7662 }, - {5039,2733,6869 ,7672,5367,7662 }, {5046,1081,2993 ,5232,3745,3744 }, - {7680,7679,7625 ,7673,7674,7139 }, {7118,7145,7144 ,7628,7629,7653 }, - {7651,7680,7625 ,7675,7673,7139 }, {7858,7907,7881 ,7368,7367,7480 }, - {8054,8053,8024 ,7402,7676,7511 }, {7511,7533,7510 ,6677,7039,1873 }, - {7692,7736,7691 ,7490,6752,4419 }, {7272,7322,7321 ,7666,75,7501 }, - {3843,935,3933 ,7677,5264,7678 }, {6552,2278,6784 ,7679,3495,7472 }, - {7325,7383,7382 ,7465,7512,7466 }, {2278,2243,2242 ,3495,1993,2551 }, - {5681,2453,5659 ,2934,42,3053 }, {7192,7207,7191 ,7648,7608,7634 }, - {7462,7494,7435 ,4310,4309,6244 }, {795,1511,1344 ,302,4921,300 }, - {1511,795,4377 ,4921,302,3090 }, {7426,7425,7399 ,7537,3995,7428 }, - {7347,7346,7313 ,7576,7584,7583 }, {7189,7205,7188 ,7493,7669,7503 }, - {7288,7347,7313 ,7577,7576,7583 }, {7131,7130,7105 ,7654,6823,5279 }, - {7313,7312,7263 ,7583,4333,627 }, {7680,7701,7679 ,7673,3515,7674 }, - {7224,7242,7223 ,7491,7627,7492 }, {7437,7496,7465 ,5938,7470,7581 }, - {7496,7522,7465 ,7470,7395,7581 }, {4897,7837,4264 ,5442,5967,5540 }, - {7837,3912,3740 ,5967,7680,7639 }, {3740,3912,1413 ,7639,7680,7659 }, - {6477,7669,3423 ,7671,7681,7660 }, {3423,7861,3633 ,7660,7682,7661 }, - {7385,7412,7384 ,7630,3765,7683 }, {8136,8063,8140 ,2449,465,2269 }, - {7553,7552,7495 ,7655,5546,4308 }, {7520,7553,7495 ,7658,7655,4308 }, - {7878,7929,7877 ,7411,7684,7549 }, {7626,7624,7570 ,7438,7439,5204 }, - {8060,3783,8037 ,7685,5311,4528 }, {8043,5557,5558 ,6397,756,2302 }, - {7205,7221,7204 ,7669,7545,5120 }, {3326,6346,6347 ,826,4883,451 }, - {8021,8051,8037 ,7365,6172,4528 }, {2280,2243,8053 ,3613,1993,7676 }, - {7571,7626,7570 ,5126,7438,5204 }, {2484,2485,2524 ,3499,2815,3395 }, - {6898,6870,2205 ,1946,2616,2874 }, {7599,7626,7571 ,5125,7438,5126 }, - {7513,7571,7512 ,3611,5126,5203 }, {7651,7625,7626 ,7675,7139,7438 }, - {7223,7222,7189 ,7492,628,7493 }, {2141,8101,8091 ,2015,383,2167 }, - {3862,7810,1494 ,550,552,1083 }, {14,302,223 ,1986,622,1985 }, - {91,14,223 ,1984,1986,1985 }, {7384,7359,7332 ,7683,7686,6685 }, - {7333,7384,7332 ,4353,7683,6685 }, {7411,7410,7359 ,3767,3766,7686 }, - {7384,7411,7359 ,7683,3767,7686 }, {7232,7248,7231 ,2124,73,6944 }, - {7691,7690,7666 ,4419,6466,7566 }, {7223,7264,7222 ,7492,626,628 }, - {7288,7263,7264 ,7577,627,626 }, {7798,7851,7825 ,4728,6625,3768 }, - {7850,7849,7824 ,3769,7551,3770 }, {7999,8022,7998 ,4583,4123,7209 }, - {7751,7750,7701 ,4332,7687,3515 }, {8040,8039,8001 ,7688,7476,7689 }, - {8002,8040,8001 ,3777,7688,7689 }, {1413,3912,6477 ,7659,7680,7671 }, - {7669,3863,7861 ,7681,7690,7682 }, {3423,7669,7861 ,7660,7681,7682 }, - {3863,3538,3633 ,7690,7691,7661 }, {7861,3863,3633 ,7682,7690,7661 }, - {3633,3538,5039 ,7661,7691,7672 }, {5039,4573,2733 ,7672,5314,5367 }, - {4303,85,166 ,3728,2504,3729 }, {7876,7927,7902 ,1725,1716,7692 }, - {7958,8007,7957 ,3855,3854,7385 }, {7706,7730,7657 ,7693,4413,7417 }, - {7955,8003,7979 ,4254,3776,3775 }, {7299,7275,6346 ,7694,1854,4883 }, - {7329,7328,7275 ,7695,7552,1854 }, {7299,7329,7275 ,7694,7695,1854 }, - {7329,7357,7328 ,7695,7597,7552 }, {7652,7651,7626 ,7696,7675,7438 }, - {8054,2280,8053 ,7402,3613,7676 }, {2326,2325,2280 ,3588,1994,3613 }, - {7730,7776,7729 ,4413,4412,7697 }, {8043,5558,5599 ,6397,2302,2213 }, - {4558,7918,4559 ,4209,5555,5237 }, {7754,7753,7704 ,7350,3643,3562 }, - {7399,7398,7346 ,7428,7429,7584 }, {7701,7700,7679 ,3515,7698,7674 }, - {7349,7375,7315 ,7609,7699,7496 }, {3402,1538,3400 ,3660,0,3659 }, - {1973,3862,1494 ,551,550,1083 }, {7597,7596,7534 ,7700,7701,7314 }, - {7534,7535,7481 ,7314,7517,7542 }, {7929,7977,7928 ,7684,1714,1724 }, - {7104,7117,7090 ,5280,7650,4080 }, {7091,7104,7090 ,4153,5280,4080 }, - {7656,7683,7603 ,7401,5267,5266 }, {7635,7613,7553 ,7646,5106,7655 }, - {7522,7521,7465 ,7395,7657,7581 }, {3895,3912,7837 ,4455,7680,5967 }, - {3912,7388,6477 ,7680,7702,7671 }, {7388,7669,6477 ,7702,7681,7671 }, - {3863,587,5039 ,7690,7703,7672 }, {3538,3863,5039 ,7691,7690,7672 }, - {587,3401,4573 ,7703,7704,5314 }, {5039,587,4573 ,7672,7703,5314 }, - {7462,7520,7495 ,4310,7658,4308 }, {7265,7290,7243 ,7497,7635,7632 }, - {7569,7597,7534 ,7705,7700,7314 }, {7407,7406,7357 ,7706,7538,7597 }, - {7407,7432,7406 ,7706,7554,7538 }, {7270,7292,7247 ,2555,7594,7360 }, - {1991,597,153 ,7707,791,663 }, {8105,8137,8107 ,3791,2174,658 }, - {7219,7261,7218 ,1529,1528,7708 }, {5523,8055,3121 ,7709,7710,2076 }, - {5644,3724,3615 ,4133,4132,201 }, {3724,5683,5682 ,4132,3939,3783 }, - {3615,3724,5682 ,201,4132,3783 }, {7346,7398,7345 ,7584,7429,7588 }, - {7464,7463,7412 ,4246,7711,3765 }, {7689,402,7712 ,6444,5349,5350 }, - {7130,7117,7104 ,6823,7650,5280 }, {7623,7677,7622 ,7427,7426,7460 }, - {7133,7165,7132 ,1989,7265,7621 }, {7144,7145,7170 ,7653,7629,7652 }, - {3634,4813,68 ,5507,4088,4087 }, {7334,3912,3895 ,7712,7680,4455 }, - {3376,7334,3895 ,4466,7712,4455 }, {7388,7584,7669 ,7702,7713,7681 }, - {7584,3863,7669 ,7713,7690,7681 }, {587,7583,3401 ,7703,7714,7704 }, - {7954,7953,7903 ,7715,7716,7717 }, {7904,7954,7903 ,7513,7715,7717 }, - {7139,7140,7161 ,1025,7415,2559 }, {7115,7116,7139 ,1024,7262,1025 }, - {7263,7262,7241 ,627,4335,4465 }, {7492,7490,7491 ,7718,7478,7604 }, - {5556,5555,5535 ,3511,6338,3512 }, {8023,8022,7999 ,4582,4123,4583 }, - {6431,5495,6522 ,7719,4134,7720 }, {3121,791,6658 ,2076,7643,7665 }, - {6658,791,1350 ,7665,7643,509 }, {1991,2654,597 ,7707,2773,791 }, - {1350,5570,6658 ,509,508,7665 }, {7715,3724,5495 ,7721,4132,4134 }, - {3338,4207,7739 ,4147,4247,7571 }, {7458,7516,7487 ,7550,5708,5707 }, - {7482,7481,7425 ,7722,7542,3995 }, {7722,7721,7676 ,7645,7454,7461 }, - {7677,7722,7676 ,7426,7645,7461 }, {7455,7514,7484 ,7579,3610,3612 }, - {7751,7801,7750 ,4332,1618,7687 }, {7244,7265,7243 ,7620,7497,7632 }, - {5026,4744,4859 ,4225,4424,5039 }, {2618,7334,3376 ,4454,7712,4466 }, - {7334,2618,3912 ,7712,4454,7680 }, {3912,2618,7388 ,7680,4454,7702 }, - {4546,3863,7584 ,7723,7690,7713 }, {4546,881,3863 ,7723,7724,7690 }, - {881,587,3863 ,7724,7703,7690 }, {7876,7902,7852 ,1725,7692,7412 }, - {8050,3783,4589 ,4529,5311,776 }, {382,1444,4207 ,3534,4035,4247 }, - {7721,7770,7720 ,7454,4272,4271 }, {7550,7549,7490 ,7725,7605,7478 }, - {7492,7550,7490 ,7718,7725,7478 }, {7824,7797,7747 ,3770,3506,331 }, - {7379,7404,7378 ,7430,7726,7431 }, {7116,7140,7139 ,7262,7415,1025 }, - {382,4207,1005 ,3534,4247,3535 }, {8059,8034,2275 ,4235,7586,3152 }, - {7689,7688,7613 ,6444,6443,5106 }, {7886,2296,2295 ,6561,2664,3160 }, - {3737,5495,5571 ,7642,4134,4616 }, {1218,3008,6891 ,3255,546,813 }, - {1517,1622,235 ,600,4238,598 }, {145,2694,2627 ,810,811,2776 }, - {3934,5683,3724 ,7727,3939,4132 }, {3934,3009,5683 ,7727,3747,3939 }, - {2419,2959,890 ,3353,4608,3283 }, {7647,7675,7696 ,4967,5192,7728 }, - {7495,7552,7494 ,4308,5546,4309 }, {7130,7143,7142 ,6823,7651,7729 }, - {8073,8085,2343 ,2567,2016,2685 }, {3693,4590,278 ,5347,1490,1489 }, - {7978,7977,7929 ,7730,1714,7684 }, {7876,7852,7853 ,1725,7412,1617 }, - {4819,3401,3139 ,5216,7704,5400 }, {6292,6282,6283 ,5403,6617,4298 }, - {2618,3682,7388 ,4454,7731,7702 }, {3682,7839,7388 ,7731,7732,7702 }, - {7388,7839,7584 ,7702,7732,7713 }, {881,6712,587 ,7724,7733,7703 }, - {6712,7911,7583 ,7733,7734,7714 }, {587,6712,7583 ,7703,7733,7714 }, - {7911,3139,3401 ,7734,5400,7704 }, {7583,7911,3401 ,7714,7734,7704 }, - {7771,7824,7770 ,4336,3770,4272 }, {7803,7854,7828 ,4636,7514,7735 }, - {7117,7142,7141 ,7650,7729,7414 }, {7485,7514,7456 ,7636,3610,7578 }, - {7849,7850,7824 ,7551,3769,3770 }, {7711,7710,7663 ,7736,7560,7559 }, - {7850,7849,7824 ,3769,7551,3770 }, {7664,7711,7663 ,7611,7736,7559 }, - {7675,7647,7696 ,5192,4967,7728 }, {5535,5519,5536 ,3512,6337,754 }, - {2296,7886,2264 ,2664,6561,4166 }, {818,2844,906 ,1018,1329,1019 }, - {3121,8055,791 ,2076,7710,7643 }, {3737,6522,5495 ,7642,7720,4134 }, - {4573,3401,4819 ,5314,7704,5216 }, {6169,6140,6141 ,2334,2333,2386 }, - {3934,5038,3009 ,7727,3628,3747 }, {4883,1388,4774 ,5538,6311,5332 }, - {7117,7130,7142 ,7650,6823,7729 }, {7375,7428,7374 ,7699,7670,4988 }, - {3693,278,3638 ,5347,1489,5950 }, {8001,8039,8023 ,7689,7476,4582 }, - {8001,8023,8000 ,7689,4582,4581 }, {7877,7928,7876 ,7549,1724,1725 }, - {5495,6431,7715 ,4134,7719,7721 }, {5080,7839,3682 ,7737,7732,7731 }, - {5080,7584,7839 ,7737,7713,7732 }, {5080,2307,7584 ,7737,7738,7713 }, - {7584,2307,4546 ,7713,7738,7723 }, {6712,3139,7911 ,7733,5400,7734 }, - {6797,8108,8123 ,2246,2287,2247 }, {7312,7345,7311 ,4333,7588,4334 }, - {7116,7117,7141 ,7262,7650,7414 }, {7825,7851,7798 ,3768,6625,4728 }, - {7933,7959,7908 ,7507,7607,7366 }, {3297,3296,7783 ,4203,4159,7616 }, - {7882,7933,7908 ,7487,7507,7366 }, {886,2379,213 ,3464,3238,3606 }, - {5519,7962,5536 ,6337,7739,754 }, {7962,5522,5536 ,7739,755,754 }, - {3702,4249,1185 ,1303,6136,6159 }, {5523,2708,8055 ,7709,7740,7710 }, - {2708,6437,791 ,7740,399,7643 }, {8055,2708,791 ,7710,7740,7643 }, - {3737,7785,6522 ,7642,7741,7720 }, {6431,1266,3724 ,7719,7742,4132 }, - {7715,6431,3724 ,7721,7719,4132 }, {1266,3739,3934 ,7742,7743,7727 }, - {3724,1266,3934 ,4132,7742,7727 }, {3702,1185,5520 ,1303,6159,1304 }, - {7725,7702,7703 ,7420,3513,7667 }, {7675,7719,7696 ,5192,6541,7728 }, - {7385,7384,7333 ,7630,7683,4353 }, {7625,7678,7623 ,7139,7425,7427 }, - {7373,7427,7399 ,4989,7536,7428 }, {7750,7772,7748 ,7687,7744,7644 }, - {3875,2618,3184 ,5845,4454,4453 }, {3875,3682,2618 ,5845,7731,4454 }, - {2307,3483,4546 ,7738,7745,7723 }, {3483,881,4546 ,7745,7724,7723 }, - {2277,3693,4572 ,3522,5347,5949 }, {7997,7996,7950 ,7210,7328,7211 }, - {2486,2527,2526 ,2814,2637,2636 }, {7803,7828,7775 ,4636,7735,7509 }, - {7376,7351,7402 ,7746,6587,6589 }, {3296,2265,7783 ,4159,2662,7616 }, - {7882,7908,7859 ,7487,7366,7598 }, {2264,7886,2265 ,4166,6561,2662 }, - {7912,5519,5493 ,7747,6337,6336 }, {5519,7912,7962 ,6337,7747,7739 }, - {7962,7984,5522 ,7739,7748,755 }, {2708,3914,791 ,7740,7749,7643 }, - {6437,2708,791 ,399,7740,7643 }, {3914,3790,3737 ,7749,399,7642 }, - {791,3914,3737 ,7643,7749,7642 }, {7785,7360,6522 ,7741,7750,7720 }, - {6522,7360,6431 ,7720,7750,7719 }, {3739,3910,3934 ,7743,7751,7727 }, - {3934,3910,5038 ,7727,7751,3628 }, {7597,7622,7596 ,7700,7460,7701 }, - {7625,7623,7624 ,7139,7427,7439 }, {7190,7189,7142 ,7633,7493,7729 }, - {7173,7210,7172 ,7264,7499,7405 }, {8039,8038,8023 ,7476,4121,4582 }, - {7540,7628,7602 ,5709,7528,5867 }, {7765,5080,3682 ,7752,7737,7731 }, - {3875,7765,3682 ,5845,7752,7731 }, {3483,1526,6712 ,7745,7753,7733 }, - {881,3483,6712 ,7724,7745,7733 }, {1526,3171,6712 ,7753,7754,7733 }, - {3171,3139,6712 ,7754,5400,7733 }, {3171,4846,3139 ,7754,4237,5400 }, - {7877,7876,7826 ,7549,1725,1616 }, {3295,3296,177 ,7565,4159,3618 }, - {3297,3313,3296 ,4203,4160,4159 }, {7912,7963,7962 ,7747,7755,7739 }, - {7962,7963,7984 ,7739,7755,7748 }, {7963,7985,5522 ,7755,7756,755 }, - {7984,7963,5522 ,7748,7755,755 }, {5522,7985,5523 ,755,7756,7709 }, - {3914,7467,3737 ,7749,7757,7642 }, {3790,3914,3737 ,399,7749,7642 }, - {3737,7467,7785 ,7642,7757,7741 }, {7360,1266,6431 ,7750,7742,7719 }, - {3910,3739,1266 ,7751,7743,7742 }, {3567,5038,3910 ,7758,3628,7751 }, - {3614,4839,5038 ,7759,5484,3628 }, {3567,3614,5038 ,7758,7759,3628 }, - {3614,5092,4839 ,7759,3953,5484 }, {7701,7724,7700 ,3515,7760,7698 }, - {7143,7190,7142 ,7651,7633,7729 }, {7288,7313,7263 ,7577,7583,627 }, - {7727,7726,7681 ,3563,7418,7459 }, {7682,7727,7681 ,3564,3563,7459 }, - {7580,7636,7553 ,7596,7567,7655 }, {7636,7666,7635 ,7567,7566,7646 }, - {7761,7765,3875 ,7761,7752,5845 }, {7761,5080,7765 ,7761,7737,7752 }, - {3639,2307,5080 ,7762,7738,7737 }, {7761,3639,5080 ,7761,7762,7737 }, - {7936,7935,7884 ,5528,5527,7391 }, {7777,7778,7807 ,4411,7601,7602 }, - {7607,7660,7606 ,7455,7381,7457 }, {5493,7888,7912 ,6336,7763,7747 }, - {5214,5215,5235 ,6272,6313,6385 }, {7985,8044,2708 ,7756,7764,7740 }, - {5523,7985,2708 ,7709,7756,7740 }, {3914,3188,7467 ,7749,7765,7757 }, - {7467,6482,7785 ,7757,7766,7741 }, {7785,6482,7360 ,7741,7766,7750 }, - {7360,6482,1266 ,7750,7766,7742 }, {4020,3910,1266 ,7767,7751,7742 }, - {2097,2165,2164 ,846,1041,3583 }, {7426,7482,7425 ,7537,7722,3995 }, - {7773,7802,7751 ,7668,6566,4332 }, {7573,7540,7602 ,2013,5709,5867 }, - {7151,7150,3293 ,1202,7488,1988 }, {7731,7778,7777 ,7516,7601,4411 }, - {7756,7731,7777 ,7768,7516,4411 }, {7685,7731,7756 ,7518,7516,7768 }, - {7212,7211,7173 ,7208,7500,7264 }, {6610,3483,2307 ,7769,7745,7738 }, - {3639,6610,2307 ,7762,7769,7738 }, {3483,6610,1526 ,7745,7769,7753 }, - {8067,8091,8083 ,2168,2167,2103 }, {7320,7319,7292 ,7282,7432,7594 }, - {7515,7540,7573 ,1079,5709,2013 }, {7830,7829,7806 ,7770,7614,7612 }, - {7636,7635,7553 ,7567,7646,7655 }, {7950,7996,7949 ,7211,7328,7591 }, - {7481,7480,7454 ,7542,7463,3996 }, {7397,7424,7371 ,1186,1188,3748 }, - {7888,7938,7912 ,7763,7771,7747 }, {7912,7938,7963 ,7747,7771,7755 }, - {7985,8027,8044 ,7756,7772,7764 }, {8044,8027,2708 ,7764,7772,7740 }, - {8027,3689,3914 ,7772,7773,7749 }, {2708,8027,3914 ,7740,7772,7749 }, - {6482,1939,1266 ,7766,7774,7742 }, {1939,7862,1266 ,7774,7775,7742 }, - {1266,7862,4020 ,7742,7775,7767 }, {4020,3567,3910 ,7767,7758,7751 }, - {3567,5092,3614 ,7758,3953,7759 }, {7600,7627,7572 ,7556,7582,5124 }, - {7145,7146,7162 ,7629,7530,7649 }, {7146,7147,7162 ,7530,6937,7649 }, - {7773,7751,7752 ,7668,4332,3514 }, {402,448,7759 ,5349,1172,399 }, - {7270,7320,7292 ,2555,7282,7594 }, {7403,7429,7457 ,6588,7572,1078 }, - {7174,7212,7173 ,7610,7208,7264 }, {7935,7934,7883 ,5527,7486,7452 }, - {7686,7685,7632 ,7553,7518,7555 }, {6483,7761,3875 ,3584,7761,5845 }, - {2096,6483,3875 ,788,3584,5845 }, {6610,3767,1526 ,7769,7776,7753 }, - {3767,3171,1526 ,7776,7754,7753 }, {3767,6412,4846 ,7776,7777,4237 }, - {3171,3767,4846 ,7754,7776,4237 }, {235,1622,4846 ,598,4238,4237 }, - {6412,235,4846 ,7777,598,4237 }, {1993,4075,342 ,4544,4521,4542 }, - {3405,3456,8086 ,1798,1145,4823 }, {7272,7271,7230 ,7666,2554,7498 }, - {7956,7981,7931 ,7403,4252,7508 }, {3136,2654,2548 ,2783,2773,2813 }, - {5479,7840,5493 ,5387,7778,6336 }, {2287,8007,99 ,3735,3854,3743 }, - {7840,7888,5493 ,7778,7763,6336 }, {7963,7938,7985 ,7755,7771,7756 }, - {8027,3723,3689 ,7772,7779,7773 }, {3723,3821,3914 ,7779,7780,7749 }, - {3689,3723,3914 ,7773,7779,7749 }, {3914,3821,3188 ,7749,7780,7765 }, - {3188,7787,7467 ,7765,7781,7757 }, {7467,7787,6482 ,7757,7781,7766 }, - {1939,3374,7862 ,7774,7782,7775 }, {3374,3586,4020 ,7782,7783,7767 }, - {7862,3374,4020 ,7775,7782,7767 }, {3586,3722,4020 ,7783,7784,7767 }, - {3823,3567,4020 ,7785,7758,7767 }, {3722,3823,4020 ,7784,7785,7767 }, - {3823,5092,3567 ,7785,3953,7758 }, {7189,7188,7141 ,7493,7503,7414 }, - {7242,7264,7223 ,7627,626,7492 }, {7658,7706,7657 ,7505,7693,7417 }, - {7554,7523,3351 ,7786,7393,1444 }, {7128,7127,7114 ,5391,7245,5392 }, - {7910,6483,2096 ,3582,3584,788 }, {2207,3639,7761 ,7787,7762,7761 }, - {6483,2207,7761 ,3584,7787,7761 }, {8086,3456,5771 ,4823,1145,2868 }, - {7352,7377,7403 ,7595,7592,6588 }, {7212,7230,7211 ,7208,7498,7500 }, - {7614,7582,7523 ,7788,7469,7393 }, {7554,7614,7523 ,7786,7788,7393 }, - {7276,6346,3326 ,3696,4883,826 }, {4555,4582,7716 ,5496,5478,5549 }, - {7840,7889,7888 ,7778,7789,7763 }, {7889,7913,7888 ,7789,7790,7763 }, - {7913,7939,7938 ,7790,7791,7771 }, {7888,7913,7938 ,7763,7790,7771 }, - {7939,7964,7938 ,7791,7792,7771 }, {7938,7964,7985 ,7771,7792,7756 }, - {7964,8010,7985 ,7792,7793,7756 }, {7985,8010,8027 ,7756,7793,7772 }, - {3723,1123,3821 ,7779,7794,7780 }, {3821,7784,7787 ,7780,7795,7781 }, - {3188,3821,7787 ,7765,7780,7781 }, {7787,7784,6482 ,7781,7795,7766 }, - {7784,1939,6482 ,7795,7774,7766 }, {3766,5092,3823 ,3954,3953,7785 }, - {7556,3766,3823 ,5116,3954,7785 }, {8133,8131,8107 ,2131,2307,658 }, - {7242,7288,7264 ,7627,7577,626 }, {8022,8021,7998 ,4123,7365,7209 }, - {7351,7352,7403 ,6587,7595,6588 }, {7377,7429,7403 ,7592,7572,6588 }, - {7276,7299,6346 ,3696,7694,4883 }, {7330,7329,7299 ,7796,7695,7694 }, - {7358,7357,7329 ,7797,7597,7695 }, {7330,7358,7329 ,7796,7797,7695 }, - {1973,1659,4685 ,551,5132,4894 }, {3896,6610,3639 ,7798,7769,7762 }, - {2207,3896,3639 ,7787,7798,7762 }, {3896,3767,6610 ,7798,7776,7769 }, - {7317,7318,7351 ,5947,7593,6587 }, {7250,7249,7232 ,3418,7622,2124 }, - {7233,7250,7232 ,2125,3418,2124 }, {7640,7641,4577 ,5351,5356,5352 }, - {6320,7439,7500 ,190,7297,326 }, {7500,7524,4595 ,326,1630,5289 }, - {4557,4558,4584 ,5310,4209,5308 }, {7433,7432,7407 ,7799,7554,7706 }, - {3766,4922,4585 ,3954,5256,3955 }, {5479,7814,7840 ,5387,6988,7778 }, - {7863,7864,7889 ,7800,7801,7789 }, {7840,7863,7889 ,7778,7800,7789 }, - {7864,7914,7913 ,7801,7802,7790 }, {7889,7864,7913 ,7789,7801,7790 }, - {7913,7914,7939 ,7790,7802,7791 }, {7964,7986,8010 ,7792,7803,7793 }, - {7986,8010,8027 ,7803,7793,7772 }, {8010,7986,8027 ,7793,7803,7772 }, - {8010,8045,3723 ,7793,7804,7779 }, {8027,8010,3723 ,7772,7793,7779 }, - {1123,7784,3821 ,7794,7795,7780 }, {7784,5023,1939 ,7795,7805,7774 }, - {5023,3374,1939 ,7805,7782,7774 }, {3374,3722,3586 ,7782,7784,7783 }, - {7556,3823,3722 ,5116,7785,7784 }, {3121,5522,5523 ,2076,755,7709 }, - {7653,7702,7652 ,7638,3513,7696 }, {7120,7119,7093 ,6938,7529,4318 }, - {7272,7321,7271 ,7666,7501,2554 }, {7208,7209,7226 ,1671,7523,6686 }, - {7433,7434,7432 ,7799,7806,7554 }, {7492,7491,7432 ,7718,7604,7554 }, - {7434,7492,7432 ,7806,7718,7554 }, {3830,3976,5483 ,5882,919,171 }, - {4961,2207,6483 ,2905,7787,3584 }, {6802,3767,3896 ,7807,7776,7798 }, - {6802,3842,3767 ,7807,7808,7776 }, {3767,3842,6412 ,7776,7808,7777 }, - {6412,3842,235 ,7777,7808,598 }, {2485,2486,2526 ,2815,2814,2636 }, - {7243,7242,7224 ,7632,7627,7491 }, {7318,7352,7351 ,7593,7595,6587 }, - {7488,7541,7517 ,7585,7515,7484 }, {7439,7468,7500 ,7297,7809,326 }, - {7468,7524,7500 ,7809,1630,326 }, {99,8007,2306 ,3743,3854,6405 }, - {7611,7610,7549 ,7810,7606,7605 }, {7550,7611,7549 ,7725,7810,7605 }, - {6706,7841,7840 ,5389,7811,7778 }, {7814,6706,7840 ,6988,5389,7778 }, - {7841,7864,7863 ,7811,7801,7800 }, {7840,7841,7863 ,7778,7811,7800 }, - {7939,7914,7964 ,7791,7802,7792 }, {8010,7986,8045 ,7793,7803,7804 }, - {8045,61,1123 ,7804,7812,7794 }, {3723,8045,1123 ,7779,7804,7794 }, - {1123,3512,7784 ,7794,7813,7795 }, {7784,7176,5023 ,7795,7814,7805 }, - {5023,3827,3374 ,7805,7815,7782 }, {3827,7817,3722 ,7815,7816,7784 }, - {3374,3827,3722 ,7782,7815,7784 }, {8009,7556,3722 ,7817,5116,7784 }, - {8022,8052,8021 ,4123,4122,7365 }, {8052,8051,8021 ,4122,6172,7365 }, - {7776,7806,7755 ,4412,7612,7519 }, {7209,7246,7225 ,7523,3772,1672 }, - {7226,7209,7225 ,6686,7523,1672 }, {7729,7755,7705 ,7697,7519,7349 }, - {7728,7729,7705 ,7818,7697,7349 }, {7248,7294,7323 ,73,7819,74 }, - {7611,7664,7610 ,7810,7611,7606 }, {3352,3378,3351 ,2724,1442,1444 }, - {3859,2207,4961 ,7820,7787,2905 }, {3859,3896,2207 ,7820,7798,7787 }, - {7268,7318,7317 ,3773,7593,5947 }, {6143,7057,6107 ,4394,7207,7232 }, - {6304,7439,3533 ,7233,7297,192 }, {7525,7524,7468 ,7821,1630,7809 }, - {7525,4575,7524 ,7821,3128,1630 }, {4589,3783,4638 ,776,5311,5154 }, - {2333,7711,7664 ,3537,7736,7611 }, {2333,7710,7711 ,3537,7560,7736 }, - {7841,7865,7864 ,7811,7822,7801 }, {7914,7940,7964 ,7802,7823,7792 }, - {7940,7987,7986 ,7823,7824,7803 }, {7964,7940,7986 ,7792,7823,7803 }, - {7986,8028,8045 ,7803,7825,7804 }, {61,1097,3512 ,7812,7826,7813 }, - {1123,61,3512 ,7794,7812,7813 }, {3512,1097,7784 ,7813,7826,7795 }, - {7176,6683,5023 ,7814,7827,7805 }, {5023,6683,3827 ,7805,7827,7815 }, - {3827,3692,7817 ,7815,7828,7816 }, {7817,7762,3722 ,7816,7829,7784 }, - {7762,8009,3722 ,7829,7817,7784 }, {6760,7556,8009 ,5117,5116,7817 }, - {7762,6760,8009 ,7829,5117,7817 }, {5522,3121,5558 ,755,2076,2302 }, - {7625,7624,7598 ,7139,7439,7140 }, {7600,7653,7627 ,7556,7638,7582 }, - {7653,7652,7627 ,7638,7696,7582 }, {7349,7401,7375 ,7609,7619,7699 }, - {7459,7458,7404 ,7485,7550,7726 }, {3314,3297,7710 ,3575,4203,7560 }, - {2333,3314,7710 ,3537,3575,7560 }, {1274,1316,1315 ,1687,1657,1627 }, - {2548,3896,3859 ,2813,7798,7820 }, {2654,6802,3896 ,2773,7807,7798 }, - {2548,2654,3896 ,2813,2773,7798 }, {7171,7209,7208 ,4306,7523,1671 }, - {7628,7681,7654 ,7528,7459,7637 }, {5112,6120,5113 ,6021,142,141 }, - {7057,6143,5936 ,7207,4394,4393 }, {6083,6304,6303 ,3989,7233,7261 }, - {7413,7439,6304 ,7830,7297,7233 }, {7469,7468,7439 ,7831,7809,7297 }, - {7413,7469,7439 ,7830,7831,7297 }, {7525,7585,4575 ,7821,6805,3128 }, - {7555,3351,3377 ,7832,1444,1443 }, {177,2265,3295 ,3618,2662,7565 }, - {6705,7815,6706 ,4158,5146,5389 }, {6706,7815,7841 ,5389,5146,7811 }, - {7865,7890,7864 ,7822,7833,7801 }, {7864,7890,7914 ,7801,7833,7802 }, - {7914,7890,7940 ,7802,7833,7823 }, {7986,7987,8028 ,7803,7824,7825 }, - {8028,8056,8045 ,7825,7834,7804 }, {8045,8056,61 ,7804,7834,7812 }, - {1097,7301,7784 ,7826,7835,7795 }, {7784,7301,7176 ,7795,7835,7814 }, - {7176,7301,6683 ,7814,7835,7827 }, {448,401,402 ,1172,1387,5349 }, - {7347,7399,7346 ,7576,7428,7584 }, {7514,7572,7513 ,3610,5124,3611 }, - {7657,7728,7705 ,7417,7818,7349 }, {7780,7834,7809 ,7389,7390,7449 }, - {7628,7654,7601 ,7528,7637,7544 }, {2834,3859,4961 ,2860,7820,2905 }, - {2834,2548,3859 ,2860,2813,7820 }, {1991,3842,6802 ,7707,7808,7807 }, - {2654,1991,6802 ,2773,7707,7807 }, {3842,1991,153 ,7808,7707,663 }, - {7834,7833,7809 ,7390,7392,7449 }, {7255,6167,6234 ,7238,5974,5973 }, - {7361,6304,6083 ,7836,7233,3989 }, {7361,7413,6304 ,7836,7830,7233 }, - {7469,7525,7468 ,7831,7821,7809 }, {7641,7640,7585 ,5356,5351,6805 }, - {7668,7667,7582 ,7590,7589,7469 }, {2285,2330,2329 ,3701,3693,3680 }, - {2165,2097,2143 ,1041,846,953 }, {7815,7842,7841 ,5146,7837,7811 }, - {7841,7842,7865 ,7811,7837,7822 }, {7890,7915,7940 ,7833,7838,7823 }, - {7987,8011,8028 ,7824,7839,7825 }, {8011,3003,8056 ,7839,7840,7834 }, - {8028,8011,8056 ,7825,7839,7834 }, {8056,3003,61 ,7834,7840,7812 }, - {7301,3416,6683 ,7835,7841,7827 }, {6683,3416,3827 ,7827,7841,7815 }, - {3416,3894,3827 ,7841,7842,7815 }, {3827,3894,3692 ,7815,7842,7828 }, - {3692,7762,7817 ,7828,7829,7816 }, {7760,6760,7762 ,7843,5117,7829 }, - {7760,2814,6760 ,7843,5255,5117 }, {2049,2096,2048 ,758,788,5461 }, - {6760,2814,4636 ,5117,5255,5118 }, {7902,7952,7901 ,7692,5475,7413 }, - {7119,7120,7147 ,7529,6938,6937 }, {7292,7319,7352 ,7594,7432,7595 }, - {7703,7702,7653 ,7667,3513,7638 }, {2834,2616,2548 ,2860,2812,2813 }, - {7625,7679,7624 ,7139,7674,7439 }, {7414,7413,7361 ,7844,7830,7836 }, - {7526,7525,7469 ,7845,7821,7831 }, {7526,7585,7525 ,7845,6805,7821 }, - {4583,4556,7788 ,5498,5497,7313 }, {7865,7842,7890 ,7822,7837,7833 }, - {7915,7965,7940 ,7838,7846,7823 }, {7940,7965,7987 ,7823,7846,7824 }, - {3301,1097,61 ,7847,7826,7812 }, {3003,3301,61 ,7840,7847,7812 }, - {1097,7811,7301 ,7826,7848,7835 }, {5035,7762,3692 ,7849,7829,7828 }, - {3894,5035,3692 ,7842,7849,7828 }, {5035,6846,7762 ,7849,7850,7829 }, - {401,2334,7712 ,1387,7851,5350 }, {7749,7750,7748 ,7663,7687,7644 }, - {7121,7132,7120 ,7852,7621,6938 }, {7132,7148,7120 ,7621,6936,6938 }, - {7829,7880,7857 ,7614,7531,7533 }, {7438,7437,3321 ,7351,5938,2461 }, - {7345,7372,7311 ,7588,4373,4334 }, {2484,7713,7668 ,3499,7489,7590 }, - {7949,7974,7925 ,7591,4171,7294 }, {6278,7106,7092 ,3967,7573,3968 }, - {7243,7289,7242 ,7632,7575,7627 }, {7596,7595,7533 ,7701,4019,7039 }, - {7140,7141,7161 ,7415,7414,2559 }, {7770,7824,7747 ,4272,3770,331 }, - {7291,7316,7350 ,3774,5948,7618 }, {7336,6083,6014 ,7853,3989,6592 }, - {7336,7361,6083 ,7853,7836,3989 }, {7470,7469,7413 ,7854,7831,7830 }, - {7414,7470,7413 ,7844,7854,7830 }, {7557,7585,7526 ,7855,6805,7845 }, - {7557,7616,7585 ,7855,7856,6805 }, {7616,7641,7585 ,7856,5356,6805 }, - {7658,7657,7605 ,7505,7417,5239 }, {7300,7299,7276 ,7857,7694,3696 }, - {3306,7300,7276 ,3695,7857,3696 }, {7868,4557,7818 ,7858,5310,5309 }, - {2281,2282,2327 ,3626,3663,3627 }, {6705,5439,7815 ,4158,4157,5146 }, - {7842,7866,7890 ,7837,7859,7833 }, {7866,7915,7890 ,7859,7838,7833 }, - {7965,7988,8011 ,7846,7860,7839 }, {7987,7965,8011 ,7824,7846,7839 }, - {3301,7812,7811 ,7847,7861,7848 }, {1097,3301,7811 ,7826,7847,7848 }, - {7811,7812,7301 ,7848,7861,7835 }, {6745,7762,6846 ,7862,7829,7850 }, - {7762,6745,7760 ,7829,7862,7843 }, {6745,3789,2814 ,7862,7863,5255 }, - {7760,6745,2814 ,7843,7862,5255 }, {3789,1973,4906 ,7863,551,4895 }, - {2814,3789,4906 ,5255,7863,4895 }, {7750,7800,7772 ,7687,7568,7744 }, - {7194,7193,7147 ,1670,7647,6937 }, {8006,8005,7956 ,7407,7527,7403 }, - {7300,7330,7299 ,7857,7796,7694 }, {7408,7407,7357 ,7864,7706,7597 }, - {7358,7408,7357 ,7797,7864,7597 }, {7434,7433,7407 ,7806,7799,7706 }, - {7408,7434,7407 ,7864,7806,7706 }, {7493,7492,7434 ,7865,7718,7806 }, - {7493,7550,7492 ,7865,7725,7718 }, {7362,7361,7336 ,7866,7836,7853 }, - {7362,7414,7361 ,7866,7844,7836 }, {7470,7526,7469 ,7854,7845,7831 }, - {7616,7671,7641 ,7856,7867,5356 }, {7641,7671,4579 ,5356,7867,5355 }, - {7815,5440,7842 ,5146,5147,7837 }, {7842,5440,5410 ,7837,5147,4285 }, - {7867,7916,7915 ,7868,7869,7838 }, {7866,7867,7915 ,7859,7868,7838 }, - {7916,7941,7915 ,7869,7870,7838 }, {7915,7941,7965 ,7838,7870,7846 }, - {7988,8029,3003 ,7860,7871,7840 }, {8011,7988,3003 ,7839,7860,7840 }, - {3003,4030,3301 ,7840,7872,7847 }, {7812,8026,7301 ,7861,7873,7835 }, - {8026,3991,3416 ,7873,7874,7841 }, {7301,8026,3416 ,7835,7873,7841 }, - {3991,3481,3416 ,7874,7875,7841 }, {3481,8042,3894 ,7875,399,7842 }, - {3416,3481,3894 ,7841,7875,7842 }, {3789,1852,1973 ,7863,7876,551 }, - {8036,4589,4588 ,7327,776,775 }, {7400,7455,7428 ,7580,7579,7670 }, - {7121,7120,7094 ,7852,6938,4317 }, {7957,8006,7956 ,7385,7407,7403 }, - {7859,7908,7858 ,7598,7366,7368 }, {7611,7687,7664 ,7810,7877,7611 }, - {7687,2333,7664 ,7877,3537,7611 }, {7302,6014,6259 ,7878,6592,6718 }, - {7302,7336,6014 ,7878,7853,6592 }, {7415,7414,7362 ,7879,7844,7866 }, - {7501,7526,7470 ,7880,7845,7854 }, {7558,7557,7526 ,7881,7855,7845 }, - {7501,7558,7526 ,7880,7881,7845 }, {7672,7671,7616 ,5450,7867,7856 }, - {7671,7672,4579 ,7867,5450,5355 }, {6531,8134,8120 ,2280,3263,906 }, - {7676,7720,7699 ,7461,4271,3951 }, {5410,7867,7866 ,4285,7868,7859 }, - {7842,5410,7866 ,7837,4285,7859 }, {7916,7942,7941 ,7869,7882,7870 }, - {7942,7966,7965 ,7882,7883,7846 }, {7941,7942,7965 ,7870,7882,7846 }, - {7966,7988,7965 ,7883,7860,7846 }, {8029,4622,4030 ,7871,7884,7872 }, - {3003,8029,4030 ,7840,7871,7872 }, {4030,4622,3301 ,7872,7884,7847 }, - {3481,6294,3894 ,7875,7885,7842 }, {8042,3481,3894 ,399,7875,7842 }, - {6294,7670,5035 ,7885,7886,7849 }, {3894,6294,5035 ,7842,7885,7849 }, - {936,3933,935 ,5234,7678,5264 }, {7400,7428,7375 ,7580,7670,7699 }, - {8006,2285,8005 ,7407,3701,7527 }, {7685,7756,7730 ,7518,7768,4413 }, - {7708,7707,7660 ,7388,7382,7381 }, {7857,7879,7856 ,7533,7532,4635 }, - {7884,7883,7833 ,7391,7452,7392 }, {7363,7362,7336 ,7887,7866,7853 }, - {7302,7363,7336 ,7878,7887,7853 }, {7440,7470,7414 ,7888,7854,7844 }, - {7415,7440,7414 ,7879,7888,7844 }, {7440,7501,7470 ,7888,7880,7854 }, - {7617,7616,7557 ,7889,7856,7855 }, {7558,7617,7557 ,7881,7889,7855 }, - {7685,7706,7658 ,7518,7693,7505 }, {7867,5410,5411 ,7868,4285,4284 }, - {7555,7554,3351 ,7832,7786,1444 }, {7949,7995,7974 ,7591,4135,4171 }, - {4264,7837,3740 ,5540,5967,7639 }, {7942,7989,7988 ,7882,7890,7860 }, - {7966,7942,7988 ,7883,7882,7860 }, {2950,3301,4622 ,7891,7847,7884 }, - {2950,7812,3301 ,7891,7861,7847 }, {7812,2950,8026 ,7861,7891,7873 }, - {3481,7670,6294 ,7875,7886,7885 }, {7670,6604,6846 ,7886,7892,7850 }, - {5035,7670,6846 ,7849,7886,7850 }, {6604,5042,6745 ,7892,7893,7862 }, - {6846,6604,6745 ,7850,7892,7862 }, {5042,7737,3789 ,7893,7894,7863 }, - {6745,5042,3789 ,7862,7893,7863 }, {7737,7080,1852 ,7894,7895,7876 }, - {3789,7737,1852 ,7863,7894,7876 }, {7080,7810,1973 ,7895,552,551 }, - {1852,7080,1973 ,7876,7895,551 }, {8004,8025,7980 ,7404,7510,4253 }, - {7685,7658,7631 ,7518,7505,7504 }, {7352,7319,7377 ,7595,7432,7592 }, - {7622,7650,7595 ,7460,7237,4019 }, {7730,7756,7777 ,4413,7768,4411 }, - {7295,7324,7323 ,7562,7617,74 }, {7706,7685,7730 ,7693,7518,4413 }, - {7294,7295,7323 ,7819,7562,74 }, {6234,6167,6259 ,5973,5974,6718 }, - {6167,7302,6259 ,5974,7878,6718 }, {7363,7415,7362 ,7887,7879,7866 }, - {7502,7501,7440 ,7896,7880,7888 }, {7502,7558,7501 ,7896,7881,7880 }, - {7617,7672,7616 ,7889,5450,7856 }, {1210,5017,4144 ,4739,5092,4761 }, - {4562,8057,1381 ,5018,7897,5193 }, {4839,4730,5038 ,5484,5438,3628 }, - {7867,5418,7916 ,7868,3471,7869 }, {7916,5418,7942 ,7869,3471,7882 }, - {7989,8012,7988 ,7890,7898,7860 }, {8030,8029,7988 ,7899,7871,7860 }, - {8012,8030,7988 ,7898,7899,7860 }, {8030,4622,8029 ,7899,7884,7871 }, - {2950,7466,8026 ,7891,7900,7873 }, {7466,3991,8026 ,7900,7874,7873 }, - {1312,3481,3991 ,7901,7875,7874 }, {7466,1312,3991 ,7900,7901,7874 }, - {3481,3937,7670 ,7875,7902,7886 }, {5042,7063,7737 ,7893,7903,7894 }, - {7737,7063,7080 ,7894,7903,7895 }, {7928,7977,7927 ,1724,1714,1716 }, - {7225,7267,7245 ,1672,4331,7506 }, {7958,7957,7932 ,3855,7385,7408 }, - {7632,7685,7631 ,7555,7518,7504 }, {7615,7614,7554 ,2816,7788,7786 }, - {7555,7615,7554 ,7832,2816,7786 }, {7615,7582,7614 ,2816,7469,7788 }, - {2485,7668,7582 ,2815,7590,7469 }, {7615,2485,7582 ,2816,2815,7469 }, - {8051,8060,8037 ,6172,7685,4528 }, {6319,6304,3533 ,6789,7233,192 }, - {7666,7690,7635 ,7566,6466,7646 }, {2485,2484,7668 ,2815,3499,7590 }, - {7303,7302,6167 ,7904,7878,5974 }, {7389,7415,7363 ,7905,7879,7887 }, - {7441,7440,7415 ,7906,7888,7879 }, {7389,7441,7415 ,7905,7906,7879 }, - {7559,7558,7502 ,7907,7881,7896 }, {7642,7672,7617 ,7908,5450,7889 }, - {7642,4555,7672 ,7908,5496,5450 }, {4555,7716,7672 ,5496,5549,5450 }, - {2484,2451,7713 ,3499,2102,7489 }, {5411,5418,7867 ,4284,3471,7868 }, - {7315,7375,7314 ,7496,7699,7909 }, {5418,7917,7942 ,3471,4920,7882 }, - {8012,7989,8030 ,7898,7890,7899 }, {3843,4622,8030 ,7677,7884,7899 }, - {7740,3937,3481 ,7910,7902,7875 }, {1312,7740,3481 ,7901,7910,7875 }, - {3937,7740,7670 ,7902,7910,7886 }, {7810,3862,1494 ,552,550,1083 }, - {5598,8043,5599 ,2216,6397,2213 }, {6706,6741,6705 ,5389,5388,4158 }, - {7267,7266,7245 ,4331,6769,7506 }, {7295,7294,7249 ,7562,7819,7622 }, - {3305,7300,3306 ,879,7857,3695 }, {7331,7330,7300 ,7911,7796,7857 }, - {7331,7358,7330 ,7911,7797,7796 }, {7824,7849,7797 ,3770,7551,3506 }, - {7337,7363,7302 ,7912,7887,7878 }, {7303,7337,7302 ,7904,7912,7878 }, - {7337,7389,7363 ,7912,7905,7887 }, {7441,7502,7440 ,7906,7896,7888 }, - {7586,7617,7558 ,7913,7889,7881 }, {7559,7586,7558 ,7907,7913,7881 }, - {7586,7642,7617 ,7913,7908,7889 }, {7409,7408,7358 ,6245,7864,7797 }, - {7435,7434,7408 ,6244,7806,7864 }, {7409,7435,7408 ,6245,6244,7864 }, - {7613,7688,7634 ,5106,6443,7474 }, {7917,7967,7942 ,4920,7914,7882 }, - {7942,7967,7989 ,7882,7914,7890 }, {3933,4622,3843 ,7678,7884,7677 }, - {3251,2950,4622 ,7915,7891,7884 }, {3933,3251,4622 ,7678,7915,7884 }, - {3251,7466,2950 ,7915,7900,7891 }, {7466,7498,1312 ,7900,7916,7901 }, - {7740,6054,7670 ,7910,7917,7886 }, {6054,7786,7670 ,7917,7918,7886 }, - {7670,7786,6604 ,7886,7918,7892 }, {7786,6845,5042 ,7918,7919,7893 }, - {6604,7786,5042 ,7892,7918,7893 }, {6845,6743,7063 ,7919,7920,7903 }, - {5042,6845,7063 ,7893,7919,7903 }, {6743,1351,7080 ,7920,1162,7895 }, - {7063,6743,7080 ,7903,7920,7895 }, {1351,8008,7810 ,1162,1163,552 }, - {7080,1351,7810 ,7895,1162,552 }, {7810,8008,3862 ,552,1163,550 }, - {4582,4581,7716 ,5478,5430,5549 }, {7534,7596,7533 ,7314,7701,7039 }, - {7676,7699,7650 ,7461,3951,7237 }, {7175,7212,7174 ,2347,7208,7610 }, - {7551,7550,7493 ,5108,7725,7865 }, {7255,7303,6167 ,7238,7904,5974 }, - {7390,7389,7337 ,7921,7905,7912 }, {7503,7502,7441 ,7922,7896,7906 }, - {7503,7559,7502 ,7922,7907,7896 }, {7643,7642,7586 ,7923,7908,7913 }, - {7612,7611,7550 ,5107,7810,7725 }, {7551,7612,7550 ,5108,5107,7725 }, - {860,1183,953 ,1385,1238,1237 }, {8013,7989,7967 ,7924,7890,7914 }, - {8013,8030,7989 ,7924,7899,7890 }, {7816,7466,3251 ,7925,7900,7915 }, - {6198,7498,7466 ,7926,7916,7900 }, {7816,6198,7466 ,7925,7926,7900 }, - {6198,1312,7498 ,7926,7901,7916 }, {8049,2317,8035 ,5393,3129,6675 }, - {7902,7901,7852 ,7692,7413,7412 }, {7175,7174,7151 ,2347,7610,1202 }, - {7665,7687,7611 ,7927,7877,7810 }, {2334,2333,7687 ,7851,3537,7877 }, - {5672,5718,5744 ,5324,6126,6090 }, {7304,7303,7255 ,7928,7904,7238 }, - {7304,7337,7303 ,7928,7912,7904 }, {7442,7441,7389 ,7929,7906,7905 }, - {7390,7442,7389 ,7921,7929,7905 }, {7527,7559,7503 ,7930,7907,7922 }, - {7527,7586,7559 ,7930,7913,7907 }, {7694,4555,7642 ,7931,5496,7908 }, - {7643,7694,7642 ,7923,7931,7908 }, {935,8030,8013 ,5264,7899,7924 }, - {4058,4055,1253 ,4708,3678,2353 }, {7816,3251,3933 ,7925,7915,7678 }, - {6198,7961,1312 ,7926,7932,7901 }, {3565,7740,1312 ,7933,7910,7901 }, - {7961,3565,1312 ,7932,7933,7901 }, {7740,3565,6054 ,7910,7933,7917 }, - {7248,7272,7231 ,73,7666,6944 }, {7291,7350,7349 ,3774,7618,7609 }, - {7350,7376,7349 ,7618,7746,7609 }, {7349,7376,7401 ,7609,7746,7619 }, - {7376,7402,7401 ,7746,6589,7619 }, {8050,8037,3783 ,4529,4528,5311 }, - {7401,7400,7375 ,7619,7580,7699 }, {7192,7191,7170 ,7648,7634,7652 }, - {4126,3141,4176 ,124,4701,4703 }, {6347,6346,7860 ,451,4883,452 }, - {5483,5261,3830 ,171,173,5882 }, {6282,6060,5115 ,6617,5914,5913 }, - {5109,5108,7166 ,4182,4184,5971 }, {1934,1418,22 ,4620,4619,4066 }, - {7891,7918,4558 ,7934,5555,4209 }, {2410,3670,489 ,1,281,3639 }, - {7256,7255,5845 ,7935,7238,143 }, {6120,7256,5845 ,142,7935,143 }, - {7338,7337,7304 ,7936,7912,7928 }, {7338,7390,7337 ,7936,7921,7912 }, - {7442,7503,7441 ,7929,7922,7906 }, {7587,7586,7527 ,7937,7913,7930 }, - {7587,7643,7586 ,7937,7923,7913 }, {7717,4556,4555 ,7938,5497,5496 }, - {7694,7717,4555 ,7931,7938,5496 }, {2317,2275,8035 ,3129,3152,6675 }, - {4558,4557,7891 ,4209,5310,7934 }, {17,15,438 ,5190,497,498 }, - {4423,3672,160 ,4289,4277,4295 }, {4680,160,3672 ,5368,4295,4277 }, - {974,7816,3933 ,5366,7925,7678 }, {936,974,3933 ,5234,5366,7678 }, - {3565,7961,6198 ,7933,7932,7926 }, {3565,6759,6054 ,7933,7939,7917 }, - {6054,6759,7786 ,7917,7939,7918 }, {6759,7738,6845 ,7939,7940,7919 }, - {7786,6759,6845 ,7918,7939,7919 }, {7738,1067,6743 ,7940,7941,7920 }, - {6845,7738,6743 ,7919,7940,7920 }, {1067,1352,1351 ,7941,1262,1162 }, - {6743,1067,1351 ,7920,7941,1162 }, {7627,7652,7626 ,7582,7696,7438 }, - {7315,7314,7265 ,7496,7909,7497 }, {7402,7403,7401 ,6589,6588,7619 }, - {7569,7534,7536 ,7705,7314,5205 }, {5106,7134,5108 ,5926,7942,4184 }, - {7166,7177,7197 ,5971,7943,7234 }, {7197,7177,6120 ,7234,7943,142 }, - {7277,7255,7256 ,7944,7238,7935 }, {7277,7304,7255 ,7944,7928,7238 }, - {7391,7390,7338 ,7945,7921,7936 }, {7471,7503,7442 ,7946,7922,7929 }, - {7528,7527,7503 ,7947,7930,7922 }, {7471,7528,7503 ,7946,7947,7922 }, - {7644,7643,7587 ,7948,7923,7937 }, {7717,7766,4556 ,7938,7949,5497 }, - {4556,7766,7788 ,5497,7949,7313 }, {7891,7868,7918 ,7934,7858,5555 }, - {7918,7968,4560 ,5555,7950,5236 }, {7607,7606,7578 ,7455,7457,7462 }, - {7805,7857,7804 ,7520,7533,4634 }, {7189,7222,7205 ,7493,628,7669 }, - {7652,7702,7651 ,7696,3513,7675 }, {1091,160,4680 ,4597,4295,5368 }, - {974,7335,7816 ,5366,4265,7925 }, {7335,6198,7816 ,4265,7926,7925 }, - {6759,1067,7738 ,7939,7941,7940 }, {7483,7482,7426 ,7574,7722,7537 }, - {7605,7604,7542 ,5239,7416,5240 }, {7210,7247,7228 ,7499,7360,7524 }, - {7207,7244,7206 ,7608,7620,7631 }, {7456,7403,7485 ,7578,6588,7636 }, - {7773,7827,7802 ,7668,7410,6566 }, {3303,7385,7333 ,1049,7630,4353 }, - {7094,7120,7093 ,4317,6938,4318 }, {7487,7458,7515 ,5707,7550,1079 }, - {3518,6133,7096 ,4338,4390,4337 }, {6133,5106,7096 ,4390,5926,4337 }, - {7152,5108,7134 ,7951,4184,7942 }, {7152,7166,5108 ,7951,5971,4184 }, - {7213,6120,7177 ,7952,142,7943 }, {7339,7338,7304 ,7953,7936,7928 }, - {7277,7339,7304 ,7944,7953,7928 }, {7416,7442,7390 ,7954,7929,7921 }, - {7391,7416,7390 ,7945,7954,7921 }, {7416,7471,7442 ,7954,7946,7929 }, - {7528,7587,7527 ,7947,7937,7930 }, {7673,7643,7644 ,7955,7923,7948 }, - {7673,7694,7643 ,7955,7931,7923 }, {7673,7717,7694 ,7955,7938,7931 }, - {7819,7818,7788 ,7956,5309,7313 }, {7766,7819,7788 ,7949,7956,7313 }, - {7919,7918,7868 ,7957,5555,7858 }, {7918,7919,7968 ,5555,7957,7950 }, - {4560,7968,4561 ,5236,7950,5361 }, {7857,7856,7804 ,7533,4635,4634 }, - {7430,7458,7487 ,7587,7550,5707 }, {4957,8062,5026 ,2733,3272,4225 }, - {1945,3565,6198 ,7958,7933,7926 }, {7335,1945,6198 ,4265,7958,7926 }, - {3565,1945,6759 ,7933,7958,7939 }, {1067,1353,1352 ,7941,1205,1262 }, - {7118,7131,7105 ,7628,7654,5279 }, {7801,7800,7750 ,1618,7568,7687 }, - {7401,7403,7456 ,7619,6588,7578 }, {7701,7750,7724 ,3515,7687,7760 }, - {7404,7430,7378 ,7726,7587,7431 }, {7429,7430,7487 ,7572,7587,5707 }, - {7132,7165,7164 ,7621,7265,7521 }, {7458,7487,7515 ,7550,5707,1079 }, - {7111,5106,6133 ,7959,5926,4390 }, {7178,7177,7166 ,7960,7943,5971 }, - {7152,7178,7166 ,7951,7960,5971 }, {7234,7256,6120 ,7961,7935,142 }, - {7213,7234,6120 ,7952,7961,142 }, {7234,7277,7256 ,7961,7944,7935 }, - {7339,7391,7338 ,7953,7945,7936 }, {7472,7471,7416 ,7962,7946,7954 }, - {7472,7528,7471 ,7962,7947,7946 }, {7588,7587,7528 ,7963,7937,7947 }, - {7588,7644,7587 ,7963,7948,7937 }, {7718,7717,7673 ,7964,7938,7955 }, - {7718,7766,7717 ,7964,7949,7938 }, {7819,7868,7818 ,7956,7858,5309 }, - {7943,7968,7919 ,7965,7950,7957 }, {7968,8014,4561 ,7950,7966,5361 }, - {7437,7465,7436 ,5938,7581,4245 }, {7188,7204,7187 ,7503,5120,7330 }, - {4582,4556,4583 ,5478,5497,5498 }, {3734,1945,7335 ,7967,7958,4265 }, - {1945,3448,6759 ,7958,7968,7939 }, {3448,5614,6759 ,7968,7969,7939 }, - {5614,1267,1067 ,7969,1353,7941 }, {6759,5614,1067 ,7939,7969,7941 }, - {1067,1267,1353 ,7941,1353,1205 }, {7750,7749,7723 ,7687,7663,7664 }, - {7724,7750,7723 ,7760,7687,7664 }, {7106,7118,7105 ,7573,7628,5279 }, - {7538,7602,7537 ,2014,5867,7543 }, {7403,7486,7485 ,6588,7436,7636 }, - {7927,7952,7902 ,1716,5475,7692 }, {7725,7773,7752 ,7420,7668,3514 }, - {7486,7457,7538 ,7436,1078,2014 }, {7545,7546,7578 ,7398,7397,7462 }, - {7123,7134,5106 ,7970,7942,5926 }, {7111,7123,5106 ,7959,7970,5926 }, - {7123,7152,7134 ,7970,7951,7942 }, {7178,7213,7177 ,7960,7952,7943 }, - {7278,7277,7234 ,7971,7944,7961 }, {7364,7391,7339 ,7972,7945,7953 }, - {7417,7416,7391 ,7973,7954,7945 }, {7364,7417,7391 ,7972,7973,7945 }, - {7529,7528,7472 ,7974,7947,7962 }, {7618,7644,7588 ,7975,7948,7963 }, - {7618,7673,7644 ,7975,7955,7948 }, {7767,7766,7718 ,7976,7949,7964 }, - {7869,7868,7819 ,7977,7858,7956 }, {7869,7919,7868 ,7977,7957,7858 }, - {7990,7968,7943 ,7978,7950,7965 }, {7968,7990,8014 ,7950,7978,7966 }, - {7990,8031,4561 ,7978,7979,5361 }, {8014,7990,4561 ,7966,7978,5361 }, - {4561,8031,4562 ,5361,7979,5018 }, {99,2306,100 ,3743,6405,2823 }, - {8051,278,3783 ,6172,1489,5311 }, {7518,7545,7544 ,7396,7398,7980 }, - {7456,7514,7455 ,7578,3610,7579 }, {7544,7545,7578 ,7980,7398,7462 }, - {7141,7188,7161 ,7414,7503,2559 }, {976,3734,7335 ,782,7967,4265 }, - {5614,7937,1267 ,7969,7981,1353 }, {7570,7598,7569 ,5204,7140,7705 }, - {7598,7624,7597 ,7140,7439,7700 }, {7679,7700,7678 ,7674,7698,7425 }, - {7780,7809,7779 ,7389,7449,7447 }, {7084,7111,6133 ,4391,7959,4390 }, - {7153,7152,7123 ,7982,7951,7970 }, {7214,7213,7178 ,7983,7952,7960 }, - {7235,7234,7213 ,7984,7961,7952 }, {7214,7235,7213 ,7983,7984,7952 }, - {7340,7339,7277 ,7985,7953,7944 }, {7278,7340,7277 ,7971,7985,7944 }, - {7340,7364,7339 ,7985,7972,7953 }, {7417,7472,7416 ,7973,7962,7954 }, - {7589,7588,7528 ,7986,7963,7947 }, {7529,7589,7528 ,7974,7986,7947 }, - {7589,7618,7588 ,7986,7975,7963 }, {7674,7673,7618 ,7987,7955,7975 }, - {7674,7718,7673 ,7987,7964,7955 }, {7789,7819,7766 ,7988,7956,7949 }, - {7767,7789,7766 ,7976,7988,7949 }, {7892,7919,7869 ,7989,7957,7977 }, - {7944,7943,7919 ,7990,7965,7957 }, {7892,7944,7919 ,7989,7990,7957 }, - {8032,8031,7990 ,7991,7979,7978 }, {8031,8032,4562 ,7979,7991,5018 }, - {8008,1428,3862 ,1163,1126,550 }, {8032,8057,4562 ,7991,7897,5018 }, - {7657,7729,7728 ,7417,7697,7818 }, {1029,3734,976 ,3930,7967,782 }, - {7499,1945,3734 ,7992,7958,7967 }, {1029,7499,3734 ,3930,7992,7967 }, - {7499,4297,3448 ,7992,7993,7968 }, {1945,7499,3448 ,7958,7992,7968 }, - {7624,7623,7597 ,7439,7427,7700 }, {7724,7723,7678 ,7760,7664,7425 }, - {7700,7724,7678 ,7698,7760,7425 }, {7131,7118,7144 ,7654,7628,7653 }, - {7486,7538,7485 ,7436,2014,7636 }, {7602,7601,7537 ,5867,7544,7543 }, - {7799,7798,7771 ,4727,4728,4336 }, {7853,7852,7800 ,1617,7412,7568 }, - {7485,7537,7514 ,7636,7543,3610 }, {7273,7325,7296 ,3467,7465,7471 }, - {7147,7163,7194 ,6937,5460,1670 }, {7097,7111,7084 ,7994,7959,4391 }, - {7097,7123,7111 ,7994,7970,7959 }, {7179,7178,7152 ,7995,7960,7951 }, - {7153,7179,7152 ,7982,7995,7951 }, {7235,7278,7234 ,7984,7971,7961 }, - {7365,7364,7340 ,7996,7972,7985 }, {7473,7472,7417 ,7997,7962,7973 }, - {7473,7529,7472 ,7997,7974,7962 }, {7619,7618,7589 ,7998,7975,7986 }, - {7695,7718,7674 ,7999,7964,7987 }, {7695,7767,7718 ,7999,7976,7964 }, - {7843,7819,7789 ,8000,7956,7988 }, {7843,7869,7819 ,8000,7977,7956 }, - {7843,7892,7869 ,8000,7989,7977 }, {7944,7990,7943 ,7990,7978,7965 }, - {8032,1381,8057 ,7991,5193,7897 }, {8025,2281,8024 ,7510,3626,7511 }, - {7355,7383,7325 ,7435,7512,7465 }, {7222,7221,7205 ,628,7545,7669 }, - {4578,4577,7641 ,5353,5352,5356 }, {4297,6695,5614 ,7993,8001,7969 }, - {3448,4297,5614 ,7968,7993,7969 }, {6695,7887,7937 ,8001,8002,7981 }, - {5614,6695,7937 ,7969,8001,7981 }, {7887,1314,1267 ,8002,1409,1353 }, - {7937,7887,1267 ,7981,8002,1353 }, {7722,7771,7721 ,7645,4336,7454 }, - {7598,7597,7569 ,7140,7700,7705 }, {7901,7951,7900 ,7413,7546,6922 }, - {7758,7780,7779 ,7387,7389,7447 }, {2487,7615,7555 ,4427,2816,7832 }, - {7085,7084,6186 ,8003,4391,4365 }, {7082,7085,6186 ,6462,8003,4365 }, - {7085,7097,7084 ,8003,7994,4391 }, {7124,7123,7097 ,8004,7970,7994 }, - {7124,7153,7123 ,8004,7982,7970 }, {7198,7178,7179 ,8005,7960,7995 }, - {7198,7214,7178 ,8005,7983,7960 }, {7279,7278,7235 ,8006,7971,7984 }, - {7279,7340,7278 ,8006,7985,7971 }, {7418,7417,7364 ,8007,7973,7972 }, - {7365,7418,7364 ,7996,8007,7972 }, {7504,7529,7473 ,8008,7974,7997 }, - {7504,7589,7529 ,8008,7986,7974 }, {7741,7767,7695 ,8009,7976,7999 }, - {7741,7789,7767 ,8009,7988,7976 }, {7893,7892,7843 ,8010,7989,8000 }, - {7991,7990,7944 ,8011,7978,7990 }, {7991,8032,7990 ,8011,7991,7978 }, - {8032,8058,1381 ,7991,8012,5193 }, {3304,7300,3305 ,1050,7857,879 }, - {1029,978,3671 ,3930,1620,3089 }, {5437,6705,6740 ,6259,4158,6894 }, - {1178,342,4075 ,206,4542,4521 }, {7679,7678,7625 ,7674,7425,7139 }, - {7570,7569,7536 ,5204,7705,5205 }, {7624,7679,7625 ,7439,7674,7139 }, - {7681,7703,7654 ,7459,7667,7637 }, {7827,7826,7802 ,7410,1616,6566 }, - {3304,7331,7300 ,1050,7911,7857 }, {7359,7358,7331 ,7686,7797,7911 }, - {7098,7097,7085 ,8013,7994,8003 }, {7154,7153,7124 ,8014,7982,8004 }, - {7154,7179,7153 ,8014,7995,7982 }, {7236,7235,7214 ,8015,7984,7983 }, - {7198,7236,7214 ,8005,8015,7983 }, {7305,7340,7279 ,8016,7985,8006 }, - {7305,7365,7340 ,8016,7996,7985 }, {7418,7473,7417 ,8007,7997,7973 }, - {7590,7589,7504 ,8017,7986,8008 }, {7790,7789,7741 ,8018,7988,8009 }, - {7790,7843,7789 ,8018,8000,7988 }, {7945,7944,7892 ,8019,7990,7989 }, - {7893,7945,7892 ,8010,8019,7989 }, {8015,8032,7991 ,8020,7991,8011 }, - {8015,8058,8032 ,8020,8012,7991 }, {213,2379,4163 ,3606,3238,4863 }, - {7850,7900,7849 ,3769,6922,7551 }, {7359,7409,7358 ,7686,6245,7797 }, - {7119,7146,7145 ,7529,7530,7629 }, {7854,7903,7878 ,7514,7717,7411 }, - {3671,7499,1029 ,3089,7992,3930 }, {3671,1077,4297 ,3089,2694,7993 }, - {7499,3671,4297 ,7992,3089,7993 }, {1077,308,4297 ,2694,8021,7993 }, - {4297,308,6695 ,7993,8021,8001 }, {308,4047,7887 ,8021,8022,8002 }, - {6695,308,7887 ,8001,8021,8002 }, {7887,4047,1314 ,8002,8022,1409 }, - {2403,3191,2165 ,2904,2903,1041 }, {7107,7118,7106 ,7494,7628,7573 }, - {8041,2281,8025 ,7548,3626,7510 }, {7494,7493,7434 ,4309,7865,7806 }, - {7435,7494,7434 ,6244,4309,7806 }, {8004,8041,8025 ,7404,7548,7510 }, - {5946,7085,7082 ,5481,8003,6462 }, {7125,7124,7097 ,8023,8004,7994 }, - {7098,7125,7097 ,8013,8023,7994 }, {7180,7179,7154 ,8024,7995,8014 }, - {7180,7198,7179 ,8024,8005,7995 }, {7280,7279,7235 ,8025,8006,7984 }, - {7236,7280,7235 ,8015,8025,7984 }, {7280,7305,7279 ,8025,8016,8006 }, - {7366,7365,7305 ,8026,7996,8016 }, {7366,7418,7365 ,8026,8007,7996 }, - {7443,7473,7418 ,8027,7997,8007 }, {7505,7504,7473 ,8028,8008,7997 }, - {7443,7505,7473 ,8027,8028,7997 }, {7505,7560,7504 ,8028,8029,8008 }, - {7560,7590,7504 ,8029,8017,8008 }, {7742,7741,7695 ,8030,8009,7999 }, - {7844,7843,7790 ,8031,8000,8018 }, {7844,7893,7843 ,8031,8010,8000 }, - {7945,7991,7944 ,8019,8011,7990 }, {8047,8058,8015 ,8032,8012,8020 }, - {8047,6921,1381 ,8032,8033,5193 }, {8058,8047,1381 ,8012,8032,5193 }, - {2487,7555,3377 ,4427,7832,1443 }, {7634,7611,7612 ,7474,7810,5107 }, - {7542,7604,7541 ,5240,7416,7515 }, {4047,7638,1314 ,8022,7540,1409 }, - {8030,935,3843 ,7899,5264,7677 }, {3298,4518,1879 ,7424,1281,1283 }, - {6277,7107,6278 ,4387,7494,3967 }, {7776,7830,7806 ,4412,7770,7612 }, - {7982,2306,8007 ,3853,6405,3854 }, {7634,7665,7611 ,7474,7927,7810 }, - {7688,7687,7665 ,6443,7877,7927 }, {7634,7688,7665 ,7474,6443,7927 }, - {7083,7085,5946 ,5483,8003,5481 }, {7083,7098,7085 ,5483,8013,8003 }, - {7155,7154,7124 ,8034,8014,8004 }, {7125,7155,7124 ,8023,8034,8004 }, - {7215,7198,7180 ,8035,8005,8024 }, {7199,7215,7180 ,8036,8035,8024 }, - {7257,7236,7198 ,8037,8015,8005 }, {7215,7257,7198 ,8035,8037,8005 }, - {7281,7280,7236 ,8038,8025,8015 }, {7257,7281,7236 ,8037,8038,8015 }, - {7306,7305,7280 ,8039,8016,8025 }, {7281,7306,7280 ,8038,8039,8025 }, - {7419,7418,7366 ,8040,8007,8026 }, {7419,7443,7418 ,8040,8027,8007 }, - {7505,7561,7560 ,8028,8041,8029 }, {7791,7790,7741 ,8042,8018,8009 }, - {7742,7791,7741 ,8030,8042,8009 }, {7894,7893,7844 ,8043,8010,8031 }, - {7969,7991,7945 ,8044,8011,8019 }, {8016,8015,7991 ,8045,8020,8011 }, - {7969,8016,7991 ,8044,8045,8011 }, {3785,6921,8047 ,8046,8033,8032 }, - {6921,1169,1381 ,8033,5100,5193 }, {3785,1169,6921 ,8046,5100,8033 }, - {3948,4296,303 ,280,6023,4086 }, {1583,1253,1606 ,5415,2353,3677 }, - {5493,5518,5492 ,6336,6316,6315 }, {7959,2306,7958 ,7607,6405,3855 }, - {5557,5556,5536 ,756,3511,754 }, {1315,1356,1355 ,1627,1530,1408 }, - {308,7638,4047 ,8021,7540,8022 }, {402,7759,448 ,5349,399,1172 }, - {7681,7725,7703 ,7459,7420,7667 }, {7908,7959,7907 ,7366,7607,7367 }, - {4368,68,1005 ,4148,4087,3535 }, {7326,7355,7325 ,7434,7435,7465 }, - {643,644,740 ,3285,1176,1595 }, {7099,7098,7083 ,8047,8013,5483 }, - {7181,7180,7154 ,8048,8024,8014 }, {7155,7181,7154 ,8034,8048,8014 }, - {7181,7199,7180 ,8048,8036,8024 }, {7181,7215,7199 ,8048,8035,8036 }, - {7258,7257,7215 ,8049,8037,8035 }, {7282,7281,7257 ,8050,8038,8037 }, - {7258,7282,7257 ,8049,8050,8037 }, {7282,7306,7281 ,8050,8039,8038 }, - {7282,7307,7306 ,8050,8051,8039 }, {7444,7443,7419 ,8052,8027,8040 }, - {7791,7844,7790 ,8042,8031,8018 }, {7920,7945,7893 ,8053,8019,8010 }, - {7894,7920,7893 ,8043,8053,8010 }, {7920,7969,7945 ,8053,8044,8019 }, - {8048,8047,8015 ,8054,8032,8020 }, {8016,8048,8015 ,8045,8054,8020 }, - {7546,7607,7578 ,7397,7455,7462 }, {3842,153,235 ,7808,663,598 }, - {7638,1274,1315 ,7540,1687,1627 }, {7639,308,1077 ,8055,8021,2694 }, - {1078,7639,1077 ,5060,8055,2694 }, {7639,2993,308 ,8055,3744,8021 }, - {308,2993,7638 ,8021,3744,7540 }, {2993,1274,7638 ,3744,1687,7540 }, - {7624,7625,7570 ,7439,7139,5204 }, {7244,7243,7206 ,7620,7632,7631 }, - {7463,7462,7410 ,7711,4310,3766 }, {7107,7106,6278 ,7494,7573,3967 }, - {7464,7462,7463 ,4246,4310,7711 }, {2306,7982,7958 ,6405,3853,3855 }, - {7126,7125,7098 ,8056,8023,8013 }, {7099,7126,7098 ,8047,8056,8013 }, - {7167,7181,7155 ,8057,8048,8034 }, {7237,7215,7181 ,8058,8035,8048 }, - {7237,7258,7215 ,8058,8049,8035 }, {7237,7282,7258 ,8058,8050,8049 }, - {7341,7307,7282 ,8059,8051,8050 }, {7307,7341,7282 ,8051,8059,8050 }, - {7367,7392,7366 ,8060,8061,8026 }, {7392,7419,7366 ,8061,8040,8026 }, - {7506,7505,7443 ,8062,8028,8027 }, {7444,7506,7443 ,8052,8062,8027 }, - {7506,7562,7561 ,8062,8063,8041 }, {7505,7506,7561 ,8028,8062,8041 }, - {7820,7844,7791 ,8064,8031,8042 }, {7820,7894,7844 ,8064,8043,8031 }, - {7970,7969,7920 ,8065,8044,8053 }, {7970,8016,7969 ,8065,8045,8044 }, - {3721,3785,8047 ,8066,8046,8032 }, {8048,3721,8047 ,8054,8066,8032 }, - {3721,1169,3785 ,8066,5100,8046 }, {4580,4579,7672 ,5410,5355,5450 }, - {3293,7149,7133 ,1988,7263,1989 }, {7542,7541,7488 ,5240,7515,7585 }, - {7959,7958,7907 ,7607,3855,7367 }, {7677,7676,7622 ,7426,7461,7460 }, - {5046,7639,1078 ,5232,8055,5060 }, {5046,2993,7639 ,5232,3744,8055 }, - {489,2955,2473 ,3639,3640,4303 }, {7571,7570,7512 ,5126,5204,5203 }, - {7807,7830,7776 ,7602,7770,4412 }, {7151,7174,7150 ,1202,7610,7488 }, - {7777,7807,7776 ,4411,7602,4412 }, {4557,7868,7891 ,5310,7858,7934 }, - {7776,7755,7729 ,4412,7519,7697 }, {5952,7099,7083 ,6595,8047,5483 }, - {7135,7155,7125 ,8067,8034,8023 }, {7126,7135,7125 ,8056,8067,8023 }, - {7156,7167,7155 ,8068,8057,8034 }, {7135,7156,7155 ,8067,8068,8034 }, - {7167,7156,7181 ,8057,8068,8048 }, {7156,7200,7181 ,8068,8069,8048 }, - {7200,7216,7181 ,8069,8070,8048 }, {7216,7237,7181 ,8070,8058,8048 }, - {7283,7282,7237 ,8071,8050,8058 }, {7283,7307,7282 ,8071,8051,8050 }, - {7307,7368,7341 ,8051,8072,8059 }, {7392,7444,7419 ,8061,8052,8040 }, - {7870,7894,7820 ,8073,8043,8064 }, {7921,7920,7894 ,8074,8053,8043 }, - {7870,7921,7894 ,8073,8074,8043 }, {8017,8016,7970 ,8075,8045,8065 }, - {4563,1169,3721 ,3024,5100,8066 }, {7484,7513,7483 ,3612,3611,7574 }, - {7596,7622,7595 ,7701,7460,4019 }, {7404,7458,7430 ,7726,7550,7587 }, - {7231,7230,7212 ,6944,7498,7208 }, {2243,6552,8053 ,1993,7679,7676 }, - {489,1101,2410 ,3639,2,1 }, {7100,7099,5952 ,8076,8047,6595 }, - {7100,7112,7099 ,8076,8077,8047 }, {7112,7126,7099 ,8077,8056,8047 }, - {7156,7135,7126 ,8068,8067,8056 }, {7135,7156,7126 ,8067,8068,8056 }, - {7156,7201,7200 ,8068,8078,8069 }, {7201,7216,7200 ,8078,8070,8069 }, - {7238,7237,7216 ,8079,8058,8070 }, {7201,7238,7216 ,8078,8079,8070 }, - {7308,7307,7283 ,8080,8051,8071 }, {7308,7368,7307 ,8080,8072,8051 }, - {7445,7444,7392 ,8081,8052,8061 }, {7445,7506,7444 ,8081,8062,8052 }, - {7506,7563,7562 ,8062,8082,8063 }, {7821,7870,7820 ,8083,8073,8064 }, - {7921,7970,7920 ,8074,8065,8053 }, {8033,8048,8016 ,8084,8054,8045 }, - {8017,8033,8016 ,8075,8084,8045 }, {7332,7331,3304 ,6685,7911,1050 }, - {7332,7359,7331 ,6685,7686,7911 }, {7464,7521,7462 ,4246,7657,4310 }, - {7196,7212,7175 ,2401,7208,2347 }, {6108,1274,2993 ,6975,1687,3744 }, - {1172,6108,2993 ,1758,6975,3744 }, {7427,7483,7426 ,7536,7574,7537 }, - {5107,5121,5106 ,4183,5855,5926 }, {7410,7409,7359 ,3766,6245,7686 }, - {7136,7135,7126 ,8085,8067,8056 }, {7112,7136,7126 ,8077,8085,8056 }, - {7136,7157,7156 ,8085,8086,8068 }, {7135,7136,7156 ,8067,8085,8068 }, - {7259,7237,7238 ,8087,8058,8079 }, {7259,7283,7237 ,8087,8071,8058 }, - {7369,7368,7308 ,8088,8072,8080 }, {7369,7393,7368 ,8088,8089,8072 }, - {7474,7506,7445 ,8090,8062,8081 }, {7474,7564,7563 ,8090,8091,8082 }, - {7506,7474,7563 ,8062,8090,8082 }, {7871,7870,7821 ,8092,8073,8083 }, - {7971,7970,7921 ,8093,8065,8074 }, {7971,8017,7970 ,8093,8075,8065 }, - {6340,8048,8033 ,8094,8054,8084 }, {6340,3721,8048 ,8094,8066,8054 }, - {2315,4563,3721 ,3068,3024,8066 }, {6340,2315,3721 ,8094,3068,8066 }, - {7521,7520,7462 ,7657,7658,4310 }, {7828,7827,7773 ,7735,7410,7668 }, - {7412,7463,7410 ,3765,7711,3766 }, {7723,7748,7722 ,7664,7644,7645 }, - {7953,7978,7929 ,7716,7730,7684 }, {7133,7132,7108 ,1989,7621,4111 }, - {7632,7631,7605 ,7555,7504,5239 }, {7552,7551,7493 ,5546,5108,7865 }, - {7494,7552,7493 ,4309,5546,7865 }, {7086,7100,5952 ,6743,8076,6595 }, - {7202,7201,7156 ,8095,8078,8068 }, {7157,7202,7156 ,8086,8095,8068 }, - {7309,7308,7283 ,8096,8080,8071 }, {7259,7309,7283 ,8087,8096,8071 }, - {7394,7393,7369 ,8097,8089,8088 }, {7420,7445,7392 ,8098,8081,8061 }, - {7922,7921,7870 ,8099,8074,8073 }, {7871,7922,7870 ,8092,8099,8073 }, - {7992,8017,7971 ,8100,8075,8093 }, {7992,8033,8017 ,8100,8084,8075 }, - {8024,8040,8002 ,7511,7688,3777 }, {7774,7828,7773 ,7419,7735,7668 }, - {7852,7851,7825 ,7412,6625,3768 }, {2293,2292,2262 ,2561,1983,3359 }, - {7723,7722,7677 ,7664,7645,7426 }, {7678,7723,7677 ,7425,7664,7426 }, - {7314,7374,7348 ,7909,4988,4990 }, {7145,7162,7170 ,7629,7649,7652 }, - {7903,7953,7929 ,7717,7716,7684 }, {8024,8002,8003 ,7511,3777,3776 }, - {8024,8053,8040 ,7511,7676,7688 }, {7576,7632,7605 ,7615,7555,5239 }, - {7688,7712,2334 ,6443,5350,7851 }, {7687,7688,2334 ,7877,6443,7851 }, - {7113,7112,7100 ,8101,8077,8076 }, {7086,7113,7100 ,6743,8101,8076 }, - {7217,7238,7201 ,8102,8079,8078 }, {7202,7217,7201 ,8095,8102,8078 }, - {7217,7259,7238 ,8102,8087,8079 }, {7309,7369,7308 ,8096,8088,8080 }, - {7446,7445,7420 ,8103,8081,8098 }, {7475,7474,7445 ,8104,8090,8081 }, - {7446,7475,7445 ,8103,8104,8081 }, {7474,7530,7564 ,8090,8105,8091 }, - {7822,7871,7821 ,8106,8092,8083 }, {7922,7971,7921 ,8099,8093,8074 }, - {8034,8033,7992 ,7586,8084,8100 }, {8034,6340,8033 ,7586,8094,8084 }, - {2369,2334,401 ,3257,7851,1387 }, {7730,7729,7657 ,4413,7697,7417 }, - {7903,7929,7878 ,7717,7684,7411 }, {7314,7348,7290 ,7909,4990,7635 }, - {7348,7373,7347 ,4990,4989,7576 }, {7800,7852,7825 ,7568,7412,3768 }, - {7772,7748,7722 ,7744,7644,7645 }, {7748,7772,7722 ,7644,7744,7645 }, - {7455,7427,7428 ,7579,7536,7670 }, {7512,7536,7482 ,5203,5205,7722 }, - {7904,7903,7854 ,7513,7717,7514 }, {7165,7172,7195 ,7265,7405,7522 }, - {7576,7605,7543 ,7615,5239,5238 }, {7249,7294,7248 ,7622,7819,73 }, - {7249,7248,7232 ,7622,73,2124 }, {7623,7622,7597 ,7427,7460,7700 }, - {7137,7136,7112 ,8107,8085,8077 }, {7113,7137,7112 ,8101,8107,8077 }, - {7137,7158,7157 ,8107,8108,8086 }, {7136,7137,7157 ,8085,8107,8086 }, - {7158,7182,7157 ,8108,8109,8086 }, {7182,7202,7157 ,8109,8095,8086 }, - {7260,7259,7217 ,8110,8087,8102 }, {7342,7369,7309 ,8111,8088,8096 }, - {7342,7394,7369 ,8111,8097,8088 }, {7531,7530,7474 ,8112,8105,8090 }, - {7475,7531,7474 ,8104,8112,8090 }, {7530,7531,7564 ,8105,8112,8091 }, - {7872,7871,7822 ,8113,8092,8106 }, {7946,7971,7922 ,8114,8093,8099 }, - {7993,7992,7971 ,8115,8100,8093 }, {7946,7993,7971 ,8114,8115,8093 }, - {8059,6340,8034 ,4235,8094,7586 }, {2316,2315,6340 ,3067,3068,8094 }, - {8059,2316,6340 ,4235,3067,8094 }, {2333,2334,2369 ,3537,7851,3257 }, - {7326,7325,7273 ,7434,7465,3467 }, {7425,7481,7454 ,3995,7542,3996 }, - {7231,7272,7230 ,6944,7666,7498 }, {7269,7247,7292 ,7361,7360,7594 }, - {7455,7484,7427 ,7579,3612,7536 }, {8060,8051,3783 ,7685,6172,5311 }, - {7800,7799,7748 ,7568,4727,7644 }, {7772,7800,7748 ,7744,7568,7644 }, - {7483,7512,7482 ,7574,5203,7722 }, {7375,7374,7314 ,7699,4988,7909 }, - {7209,7210,7228 ,7523,7499,7524 }, {7164,7165,7195 ,7521,7265,7522 }, - {7172,7210,7209 ,7405,7499,7523 }, {7195,7172,7209 ,7522,7405,7523 }, - {3321,7386,7387 ,2461,5512,3615 }, {7158,7183,7182 ,8108,8116,8109 }, - {7183,7202,7182 ,8116,8095,8109 }, {7218,7217,7202 ,7708,8102,8095 }, - {7183,7218,7202 ,8116,7708,8095 }, {7284,7309,7259 ,8117,8096,8087 }, - {7260,7284,7259 ,8110,8117,8087 }, {7284,7342,7309 ,8117,8111,8096 }, - {7395,7394,7342 ,8118,8097,8111 }, {7395,7421,7394 ,8118,8119,8097 }, - {7447,7475,7446 ,8120,8104,8103 }, {7591,7564,7531 ,8121,8091,8112 }, - {7895,7871,7872 ,8122,8092,8113 }, {7895,7922,7871 ,8122,8099,8092 }, - {7895,7946,7922 ,8122,8114,8099 }, {8035,8034,7992 ,6675,7586,8100 }, - {7993,8035,7992 ,8115,6675,8100 }, {7629,7705,7684 ,7399,7349,7400 }, - {7692,7691,7666 ,7490,4419,7566 }, {7637,7692,7666 ,7473,7490,7566 }, - {7690,7691,449 ,6466,4419,1169 }, {7929,7928,7877 ,7684,1724,7549 }, - {7378,7377,7319 ,7431,7592,7432 }, {7828,7854,7827 ,7735,7514,7410 }, - {278,4612,3783 ,1489,5249,5311 }, {7800,7825,7799 ,7568,3768,4727 }, - {7572,7571,7513 ,5124,5126,3611 }, {7265,7314,7290 ,7497,7909,7635 }, - {7386,7385,3303 ,5512,7630,1049 }, {7398,7397,7345 ,7429,1186,7588 }, - {7350,7317,7376 ,7618,5947,7746 }, {7317,7351,7376 ,5947,6587,7746 }, - {7114,7113,7086 ,5392,8101,6743 }, {7087,7114,7086 ,6742,5392,6743 }, - {7218,7260,7217 ,7708,8110,8102 }, {7343,7342,7284 ,2750,8111,8117 }, - {7476,7475,7447 ,8123,8104,8120 }, {7592,7591,7531 ,8124,8121,8112 }, - {7793,7822,7792 ,5726,8106,8125 }, {7793,7845,7822 ,5726,5725,8106 }, - {7845,7872,7822 ,5725,8113,8106 }, {7947,7946,7895 ,4354,8114,8122 }, - {7947,7993,7946 ,4354,8115,8114 }, {5644,3615,5660 ,4133,201,3054 }, - {7108,7121,7094 ,4111,7852,4317 }, {7108,7132,7121 ,4111,7621,7852 }, - {7601,7653,7600 ,7544,7638,7556 }, {7523,7522,7496 ,7393,7395,7470 }, - {7775,7828,7774 ,7509,7735,7419 }, {7480,7534,7511 ,7463,7314,6677 }, - {7348,7347,7289 ,4990,7576,7575 }, {7651,7702,7680 ,7675,3513,7673 }, - {7702,7701,7680 ,3513,3515,7673 }, {8053,6552,6784 ,7676,7679,7472 }, - {8053,6784,8039 ,7676,7472,7476 }, {8040,8053,8039 ,7688,7676,7476 }, - {7775,7774,7726 ,7509,7419,7418 }, {7378,7430,7377 ,7431,7587,7592 }, - {7095,7108,7094 ,3924,4111,4317 }, {6552,2243,2278 ,7679,1993,3495 }, - {7114,7127,7137 ,5392,7245,8107 }, {7113,7114,7137 ,8101,5392,8107 }, - {7127,7159,7158 ,7245,5075,8108 }, {7137,7127,7158 ,8107,7245,8108 }, - {7184,7183,7158 ,5074,8116,8108 }, {7159,7184,7158 ,5075,5074,8108 }, - {7261,7260,7218 ,1528,8110,7708 }, {7261,7284,7260 ,1528,8117,8110 }, - {7396,7395,7342 ,6716,8118,8111 }, {7343,7396,7342 ,2750,6716,8111 }, - {7507,7531,7475 ,6706,8112,8104 }, {7476,7507,7475 ,8123,6706,8104 }, - {7593,7592,7531 ,5032,8124,8112 }, {7896,7895,7872 ,4355,8122,8113 }, - {7845,7896,7872 ,5725,4355,8113 }, {7994,7993,7947 ,5582,8115,4354 }, - {7142,7189,7141 ,7729,7493,7414 }, {7725,7752,7702 ,7420,3514,3513 }, - {7682,7681,7628 ,3564,7459,7528 }, {7412,7411,7384 ,3765,3767,7683 }, - {7952,7951,7901 ,5475,7546,7413 }, {7572,7626,7599 ,5124,7438,5125 }, - {7190,7224,7189 ,7633,7491,7493 }, {7482,7536,7481 ,7722,5205,7542 }, - {7536,7534,7481 ,5205,7314,7542 }, {7660,7659,7606 ,7381,7383,7457 }, - {7088,7101,7087 ,4299,4073,6742 }, {7101,7114,7087 ,4073,5392,6742 }, - {7219,7218,7183 ,1529,7708,8116 }, {7184,7219,7183 ,5074,1529,8116 }, - {7285,7284,7261 ,2751,8117,1528 }, {7285,7343,7284 ,2751,2750,8117 }, - {7422,7395,7396 ,1404,8118,6716 }, {7449,7448,7395 ,7600,8126,8118 }, - {7422,7449,7395 ,1404,7600,8118 }, {7449,7477,7448 ,7600,1403,8126 }, - {7565,7531,7507 ,5080,8112,6706 }, {7531,7565,7593 ,8112,5080,5032 }, - {7565,7593,7592 ,5080,5032,8124 }, {7593,7565,7592 ,5032,5080,8124 }, - {7593,7645,7592 ,5032,5034,8124 }, {7896,7947,7895 ,4355,4354,8122 }, - {8018,8035,7993 ,6676,6675,8115 }, {7994,8018,7993 ,5582,6676,8115 }, - {5658,5642,5659 ,49,526,3053 } -}; -F32 vertices [8146][3] = { -{-0.128951f,0.113893f,0.0385904f},{-0.183541f,0.121141f,0.0176007f},{-0.3356f,0.267483f,0.245606f}, -{0.0990868f,0.131443f,0.150773f},{-0.0330697f,0.108447f,0.0577602f},{-0.0525675f,0.103219f,0.0581332f}, -{-0.129472f,0.111128f,0.0174721f},{0.321716f,0.0172985f,0.188251f},{0.350352f,0.00204496f,0.112787f}, -{-0.0496094f,0.0212148f,0.245825f},{0.284245f,0.0735475f,0.150304f},{-0.296733f,0.306228f,-0.0948973f}, -{0.364127f,-0.0330021f,0.152767f},{0.399804f,-0.11262f,0.0755796f},{-0.10546f,0.41535f,-0.00363974f}, -{-0.407308f,0.165107f,0.333295f},{-0.354815f,0.10291f,0.350047f},{-0.415655f,0.1722f,0.323829f}, -{0.154706f,0.137848f,0.112556f},{0.363426f,-0.0163596f,0.0577281f},{0.344481f,-0.0712067f,-0.05722f}, -{-0.47357f,0.192405f,0.152844f},{-0.433269f,-0.00220573f,0.173326f},{-0.336095f,0.297592f,0.112524f}, -{-0.431192f,0.27075f,0.192f},{0.136655f,0.102968f,0.212456f},{0.172493f,0.0906273f,0.222398f}, -{-0.0907206f,0.100833f,0.0403717f},{-0.212472f,0.206855f,0.0920485f},{-0.390158f,0.166136f,0.336426f}, -{0.0818719f,0.1177f,0.189036f},{-0.181875f,0.080962f,0.174573f},{-0.396981f,-0.110421f,-0.0611684f}, -{0.263654f,0.0893219f,0.152702f},{-0.469351f,0.0768914f,0.0379088f},{0.367586f,-0.0504292f,-0.00258511f}, -{0.373245f,-0.0554837f,0.00500307f},{-0.449931f,0.0420887f,0.0196393f},{-0.104874f,0.430758f,-0.0208675f}, -{-0.392389f,0.230186f,0.285811f},{-0.0333784f,0.0170798f,0.258757f},{-0.0197004f,0.434816f,-0.137706f}, -{-0.131067f,0.378811f,-0.0749943f},{-0.091563f,0.102653f,0.0566477f},{0.175284f,0.113482f,0.190798f}, -{-0.190955f,0.149211f,0.11763f},{-0.0545288f,0.10055f,0.0386676f},{0.216376f,0.0805312f,0.210058f}, -{0.231906f,0.0788913f,0.208501f},{0.328282f,0.00609625f,0.189769f},{0.313646f,0.0244043f,0.192785f}, -{-0.149188f,0.359988f,0.0320504f},{-0.466033f,0.134156f,0.0375229f},{-0.234677f,0.209048f,0.17485f}, -{0.385283f,-0.0772258f,0.133456f},{0.382538f,-0.0547828f,0.0755796f},{0.370396f,-0.091817f,0.193274f}, -{-0.244857f,0.283997f,0.11408f},{-0.047275f,0.301502f,-0.0171956f},{-0.337446f,0.231304f,0.282833f}, -{-0.358197f,0.206437f,0.307669f},{-0.338095f,-0.305122f,0.135758f},{-0.470593f,0.0595544f,0.0379023f}, -{-0.377309f,0.116614f,0.351275f},{-0.30036f,0.324536f,-0.112678f},{-0.115717f,0.107591f,0.0241086f}, -{-0.190904f,0.150715f,0.0987171f},{-0.335529f,0.291643f,0.0379345f},{-0.484316f,0.0419215f,0.264172f}, -{0.152538f,0.102801f,0.211254f},{0.153812f,0.0916176f,0.225215f},{-0.103138f,0.104698f,0.03515f}, -{-0.297048f,0.295598f,0.0953281f},{0.30371f,0.0399987f,0.18802f},{-0.0883798f,0.41845f,-0.0178644f}, -{0.363773f,-0.092788f,-0.0374522f},{-0.352076f,0.35386f,-0.0974052f},{0.0567345f,0.0797466f,0.236108f}, -{0.294335f,-0.114228f,0.291643f},{0.0244911f,0.341809f,-0.0740619f},{-0.166352f,0.361223f,0.0361275f}, -{-0.0908749f,0.0966914f,0.0203724f},{-0.166281f,0.380907f,0.020636f},{-0.0159899f,0.0208225f,0.260622f}, -{-0.474798f,0.157956f,0.154394f},{-0.395045f,0.398315f,-0.246642f},{-0.390222f,0.11662f,0.352786f}, -{-0.444934f,-0.0373236f,0.0384554f},{-0.215192f,0.210083f,0.100627f},{0.345137f,0.00202567f,0.153461f}, -{0.308855f,-0.0536767f,0.250738f},{-0.108379f,0.398566f,-0.000488712f},{-0.377316f,0.201955f,0.313469f}, -{-0.375985f,0.234179f,0.285843f},{-0.145947f,0.392849f,0.0136523f},{0.358667f,-0.0149577f,0.13352f}, -{-0.436697f,-0.00081026f,0.0371307f},{0.399283f,-0.148799f,0.133494f},{0.212189f,0.114485f,0.152053f}, -{0.103035f,-0.451593f,0.311926f},{0.120237f,-0.454622f,0.308067f},{0.00337286f,0.115282f,0.039375f}, -{-0.222993f,0.303122f,0.0742677f},{-0.475924f,0.161339f,0.133758f},{-0.120218f,0.428983f,-0.0409697f}, -{0.369708f,-0.0305328f,0.035433f},{-0.482419f,0.11327f,0.230475f},{0.367676f,-0.0728915f,-0.0214784f}, -{0.377534f,-0.0744864f,-0.000623756f},{0.401881f,-0.148638f,0.0949037f},{-0.0891837f,0.436147f,-0.0219092f}, -{-0.0690814f,0.436153f,-0.035285f},{-0.358043f,0.0803189f,0.354516f},{-0.358088f,0.233304f,0.28655f}, -{-0.279319f,0.131166f,0.262429f},{0.385425f,-0.113488f,0.172059f},{0.0420919f,0.1286f,0.114562f}, -{0.00494195f,0.120401f,0.0939713f},{-0.337381f,0.293245f,0.0591042f},{0.192235f,0.0807048f,0.225292f}, -{0.040645f,0.109752f,0.187454f},{-0.315466f,0.284177f,0.210495f},{-0.355651f,0.284788f,0.207601f}, -{0.230845f,0.0689946f,0.221376f},{-0.16468f,0.398669f,-0.0160702f},{-0.17619f,0.390978f,-0.014932f}, -{-0.262805f,-0.44967f,0.30907f},{-0.242143f,-0.449754f,0.311906f},{-0.374988f,0.341597f,-0.0915855f}, -{-0.352281f,0.342844f,-0.0752323f},{0.356976f,-0.0173049f,0.150998f},{0.362082f,-0.0148741f,0.0948973f}, -{0.380981f,-0.114093f,-0.0206617f},{-0.184435f,0.345584f,0.0454455f},{-0.16558f,0.340909f,0.0421787f}, -{-0.165709f,-0.44913f,0.288852f},{-0.337619f,0.365731f,-0.130787f},{-0.0571911f,-0.128935f,0.325623f}, -{-0.451268f,0.191614f,0.0565062f},{0.00446607f,0.0954117f,0.188926f},{-0.123356f,0.411967f,-0.0662551f}, -{-0.464734f,-0.114524f,0.0774059f},{-0.306225f,0.300492f,-0.0590077f},{-0.299421f,0.28583f,-0.0583004f}, -{-0.354731f,0.187467f,-0.0365647f},{-0.341722f,0.209897f,0.299611f},{-0.372673f,0.355731f,-0.115045f}, -{-0.385148f,0.355165f,-0.137288f},{0.300727f,0.0312016f,0.203305f},{0.36657f,-0.0529501f,0.171216f}, -{0.351934f,-0.00997397f,0.15514f},{0.369599f,-0.0327063f,0.114176f},{0.00206744f,0.0217871f,0.263509f}, -{-0.356776f,0.0418636f,0.346581f},{0.198151f,0.0257355f,0.254262f},{0.193315f,0.0190926f,0.258641f}, -{-0.427719f,0.00261084f,0.190399f},{-0.126475f,0.393608f,0.0137423f},{-0.296354f,0.0562426f,-0.0510337f}, -{-0.347265f,0.359448f,-0.298396f},{-0.479319f,0.22715f,0.16903f},{0.0213916f,0.0220122f,0.268834f}, -{0.136095f,-0.453715f,0.305103f},{-0.0334105f,0.025877f,0.251471f},{-0.467107f,0.112029f,0.0377737f}, -{0.173676f,0.0207453f,0.26203f},{-0.388287f,0.395016f,-0.225517f},{0.286335f,0.0563905f,0.187177f}, -{0.310623f,-0.0532523f,-0.0824153f},{0.380795f,-0.0549564f,0.0370728f},{0.11616f,0.0201923f,0.278827f}, -{-0.316392f,0.233002f,0.268442f},{-0.356088f,0.115495f,0.345635f},{0.0212115f,0.12235f,0.0571364f}, -{0.137176f,0.139404f,0.078647f},{-0.300958f,0.264255f,0.243015f},{0.331607f,0.0236327f,0.15067f}, -{0.251944f,-0.450976f,0.265889f},{0.216614f,-0.108614f,0.324626f},{0.0391209f,0.0243529f,0.272146f}, -{0.350159f,0.00359473f,0.094788f},{-0.396447f,-0.0920678f,-0.0587827f},{0.375457f,-0.0619272f,0.15114f}, -{0.378859f,-0.0548986f,0.11417f},{-0.389926f,0.0207453f,-0.016649f},{-0.39327f,0.168007f,-0.0230282f}, -{0.154043f,-0.0357931f,-0.124575f},{0.175965f,-0.0327128f,-0.11952f},{0.175354f,0.128549f,0.150741f}, -{0.13623f,0.136156f,0.134343f},{0.0985016f,0.136529f,0.115032f},{-0.131163f,0.107514f,0.129051f}, -{-0.108649f,0.108993f,0.0566349f},{-0.0375068f,0.0839973f,0.175737f},{-0.298868f,0.291508f,0.0583325f}, -{-0.192608f,0.14804f,0.134388f},{-0.146976f,0.401826f,-5.1427e-05f},{-0.260792f,-0.433774f,0.302235f}, -{-0.242266f,-0.432822f,0.30464f},{-0.223154f,-0.432128f,0.300621f},{0.0791068f,0.13325f,0.0571686f}, -{-0.472972f,0.157127f,0.17238f},{0.0598019f,0.0811099f,-0.0603196f},{-0.202678f,-0.451117f,0.299971f}, -{-0.185881f,-0.450905f,0.295753f},{-0.180223f,-0.444307f,0.292126f},{-0.295923f,0.435491f,-0.378264f}, -{-0.316868f,0.344902f,-0.112511f},{-0.109878f,0.101553f,0.133636f},{-0.413f,0.264339f,0.224707f}, -{-0.317749f,0.291528f,0.0568664f},{0.0993119f,0.117025f,0.191344f},{-0.468773f,-0.114106f,0.115938f}, -{0.247809f,0.0718048f,0.209132f},{-0.314025f,0.307527f,-0.0538375f},{-0.106804f,0.102318f,0.0163725f}, -{-0.108328f,0.0983956f,0.000623793f},{-0.124166f,0.104466f,-0.00183272f},{-0.430954f,-0.0187196f,0.0181731f}, -{0.359516f,-0.056757f,0.189949f},{0.360924f,-0.0149963f,0.114183f},{-0.203379f,0.301547f,0.0699592f}, -{0.043931f,0.0177872f,0.276653f},{-0.127337f,0.404874f,0.00522815f},{0.377033f,-0.0575802f,0.132555f}, -{0.396801f,-0.148973f,0.15276f},{-0.0911514f,0.443073f,-0.0347513f},{-0.0342529f,0.307598f,-0.0218771f}, -{0.250387f,0.0819974f,0.190296f},{0.0618919f,0.132337f,0.0979776f},{0.370126f,-0.0498955f,0.154092f}, -{-0.0687534f,0.038256f,0.2229f},{-0.0509598f,0.0395936f,0.228051f},{-0.0323752f,0.0376065f,0.242114f}, -{-0.0172824f,0.0393235f,0.24722f},{-0.376454f,0.0422173f,0.34442f},{0.101807f,-0.434835f,0.310807f}, -{0.117163f,-0.4376f,0.307746f},{0.137092f,-0.437143f,0.30435f},{0.157136f,-0.433986f,0.301926f}, -{-0.221996f,0.323739f,0.0583004f},{-0.204993f,0.322929f,0.060056f},{-0.183592f,0.321295f,0.0548343f}, -{0.0599755f,0.0178001f,0.277393f},{-0.371612f,0.134066f,0.346529f},{-0.279319f,0.293347f,0.151384f}, -{0.30418f,0.0563133f,0.149526f},{0.351574f,-0.0295231f,-0.00458504f},{-0.42516f,0.173576f,0.00514455f}, -{0.34978f,-0.0516575f,-0.0410598f},{-0.128784f,0.378316f,0.0167776f},{-0.374165f,0.0802225f,0.35258f}, -{0.335857f,-0.0209511f,-0.0349313f},{0.348609f,-0.0342754f,-0.0208739f},{0.403219f,-0.148555f,0.0756182f}, -{-0.35369f,-0.109778f,-0.0902029f},{-0.334462f,-0.109334f,-0.0956625f},{-0.376461f,-0.110086f,-0.0797852f}, -{-0.0688499f,0.453792f,-0.0389762f},{-0.059101f,0.454365f,-0.0439343f},{-0.241449f,0.312247f,0.0639594f}, -{-0.275866f,0.297437f,0.0577409f},{-0.2969f,0.288724f,0.040526f},{-0.12452f,0.104569f,0.134652f}, -{-0.0449085f,0.106698f,0.07684f},{-0.352564f,0.250764f,0.267805f},{-0.335652f,0.284769f,0.209781f}, -{-0.391682f,-0.0901193f,0.243947f},{0.358397f,-0.0700492f,-0.0368027f},{-0.455037f,0.160406f,0.031118f}, -{-0.207244f,-0.435819f,0.296801f},{-0.202177f,-0.427382f,0.290885f},{-0.184473f,-0.42978f,0.288955f}, -{-0.167245f,-0.431086f,0.284589f},{-0.145227f,-0.433259f,0.278943f},{-0.336938f,0.340073f,-0.0762226f}, -{-0.328333f,0.331713f,-0.0703771f},{-0.316347f,0.321379f,-0.0740426f},{-0.0900582f,-0.471773f,0.341359f}, -{-0.0745475f,-0.4318f,0.343346f},{-0.0611524f,-0.427793f,0.349043f},{-0.0524774f,-0.43423f,0.355699f}, -{-0.0348703f,-0.432513f,0.355416f},{0.174666f,0.132105f,0.133629f},{-0.183251f,0.359828f,0.0370985f}, -{0.249275f,0.0920421f,0.17031f},{0.0221054f,-0.433337f,0.336742f},{0.0347738f,-0.433311f,0.332144f}, -{0.0444905f,-0.433279f,0.329301f},{0.0604707f,-0.433246f,0.324092f},{0.0795826f,-0.433169f,0.317919f}, -{0.0923282f,-0.433124f,0.313591f},{0.174236f,-0.432449f,0.299399f},{0.231996f,0.02189f,0.248693f}, -{0.00507055f,0.11743f,0.131449f},{-0.234034f,0.228925f,0.155545f},{-0.29074f,0.399447f,-0.339243f}, -{-0.127562f,0.398585f,-0.0706215f},{-0.237796f,0.133533f,0.232089f},{-0.313929f,0.1495f,0.285862f}, -{0.381296f,-0.054815f,0.0948651f},{-0.145844f,0.379223f,0.0246809f},{-0.121864f,0.413382f,-0.00367832f}, -{-0.491158f,0.0606347f,0.172946f},{0.400736f,-0.130665f,0.0370921f},{0.0808816f,0.0201151f,0.278145f}, -{-0.186242f,0.340336f,-0.0426803f},{-0.156436f,0.340195f,-0.0631619f},{-0.224472f,-0.266313f,0.252731f}, -{-0.128655f,-0.114562f,-0.142401f},{-0.35713f,0.187769f,0.318234f},{-0.429134f,0.265882f,0.206386f}, -{-0.286734f,0.292544f,0.0523327f},{-0.331015f,0.359448f,-0.337012f},{0.100733f,0.101122f,0.215254f}, -{-0.0531848f,0.10417f,0.0738497f},{-0.14904f,0.117983f,0.0386033f},{-0.373393f,0.250249f,0.26711f}, -{-0.354667f,0.335179f,-0.0613485f},{-0.268779f,-0.426436f,0.293341f},{-0.139356f,-0.426771f,0.273869f}, -{0.0225041f,0.1217f,0.133989f},{-0.0367802f,0.104563f,0.0376901f},{-0.0706633f,0.0942864f,0.0189769f}, -{-0.0814154f,-0.420617f,0.334337f},{-0.0697952f,-0.416919f,0.335648f},{-0.0543552f,-0.414475f,0.34179f}, -{-0.0346131f,-0.419498f,0.351449f},{-0.0170702f,-0.416186f,0.34624f},{0.00188095f,-0.415935f,0.338169f}, -{0.0178869f,-0.420668f,0.334645f},{0.0227227f,-0.414559f,0.328748f},{0.040407f,-0.417208f,0.323945f}, -{0.0598148f,-0.417697f,0.317784f},{0.0748561f,-0.419485f,0.314562f},{0.0834925f,-0.416739f,0.312395f}, -{0.0984952f,-0.418398f,0.310614f},{0.117794f,-0.423285f,0.306016f},{0.137111f,-0.423485f,0.305263f}, -{0.156243f,-0.418347f,0.308177f},{0.0988103f,0.076422f,0.243336f},{0.155008f,0.0210347f,0.268956f}, -{-0.411038f,0.251838f,0.247265f},{-0.410543f,0.241999f,0.261284f},{-0.391753f,0.24632f,0.26695f}, -{-0.177489f,0.115868f,0.134214f},{-0.411945f,0.133436f,0.346246f},{-0.219327f,0.284595f,0.0821324f}, -{0.352751f,-0.0704608f,-0.0463586f},{0.398987f,-0.130729f,0.114176f},{0.116977f,-0.0373878f,-0.131128f}, -{-0.368583f,-0.130304f,-0.0862995f},{-0.3536f,-0.12826f,-0.09237f},{-0.334333f,-0.127784f,-0.0978939f}, -{0.273512f,0.0615929f,0.194058f},{-0.141073f,0.358805f,0.025742f},{0.0806308f,0.134607f,0.114048f}, -{-0.364178f,0.164824f,0.332523f},{0.155439f,0.131526f,0.151584f},{-0.31679f,0.289103f,0.040764f}, -{-0.321736f,0.316562f,-0.055458f},{-0.0391209f,-0.127449f,0.348703f},{-0.112816f,0.109611f,0.0410405f}, -{0.0798013f,-0.0758304f,0.343391f},{0.0260024f,0.107771f,0.182155f},{0.0239188f,0.112517f,0.170445f}, -{0.419128f,-0.26322f,0.170818f},{-0.261185f,-0.414012f,0.28657f},{-0.241172f,-0.412675f,0.287026f}, -{-0.223064f,-0.41227f,0.283753f},{-0.203772f,-0.416855f,0.282943f},{-0.184422f,-0.416925f,0.28019f}, -{-0.16511f,-0.417112f,0.276949f},{-0.152256f,-0.417196f,0.276872f},{-0.144545f,-0.412295f,0.271689f}, -{-0.130668f,-0.413524f,0.27093f},{-0.33933f,0.299868f,0.00039872f},{-0.454754f,0.269998f,0.156593f}, -{-0.355445f,0.290942f,0.187936f},{-0.373869f,0.292685f,0.171158f},{0.0630687f,-0.0750779f,0.341372f}, -{0.301582f,0.036359f,-0.0174399f},{-0.484972f,0.043542f,0.227652f},{-0.0878975f,-0.413839f,0.323211f}, -{-0.0364779f,-0.410373f,0.346343f},{0.117851f,-0.412816f,0.316787f},{0.137098f,-0.412019f,0.321604f}, -{0.153001f,-0.412225f,0.319591f},{0.17729f,-0.415324f,0.301707f},{-0.12652f,0.0335809f,0.221356f}, -{-0.107344f,0.0338317f,0.222655f},{-0.206402f,0.0359345f,0.223974f},{0.0985531f,0.0223723f,0.27902f}, -{0.386113f,-0.167943f,-0.0205717f},{0.059982f,0.0266615f,0.27331f},{-0.324829f,0.228083f,0.278538f}, -{-0.143298f,0.411575f,-0.0170091f},{0.230079f,0.0996624f,0.170142f},{0.00333428f,0.11907f,0.0747822f}, -{-0.0342851f,0.0952124f,0.1515f},{0.367097f,-0.0327707f,0.133501f},{0.305479f,-0.430276f,0.202965f}, -{0.325279f,-0.432378f,0.19436f},{-0.201129f,0.301309f,-0.0341211f},{-0.0687792f,0.41562f,-0.106234f}, -{0.285402f,-0.132542f,-0.130118f},{-0.0900582f,-0.113913f,-0.148195f},{-0.470496f,0.263483f,0.113199f}, -{0.327536f,0.0208932f,0.172078f},{0.349542f,-0.0149705f,0.174387f},{-0.0496415f,0.456307f,-0.0524292f}, -{0.284888f,-0.115135f,0.298344f},{0.155542f,0.11745f,0.189016f},{-0.0713836f,0.10136f,0.0766085f}, -{-0.462342f,0.0766857f,0.0217871f},{0.0812353f,-0.0669496f,0.329192f},{-0.304309f,0.282583f,-0.0389569f}, -{-0.0486705f,-0.130169f,0.338889f},{-0.20372f,-0.40854f,0.273586f},{-0.184428f,-0.408527f,0.272853f}, -{-0.16513f,-0.408553f,0.27212f},{-0.0558985f,-0.105444f,-0.178663f},{-0.0901482f,0.0915726f,0.00273948f}, -{-0.0718337f,-0.401498f,0.322466f},{-0.0522974f,-0.402662f,0.335115f},{-0.0364715f,-0.402199f,0.338381f}, -{-0.017321f,-0.402579f,0.335468f},{0.0019967f,-0.39737f,0.321578f},{0.0213466f,-0.399299f,0.320356f}, -{0.0406707f,-0.398978f,0.322536f},{0.0598727f,-0.40427f,0.318427f},{0.0792611f,-0.403119f,0.324491f}, -{0.0985981f,-0.40245f,0.327597f},{0.117851f,-0.402424f,0.330645f},{0.135806f,-0.396515f,0.336793f}, -{0.143484f,-0.402212f,0.331796f},{0.156288f,-0.402759f,0.327501f},{0.174705f,-0.396778f,0.321295f}, -{-0.393251f,0.175088f,0.330491f},{-0.266657f,0.267921f,0.222089f},{0.0760586f,0.0268223f,0.274274f}, -{-0.374171f,0.17521f,0.329848f},{-0.355291f,0.17002f,0.325764f},{-0.338089f,0.249195f,0.268101f}, -{-0.320527f,0.247998f,0.262757f},{-0.415784f,-0.109244f,-0.0416578f},{-0.395386f,0.21018f,0.303913f}, -{-0.373586f,0.262403f,0.248712f},{0.32452f,-0.413421f,0.205273f},{0.343323f,-0.413382f,0.207029f}, -{0.362815f,-0.411697f,0.208823f},{-0.164191f,0.322324f,0.0389441f},{0.313955f,0.0451368f,0.154735f}, -{-0.158712f,0.3742f,0.0292852f},{0.359059f,-0.0334201f,0.173133f},{-0.0546896f,0.469323f,-0.0593164f}, -{-0.0400727f,0.470847f,-0.0605961f},{0.0435195f,0.129552f,0.0968393f},{-0.0157969f,0.114247f,0.0771229f}, -{0.117157f,0.11671f,0.191499f},{0.174936f,0.0809942f,0.231182f},{-0.335555f,0.259117f,0.257201f}, -{-0.375753f,0.328079f,-0.0684286f},{-0.333819f,0.326189f,-0.0550915f},{0.079872f,0.130202f,0.15094f}, -{-0.299608f,0.266673f,-0.01771f},{-0.319523f,0.302595f,-0.0367641f},{-0.338307f,0.319167f,-0.0382881f}, -{-0.259654f,-0.401923f,0.265567f},{-0.243262f,-0.398174f,0.263728f},{-0.223244f,-0.399826f,0.264204f}, -{-0.202125f,-0.398084f,0.262995f},{-0.184454f,-0.395691f,0.263561f},{-0.165162f,-0.39537f,0.266602f}, -{-0.145806f,-0.395466f,0.26576f},{-0.125568f,-0.396727f,0.264596f},{-0.33623f,0.347474f,-0.0918877f}, -{-0.320829f,0.338645f,-0.0939005f},{-0.312437f,0.328272f,-0.0923378f},{-0.0557121f,-0.394527f,0.325006f}, -{-0.0364844f,-0.394418f,0.326536f},{-0.0172053f,-0.394688f,0.322485f},{0.0600206f,-0.393145f,0.332857f}, -{0.0792804f,-0.393036f,0.334504f},{0.0985531f,-0.392971f,0.336433f},{0.117832f,-0.39245f,0.340124f}, -{0.156339f,-0.393138f,0.334845f},{0.0406707f,0.0795794f,0.232591f},{0.398286f,-0.112762f,0.0371114f}, -{-0.471802f,0.0156329f,0.116536f},{-0.261165f,0.293142f,0.0956368f},{-0.389849f,0.0793929f,0.346034f}, -{-0.306746f,0.246095f,0.256661f},{-0.298302f,0.250976f,0.25041f},{-0.280772f,0.250551f,0.242918f}, -{-0.46694f,0.210668f,0.209247f},{-0.390171f,0.13925f,0.349031f},{0.0996849f,0.137295f,0.0955082f}, -{0.392878f,-0.114517f,0.148445f},{0.387965f,-0.0771036f,0.114151f},{-0.167509f,0.121359f,0.0380695f}, -{-0.292045f,0.246281f,-0.0204173f},{-0.305653f,0.278718f,-0.0245008f},{-0.330192f,0.311321f,-0.0337481f}, -{-0.353953f,0.322311f,-0.0375743f},{-0.241449f,-0.391994f,0.247227f},{0.133755f,0.0177294f,0.27601f}, -{-0.225064f,-0.391692f,0.245606f},{-0.206987f,-0.391981f,0.254288f},{-0.108894f,-0.390431f,0.265098f}, -{-0.12789f,0.110627f,0.113739f},{0.061924f,-0.0584675f,0.301945f},{-0.164365f,0.120048f,0.0967365f}, -{-0.355046f,0.31082f,-0.0183531f},{-0.0707984f,-0.389782f,0.304061f},{-0.0525739f,-0.386701f,0.310003f}, -{-0.0365165f,-0.386663f,0.310286f},{-0.0172696f,-0.386669f,0.309868f},{-0.00438252f,-0.386444f,0.312517f}, -{0.00376513f,-0.378708f,0.321295f},{0.0171538f,-0.381898f,0.327108f},{0.0257387f,-0.378104f,0.334478f}, -{0.0406578f,-0.379377f,0.337777f},{0.0599562f,-0.378895f,0.342388f},{0.077647f,-0.380804f,0.345982f}, -{0.0985402f,-0.38256f,0.350053f},{0.117819f,-0.380734f,0.347635f},{0.137118f,-0.382952f,0.347024f}, -{0.156358f,-0.378824f,0.342722f},{0.174801f,-0.375428f,0.33705f},{-0.293306f,0.246314f,-0.0577537f}, -{-0.475679f,0.0771036f,0.0506543f},{-0.0662712f,-0.117623f,-0.186586f},{-0.344249f,0.391113f,-0.324369f}, -{-0.370872f,0.116569f,0.349307f},{-0.281731f,0.208894f,-0.0190347f},{-0.5f,0.077991f,0.134201f}, -{0.324681f,0.0208289f,3.86026e-05f},{-0.229899f,0.187364f,0.172335f},{0.0615768f,0.0731359f,0.242584f}, -{0.0284267f,0.126562f,0.092563f},{-0.288219f,0.291238f,-0.147847f},{-0.4415f,-0.0193434f,0.147532f}, -{-0.467686f,0.192663f,0.210759f},{-0.0701425f,0.0924215f,0.13388f},{-0.0727147f,0.0979968f,0.0376001f}, -{0.323954f,-0.394007f,0.213292f},{0.342847f,-0.391544f,0.213176f},{0.360828f,-0.392122f,0.216964f}, -{0.383348f,-0.393878f,0.215118f},{-0.147085f,0.03751f,0.223375f},{-0.458689f,0.0765956f,0.0121733f}, -{-0.302842f,0.289637f,-0.244211f},{-0.340597f,0.0807112f,0.352227f},{0.289364f,-0.0535095f,0.267676f}, -{-0.454792f,0.0574001f,0.0140382f},{-0.0704125f,0.457548f,-0.0739462f},{-0.186518f,0.37503f,0.0173564f}, -{-0.296971f,0.266294f,-0.0383975f},{-0.372493f,-0.095058f,0.263213f},{0.211855f,0.119019f,0.132903f}, -{0.00716052f,-0.077483f,0.319726f},{0.051172f,0.127642f,0.144291f},{-0.146391f,0.0978682f,0.152773f}, -{-0.220929f,-0.380824f,0.227735f},{-0.216241f,-0.383261f,0.241401f},{-0.203604f,-0.379036f,0.247278f}, -{-0.190981f,-0.378271f,0.254436f},{-0.181271f,-0.377904f,0.258603f},{-0.16522f,-0.377525f,0.26302f}, -{-0.145799f,-0.377525f,0.263201f},{-0.126462f,-0.377846f,0.259464f},{-0.107247f,-0.382239f,0.256744f}, -{0.322456f,0.0356259f,0.151847f},{-0.0665799f,-0.379133f,0.281078f},{-0.0513521f,-0.377171f,0.28455f}, -{-0.039391f,-0.375152f,0.289258f},{-0.0298029f,-0.374271f,0.298216f},{-0.0215267f,-0.374946f,0.305939f}, -{-0.0127359f,-0.370882f,0.315977f},{0.0824057f,-0.373371f,0.353378f},{0.0985209f,-0.372914f,0.357963f}, -{0.117813f,-0.373351f,0.35251f},{0.137092f,-0.373358f,0.352329f},{0.382756f,-0.0957782f,-0.00136328f}, -{0.394679f,-0.112903f,0.133449f},{-0.389026f,0.097283f,0.348497f},{-0.431128f,0.0196778f,0.305193f}, -{-0.480425f,0.0439793f,0.0615414f},{-0.359651f,0.151455f,0.335198f},{-0.371837f,0.151802f,0.340677f}, -{-0.390171f,0.152741f,0.343436f},{-0.485364f,0.0427446f,0.0765506f},{0.0792932f,0.075213f,0.243651f}, -{0.211874f,0.12071f,0.11453f},{0.368583f,-0.386328f,0.219067f},{0.378274f,-0.386367f,0.21906f}, -{-0.337825f,0.0426482f,0.344201f},{0.249532f,0.0981319f,0.152027f},{0.249686f,0.101135f,0.132594f}, -{0.362307f,-0.0139031f,0.0751937f},{0.00535994f,0.324311f,-0.055323f},{-0.38965f,0.24396f,-0.0210861f}, -{-0.449429f,0.0762419f,-0.000784522f},{-0.313697f,0.286287f,-0.0181602f},{0.191984f,0.110247f,0.189306f}, -{0.00652389f,0.103746f,0.175383f},{-0.165008f,0.392573f,0.00273305f},{-0.35423f,0.294576f,0.173287f}, -{-0.148886f,0.0846597f,0.176888f},{0.207527f,0.0906723f,0.204206f},{-0.107138f,-0.373834f,0.252796f}, -{-0.0889843f,-0.372149f,0.249992f},{-0.304759f,0.320221f,-0.0956882f},{-0.127182f,0.0754059f,0.190611f}, -{-0.108315f,0.0574837f,0.2049f},{-0.0575576f,-0.37148f,0.267104f},{-0.00203533f,-0.363551f,0.329006f}, -{0.00388088f,-0.355828f,0.334677f},{0.0214687f,-0.361326f,0.336883f},{0.0406707f,-0.360625f,0.344819f}, -{0.055667f,-0.361725f,0.348799f},{0.0642198f,-0.358439f,0.352214f},{0.0792354f,-0.359455f,0.35694f}, -{0.0985466f,-0.358947f,0.36204f},{0.117877f,-0.3595f,0.356509f},{0.137105f,-0.359757f,0.353866f}, -{0.156378f,-0.360297f,0.347982f},{0.175998f,-0.359152f,0.34514f},{0.0201054f,0.075766f,0.229575f}, -{-0.297833f,0.399453f,-0.320176f},{-0.259847f,0.0370792f,0.247214f},{0.138578f,0.0243465f,0.272544f}, -{-0.165155f,0.0381917f,0.222835f},{-0.403103f,0.116607f,0.351969f},{0.347426f,-0.0926658f,-0.0576316f}, -{-0.0582393f,0.457156f,-0.0944021f},{-0.298656f,0.344491f,-0.167519f},{-0.411636f,0.151661f,0.338497f}, -{0.0989132f,0.137185f,0.0767821f},{-0.409958f,0.207415f,0.298743f},{0.293691f,0.0650204f,0.156272f}, -{-0.0904505f,0.103559f,0.0759075f},{0.330603f,-0.375428f,0.21762f},{0.34297f,-0.373139f,0.213922f}, -{0.360808f,-0.371872f,0.216546f},{0.368557f,-0.377094f,0.219009f},{0.381483f,-0.372547f,0.219614f}, -{-0.43289f,0.251657f,0.227395f},{-0.313485f,0.255098f,0.254429f},{0.330089f,-0.0531044f,0.230706f}, -{0.30589f,0.0219928f,0.206784f},{0.38237f,-0.0548664f,0.0563198f},{-0.0897302f,0.0956175f,0.133906f}, -{-0.0879168f,0.0444037f,0.215536f},{-0.184441f,0.134401f,0.132915f},{0.19945f,0.101727f,0.198026f}, -{0.193605f,0.0958233f,0.20917f},{-0.354416f,0.26648f,0.245555f},{-0.279338f,0.282004f,0.207678f}, -{-0.355966f,0.29347f,0.0546414f},{-0.354564f,0.296814f,0.0935083f},{-0.201322f,-0.362393f,0.24315f}, -{-0.188229f,-0.361403f,0.253625f},{-0.179206f,-0.358567f,0.258988f},{-0.165188f,-0.359371f,0.263709f}, -{-0.145793f,-0.359403f,0.263953f},{-0.126449f,-0.359776f,0.259644f},{-0.107138f,-0.360413f,0.252352f}, -{-0.0891901f,-0.360021f,0.246384f},{-0.280136f,0.293167f,0.0344748f},{-0.461268f,0.0941706f,0.0216842f}, -{-0.336494f,0.291135f,0.190476f},{-0.0558021f,-0.358059f,0.265053f},{-0.0402142f,-0.356979f,0.28747f}, -{-0.0301695f,-0.353416f,0.302608f},{-0.0231215f,-0.359397f,0.309508f},{-0.0135977f,-0.353481f,0.321681f}, -{-0.410967f,0.0985306f,0.345783f},{-0.396711f,0.102801f,0.350773f},{-0.184447f,0.0336581f,0.224674f}, -{-0.111086f,0.423491f,-0.0134915f},{-0.415186f,0.115971f,0.347674f},{-0.128141f,0.419125f,-0.017665f}, -{-0.290862f,0.286274f,-0.096402f},{0.0463683f,0.437201f,-0.168316f},{0.342841f,-0.1328f,-0.0902865f}, -{0.392421f,-0.0813864f,0.0755796f},{0.356911f,-0.0199286f,0.0177872f},{-0.467024f,-0.0708209f,0.0964471f}, -{0.120951f,0.0267194f,0.27448f},{0.39419f,-0.368914f,0.21897f},{0.215842f,0.0233819f,0.252313f}, -{0.273377f,0.0811099f,0.153577f},{-0.455577f,-0.0533295f,0.056577f},{-0.372969f,0.334041f,-0.0745571f}, -{-0.0136491f,0.113437f,0.0573872f},{-0.357477f,0.241433f,0.278769f},{-0.318064f,0.290531f,0.191627f}, -{-0.335851f,0.278583f,0.225047f},{0.0617826f,0.127681f,0.153719f},{-0.296881f,0.294119f,0.0776695f}, -{-0.319003f,0.265046f,0.24715f},{-0.373631f,0.290094f,0.039928f},{0.00397734f,0.118176f,0.0573101f}, -{-0.260651f,0.281702f,0.190142f},{-0.0537893f,0.0964342f,0.0183338f},{-0.0705605f,-0.359037f,0.248056f}, -{0.0407607f,0.122652f,0.154567f},{-0.0711907f,0.0987235f,0.114543f},{-0.393714f,0.293534f,0.135147f}, -{-0.398814f,0.379653f,-0.243941f},{-0.390955f,-0.0752966f,-0.0572136f},{0.0226327f,0.119938f,0.0371885f}, -{0.0990097f,0.135777f,0.0580818f},{0.118314f,0.138742f,0.0781197f},{0.193155f,0.128774f,0.0961062f}, -{0.00290986f,-0.337115f,0.339397f},{0.021816f,-0.338973f,0.343912f},{0.0373589f,-0.346973f,0.348111f}, -{0.0422784f,-0.339674f,0.352953f},{0.0599305f,-0.341577f,0.356876f},{0.0792289f,-0.34159f,0.357185f}, -{0.0984695f,-0.341307f,0.36004f},{0.117845f,-0.341372f,0.359075f},{0.13715f,-0.341886f,0.354227f}, -{0.154841f,-0.339893f,0.35168f},{0.159619f,-0.346709f,0.349931f},{0.174454f,-0.341944f,0.348754f}, -{0.137098f,0.0797274f,0.234539f},{0.117382f,0.0827112f,0.233671f},{0.370126f,-0.168323f,-0.0577537f}, -{0.174396f,0.134163f,0.114022f},{-0.37837f,0.0210347f,-0.026295f},{-0.108617f,0.021382f,0.232044f}, -{-0.244954f,0.282261f,0.132735f},{0.134796f,0.118331f,0.188508f},{0.080155f,0.135185f,0.0954117f}, -{0.154551f,0.135873f,0.13087f},{-0.0725411f,0.100325f,0.0573808f},{0.344815f,-0.357931f,0.214012f}, -{0.362172f,-0.354844f,0.214276f},{0.379804f,-0.352291f,0.21708f},{0.384653f,-0.358947f,0.218803f}, -{0.397688f,-0.359384f,0.218797f},{-0.3901f,0.188508f,0.322067f},{-0.0718144f,-0.112768f,-0.167171f}, -{-0.0893123f,0.0619337f,-0.0559532f},{-0.196769f,0.307952f,0.0660493f},{-0.0233851f,-0.14159f,0.366895f}, -{0.234459f,0.103842f,0.15258f},{0.360461f,-0.0519726f,-0.020398f},{0.29238f,0.0452911f,0.195595f}, -{-0.375309f,0.320311f,-0.0550657f},{-0.316623f,0.297585f,0.135912f},{-0.372744f,0.282557f,0.208784f}, -{-0.280592f,0.294556f,0.0755024f},{0.0436802f,0.118305f,0.171557f},{0.288746f,0.0260571f,-0.0418957f}, -{-0.129755f,0.113996f,0.0951288f},{-0.180081f,-0.338169f,0.260667f},{-0.1652f,-0.341037f,0.266506f}, -{-0.145831f,-0.340947f,0.267734f},{-0.126501f,-0.341346f,0.263303f},{-0.111459f,-0.340401f,0.257233f}, -{-0.102952f,-0.343745f,0.252982f},{-0.0870229f,-0.340838f,0.24742f},{-0.0707341f,-0.340246f,0.248249f}, -{-0.0517122f,0.0829363f,0.168059f},{0.210993f,0.110421f,0.169995f},{-0.413405f,0.28711f,0.152953f}, -{-0.497717f,0.108736f,0.150156f},{0.0393395f,0.123218f,0.0331629f},{0.23114f,0.112247f,0.112472f}, -{-0.130822f,0.421536f,-0.0386354f},{-0.0864056f,0.0360117f,0.224057f},{-0.0163243f,0.0771229f,0.207485f}, -{-0.00137296f,0.0807627f,0.209697f},{-0.330996f,0.341243f,-0.336857f},{-0.0541558f,0.100904f,0.114061f}, -{-0.126514f,0.0204431f,0.231858f},{-0.301518f,0.303784f,-0.0767113f},{-0.0140221f,0.0699463f,0.219871f}, -{0.364416f,-0.0319861f,0.0164239f},{-0.224549f,0.247941f,0.115726f},{0.274798f,-0.0509115f,0.27484f}, -{0.00366868f,0.07248f,0.224784f},{-0.287434f,0.264455f,0.238854f},{0.370429f,-0.0281663f,0.0755924f}, -{-0.486129f,0.0955853f,0.211286f},{0.402524f,-0.352805f,0.217183f},{-0.392492f,-0.263876f,0.0960741f}, -{-0.373374f,0.363596f,-0.131899f},{-0.14733f,0.115932f,0.0203659f},{0.0461496f,0.417517f,-0.14905f}, -{-0.033507f,0.477419f,-0.0714961f},{0.0626121f,-0.0658371f,0.325713f},{-0.375084f,-0.149693f,0.26284f}, -{-0.239854f,-0.356509f,0.0785891f},{0.0611009f,0.100196f,0.210476f},{-0.317877f,0.29727f,0.153204f}, -{0.0992733f,-0.0652519f,0.325842f},{-0.278129f,0.268152f,0.230417f},{-0.015932f,0.110305f,0.0387448f}, -{-0.0342465f,0.10972f,0.0948008f},{-0.412993f,0.28383f,0.1722f},{-0.0337063f,0.0961191f,0.00265588f}, -{-0.0527154f,0.0908974f,-0.00167195f},{-0.0925019f,0.43587f,-0.0756246f},{0.0438153f,0.125867f,0.0425581f}, -{0.174287f,0.134928f,0.0941706f},{0.0213144f,-0.318408f,0.354863f},{0.0406578f,-0.323224f,0.361603f}, -{0.0599305f,-0.322896f,0.366046f},{0.0792418f,-0.323166f,0.36249f},{0.097312f,-0.323829f,0.363519f}, -{0.117806f,-0.327424f,0.364271f},{0.138397f,-0.323951f,0.364387f},{0.157805f,-0.321604f,0.357699f}, -{0.177978f,-0.320755f,0.346786f},{0.027848f,0.0706215f,0.238475f},{-0.223636f,0.0383203f,0.226314f}, -{0.156378f,0.0796759f,0.235767f},{0.319929f,0.0325649f,0.169229f},{-0.147516f,0.116594f,0.0961384f}, -{-0.313749f,0.293438f,0.17811f},{0.136738f,0.138626f,0.116125f},{0.362358f,-0.337057f,0.210244f}, -{0.381406f,-0.336684f,0.213376f},{0.400826f,-0.336677f,0.215897f},{0.419559f,-0.337655f,0.210829f}, -{0.394679f,-0.0948008f,0.0948716f},{0.394659f,-0.0958233f,0.0384039f},{-0.407849f,0.0805119f,0.336343f}, -{-0.446053f,0.00109963f,0.0566477f},{-0.35713f,0.225485f,-0.0908974f},{-0.290335f,0.285129f,-0.168438f}, -{-0.410299f,-0.0898621f,0.228141f},{-0.392196f,-0.111135f,0.247098f},{-0.0742517f,0.0636057f,0.19465f}, -{-0.239397f,0.266126f,0.172747f},{-0.353374f,0.279753f,0.221408f},{-0.342693f,0.295778f,0.0180895f}, -{-0.0354876f,0.101129f,0.021517f},{-0.394749f,0.288923f,0.172605f},{-0.167168f,-0.32107f,0.268577f}, -{-0.145838f,-0.322485f,0.272036f},{-0.126526f,-0.322742f,0.268795f},{-0.107189f,-0.323552f,0.26003f}, -{-0.0880133f,-0.319681f,0.25241f},{-0.0712421f,-0.318022f,0.250693f},{-0.0627793f,-0.324871f,0.257233f}, -{-0.410318f,-0.0753159f,-0.0372528f},{0.251095f,0.101746f,0.11134f},{0.295132f,0.0662294f,0.136947f}, -{0.00121216f,-0.316614f,0.345314f},{0.0165557f,-0.3217f,0.349564f},{0.10499f,-0.317848f,0.370618f}, -{0.117826f,-0.31788f,0.370683f},{0.130649f,-0.317958f,0.36993f},{0.176743f,0.0583454f,0.244372f}, -{0.00338572f,0.0562169f,0.241201f},{0.117774f,0.062088f,0.253291f},{-0.497955f,0.0649368f,0.134272f}, -{-0.0534099f,0.0723128f,0.189705f},{-0.0364844f,0.0692196f,0.207273f},{-0.14578f,0.0250796f,0.232591f}, -{-0.0344716f,0.0794894f,0.189962f},{-0.374126f,0.210926f,0.306852f},{-0.238844f,0.227845f,0.173602f}, -{-0.410041f,0.290004f,0.114492f},{0.193695f,0.128131f,0.11462f},{-0.291917f,0.284917f,-0.187685f}, -{-0.185264f,0.100659f,-0.0401788f},{0.378094f,-0.0563068f,0.0186489f},{-0.335382f,0.168773f,-0.0424552f}, -{-0.433976f,0.0221343f,0.0171313f},{-0.0405421f,0.318511f,-0.00552392f},{-0.446175f,0.191441f,0.0372014f}, -{-0.303505f,0.396077f,-0.300685f},{-0.369811f,0.296563f,0.0990451f},{-0.41217f,0.00878431f,0.29855f}, -{-0.294347f,0.26549f,-0.148452f},{-0.355812f,0.360175f,-0.111141f},{-0.122121f,0.0838623f,0.17701f}, -{0.0430565f,0.127186f,0.132041f},{0.251764f,0.0635028f,0.215164f},{-0.414492f,0.283952f,0.0753931f}, -{0.0616346f,0.114093f,0.190187f},{-0.393785f,0.291817f,0.153937f},{-0.21853f,0.153397f,0.19463f}, -{0.0606958f,0.12844f,0.0401531f},{0.156468f,0.137963f,0.0765185f},{0.212903f,0.120986f,0.0972252f}, -{0.285743f,0.0747886f,0.133443f},{0.322745f,0.0380438f,0.133648f},{0.0598791f,0.122337f,0.171763f}, -{0.00871031f,-0.310562f,0.351905f},{0.022324f,-0.300466f,0.358908f},{0.0406643f,-0.300415f,0.366676f}, -{0.0599112f,-0.304537f,0.371184f},{0.0776341f,-0.302247f,0.37139f},{0.0824636f,-0.309083f,0.368606f}, -{0.0985209f,-0.304286f,0.373448f},{0.117813f,-0.304202f,0.374747f},{0.137195f,-0.304408f,0.372367f}, -{0.154828f,-0.298685f,0.366991f},{0.0213273f,0.057548f,0.247812f},{0.0985338f,0.0622102f,0.25522f}, -{0.0792868f,0.0621138f,0.253786f},{0.058355f,0.0599402f,0.252802f},{-0.315717f,0.074795f,-0.0470338f}, -{-0.147941f,-0.114858f,-0.139577f},{-0.499453f,0.0780746f,0.153526f},{0.0407157f,0.0706859f,0.241639f}, -{-0.495396f,0.0597666f,0.154915f},{-0.497685f,0.0649883f,0.147159f},{-0.228092f,-0.345076f,0.134433f}, -{-0.294791f,0.267618f,-0.0566284f},{0.390299f,-0.0928009f,0.13505f},{-0.460947f,-0.0740812f,0.151326f}, -{0.34706f,-0.0158773f,-0.00152405f},{-0.109517f,-0.0777853f,-0.137243f},{0.376653f,-0.0786599f,0.17076f}, -{0.365869f,-0.0745892f,0.190193f},{0.363696f,-0.318266f,0.207685f},{0.381502f,-0.319244f,0.204617f}, -{0.40073f,-0.318884f,0.209607f},{0.420138f,-0.319025f,0.208566f},{0.437951f,-0.319417f,0.20245f}, -{0.369933f,-0.0920999f,-0.0271052f},{0.368705f,-0.130832f,-0.0560946f},{-0.049873f,-0.115167f,-0.203183f}, -{0.211038f,0.0167455f,0.257136f},{-0.379412f,0.294782f,0.094132f},{-0.26359f,-0.323951f,0.152619f}, -{-0.262368f,-0.314035f,0.17366f},{-0.237912f,-0.316794f,0.186206f},{-0.0326967f,0.10682f,0.0438636f}, -{-0.20235f,0.169075f,0.116073f},{0.118134f,-0.0765313f,0.340639f},{0.21082f,0.0727243f,0.222758f}, -{0.273814f,0.0845117f,0.133552f},{-0.168879f,-0.303199f,0.271104f},{-0.145831f,-0.303958f,0.276428f}, -{-0.130816f,-0.302563f,0.275625f},{-0.122237f,-0.305829f,0.272621f},{-0.106399f,-0.303109f,0.263882f}, -{-0.0943796f,-0.310286f,0.256275f},{-0.0640912f,-0.298698f,0.260358f},{0.116778f,0.137475f,0.0591364f}, -{-0.00123792f,-0.300711f,0.346651f},{0.0064017f,-0.29565f,0.352953f},{0.193656f,0.0561783f,0.240912f}, -{0.0406964f,0.0575415f,0.251998f},{-0.454329f,0.265078f,0.171268f},{-0.374191f,0.188579f,0.321874f}, -{0.393528f,-0.0958104f,0.112845f},{-0.28784f,0.306234f,-0.186463f},{-0.294412f,0.22542f,-0.0373107f}, -{0.116006f,0.0725186f,0.244153f},{-0.406286f,0.187454f,0.318363f},{0.0225812f,0.0918942f,0.209479f}, -{0.00791934f,0.0883766f,0.206103f},{0.389103f,-0.0944214f,0.0165911f},{0.0820649f,0.110228f,0.202257f}, -{0.34052f,-0.0172085f,-0.0195042f},{-0.0263304f,0.489116f,-0.0886531f},{0.248947f,0.0197486f,0.243478f}, -{-0.168088f,0.11853f,0.0191827f},{-0.316135f,0.285476f,0.0214334f},{0.199309f,0.123707f,0.138098f}, -{-0.130539f,0.340433f,-0.0769428f},{-0.168757f,0.282673f,-0.0395293f},{-0.262477f,-0.306961f,0.190913f}, -{-0.248754f,-0.306363f,0.199158f},{-0.241404f,-0.30264f,0.209144f},{-0.226517f,-0.30462f,0.214861f}, -{-0.220517f,-0.297997f,0.228745f},{-0.334128f,0.292537f,0.0193499f},{0.12034f,0.102511f,0.213646f}, -{-0.00977785f,0.106678f,0.150645f},{-0.158596f,-0.299476f,0.275477f},{-0.0922382f,-0.295058f,0.258191f}, -{-0.0836661f,-0.298428f,0.254474f},{-0.0729784f,-0.298473f,0.253889f},{0.26649f,0.0916369f,0.117077f}, -{-0.190666f,0.149082f,0.0814894f},{0.0624771f,-0.285798f,0.370689f},{0.0792096f,-0.282055f,0.372721f}, -{0.0985145f,-0.281901f,0.37465f},{0.117839f,-0.282023f,0.372728f},{0.135021f,-0.285078f,0.371737f}, -{-0.384634f,0.285682f,-0.0195363f},{-0.365921f,0.285611f,-0.167583f},{-0.436446f,-0.072017f,-0.00124753f}, -{-0.393296f,0.420102f,-0.300125f},{0.117993f,0.13842f,0.114485f},{-0.00438894f,0.0613614f,0.234333f}, -{0.138333f,0.0583068f,0.250847f},{0.156365f,0.0574451f,0.249677f},{-0.0237452f,0.0260378f,0.254352f}, -{-0.0153532f,0.492762f,-0.111482f},{0.377837f,-0.168593f,-0.0397929f},{-0.185393f,0.0721263f,0.186496f}, -{-0.483801f,0.0392528f,0.243741f},{0.042587f,0.0987364f,0.206804f},{-0.224215f,0.077676f,-0.0580238f}, -{0.230002f,-0.0166554f,-0.0977975f},{-0.4969f,0.0778046f,0.108485f},{0.367573f,-0.299026f,0.205903f}, -{0.380936f,-0.299971f,0.193582f},{0.400666f,-0.305829f,0.201531f},{0.420099f,-0.305752f,0.203434f}, -{0.436356f,-0.306016f,0.20063f},{0.341741f,-5.1417e-05f,0.171615f},{-0.202093f,0.36168f,-0.0182052f}, -{-0.201186f,0.151178f,0.0380438f},{-0.488078f,0.0601395f,0.0764606f},{-0.448252f,-0.0895855f,0.0194399f}, -{-0.393412f,0.344047f,-0.149654f},{0.117459f,0.135951f,0.132729f},{-0.164313f,0.113675f,-0.000199332f}, -{0.0989518f,0.127655f,0.167152f},{-0.0500788f,-0.228308f,0.323366f},{-0.27694f,-0.0338896f,-0.106755f}, -{-0.370396f,0.0185782f,-0.0336966f},{-0.295794f,-0.126658f,-0.111752f},{-0.0936851f,-0.131616f,-0.151423f}, -{-0.238973f,-0.29491f,0.222932f},{-0.202286f,-0.297161f,0.245465f},{-0.0333719f,0.109694f,0.0763513f}, -{-0.0296614f,0.0897592f,0.167371f},{0.0786695f,0.123347f,0.175994f},{-0.168943f,-0.283489f,0.272975f}, -{-0.160821f,-0.281419f,0.276036f},{-0.145825f,-0.285753f,0.278242f},{-0.129748f,-0.285824f,0.277483f}, -{-0.120128f,-0.286074f,0.274557f},{-0.108096f,-0.280833f,0.269747f},{0.400743f,-0.26821f,0.171223f}, -{0.00295487f,-0.278332f,0.355899f},{0.0232565f,-0.279888f,0.357892f},{0.0406385f,-0.278293f,0.364316f}, -{0.0567345f,-0.277907f,0.368689f},{0.141478f,-0.276448f,0.368638f},{0.156448f,-0.27821f,0.365229f}, -{0.175676f,-0.279399f,0.358818f},{0.211045f,0.0524614f,0.239362f},{0.214877f,0.0620109f,0.23178f}, -{0.232105f,0.0548535f,0.232835f},{-0.145909f,0.111578f,0.00139547f},{-0.0464005f,0.0519598f,0.221433f}, -{-0.0185621f,0.057683f,0.231478f},{-0.0368445f,0.0611492f,0.217067f},{-0.0323945f,0.0551622f,0.226597f}, -{-0.19781f,0.074332f,0.192772f},{0.192299f,0.127025f,0.132755f},{-0.205212f,0.0821774f,-0.0591942f}, -{0.388569f,-0.0771293f,0.0370728f},{0.400678f,-0.297257f,0.19555f},{0.420054f,-0.297135f,0.198842f}, -{0.441655f,-0.301283f,0.19654f},{-0.335304f,0.297888f,0.131488f},{-0.0276101f,0.469104f,-0.12489f}, -{0.352101f,-0.0110286f,0.0177551f},{0.360448f,-0.0154014f,0.0383075f},{-0.279878f,-0.245182f,0.263554f}, -{-0.287602f,0.306273f,-0.167165f},{0.193502f,0.121919f,0.155243f},{-0.285531f,0.295643f,0.136697f}, -{-0.313794f,-0.127957f,-0.107437f},{-0.355831f,0.0205974f,-0.0426095f},{-0.130803f,0.359609f,-0.077766f}, -{-0.186859f,0.28138f,-0.0334073f},{-0.24433f,-0.134356f,-0.131822f},{-0.167233f,-0.133996f,-0.132356f}, -{-0.223951f,-0.281438f,0.243188f},{-0.20572f,-0.282975f,0.250712f},{-0.182113f,0.1366f,0.0737919f}, -{0.135484f,0.108517f,0.202894f},{-0.18356f,-0.279534f,0.265901f},{-0.0879747f,-0.278223f,0.260789f}, -{-0.0702068f,-0.279232f,0.261265f},{0.305427f,0.0570914f,0.132311f},{-0.375142f,0.289232f,0.0207582f}, -{0.264046f,0.0732838f,0.189634f},{-0.411848f,0.287926f,0.0950838f},{-0.205019f,0.0557153f,0.210122f}, -{-0.480084f,0.19674f,0.133552f},{0.338147f,0.00136971f,0.0018842f},{-0.476972f,0.230957f,0.175345f}, -{-0.355728f,0.297624f,0.133636f},{-0.246651f,0.279303f,0.167962f},{-0.0530112f,0.0594643f,0.209794f}, -{-0.126539f,0.055741f,0.208636f},{-0.218845f,0.228192f,0.0964406f},{-0.336816f,-0.298267f,0.151834f}, -{-0.213984f,0.22834f,0.0841131f},{-0.391283f,0.306183f,-0.092087f},{0.0407736f,0.0879972f,0.222765f}, -{-0.45168f,-0.00158838f,0.11534f},{-0.455892f,-0.0366419f,0.0770072f},{0.381489f,-0.28293f,0.187782f}, -{0.401958f,-0.285271f,0.18701f},{0.420028f,-0.28419f,0.190418f},{0.440233f,-0.2852f,0.189164f}, -{0.454818f,-0.287116f,0.184952f},{-0.455397f,0.116048f,0.0136652f},{0.393431f,-0.149236f,0.165538f}, -{0.397322f,-0.130832f,0.133475f},{-0.389045f,0.304453f,-0.0738818f},{0.0624385f,0.131861f,0.116678f}, -{0.0188322f,0.124157f,0.0999389f},{-0.39282f,0.284447f,0.190309f},{-0.410717f,0.28057f,0.187344f}, -{-0.411199f,0.14786f,-0.0154207f},{-0.148224f,-0.0326613f,-0.120858f},{-0.277596f,-0.127739f,-0.117417f}, -{-0.109337f,-0.1326f,-0.147597f},{-0.432639f,0.0430211f,0.00153052f},{0.0408443f,-0.128112f,-0.22517f}, -{0.0573968f,-0.129739f,-0.22351f},{-0.352564f,-0.296453f,0.132806f},{-0.275538f,0.0185846f,-0.0867432f}, -{0.193212f,-0.0152085f,-0.111154f},{0.0769332f,-0.0398701f,-0.138259f},{-0.164197f,-0.260545f,0.278866f}, -{-0.145831f,-0.263123f,0.278891f},{-0.126565f,-0.263149f,0.278416f},{-0.0620655f,-0.272274f,0.272744f}, -{0.337304f,0.0145397f,0.15276f},{0.00310277f,0.112209f,0.149577f},{-0.0144401f,0.115237f,0.0962863f}, -{-0.327472f,0.350182f,-0.107154f},{0.00212531f,-0.260641f,0.36076f},{0.0213594f,-0.260738f,0.360857f}, -{0.0393653f,-0.261162f,0.366098f},{0.0534356f,-0.264596f,0.368779f},{0.0611781f,-0.258808f,0.373814f}, -{0.0792032f,-0.259554f,0.376354f},{0.0985724f,-0.259548f,0.375911f},{0.11661f,-0.258937f,0.372213f}, -{0.124263f,-0.264455f,0.369448f},{0.137131f,-0.260082f,0.368824f},{0.156442f,-0.260197f,0.367474f}, -{0.174088f,-0.26149f,0.362419f},{0.119292f,0.139082f,0.0968779f},{-0.2802f,0.290557f,0.171351f}, -{0.229996f,0.110646f,0.132195f},{-0.109022f,0.434558f,-0.0368477f},{-0.422999f,-0.0430147f,-0.0129578f}, -{-0.491306f,0.112672f,0.0954632f},{-0.0883412f,0.282075f,-0.017948f},{-0.374158f,0.301206f,-0.0189126f}, -{0.389772f,-0.0770072f,0.0948587f},{-0.483769f,0.113212f,0.211196f},{0.394511f,-0.28037f,0.180206f}, -{0.342667f,-0.0349056f,-0.0382753f},{-0.473531f,0.156477f,0.0759461f},{0.389534f,-0.149706f,0.175306f}, -{0.0982959f,0.134517f,0.133417f},{-0.337054f,0.333996f,-0.0643002f},{-0.276277f,0.294023f,0.13069f}, -{-0.277306f,0.0785955f,-0.0460114f},{-0.0315778f,-0.0332529f,-0.136658f},{-0.127317f,-0.132041f,-0.143925f}, -{-0.426549f,0.02861f,0.00250155f},{-0.128854f,0.301077f,-0.0589884f},{-0.278753f,-0.469413f,0.302203f}, -{0.0773062f,-0.12761f,-0.219813f},{0.172454f,-0.0427896f,-0.123256f},{-0.187843f,-0.26084f,0.272191f}, -{-0.113729f,-0.258757f,0.276936f},{-0.104051f,-0.259207f,0.271914f},{-0.0879875f,-0.259824f,0.26484f}, -{-0.0720845f,-0.259599f,0.266577f},{-0.0622327f,-0.263258f,0.277489f},{-0.394241f,0.269374f,0.228842f}, -{-0.335729f,0.357956f,-0.114884f},{0.0471721f,-0.255252f,0.371371f},{0.231275f,0.0376065f,0.242577f}, -{0.214254f,0.039047f,0.245555f},{0.193701f,0.0395293f,0.248011f},{0.137041f,0.0399408f,0.264982f}, -{-0.395611f,-0.0363718f,-0.0398958f},{-0.184415f,0.0511366f,0.207254f},{-0.165162f,0.0555931f,0.206206f}, -{0.13061f,0.0531944f,0.257889f},{0.0631459f,0.0534131f,0.257059f},{0.0792997f,0.0532909f,0.260519f}, -{-0.464458f,-0.0707308f,0.13496f},{0.0191151f,0.123244f,0.0768143f},{0.0229864f,0.0375293f,0.259985f}, -{0.0627729f,0.0895791f,0.227163f},{-0.463654f,-0.0535095f,0.115585f},{-0.467435f,0.175088f,0.249355f}, -{-0.335201f,0.126498f,-0.0476833f},{-0.374236f,0.166104f,0.335076f},{-0.386859f,0.219858f,0.297997f}, -{0.380821f,-0.264872f,0.188431f},{0.388351f,-0.261998f,0.177435f},{0.423237f,-0.271322f,0.180637f}, -{0.436163f,-0.271342f,0.18065f},{0.439211f,-0.262004f,0.171268f},{0.456632f,-0.264982f,0.169377f}, -{-0.456857f,0.178387f,0.0565448f},{-0.482386f,0.113315f,0.246545f},{-0.467062f,-0.0924408f,0.115816f}, -{0.194987f,0.116318f,0.171358f},{-0.261352f,0.307244f,0.0568342f},{-0.200421f,0.169313f,0.0971352f}, -{-0.374416f,0.271509f,0.233639f},{-0.335163f,0.112466f,-0.0477927f},{-0.258773f,0.226115f,-0.00123467f}, -{-0.393804f,0.03497f,-0.0210218f},{-0.354018f,0.0368027f,-0.039317f},{-0.355484f,-0.0172342f,-0.0600495f}, -{-0.31609f,0.322536f,-0.355358f},{0.0926755f,-0.130157f,-0.217909f},{-0.335259f,0.149905f,-0.0439343f}, -{-0.181123f,-0.254043f,0.278435f},{0.0232758f,0.118369f,0.151114f},{-0.261442f,0.291328f,0.114311f}, -{0.393675f,-0.243696f,0.164818f},{-0.241166f,0.285862f,0.0968522f},{0.00107712f,-0.243542f,0.364078f}, -{0.0200218f,-0.24322f,0.365615f},{0.0341693f,-0.246654f,0.369499f},{0.0419697f,-0.240822f,0.374194f}, -{0.0599434f,-0.241111f,0.381923f},{0.0792032f,-0.240925f,0.385602f},{0.0986367f,-0.241163f,0.383222f}, -{0.117961f,-0.24178f,0.375203f},{0.137105f,-0.241966f,0.371827f},{0.155162f,-0.241085f,0.371737f}, -{0.162937f,-0.246699f,0.368901f},{0.17383f,-0.244648f,0.364509f},{0.174834f,0.0401402f,0.253387f}, -{0.079274f,0.0400695f,0.267934f},{0.0985466f,0.0401531f,0.269933f},{-0.203836f,0.345873f,0.0429697f}, -{-0.164274f,0.0726086f,-0.0688466f},{-0.358075f,0.0621845f,0.353944f},{-0.145851f,0.0558053f,0.208431f}, -{-0.23478f,0.273348f,0.119552f},{-0.075422f,-0.128607f,-0.188123f},{-0.374101f,0.219845f,0.299508f}, -{-0.487467f,0.0957654f,0.246648f},{0.0421626f,0.379396f,-0.112202f},{-0.494547f,0.0776953f,0.0956625f}, -{-0.185155f,0.361628f,-0.0377029f},{-0.222581f,0.320916f,-0.0162438f},{-0.333845f,0.455805f,-0.360246f}, -{-0.0507476f,0.089682f,0.150297f},{-0.0236616f,0.476936f,-0.0794251f},{0.379033f,-0.132401f,-0.0399087f}, -{-0.301878f,0.374702f,-0.262763f},{0.145664f,0.124092f,0.178522f},{-0.108244f,0.0928395f,0.151944f}, -{0.0404135f,0.126813f,0.0586219f},{0.135054f,-0.127571f,-0.203164f},{-0.0112247f,0.438005f,-0.144606f}, -{-0.072734f,0.359937f,-0.0974245f},{-0.220543f,0.301103f,-0.0205524f},{-0.373818f,0.130832f,-0.0395228f}, -{-0.392614f,-0.243664f,0.169242f},{-0.261757f,-0.243966f,0.268281f},{0.0427349f,-0.0352593f,-0.139185f}, -{0.173277f,-0.0130157f,-0.115823f},{-0.233218f,0.26767f,-0.00997394f},{-0.354545f,0.149802f,-0.0412012f}, -{0.0590817f,-0.038436f,-0.138549f},{0.0962187f,-0.0401659f,-0.135404f},{-0.205199f,-0.245934f,0.271065f}, -{-0.18439f,-0.24041f,0.280261f},{-0.16513f,-0.240243f,0.28266f},{-0.145838f,-0.240417f,0.280621f}, -{-0.126539f,-0.240442f,0.280351f},{-0.110527f,-0.240725f,0.276801f},{-0.100849f,-0.241124f,0.272139f}, -{-0.0879618f,-0.241356f,0.26866f},{-0.0735121f,-0.243021f,0.271695f},{-0.00337933f,0.492537f,-0.113347f}, -{-0.317472f,0.297238f,0.116948f},{-0.0153661f,-0.243426f,0.356516f},{0.0277515f,-0.237652f,0.370252f}, -{0.0180412f,0.0443137f,0.254815f},{0.00199026f,0.0394907f,0.251567f},{-0.353812f,0.421253f,-0.335127f}, -{0.117768f,0.040063f,0.268416f},{-0.413405f,0.0750072f,0.329256f},{-0.374242f,0.0575351f,0.350259f}, -{-0.052844f,-0.108042f,-0.188348f},{0.384242f,-0.0774573f,0.0178387f},{-0.295814f,0.248108f,-0.0951802f}, -{0.374782f,-0.0371177f,0.0563133f},{-0.431687f,-0.0206167f,0.174149f},{-0.262426f,0.0814058f,-0.0432848f}, -{-0.232131f,0.222996f,0.147841f},{-0.498682f,0.0778946f,0.118131f},{0.381869f,-0.0774123f,0.152754f}, -{0.39637f,-0.0947558f,0.0563198f},{0.395785f,-0.0947944f,0.0755731f},{-0.0144465f,0.475528f,-0.0930967f}, -{-0.499794f,0.0954053f,0.134105f},{-0.181695f,0.13424f,0.111701f},{0.0992669f,-0.0618051f,0.315527f}, -{-0.173129f,0.125771f,0.0961706f},{0.0410308f,0.437073f,-0.180007f},{0.0606893f,0.131822f,0.0790457f}, -{0.0422205f,0.128587f,0.0778303f},{-0.299563f,-0.286512f,0.210231f},{-0.224967f,-0.134337f,-0.130665f}, -{-0.240542f,-0.24324f,0.268872f},{-0.222382f,-0.236063f,0.278094f},{-0.203759f,-0.236327f,0.277837f}, -{-0.0662455f,-0.244134f,0.282017f},{-0.0150638f,0.0949101f,0.171576f},{0.136841f,0.0919456f,0.224951f}, -{-0.0157776f,-0.22544f,0.361185f},{0.000794167f,-0.225234f,0.368072f},{0.0213787f,-0.223877f,0.374052f}, -{0.0406257f,-0.223716f,0.376637f},{0.0598534f,-0.223292f,0.38229f},{0.0791775f,-0.222861f,0.387647f}, -{0.0985981f,-0.222919f,0.387023f},{0.117948f,-0.223639f,0.377994f},{0.137118f,-0.223948f,0.373403f}, -{0.156416f,-0.223999f,0.372702f},{-0.090592f,0.0532009f,0.206051f},{-0.34297f,0.0636636f,0.352458f}, -{-0.0703997f,0.290158f,-0.0165332f},{-0.284708f,0.379017f,-0.377833f},{-0.45514f,0.209556f,0.0755989f}, -{-0.494347f,0.11282f,0.114749f},{0.268683f,-0.0564612f,0.282975f},{0.194537f,-0.111244f,0.342343f}, -{-0.296611f,0.363667f,-0.261374f},{-0.297511f,0.3259f,-0.302222f},{0.343941f,0.00187775f,0.0181281f}, -{-0.468908f,0.192592f,0.191454f},{-0.375361f,0.225684f,-0.0372335f},{-0.355014f,0.303019f,-0.000675201f}, -{-0.0488313f,0.474744f,-0.0766149f},{-0.246246f,0.281399f,0.151879f},{-0.257455f,0.269065f,0.208636f}, -{0.174744f,0.100158f,0.210199f},{0.079036f,0.134716f,0.0765378f},{0.0479759f,-0.0634577f,0.315347f}, -{-0.410916f,-0.244957f,0.0971287f},{-0.300309f,-0.225928f,0.270416f},{-0.285795f,-0.230604f,0.273258f}, -{-0.278888f,-0.223343f,0.279052f},{-0.261577f,-0.222134f,0.282904f},{-0.242298f,-0.222289f,0.282107f}, -{-0.22298f,-0.221877f,0.285393f},{-0.203714f,-0.222083f,0.285406f},{-0.184409f,-0.222237f,0.2821f}, -{-0.165091f,-0.22189f,0.285695f},{-0.145857f,-0.222089f,0.283624f},{-0.126565f,-0.222385f,0.2803f}, -{-0.108591f,-0.221703f,0.277496f},{-0.100791f,-0.227491f,0.27358f},{-0.0881419f,-0.223144f,0.272596f}, -{-0.0739558f,-0.223639f,0.284351f},{-0.336217f,0.297823f,0.151391f},{-0.147182f,0.0735861f,0.191962f}, -{-0.29937f,0.29637f,0.113135f},{0.00855597f,-0.219588f,0.371474f},{0.173477f,-0.226604f,0.366233f}, -{-0.0686891f,0.0249445f,0.235433f},{-0.107273f,0.0425002f,0.216681f},{0.156384f,0.0377673f,0.260976f}, -{0.0407028f,0.0399023f,0.263438f},{-0.444516f,0.265792f,0.186676f},{-0.467911f,0.154201f,0.265496f}, -{-0.302463f,0.414012f,-0.326099f},{-0.298592f,0.324703f,-0.321835f},{0.358082f,-0.131404f,-0.0702742f}, -{-0.353754f,-0.0912832f,-0.0882094f},{-0.299068f,-0.470126f,0.283869f},{-0.24132f,0.074795f,-0.0535545f}, -{0.374872f,-0.0370663f,0.0755796f},{-0.442111f,0.186791f,0.0245266f},{-0.288733f,0.291187f,-0.160702f}, -{-0.369458f,0.343667f,-0.225948f},{-0.20646f,0.188856f,0.0770972f},{-0.207276f,0.36332f,-0.00239219f}, -{-0.201894f,0.337012f,0.0508022f},{0.370101f,-0.030417f,0.0964921f},{-0.353863f,0.341475f,-0.266004f}, -{0.270104f,0.0767435f,0.174123f},{-0.0709399f,0.0747307f,0.171718f},{-0.295724f,-0.145172f,-0.112659f}, -{-0.293743f,-0.218173f,0.276744f},{-0.413405f,0.288653f,0.134073f},{-0.0186972f,-0.208701f,0.366625f}, -{0.00206101f,-0.206116f,0.373248f},{0.021353f,-0.205884f,0.376374f},{0.0405871f,-0.205492f,0.381493f}, -{0.0599112f,-0.205466f,0.381756f},{0.0791711f,-0.205145f,0.385036f},{0.0985788f,-0.20519f,0.385107f}, -{0.117954f,-0.20571f,0.37865f},{0.135883f,-0.207164f,0.371152f},{0.156429f,-0.210713f,0.370966f}, -{0.174756f,-0.206218f,0.364522f},{-0.139291f,0.0428411f,0.217427f},{-0.126533f,0.0425131f,0.215742f}, -{-0.0522266f,0.074705f,-0.0390855f},{-0.333394f,0.0598566f,0.34896f},{-0.287885f,0.291277f,-0.131764f}, -{-0.431173f,0.00439213f,0.228957f},{-0.341844f,0.305032f,-0.30435f},{-0.289981f,0.327424f,-0.226411f}, -{-0.128449f,0.417761f,-0.0551043f},{0.311414f,0.0249767f,-0.0201601f},{-0.44314f,0.0112151f,0.176419f}, -{0.0824057f,0.10318f,0.211826f},{-0.0110447f,0.0887367f,0.188309f},{-0.2751f,0.294196f,0.114035f}, -{0.136385f,0.13952f,0.0976303f},{-0.15259f,0.4069f,-0.0203916f},{-0.355439f,0.296917f,0.15249f}, -{-0.298379f,0.284621f,0.207093f},{-0.188627f,0.134748f,0.0421466f},{0.0227613f,-0.0735539f,0.322916f}, -{-0.300161f,-0.204315f,0.28037f},{-0.280792f,-0.203897f,0.284615f},{-0.262837f,-0.204418f,0.289843f}, -{-0.241012f,-0.204463f,0.290389f},{-0.223006f,-0.20344f,0.290955f},{-0.20372f,-0.203415f,0.291714f}, -{-0.184447f,-0.204051f,0.283586f},{-0.165085f,-0.203865f,0.286023f},{-0.145883f,-0.203762f,0.286615f}, -{-0.126617f,-0.20409f,0.282403f},{-0.107267f,-0.204598f,0.277039f},{-0.0923797f,-0.206405f,0.274557f}, -{-0.0837562f,-0.204218f,0.281071f},{-0.355046f,0.297367f,0.112987f},{-0.336307f,-0.150278f,0.285238f}, -{-0.487762f,0.134806f,0.114614f},{-0.482329f,0.0442815f,0.212868f},{-0.0140028f,-0.201762f,0.371712f}, -{0.143561f,-0.201923f,0.369551f},{0.156435f,-0.201974f,0.368638f},{-0.0880261f,0.024996f,0.233221f}, -{0.059982f,0.039973f,0.265908f},{0.348371f,0.00301599f,0.0364619f},{-0.443899f,0.00239864f,0.152715f}, -{-0.184351f,0.0597987f,0.197691f},{-0.210749f,0.187782f,0.114382f},{-0.461558f,-0.0538053f,0.0771036f}, -{-0.10955f,0.418713f,-0.0740105f},{-0.414472f,-0.091817f,-0.0382946f},{0.257905f,0.0859651f,0.173544f}, -{-0.297826f,0.293663f,0.170663f},{-0.451365f,0.272699f,0.0952381f},{-0.39556f,-0.0537346f,0.230526f}, -{0.0591974f,0.130395f,0.0599724f},{-0.375438f,0.296023f,0.132079f},{-0.491286f,0.0431047f,0.115115f}, -{-0.0537957f,-0.127237f,-0.212315f},{-0.255082f,-0.19854f,0.294325f},{-0.248722f,-0.198617f,0.294601f}, -{-0.373792f,0.288287f,0.1911f},{-0.437841f,-0.00634706f,0.157153f},{-0.017186f,-0.18802f,0.376239f}, -{0.00208673f,-0.187865f,0.378702f},{0.0213594f,-0.187898f,0.378142f},{0.0406257f,-0.187563f,0.382972f}, -{0.0599434f,-0.187647f,0.381595f},{0.0792032f,-0.187698f,0.380361f},{0.0985466f,-0.187724f,0.380329f}, -{0.117897f,-0.187975f,0.377743f},{0.135915f,-0.187492f,0.372753f},{0.143619f,-0.193074f,0.369165f}, -{0.156455f,-0.18674f,0.367422f},{0.17401f,-0.184701f,0.361686f},{-0.0700203f,0.055143f,0.207614f}, -{-0.0324266f,0.323289f,-0.0133693f},{-0.445693f,-0.0196842f,0.0576059f},{-0.165226f,0.099881f,-0.0395164f}, -{-0.390203f,0.130298f,0.351384f},{-0.489756f,0.0774895f,0.0763577f},{0.397733f,-0.130909f,0.0178001f}, -{-0.423919f,-0.0212533f,0.186965f},{-0.166274f,0.102022f,0.138716f},{-0.0904505f,0.0690332f,0.183981f}, -{-0.424838f,-0.0223851f,0.00402561f},{-0.415996f,0.0336452f,-0.00662999f},{0.264181f,0.0920742f,0.134542f}, -{-0.318205f,-0.188123f,0.283174f},{-0.300154f,-0.185499f,0.289611f},{-0.280862f,-0.185582f,0.28875f}, -{-0.265815f,-0.186804f,0.292094f},{-0.257217f,-0.183473f,0.296093f},{-0.242266f,-0.184669f,0.299109f}, -{-0.224633f,-0.182792f,0.295489f},{-0.219803f,-0.189782f,0.293573f},{-0.202402f,-0.186226f,0.292949f}, -{-0.184441f,-0.185788f,0.286177f},{-0.165123f,-0.186129f,0.282422f},{-0.145786f,-0.185647f,0.287598f}, -{-0.126623f,-0.18555f,0.288177f},{-0.107254f,-0.186309f,0.279528f},{-0.0896981f,-0.187306f,0.281039f}, -{-0.443513f,0.276358f,0.15258f},{-0.0693836f,0.0744928f,-0.0386868f},{-0.0388637f,0.480525f,-0.0943957f}, -{-0.238401f,0.0368927f,0.232385f},{-0.0433909f,0.0347127f,0.237664f},{-0.0368316f,0.043542f,0.234983f}, -{0.16266f,0.0439021f,0.255214f},{-0.389939f,-0.0189576f,-0.0366419f},{-0.392827f,0.0589627f,0.341256f}, -{0.375991f,-0.116807f,-0.0382431f},{0.0163692f,0.340201f,-0.0590527f},{-0.373039f,0.0968457f,0.351513f}, -{0.118276f,0.0920421f,0.224764f},{-0.429308f,-0.0382046f,-0.000225055f},{-0.457744f,0.0940291f,0.0119932f}, -{-0.49056f,0.0783962f,0.262975f},{-0.469474f,0.264268f,0.132761f},{-0.391174f,0.0139095f,0.310685f}, -{-0.385611f,0.245272f,-0.0363332f},{-0.353696f,0.296132f,0.16404f},{-0.324514f,0.333224f,-0.078229f}, -{-0.445108f,0.278448f,0.118652f},{-0.430279f,0.283663f,0.113212f},{-0.128526f,0.100627f,-0.0182566f}, -{-0.36657f,0.325887f,-0.206386f},{-0.0509855f,0.0969615f,0.131391f},{-0.210132f,-0.180721f,0.294126f}, -{-0.0818463f,-0.180721f,0.294106f},{-0.471004f,0.0357802f,0.191126f},{-0.448297f,-0.000610921f,0.13561f}, -{-0.442606f,-0.0213112f,0.0427639f},{-0.446162f,-0.0722549f,0.0192856f},{-0.0179448f,-0.171043f,0.377518f}, -{0.00211245f,-0.17004f,0.378657f},{0.0213466f,-0.170046f,0.378406f},{0.040645f,-0.169834f,0.38119f}, -{0.0600013f,-0.170014f,0.379062f},{0.0792032f,-0.170033f,0.378354f},{0.0985145f,-0.169911f,0.380059f}, -{0.117845f,-0.169995f,0.379563f},{0.137201f,-0.17022f,0.376792f},{0.153162f,-0.168606f,0.372104f}, -{-0.448915f,0.0937333f,-0.000842398f},{0.23289f,-0.166278f,0.335951f},{-0.204704f,0.284769f,0.0757275f}, -{-0.41471f,0.190798f,-0.0013247f},{-0.410382f,0.208546f,-0.00140187f},{0.0517186f,0.38346f,-0.142471f}, -{0.172467f,0.0976303f,-0.0358766f},{0.392601f,-0.0994695f,0.130214f},{-0.165143f,0.0250153f,0.233234f}, -{-0.29827f,0.296132f,0.150831f},{-0.454452f,0.274158f,0.115559f},{-0.322289f,0.35957f,-0.357005f}, -{0.242156f,0.106408f,0.12179f},{-0.355786f,0.296743f,0.017112f},{0.0784122f,-0.0586798f,0.301765f}, -{-0.319466f,-0.169577f,0.290094f},{-0.300148f,-0.171647f,0.293836f},{-0.300161f,-0.16476f,0.295264f}, -{-0.279596f,-0.168162f,0.292409f},{-0.267975f,-0.167229f,0.292486f},{-0.258265f,-0.166953f,0.295997f}, -{-0.242253f,-0.166612f,0.300723f},{-0.222999f,-0.166676f,0.300248f},{-0.203714f,-0.166805f,0.298601f}, -{-0.190859f,-0.167011f,0.296016f},{-0.181155f,-0.167435f,0.290428f},{-0.16513f,-0.167892f,0.284531f}, -{-0.145748f,-0.167429f,0.290029f},{-0.126636f,-0.167358f,0.29093f},{-0.107286f,-0.16811f,0.281476f}, -{-0.0915051f,-0.168207f,0.282132f},{-0.0812225f,-0.16667f,0.297444f},{-0.336269f,0.43371f,-0.360361f}, -{-0.460194f,-0.0583197f,0.0643581f},{-0.442053f,-0.0419022f,0.0256198f},{-0.46739f,-0.0706922f,0.115688f}, -{-0.437983f,-0.0187454f,0.0340954f},{-0.457654f,0.0156908f,0.0572972f},{0.290991f,0.0614128f,0.172091f}, -{0.214742f,-0.166014f,0.341918f},{-0.0160863f,0.102318f,0.155519f},{-0.19774f,0.0611749f,0.198425f}, -{-0.359625f,0.0961448f,0.352092f},{-0.288039f,0.321392f,-0.205775f},{-0.355407f,0.293135f,0.0276068f}, -{0.188698f,0.125179f,0.147976f},{0.154262f,0.138607f,0.0940549f},{-0.427314f,-0.0734253f,-0.0193563f}, -{0.0803543f,0.0910968f,0.226983f},{-0.411167f,0.2732f,0.208296f},{-0.338648f,0.35368f,-0.102029f}, -{-0.0346195f,-0.146696f,0.362464f},{-0.312951f,-0.162529f,0.294518f},{-0.287312f,-0.162586f,0.294827f}, -{0.0412044f,0.120472f,0.0201666f},{-0.316572f,0.433407f,-0.377158f},{-0.453796f,-0.0718498f,0.0387576f}, -{-0.0511013f,-0.0979711f,-0.165281f},{0.0969969f,0.13352f,0.0388605f},{-0.0171667f,-0.152555f,0.373692f}, -{0.00208029f,-0.152355f,0.37629f},{0.0213466f,-0.152265f,0.377435f},{0.040645f,-0.152239f,0.377911f}, -{0.0599627f,-0.152227f,0.377975f},{0.0792225f,-0.15222f,0.377821f},{0.0985274f,-0.152207f,0.37757f}, -{0.117826f,-0.152175f,0.377834f},{0.13715f,-0.152317f,0.376425f},{0.154892f,-0.152966f,0.372168f}, -{0.060117f,-0.116163f,-0.218372f},{0.31025f,0.043169f,0.171075f},{-0.390357f,0.0435742f,0.33777f}, -{-0.200421f,0.0423909f,0.216038f},{-0.184435f,0.0424231f,0.216263f},{-0.373863f,0.291676f,0.0576702f}, -{0.398563f,-0.112672f,0.0948651f},{0.284779f,0.036822f,-0.0329957f},{-0.356718f,0.368072f,-0.127121f}, -{0.362004f,-0.11354f,-0.0547699f},{0.37592f,-0.0959776f,0.184907f},{-0.352371f,0.329661f,-0.0511109f}, -{-0.350416f,0.349609f,-0.0879136f},{-0.335491f,0.306376f,-0.0183081f},{-0.144269f,0.413292f,-0.0335102f}, -{-0.323736f,-0.150741f,0.292306f},{-0.31508f,-0.147416f,0.296183f},{-0.300141f,-0.148715f,0.298659f}, -{-0.280882f,-0.148703f,0.298859f},{-0.261558f,-0.148896f,0.296454f},{-0.242253f,-0.1486f,0.300537f}, -{-0.222999f,-0.148433f,0.302981f},{-0.203739f,-0.148516f,0.301894f},{-0.187541f,-0.148992f,0.29583f}, -{-0.17792f,-0.149333f,0.291303f},{-0.165162f,-0.149828f,0.285136f},{-0.14578f,-0.149487f,0.289341f}, -{-0.126507f,-0.149468f,0.289354f},{-0.107247f,-0.149706f,0.285361f},{-0.0910871f,-0.149449f,0.289058f}, -{-0.0810617f,-0.15332f,0.29628f},{0.0787981f,0.131018f,0.0376194f},{0.135594f,0.138047f,0.0597023f}, -{-0.0820135f,0.450468f,-0.0409954f},{0.301183f,0.0536382f,0.169024f},{-0.485132f,0.0616443f,0.282312f}, -{0.212131f,-0.149873f,0.339121f},{0.232433f,-0.146503f,0.328195f},{0.248754f,-0.148066f,0.325469f}, -{-0.340905f,-0.186457f,0.272332f},{-0.0107617f,0.0523713f,0.2385f},{0.0427671f,0.0982798f,-0.035986f}, -{-0.0806887f,-0.12606f,-0.173506f},{0.382197f,-0.0955403f,0.172059f},{0.355509f,-0.0540304f,-0.0333044f}, -{-0.041063f,0.458423f,-0.0611106f},{-0.406119f,-0.0569306f,0.221491f},{-0.445584f,-0.111585f,0.0194849f}, -{-0.467069f,-0.0925436f,0.0965628f},{-0.495499f,0.115353f,0.154947f},{-0.44869f,-0.00164623f,0.0768464f}, -{-0.392023f,0.306074f,-0.111411f},{-0.076496f,-0.147506f,0.303444f},{0.174756f,0.134362f,0.0740491f}, -{0.193958f,0.128851f,0.0764992f},{0.202891f,0.125372f,0.0889489f},{-0.0161249f,-0.128883f,0.364271f}, -{-0.0108711f,-0.139282f,0.370477f},{0.00423457f,-0.13323f,0.372734f},{0.0213594f,-0.130105f,0.374708f}, -{0.0406514f,-0.130099f,0.374599f},{0.0599434f,-0.134394f,0.377383f},{0.0792675f,-0.130028f,0.37503f}, -{0.0985466f,-0.130182f,0.372824f},{0.116559f,-0.135539f,0.372322f},{0.137111f,-0.139237f,0.371872f}, -{0.156403f,-0.130774f,0.363783f},{0.175573f,-0.130221f,0.358779f},{-0.184473f,0.336015f,0.0502106f}, -{-0.461281f,-0.0544227f,0.13352f},{-0.355394f,0.323424f,-0.246577f},{-0.451744f,-0.00167199f,0.0960677f}, -{-0.488778f,0.0948844f,0.0762548f},{0.0491334f,0.377615f,-0.128253f},{-0.290123f,0.281174f,-0.147828f}, -{-0.316212f,0.293643f,0.0745378f},{-0.0885084f,0.00246939f,-0.107488f},{-0.245648f,0.267271f,0.188579f}, -{-0.35522f,-0.131314f,0.277071f},{-0.3365f,-0.131655f,0.284145f},{-0.0710685f,0.0887624f,-0.000945289f}, -{-0.0934343f,0.0889425f,-0.00949164f},{-0.322739f,-0.130086f,0.292222f},{-0.315183f,-0.132356f,0.295907f}, -{-0.300141f,-0.130523f,0.300273f},{-0.280882f,-0.130414f,0.301405f},{-0.261577f,-0.1306f,0.299547f}, -{-0.242304f,-0.1306f,0.29927f},{-0.223006f,-0.130626f,0.299257f},{-0.20372f,-0.130697f,0.297836f}, -{-0.190917f,-0.135443f,0.295482f},{-0.182994f,-0.130414f,0.289052f},{-0.165085f,-0.131719f,0.284235f}, -{-0.145838f,-0.131475f,0.287598f},{-0.126507f,-0.131237f,0.289669f},{-0.107228f,-0.135597f,0.291778f}, -{-0.0879168f,-0.13098f,0.293013f},{-0.0879425f,-0.130915f,0.294621f},{-0.0714736f,-0.130446f,0.305527f}, -{0.23069f,0.113077f,0.0939777f},{-0.00217037f,-0.124543f,0.368593f},{0.119446f,-0.123707f,0.368496f}, -{0.137131f,-0.126099f,0.365795f},{0.115916f,-0.127546f,-0.208752f},{0.0421819f,0.35959f,-0.110189f}, -{0.231108f,-0.129925f,0.322504f},{0.252638f,-0.130735f,0.320858f},{-0.345188f,0.0937848f,0.351076f}, -{0.335356f,0.013035f,0.165834f},{0.271017f,0.0599081f,-0.0193498f},{-0.298412f,0.278538f,0.223858f}, -{-0.328951f,0.294306f,-0.000379391f},{-0.418363f,-0.014051f,-0.00224428f},{-0.4484f,-0.0194592f,0.076885f}, -{-0.45278f,0.173801f,0.037285f},{-0.107222f,-0.126234f,0.295116f},{0.24287f,0.106646f,0.0991222f}, -{0.286901f,0.0755024f,0.11489f},{0.276155f,0.0845375f,0.111495f},{0.0599434f,-0.116639f,0.373654f}, -{0.189489f,-0.132259f,0.354304f},{0.100566f,0.0614064f,-0.078184f},{-0.320572f,0.340767f,-0.359242f}, -{-0.336127f,0.0973602f,0.345577f},{0.392601f,-0.0814186f,0.0563262f},{-0.475049f,0.0359538f,0.206598f}, -{-0.202871f,0.0996367f,-0.0388219f},{-0.316951f,0.284415f,0.00184562f},{-0.277454f,0.294537f,0.0929809f}, -{-0.411881f,0.0543841f,-0.0163403f},{-0.354937f,-0.114202f,0.277496f},{-0.338848f,-0.113758f,0.281329f}, -{-0.319877f,-0.114202f,0.288807f},{-0.298855f,-0.113508f,0.297515f},{-0.280856f,-0.11235f,0.300833f}, -{-0.26159f,-0.112273f,0.301514f},{-0.242311f,-0.112556f,0.297701f},{-0.221404f,-0.115038f,0.294524f}, -{-0.207964f,-0.111225f,0.295174f},{-0.199309f,-0.114434f,0.292441f},{-0.184338f,-0.113205f,0.288563f}, -{-0.165117f,-0.11352f,0.284197f},{-0.145799f,-0.113373f,0.28655f},{-0.130745f,-0.114434f,0.292351f}, -{-0.122173f,-0.111205f,0.295257f},{-0.107202f,-0.112594f,0.296164f},{-0.0895438f,-0.110395f,0.295277f}, -{-0.0847208f,-0.11736f,0.293862f},{-0.0688177f,-0.113231f,0.299566f},{0.314353f,0.048365f,0.130472f}, -{0.296232f,0.0672069f,0.114408f},{0.00345646f,-0.109315f,0.363069f},{0.0200218f,-0.107328f,0.365249f}, -{0.0278029f,-0.112376f,0.370966f},{0.0406385f,-0.112299f,0.371165f},{0.0792482f,-0.112266f,0.371261f}, -{0.0921224f,-0.112318f,0.369847f},{0.0998071f,-0.107225f,0.367133f},{0.117819f,-0.108222f,0.364914f}, -{0.137118f,-0.108517f,0.359686f},{0.154744f,-0.111231f,0.353577f},{0.169187f,-0.113726f,0.351455f}, -{0.176898f,-0.108588f,0.347018f},{-0.467133f,0.174959f,0.210861f},{0.231218f,-0.113398f,0.318016f}, -{0.251828f,-0.112318f,0.316897f},{-0.359857f,0.393962f,-0.302936f},{-0.208434f,0.229272f,0.0730202f}, -{-0.358165f,0.219794f,0.298222f},{-0.088547f,0.37865f,-0.0349249f},{-0.24251f,0.327996f,0.0392592f}, -{-0.463049f,-0.112775f,0.153268f},{-0.438703f,0.274789f,0.168599f},{0.165303f,0.106826f,0.204071f}, -{-0.453513f,-0.111006f,0.0386933f},{-0.306514f,-0.108421f,0.293007f},{-0.226227f,-0.108337f,0.293045f}, -{0.333002f,0.0246938f,0.134394f},{0.347587f,0.00345971f,0.133533f},{0.338957f,0.0162631f,0.133475f}, -{0.0406707f,-0.103675f,0.367075f},{0.0599434f,-0.103566f,0.367712f},{0.0792289f,-0.103592f,0.367641f}, -{0.159477f,-0.104897f,0.348362f},{-0.290444f,0.419639f,-0.358619f},{-0.108759f,0.0726922f,0.186817f}, -{-0.265885f,0.250294f,0.225896f},{-0.335877f,0.29619f,0.167975f},{0.0435195f,-0.0766727f,0.33979f}, -{-0.186865f,-0.0281727f,-0.11972f},{-0.352957f,-0.0965949f,0.276917f},{-0.338732f,-0.0955661f,0.281258f}, -{-0.319453f,-0.0954246f,0.283238f},{-0.301447f,-0.0940806f,0.28956f},{-0.29364f,-0.0991994f,0.295386f}, -{-0.28083f,-0.0990579f,0.297534f},{-0.261596f,-0.0989743f,0.298177f},{-0.24878f,-0.0991415f,0.296164f}, -{-0.241012f,-0.0939198f,0.291701f},{-0.226195f,-0.0947751f,0.292621f},{-0.216536f,-0.0945114f,0.296106f}, -{-0.206923f,-0.0944471f,0.296865f},{-0.197109f,-0.0947172f,0.293367f},{-0.184235f,-0.0950259f,0.288338f}, -{-0.165072f,-0.0954438f,0.282718f},{-0.145786f,-0.0953667f,0.28421f},{-0.127684f,-0.0940548f,0.290788f}, -{-0.120019f,-0.0992058f,0.29446f},{-0.105929f,-0.0954053f,0.296241f},{-0.0879361f,-0.0943121f,0.298826f}, -{-0.069956f,-0.0952252f,0.298318f},{-0.0487605f,-0.0967557f,0.301926f},{-0.181438f,0.136401f,0.0929488f}, -{-0.0902769f,0.101141f,0.113881f},{0.0040931f,-0.0975982f,0.353577f},{0.0213594f,-0.0953667f,0.354574f}, -{0.0420018f,-0.0918363f,0.357538f},{0.0599562f,-0.0907559f,0.35831f},{0.0792354f,-0.0907495f,0.358773f}, -{0.0985145f,-0.0908138f,0.358329f},{0.117716f,-0.0909424f,0.355905f},{0.133748f,-0.0955853f,0.354484f}, -{0.138578f,-0.0892833f,0.347783f},{0.156268f,-0.0918363f,0.341719f},{0.173933f,-0.0944986f,0.336664f}, -{0.19156f,-0.0969615f,0.333533f},{-0.26022f,0.285888f,0.170528f},{0.213739f,-0.0920099f,0.319154f}, -{0.233475f,-0.093296f,0.314524f},{0.251166f,-0.0991415f,0.313752f},{-0.374191f,0.0666924f,0.352407f}, -{-0.451043f,-0.0192405f,0.0961448f},{-0.332269f,-0.219575f,0.259066f},{0.16922f,0.0707759f,0.240893f}, -{0.338417f,-0.0910389f,-0.0671361f},{0.346854f,-0.0555995f,0.209562f},{0.261487f,0.087174f,0.165654f}, -{0.0286261f,0.125449f,0.0756375f},{-0.129755f,0.108183f,0.00322178f},{-0.392241f,0.283785f,0.039973f}, -{-0.228768f,0.249053f,0.13489f},{-0.447918f,0.154857f,0.0198f},{-0.28085f,-0.0902543f,0.293039f}, -{-0.26159f,-0.0902672f,0.292994f},{-0.11362f,-0.0901707f,0.293765f},{-0.0622456f,-0.0902736f,0.291688f}, -{-0.0538922f,-0.0907688f,0.293026f},{0.134308f,-0.0709559f,0.325321f},{-0.470091f,0.152883f,0.210977f}, -{0.0999292f,-0.0751423f,0.343082f},{0.00420885f,-0.0888267f,0.342671f},{0.0204013f,-0.0871612f,0.346156f}, -{0.0343429f,-0.0868396f,0.348561f},{0.178763f,-0.0881322f,0.330054f},{0.19646f,-0.0908845f,0.326806f}, -{0.253796f,-0.0897463f,0.309816f},{0.156384f,0.070808f,0.241735f},{-0.468966f,0.0231054f,0.152175f}, -{0.280695f,0.0716119f,0.166708f},{-0.357554f,0.245761f,-0.184843f},{0.374049f,-0.0370535f,0.0402302f}, -{-0.186544f,-0.115649f,-0.13042f},{-0.335002f,0.0190412f,-0.0548728f},{-0.162197f,0.122311f,0.0764606f}, -{-0.354558f,-0.0732066f,0.268615f},{-0.337439f,-0.0784991f,0.277329f},{-0.319511f,-0.0774187f,0.27992f}, -{-0.300167f,-0.0772065f,0.283534f},{-0.280869f,-0.0770072f,0.286615f},{-0.261596f,-0.0769043f,0.287316f}, -{-0.242278f,-0.0769107f,0.287534f},{-0.222974f,-0.0768271f,0.289772f},{-0.20372f,-0.0766727f,0.290885f}, -{-0.18439f,-0.0770264f,0.285644f},{-0.16513f,-0.0773223f,0.281798f},{-0.145883f,-0.0773737f,0.280351f}, -{-0.126475f,-0.0771165f,0.285656f},{-0.108514f,-0.0758368f,0.290955f},{-0.100752f,-0.0810135f,0.295367f}, -{-0.0879618f,-0.0809556f,0.29655f},{-0.0686634f,-0.0767049f,0.291386f},{-0.0557764f,-0.081052f,0.293881f}, -{-0.050201f,-0.0766663f,0.296762f},{-0.0362336f,-0.0759976f,0.29799f},{0.40091f,-0.245092f,0.150394f}, -{-0.0724446f,0.0829427f,0.152985f},{0.402138f,-0.256538f,0.157493f},{-0.490245f,0.0784348f,0.246738f}, -{-0.210395f,0.208585f,0.0772065f},{-0.292573f,0.346523f,-0.263657f},{0.134423f,-0.0784412f,0.33788f}, -{0.156352f,-0.0750201f,0.324215f},{0.175657f,-0.0749815f,0.322626f},{0.194833f,-0.0749622f,0.319424f}, -{0.212852f,-0.0760747f,0.314954f},{0.227038f,-0.0798431f,0.313025f},{0.234697f,-0.0746085f,0.310575f}, -{0.250323f,-0.0727565f,0.304672f},{0.0985466f,0.0534002f,0.261689f},{-0.16412f,0.0707566f,0.18865f}, -{-0.316167f,0.149918f,-0.0431754f},{-0.390055f,0.201903f,0.312916f},{-0.377869f,0.291637f,-0.000598033f}, -{0.117048f,0.126986f,0.171859f},{0.228131f,0.107681f,0.147397f},{-0.298328f,0.289502f,0.188965f}, -{-0.171721f,0.126465f,0.0792193f},{-0.394267f,0.293843f,0.118659f},{-0.368435f,0.269805f,-0.18838f}, -{-0.343079f,-0.0673612f,0.271503f},{-0.0879618f,-0.0721327f,0.292659f},{-0.0188386f,-0.0762934f,0.300775f}, -{-0.431944f,0.281341f,0.151494f},{-0.319935f,0.295103f,0.0825183f},{-0.449281f,0.0184367f,0.188753f}, -{-0.495003f,0.077213f,0.174181f},{-0.299055f,0.379898f,-0.382258f},{-0.454696f,-0.0543648f,0.153725f}, -{-0.393733f,0.325218f,-0.129874f},{-0.373265f,-0.262551f,0.170258f},{-0.291672f,0.307296f,-0.114421f}, -{0.0441111f,0.40254f,-0.166966f},{-0.468316f,-0.114234f,0.0966721f},{0.220575f,-0.0708402f,0.312273f}, -{-0.351915f,0.39645f,-0.316678f},{-0.262812f,-0.285476f,0.229433f},{0.35421f,-0.0017234f,0.0884666f}, -{-0.205791f,-0.115848f,-0.128941f},{0.0423748f,-0.0679528f,0.322678f},{-0.112154f,0.0929166f,-0.0174592f}, -{-0.338815f,-0.0536574f,0.266815f},{-0.318192f,-0.0603067f,0.277399f},{-0.300148f,-0.0547378f,0.279798f}, -{-0.280869f,-0.0545706f,0.282075f},{-0.261583f,-0.0544162f,0.28419f},{-0.242285f,-0.0545127f,0.282068f}, -{-0.223012f,-0.0546413f,0.279824f},{-0.202794f,-0.0572007f,0.28174f},{-0.184409f,-0.0545899f,0.280403f}, -{-0.16585f,-0.0558438f,0.278448f},{-0.145844f,-0.0640237f,0.276596f},{-0.126539f,-0.059355f,0.278518f}, -{-0.106437f,-0.0557217f,0.281663f},{-0.0879618f,-0.0543713f,0.284711f},{-0.069538f,-0.056847f,0.288081f}, -{-0.0525224f,-0.0628726f,0.294936f},{-0.0349024f,-0.0605189f,0.295386f},{-0.0236681f,-0.0628726f,0.295888f}, -{-0.0159191f,-0.0575223f,0.291746f},{0.00101924f,-0.0573551f,0.29255f},{0.0210186f,-0.0616893f,0.296447f}, -{0.037121f,-0.0612199f,0.300068f},{0.0586637f,-0.0628147f,0.316852f},{-0.336025f,-0.204122f,0.266287f}, -{-0.467313f,0.0428668f,0.0391242f},{-0.225179f,0.228018f,0.115655f},{0.117453f,-0.0579981f,0.303013f}, -{0.137375f,-0.0581846f,0.304575f},{0.154191f,-0.0535481f,0.307862f},{0.159882f,-0.0619465f,0.315077f}, -{0.177039f,-0.058146f,0.316704f},{0.193579f,-0.0581074f,0.315887f},{0.207572f,-0.0610977f,0.313475f}, -{0.215424f,-0.0565769f,0.310035f},{0.231745f,-0.0562232f,0.30453f},{0.137086f,0.0706859f,0.241111f}, -{-0.378223f,0.24814f,-0.0724864f},{-0.335221f,0.135822f,-0.0458699f},{-0.399457f,-0.0121604f,-0.0235491f}, -{-0.0535578f,0.379184f,-0.110112f},{-0.373367f,-0.0371435f,-0.0575544f},{-0.341786f,0.0280763f,0.335539f}, -{-0.308058f,0.311559f,-0.0721327f},{-0.401502f,0.251773f,0.254165f},{-0.373033f,-0.0535931f,0.248455f}, -{-0.35549f,-0.055876f,0.259921f},{-0.321003f,-0.0483972f,0.272152f},{-0.145857f,-0.0505321f,0.271638f}, -{-0.0525482f,-0.0540433f,0.291367f},{-0.0397254f,-0.0538568f,0.293502f},{0.0228385f,-0.0523263f,0.291245f}, -{-0.30326f,0.295431f,0.163101f},{0.0406771f,-0.0539018f,0.293322f},{0.0602585f,-0.0515353f,0.292653f}, -{-0.457262f,-0.0493746f,0.141185f},{0.0962509f,-0.0508729f,0.29354f},{0.101492f,-0.0563455f,0.300158f}, -{0.169477f,-0.0530979f,0.3128f},{0.201296f,-0.0528472f,0.312299f},{0.117749f,0.053233f,0.260467f}, -{0.390685f,-0.111643f,0.156985f},{-0.475345f,0.161223f,0.114472f},{-0.261197f,0.288878f,0.151693f}, -{-0.0545738f,0.307116f,-0.00269443f},{0.136841f,0.127707f,0.169808f},{-0.361349f,-0.0472461f,0.253355f}, -{-0.206948f,-0.0458634f,0.274229f},{-0.158558f,-0.0459149f,0.272531f},{-0.126572f,-0.0460757f,0.271059f}, -{-0.113704f,-0.0459535f,0.273689f},{-0.0673773f,-0.0400694f,0.280814f},{-0.0525675f,-0.0362882f,0.28356f}, -{-0.0365037f,-0.036121f,0.286338f},{-0.0172245f,-0.0361146f,0.28664f},{0.00206101f,-0.0360632f,0.286518f}, -{0.0208578f,-0.0357095f,0.289142f},{-0.392351f,0.292659f,0.0961898f},{0.0406771f,-0.0358573f,0.29028f}, -{0.0598984f,-0.035285f,0.291958f},{0.0781615f,-0.0362239f,0.293122f},{-0.475621f,0.174612f,0.133687f}, -{0.0998392f,-0.0348349f,0.29282f},{0.117716f,-0.0360889f,0.289277f},{0.136314f,-0.0352207f,0.285862f}, -{0.14387f,-0.045259f,0.296479f},{0.160956f,-0.0419407f,0.299695f},{0.17583f,-0.0401852f,0.302826f}, -{0.194936f,-0.0400952f,0.303386f},{0.214118f,-0.040243f,0.299997f},{0.400627f,-0.130632f,0.0948716f}, -{0.332828f,0.00700302f,-0.00363974f},{-0.330687f,0.0772065f,0.348323f},{-0.437873f,-0.0194528f,0.157249f}, -{-0.294431f,0.286209f,-0.0771293f},{-0.29355f,0.247529f,-0.0371885f},{0.0945532f,0.12343f,0.178676f}, -{-0.0610366f,0.0857529f,0.151423f},{-0.407038f,0.27657f,0.20301f},{-0.373811f,-0.0350985f,0.244642f}, -{-0.356866f,-0.0345455f,0.252011f},{-0.337137f,-0.0355423f,0.258706f},{-0.319485f,-0.0328349f,0.264853f}, -{-0.300148f,-0.032597f,0.270011f},{-0.282489f,-0.0302112f,0.270975f},{-0.277653f,-0.036822f,0.27556f}, -{-0.261583f,-0.0366419f,0.276969f},{-0.245507f,-0.0366934f,0.275818f},{-0.240671f,-0.0301212f,0.271554f}, -{-0.223006f,-0.0325391f,0.269052f},{-0.203727f,-0.0325648f,0.269348f},{-0.184435f,-0.0366419f,0.276364f}, -{-0.171515f,-0.0366676f,0.276287f},{-0.163728f,-0.0314395f,0.270943f},{-0.145728f,-0.0327385f,0.26304f}, -{-0.126591f,-0.0328221f,0.263175f},{-0.107337f,-0.0325198f,0.26794f},{-0.087949f,-0.0367898f,0.27574f}, -{0.0959036f,-0.034224f,0.294183f},{0.155201f,-0.0310601f,0.28484f},{0.232279f,-0.0337417f,0.288016f}, -{-0.13297f,0.0688852f,0.199402f},{0.391347f,-0.0905115f,0.120575f},{-0.222125f,0.188631f,0.0190476f}, -{-0.327948f,-0.150542f,-0.104074f},{-0.315054f,-0.145494f,-0.109051f},{-0.341986f,-0.0289958f,0.25367f}, -{-0.261596f,-0.0278126f,0.27212f},{-0.184415f,-0.0277805f,0.272699f},{-0.0880004f,-0.0278705f,0.270538f}, -{-0.0686055f,-0.0279026f,0.273438f},{0.0856082f,-0.0265715f,0.29401f},{0.17585f,-0.0274011f,0.289965f}, -{0.194974f,-0.0273303f,0.290267f},{0.214189f,-0.027311f,0.287695f},{0.194672f,0.06612f,0.235484f}, -{0.267969f,-0.0357545f,0.266493f},{-0.466728f,0.262821f,0.150381f},{0.385425f,-0.13188f,-0.0206167f}, -{0.389643f,-0.0724414f,0.075586f},{-0.281467f,0.0204109f,0.24486f},{-0.261525f,0.0205717f,0.241574f}, -{-0.310392f,0.290357f,-0.0356644f},{-0.145876f,0.111668f,0.115758f},{-0.432285f,0.0749429f,-0.0124433f}, -{-0.313697f,0.378174f,-0.37222f},{-0.167541f,-0.0280248f,-0.121835f},{-0.354661f,-0.0164046f,0.251362f}, -{-0.337542f,-0.0145526f,0.251555f},{-0.319485f,-0.0195621f,0.258197f},{-0.300148f,-0.0149705f,0.260056f}, -{-0.280862f,-0.014887f,0.261554f},{-0.261596f,-0.0147005f,0.263207f},{-0.242291f,-0.0145526f,0.263927f}, -{-0.222999f,-0.0146362f,0.261291f},{-0.203733f,-0.0146362f,0.263233f},{-0.184415f,-0.0144947f,0.265516f}, -{-0.164975f,-0.0144047f,0.263085f},{-0.148789f,-0.0191891f,0.257831f},{-0.144102f,-0.0126362f,0.253651f}, -{-0.127877f,-0.0141346f,0.253747f},{-0.120244f,-0.0194013f,0.257014f},{-0.106038f,-0.0157037f,0.259406f}, -{-0.0880133f,-0.0146104f,0.26248f},{-0.0687213f,-0.0144304f,0.26585f},{-0.0526189f,-0.0141989f,0.271464f}, -{-0.0365165f,-0.018411f,0.27801f},{-0.0172053f,-0.0138709f,0.278679f},{0.00208029f,-0.0137295f,0.280505f}, -{0.0214173f,-0.0134787f,0.285586f},{0.0407221f,-0.01335f,0.287695f},{0.0600013f,-0.0131635f,0.291328f}, -{0.0792225f,-0.0131957f,0.29118f},{0.0985016f,-0.0144626f,0.289393f},{0.117729f,-0.0134851f,0.284865f}, -{0.137124f,-0.0134915f,0.279895f},{0.154763f,-0.016321f,0.275908f},{0.17574f,-0.0187775f,0.277612f}, -{0.195f,-0.0187132f,0.281303f},{0.214209f,-0.0186554f,0.279039f},{0.232587f,-0.022443f,0.277393f}, -{0.234607f,-0.0142053f,0.268654f},{0.25132f,-0.0183917f,0.265387f},{0.269866f,-0.0204881f,0.259439f}, -{-0.120006f,0.380965f,0.00785186f},{0.372056f,-0.0647696f,-0.00768462f},{-0.243892f,0.0184367f,0.240076f}, -{-0.239089f,0.0251375f,0.2358f},{-0.0170766f,0.0842352f,0.193164f},{-0.263885f,0.147224f,-0.0295231f}, -{-0.18664f,-0.0739912f,-0.129475f},{0.000311863f,0.455419f,-0.155603f},{-0.150854f,0.281258f,-0.0423073f}, -{0.20698f,-0.0177743f,-0.10689f},{-0.319511f,-0.0106427f,0.254622f},{-0.113922f,-0.0103469f,0.254899f}, -{-0.0365615f,-0.00949807f,0.273014f},{0.159561f,-0.00969741f,0.272583f},{0.175689f,-0.00992251f,0.269599f}, -{0.195f,-0.00995464f,0.272146f},{0.214221f,-0.00994179f,0.270396f},{0.394685f,-0.113077f,0.0178708f}, -{0.400666f,-0.148715f,0.114189f},{-0.222929f,0.0250667f,0.234173f},{-0.475608f,0.112221f,0.0505772f}, -{0.077692f,-0.019337f,-0.134529f},{-0.316244f,0.168773f,-0.0416707f},{-0.110032f,0.377866f,-0.0883573f}, -{-0.296997f,0.14986f,-0.0396772f},{-0.315826f,0.0936369f,-0.0470403f},{0.190602f,-0.0323334f,-0.116961f}, -{0.0620462f,-0.0157037f,-0.135423f},{-0.20372f,0.0249639f,0.233382f},{-0.111054f,0.321475f,-0.0743384f}, -{-0.316868f,0.0550658f,-0.0475161f},{-0.337446f,-0.0023536f,0.255272f},{-0.318115f,0.00142761f,0.253362f}, -{-0.299672f,0.00104178f,0.252127f},{-0.280965f,0.00269444f,0.250243f},{-0.26159f,0.00277804f,0.250114f}, -{-0.242298f,0.00290668f,0.250043f},{-0.223019f,0.00295167f,0.25086f},{-0.205019f,0.00393556f,0.251522f}, -{-0.197296f,-0.00129897f,0.256673f},{-0.187644f,-0.0012604f,0.256731f},{-0.182808f,0.00538888f,0.250545f}, -{-0.165053f,0.00322176f,0.250944f},{-0.145741f,0.00293882f,0.246532f},{-0.126552f,0.00269444f,0.244899f}, -{-0.107318f,0.0028745f,0.247227f},{-0.0880004f,0.00292596f,0.24967f},{-0.070374f,0.00535674f,0.250912f}, -{-0.0655895f,-0.00108035f,0.257329f},{-0.0516415f,0.00210285f,0.261696f},{-0.0365937f,0.00380054f,0.265612f}, -{-0.0172245f,0.00390985f,0.270017f},{0.000485494f,0.00627631f,0.272699f},{0.00534707f,-0.000321504f,0.277117f}, -{0.0214173f,0.00432143f,0.27902f},{0.0407607f,0.00445003f,0.282512f},{0.0600077f,0.00450149f,0.284499f}, -{0.0792675f,0.00448859f,0.284557f},{0.0985081f,0.00456576f,0.284165f},{0.117723f,0.00455291f,0.283419f}, -{0.138642f,0.00290668f,0.279039f},{0.156853f,0.00437928f,0.2714f},{0.175657f,0.00355616f,0.265027f}, -{0.194974f,0.0035176f,0.265368f},{0.214241f,0.00346614f,0.263342f},{0.231874f,0.000932473f,0.260339f}, -{0.24642f,-0.00137614f,0.257316f},{0.252175f,0.00538245f,0.251587f},{0.26894f,0.00381982f,0.247175f}, -{0.322064f,-0.0572007f,0.2416f},{-0.291949f,0.326305f,-0.244404f},{0.269679f,-0.0710202f,-0.116948f}, -{-0.216819f,0.248796f,-0.00958167f},{-0.0730684f,-0.0932189f,-0.147172f},{-0.354384f,0.00255942f,0.286846f}, -{-0.148301f,-0.0143211f,-0.117212f},{-0.167258f,-0.115186f,-0.135996f},{-0.202228f,0.26403f,-0.0192791f}, -{-0.240812f,0.26194f,-0.00583259f},{-0.321658f,-0.108916f,-0.100903f},{-0.406144f,-0.109861f,-0.0514581f}, -{-0.184435f,0.0248224f,0.232462f},{-0.0559564f,0.00782613f,0.254391f},{0.236787f,0.00754962f,0.253677f}, -{-0.471461f,0.153892f,0.192476f},{0.354989f,-0.0195428f,0.165815f},{-0.0901997f,-0.0957333f,-0.143802f}, -{-0.354236f,0.000160776f,-0.0532459f},{0.134655f,-0.0128999f,-0.11999f},{-0.22026f,0.262988f,-0.0135172f}, -{-0.0951127f,0.335848f,-0.0834057f},{-0.0741166f,-0.106421f,-0.153333f},{-0.377425f,0.102852f,0.350574f}, -{-0.223025f,0.0160702f,0.241124f},{-0.203733f,0.0163467f,0.240127f},{-0.184435f,0.0163724f,0.239883f}, -{-0.165117f,0.0162567f,0.239793f},{-0.145761f,0.0162889f,0.238417f},{-0.100932f,0.0162567f,0.237523f}, -{-0.0880326f,0.0161667f,0.238951f},{-0.0687277f,0.0162567f,0.242089f},{-0.186582f,-0.0970837f,-0.130993f}, -{-0.205849f,-0.0971673f,-0.131198f},{-0.225983f,-0.0937719f,-0.131147f},{-0.244613f,-0.0927558f,-0.129166f}, -{0.0436095f,-0.0169962f,-0.133642f},{-0.408382f,0.166136f,-0.0139224f},{-0.148024f,-0.0964985f,-0.136401f}, -{-0.167329f,-0.09673f,-0.134388f},{-0.0181698f,-0.468686f,0.352194f},{-0.0138485f,-0.474975f,0.347751f}, -{-0.277743f,0.131031f,-0.0370406f},{-0.392981f,0.111701f,-0.0340182f},{-0.36958f,-0.147365f,-0.0868654f}, -{-0.335568f,-0.145288f,-0.100267f},{-0.244214f,-0.153127f,-0.128105f},{-0.0341115f,0.355397f,-0.101212f}, -{0.0795183f,-0.471322f,0.319308f},{-0.205611f,-0.152838f,-0.129764f},{-0.354609f,0.168599f,-0.0385261f}, -{-0.27928f,0.0571686f,0.270982f},{0.28728f,0.037973f,0.209768f},{-0.196344f,0.15885f,0.115514f}, -{-0.0909392f,0.321437f,-0.0765248f},{-0.411855f,0.0734253f,-0.021562f},{-0.0920967f,0.359847f,-0.0930324f}, -{0.00476189f,0.378239f,-0.128079f},{-0.257673f,0.263824f,0.00112538f},{-0.337176f,0.294003f,0.179235f}, -{0.193759f,-0.468075f,0.296003f},{0.203868f,-0.464377f,0.29401f},{0.226909f,-0.464377f,0.281824f}, -{0.232439f,-0.471187f,0.268165f},{-0.223359f,0.0587248f,0.226636f},{0.337877f,-0.0567763f,0.223099f}, -{0.283409f,-0.0394521f,0.260898f},{0.305871f,-0.038674f,0.243973f},{-0.359792f,0.411254f,-0.319675f}, -{-0.316932f,-0.0879393f,-0.100492f},{-0.295357f,0.0945178f,-0.0458249f},{0.0972734f,-0.0184753f,-0.130112f}, -{-0.319999f,0.0210283f,-0.0620752f},{-0.208865f,-0.48248f,0.296756f},{0.281396f,0.0496897f,0.200804f}, -{-0.0529083f,-0.470326f,0.357101f},{-0.0337449f,-0.470204f,0.355718f},{-0.224896f,-0.153005f,-0.128652f}, -{0.00438891f,-0.470583f,0.342085f},{0.0221504f,-0.470403f,0.336041f},{0.0362593f,-0.467927f,0.332909f}, -{0.0427028f,-0.471567f,0.329391f},{-0.263564f,-0.15341f,-0.125424f},{0.0613195f,-0.470731f,0.324369f}, -{0.0817562f,-0.450185f,0.318607f},{0.0937622f,-0.452223f,0.314877f},{-0.305151f,0.0611363f,0.319868f}, -{-0.261365f,0.170676f,0.226269f},{0.154873f,-0.453645f,0.302691f},{0.136127f,-0.0378509f,-0.128311f}, -{0.174036f,-0.45349f,0.29981f},{0.192531f,-0.450294f,0.297367f},{0.207353f,-0.448899f,0.294859f}, -{0.214967f,-0.453947f,0.292145f},{0.229758f,-0.449645f,0.285791f},{0.242529f,-0.450461f,0.277554f}, -{-0.0154175f,0.365416f,-0.0681393f},{-0.220948f,0.0948201f,0.228051f},{-0.00928267f,0.455734f,-0.103862f}, -{-0.298984f,0.267445f,-0.185949f},{0.306624f,-0.11352f,0.283611f},{-0.26986f,-0.102743f,-0.120941f}, -{-0.277705f,-0.108697f,-0.115308f},{-0.203251f,0.266191f,0.0780875f},{0.116006f,-0.473155f,0.309173f}, -{-0.393952f,-0.00196778f,0.282595f},{-0.260201f,-0.0911417f,-0.125533f},{-0.20664f,0.0760426f,0.208784f}, -{0.0097135f,0.476647f,-0.128587f},{-0.207714f,0.11282f,0.207672f},{-0.239873f,0.0960033f,0.249375f}, -{0.0360663f,0.124607f,0.138832f},{-0.112797f,0.338169f,-0.0814507f},{-0.242034f,-0.473245f,0.309964f}, -{-0.22116f,-0.473226f,0.307559f},{-0.200228f,-0.471837f,0.302923f},{-0.185547f,-0.471965f,0.29855f}, -{-0.175104f,-0.46884f,0.296363f},{-0.165863f,-0.473663f,0.29091f},{0.080335f,-0.0869425f,-0.19045f}, -{-0.0541687f,-0.450931f,0.358381f},{-0.0333912f,-0.452834f,0.356625f},{-0.0183178f,-0.453747f,0.352214f}, -{-0.00994504f,-0.450423f,0.349217f},{0.00439533f,-0.451465f,0.343661f},{0.0232372f,-0.450738f,0.337121f}, -{0.035777f,-0.450262f,0.33262f},{0.0452815f,-0.449876f,0.329552f},{0.0613517f,-0.449175f,0.324562f}, -{0.018665f,0.454686f,-0.13352f},{0.311247f,-0.0895276f,0.271033f},{0.271274f,-0.456088f,0.2118f}, -{0.285441f,-0.447471f,0.207325f},{-0.280271f,-0.151236f,-0.117662f},{-0.373528f,0.0931996f,-0.0408604f}, -{-0.292257f,0.000778124f,-0.0879071f},{0.397997f,-0.14896f,0.0178644f},{-0.242124f,0.112556f,0.245175f}, -{-0.261217f,-0.113392f,-0.12716f},{-0.296405f,0.362252f,-0.378322f},{0.115459f,-0.0204816f,-0.125121f}, -{-0.186608f,0.262988f,-0.0231375f},{0.291949f,0.00689366f,0.23196f},{-0.378467f,0.270114f,-0.0726857f}, -{-0.241282f,0.20991f,0.191331f},{-0.266432f,0.214675f,0.220945f},{-0.321922f,0.148928f,0.300318f}, -{-0.225006f,0.150625f,0.207273f},{-0.449828f,0.0165461f,0.208109f},{0.284508f,0.00328608f,0.240012f}, -{-0.427584f,0.278917f,0.17049f},{0.00499982f,0.381267f,-0.0894312f},{-0.0553069f,0.379377f,-0.0579595f}, -{-0.256998f,0.232591f,0.213659f},{0.270477f,-0.112845f,0.308093f},{0.344745f,-0.150709f,-0.0930774f}, -{0.192775f,-0.434263f,0.297823f},{0.209186f,-0.432417f,0.295637f},{0.219372f,-0.431883f,0.293373f}, -{0.231095f,-0.4316f,0.287881f},{0.244581f,-0.431517f,0.279149f},{0.255146f,-0.431465f,0.271811f}, -{0.26494f,-0.432809f,0.261349f},{0.27321f,-0.432964f,0.247317f},{0.285917f,-0.0718819f,0.279567f}, -{0.34805f,-0.0900614f,0.229112f},{0.284939f,-0.431819f,0.227575f},{0.290688f,-0.436957f,0.212559f}, -{-0.0194303f,0.32381f,-0.0228095f},{0.0190058f,0.416668f,-0.11754f},{-0.317016f,0.0406546f,0.324202f}, -{-0.225031f,-0.115771f,-0.13096f},{-0.29591f,-0.108099f,-0.111006f},{-0.128745f,-0.0962477f,-0.138915f}, -{-0.0921482f,0.378952f,-0.0964985f},{-0.257146f,0.212231f,0.213305f},{-0.31108f,0.215099f,0.26967f}, -{0.266625f,0.0558632f,0.208238f},{-0.0705347f,0.303026f,0.00482944f},{-0.160982f,0.264551f,0.0449439f}, -{-0.241436f,-0.45848f,0.31334f},{-0.221925f,-0.453098f,0.308042f},{-0.347986f,0.126401f,-0.0469438f}, -{-0.056741f,0.419929f,-0.059683f},{-0.0377255f,0.417562f,-0.0774766f},{0.00501911f,0.418546f,-0.108415f}, -{-0.108431f,0.360291f,-0.0161152f},{-0.123684f,0.360297f,0.0013183f},{0.118681f,-0.0667567f,0.323301f}, -{-0.0209672f,-0.434443f,0.352278f},{-0.0112955f,-0.434044f,0.34923f},{0.00418956f,-0.433484f,0.343494f}, -{-0.288412f,0.311244f,-0.202566f},{-0.248072f,0.078467f,0.258558f},{-0.239661f,0.0757982f,0.249683f}, -{-0.149638f,0.267715f,0.0368927f},{-0.259879f,0.0952252f,0.267863f},{-0.231166f,0.0767757f,0.241549f}, -{-0.0733899f,0.417614f,-0.038436f},{0.298727f,0.0175557f,0.219131f},{-0.259866f,0.132851f,0.251034f}, -{-0.312057f,0.0155944f,0.265104f},{-0.338449f,0.149506f,0.320871f},{-0.300669f,0.00340824f,-0.0818816f}, -{-0.352905f,-0.0371435f,-0.0703514f},{-0.11135f,0.359725f,-0.0874891f},{-0.109395f,-0.114292f,-0.144587f}, -{-0.244433f,-0.115784f,-0.131648f},{-0.468921f,0.0167261f,0.133224f},{0.366917f,-0.111482f,0.208218f}, -{-0.198383f,0.11336f,0.189576f},{-0.0144787f,0.417626f,-0.0947879f},{-0.221199f,0.0771487f,0.229909f}, -{0.388229f,-0.0951802f,0.152728f},{-0.0728047f,0.360516f,-0.0380631f},{-0.0275329f,0.417562f,-0.0853734f}, -{-0.167503f,0.30617f,0.0426546f},{-0.204106f,0.13197f,0.189602f},{-0.198376f,0.13516f,0.172773f}, -{-0.192216f,0.125488f,0.167673f},{0.361046f,-0.170882f,-0.0731745f},{-0.229083f,0.28365f,0.0875856f}, -{0.358242f,-0.113347f,0.225941f},{-0.319581f,0.0599724f,0.339983f},{-0.0514099f,0.365204f,-0.0523841f}, -{0.268168f,0.0377544f,0.222404f},{-0.223347f,0.267413f,0.095669f},{-0.0961931f,0.384071f,-0.0266679f}, -{-0.112733f,0.380348f,-0.00300953f},{-0.0167101f,0.49093f,-0.096177f},{-0.490592f,0.0611877f,0.262905f}, -{-0.0644706f,0.415916f,-0.0521012f},{-0.0676409f,0.398431f,-0.0530208f},{0.189097f,-0.416366f,0.29518f}, -{0.197984f,-0.414379f,0.292962f},{0.21145f,-0.415858f,0.291116f},{0.230838f,-0.413607f,0.284338f}, -{0.244838f,-0.415363f,0.277721f},{0.254284f,-0.413954f,0.270718f},{0.267223f,-0.413929f,0.261072f}, -{0.277094f,-0.414038f,0.252693f},{0.28557f,-0.413279f,0.244648f},{0.293492f,-0.417189f,0.231073f}, -{0.305878f,-0.416784f,0.212713f},{-0.227327f,0.128941f,0.224642f},{-0.223224f,0.112466f,0.227247f}, -{-0.318803f,0.192f,0.286119f},{-0.101537f,0.393704f,-0.0115687f},{-0.297634f,-0.0333687f,-0.0998939f}, -{0.380833f,-0.409485f,0.203865f},{-0.3536f,-0.14678f,-0.0937976f},{-0.433192f,-0.208842f,0.0983956f}, -{-0.296804f,0.112357f,-0.0439471f},{-0.311974f,-0.108466f,-0.106807f},{0.327903f,-0.112755f,0.266737f}, -{-0.312842f,0.0968265f,0.324909f},{-0.321896f,0.0938169f,0.336722f},{-0.133099f,0.360361f,0.0160252f}, -{-0.182062f,0.285933f,0.0615414f},{0.0271084f,0.458397f,-0.14642f},{-0.0142793f,0.398547f,-0.0889875f}, -{-0.260168f,0.0768786f,0.267303f},{-0.245635f,0.248346f,0.189332f},{-0.255288f,0.250031f,0.207112f}, -{-0.254149f,0.180946f,0.213967f},{-0.0864249f,0.361982f,-0.0313945f},{-0.160506f,0.299064f,0.0497283f}, -{-0.146526f,0.304022f,0.0418829f},{-0.16522f,0.285142f,0.054307f},{0.3565f,-0.0403074f,0.185563f}, -{0.401939f,-0.130542f,0.0756053f},{-0.471544f,0.0158323f,0.0947558f},{-0.214549f,0.188586f,0.0321405f}, -{-0.0324845f,0.379506f,-0.0701778f},{-0.00051769f,0.474737f,-0.113488f},{-0.44822f,-0.0546284f,0.0385583f}, -{-0.246645f,0.0419408f,0.241221f},{-0.339844f,0.168355f,0.316575f},{-0.247905f,0.0936947f,0.258853f}, -{0.301106f,-0.410617f,0.225131f},{-0.277724f,0.15476f,0.247806f},{-0.282046f,0.0767114f,0.280949f}, -{0.402042f,-0.408662f,0.188142f},{0.418954f,-0.410295f,0.170355f},{0.435513f,-0.408321f,0.152812f}, -{0.438639f,-0.413022f,0.133706f},{0.0369602f,0.397331f,-0.12026f},{-0.015006f,0.379615f,-0.0788013f}, -{-0.296013f,0.194772f,0.249735f},{-0.271403f,0.0767499f,0.273618f},{-0.296052f,0.233439f,0.253876f}, -{-0.0931256f,0.358702f,-0.026057f},{0.0373653f,0.416655f,-0.134652f},{0.289987f,-0.0919456f,0.286853f}, -{-0.30328f,0.230276f,0.258461f},{0.289203f,-0.015723f,0.248269f},{-0.302868f,0.212533f,0.260371f}, -{-0.44323f,-0.0558117f,0.0205267f},{-0.192968f,0.266171f,0.0703579f},{0.374203f,-0.082634f,-0.0143404f}, -{0.0159127f,0.46994f,-0.135108f},{0.0217646f,0.378901f,-0.095611f},{0.0231021f,0.473882f,-0.151879f}, -{0.301756f,-0.0208418f,0.240513f},{0.309402f,-0.0145526f,0.228989f},{0.182943f,-0.402064f,0.308781f}, -{0.195637f,-0.397074f,0.30462f},{0.208427f,-0.395601f,0.296775f},{0.216311f,-0.399395f,0.289367f}, -{0.231893f,-0.396225f,0.281206f},{0.2504f,-0.396482f,0.270808f},{0.267165f,-0.396199f,0.261143f}, -{0.278348f,-0.400424f,0.254674f},{0.287988f,-0.395203f,0.249285f},{0.299434f,-0.395974f,0.239967f}, -{0.307318f,-0.396444f,0.228726f},{0.313742f,-0.401936f,0.215215f},{-0.303987f,0.113392f,0.300588f}, -{-0.294502f,0.113173f,0.285811f},{0.31917f,-0.0224945f,0.222327f},{0.400608f,-0.39247f,0.205743f}, -{0.408922f,-0.397061f,0.1951f},{0.420208f,-0.392611f,0.18883f},{0.427822f,-0.397479f,0.177113f}, -{0.439635f,-0.392412f,0.1684f},{0.446156f,-0.399505f,0.150465f},{0.361876f,-0.0899392f,0.208707f}, -{-0.231739f,0.0949937f,0.240803f},{0.22797f,-0.0427896f,0.297444f},{-0.000562705f,0.412919f,-0.102955f}, -{0.208209f,-0.114646f,0.336581f},{0.325954f,-0.0160188f,0.209434f},{-0.229314f,-0.422893f,0.297373f}, -{0.335549f,-0.0257162f,0.204546f},{0.342674f,-0.0180701f,0.189614f},{0.25267f,0.0384875f,0.231658f}, -{-0.247024f,0.193113f,0.203543f},{-0.293878f,0.160278f,0.252693f},{-0.277229f,0.176194f,0.231568f}, -{-0.183457f,0.30354f,0.0561461f},{0.0275457f,0.419292f,-0.126272f},{-0.354101f,0.131256f,0.338709f}, -{0.00573935f,0.343995f,-0.0542169f},{-0.0781551f,0.4f,-0.0418507f},{-0.3189f,0.113263f,0.32172f}, -{-0.146404f,0.283489f,0.0418765f},{-0.334025f,0.0150671f,0.30518f},{-0.00970067f,0.32399f,-0.0313044f}, -{-0.182737f,0.266159f,0.0625575f},{-0.0179705f,0.45576f,-0.0938105f},{-0.000446955f,0.455728f,-0.11372f}, -{-0.320874f,0.213749f,0.28192f},{0.302707f,0.0025787f,0.224906f},{-0.0689592f,0.379358f,-0.0494132f}, -{-0.104206f,0.378342f,-0.0179094f},{-0.1296f,0.268184f,0.0197164f},{0.370371f,-0.0281856f,0.0563133f}, -{0.187129f,-0.392251f,0.315f},{0.316977f,-0.392238f,0.220057f},{-0.284277f,0.108646f,0.277837f}, -{-0.278888f,0.114041f,0.272088f},{0.150313f,-0.00275876f,0.275464f},{0.412485f,-0.387647f,0.200412f}, -{0.431275f,-0.387942f,0.182316f},{0.455345f,-0.389711f,0.15114f},{-0.0200026f,0.310922f,-0.0380052f}, -{0.175824f,0.0522877f,-0.0882287f},{0.283087f,-0.0592392f,0.275515f},{0.00377156f,0.361879f,-0.0719591f}, -{0.390254f,-0.131533f,-0.00779394f},{0.242452f,0.0339861f,0.239407f},{-0.238729f,0.194444f,0.190971f}, -{-0.316668f,0.169814f,0.286049f},{-0.261217f,0.112659f,0.26275f},{-0.0322916f,0.455812f,-0.074795f}, -{-0.0542909f,0.3464f,-0.0339217f},{-0.127864f,0.341989f,0.00335682f},{-0.115446f,0.305971f,0.0322626f}, -{-0.129755f,0.323848f,0.0176007f},{-0.0725218f,0.318768f,0.0133436f},{-0.207887f,0.168895f,0.0386483f}, -{0.0360728f,0.453194f,-0.156779f},{0.0101058f,0.457323f,-0.124903f},{-0.211533f,0.188663f,0.0418186f}, -{-0.0685862f,0.325848f,0.002135f},{0.307324f,-0.0717597f,0.265432f},{-0.0945404f,0.40009f,-0.0183209f}, -{0.177837f,-0.382605f,0.330009f},{0.191991f,-0.377975f,0.322234f},{0.200344f,-0.382894f,0.311617f}, -{0.213064f,-0.378001f,0.30754f},{0.230722f,-0.376554f,0.301514f},{0.236652f,-0.382116f,0.290717f}, -{0.250394f,-0.377563f,0.282364f},{0.258966f,-0.38229f,0.272062f},{0.270091f,-0.377743f,0.265541f}, -{0.283795f,-0.375737f,0.258988f},{0.290463f,-0.378882f,0.253516f},{0.305235f,-0.376612f,0.245362f}, -{0.313382f,-0.382438f,0.232005f},{0.322231f,-0.377113f,0.225607f},{-0.292052f,0.0570336f,0.285714f}, -{0.262085f,-0.0423974f,0.279104f},{-0.305601f,0.0956368f,0.315276f},{-0.297235f,0.0772451f,0.304858f}, -{-0.496135f,0.0952059f,0.111591f},{-0.169921f,0.26612f,0.0528215f},{0.402376f,-0.375493f,0.214102f}, -{0.417096f,-0.373068f,0.204971f},{0.426922f,-0.375383f,0.195081f},{0.43851f,-0.372522f,0.187312f}, -{0.445326f,-0.379178f,0.174316f},{0.456529f,-0.372972f,0.168065f},{0.463731f,-0.380155f,0.151333f}, -{-0.319536f,0.0236584f,0.302132f},{0.02316f,0.398142f,-0.110672f},{-0.396113f,-0.0172985f,0.225954f}, -{-0.27838f,0.0343655f,0.251625f},{-0.204119f,0.247343f,0.0765635f},{-0.317221f,0.415234f,-0.373956f}, -{-0.00159804f,0.325687f,-0.0402495f},{-0.334713f,0.133533f,0.32381f},{-0.0906884f,0.286422f,0.00184562f}, -{0.331388f,-0.0875084f,0.251304f},{0.323703f,-0.094878f,0.262667f},{-0.335253f,0.191968f,0.304112f}, -{-0.0371403f,0.436661f,-0.0764413f},{0.0386708f,0.435954f,-0.149725f},{-0.0347031f,0.34287f,-0.0372014f}, -{-0.0741873f,0.340799f,-0.01971f},{-0.326018f,0.186438f,0.29691f},{0.0039066f,0.436693f,-0.113276f}, -{-0.470258f,0.19256f,0.17213f},{-0.1118f,0.339095f,-0.00407059f},{0.211913f,-0.109598f,-0.153326f}, -{0.170133f,0.0323526f,0.258873f},{0.203135f,-0.373306f,0.315803f},{0.24377f,-0.372367f,0.295527f}, -{0.261847f,-0.372773f,0.276416f},{-0.305415f,0.195048f,0.264442f},{-0.305382f,0.0776631f,0.321167f}, -{-0.465918f,0.174753f,0.172265f},{-0.241661f,0.0589627f,0.245458f},{-0.233565f,0.247799f,0.157506f}, -{0.470959f,-0.370734f,0.151024f},{0.00161085f,0.397589f,-0.0976882f},{-0.24631f,0.12907f,0.242384f}, -{0.341066f,-0.0399023f,0.206759f},{-0.210633f,0.208341f,0.0389377f},{-0.16785f,0.247285f,0.0393235f}, -{-0.192801f,0.0938427f,0.183113f},{0.249326f,-0.038436f,0.283213f},{-0.337317f,0.0215106f,0.322909f}, -{-0.153317f,0.299264f,0.0489309f},{0.0229285f,0.436655f,-0.130948f},{0.337767f,-0.0763126f,-0.0658564f}, -{-0.144063f,0.340651f,0.0202759f},{-0.0110833f,0.31743f,-0.0566734f},{-0.22815f,0.170766f,0.189544f}, -{-0.182615f,0.378534f,-0.0300955f},{0.403109f,-0.148568f,0.0563969f},{0.359426f,-0.0361403f,0.00128615f}, -{0.189502f,-0.359159f,0.335854f},{0.199071f,-0.359313f,0.327063f},{0.213135f,-0.359082f,0.319141f}, -{0.232253f,-0.357442f,0.31525f},{0.237815f,-0.362953f,0.309649f},{0.249886f,-0.357718f,0.301347f}, -{0.256021f,-0.363133f,0.290749f},{0.267769f,-0.358059f,0.28192f},{0.274766f,-0.363615f,0.272499f}, -{0.288528f,-0.359326f,0.266628f},{0.309479f,-0.359493f,0.252706f},{0.320102f,-0.358857f,0.242069f}, -{0.329478f,-0.360316f,0.229523f},{0.249211f,0.0551815f,0.223446f},{0.263847f,-0.0760683f,0.298569f}, -{-0.261467f,0.0591171f,0.261985f},{0.400839f,-0.148748f,0.0371628f},{-0.24278f,0.229446f,0.191351f}, -{0.420253f,-0.356452f,0.208701f},{0.441384f,-0.356554f,0.195061f},{0.452979f,-0.35586f,0.185743f}, -{0.462535f,-0.357005f,0.173551f},{0.477017f,-0.356818f,0.152979f},{-0.0931771f,0.328195f,0.000559486f}, -{-0.147105f,0.322556f,0.0240057f},{-0.332674f,0.215286f,0.291341f},{-0.484425f,0.0606154f,0.1922f}, -{0.0209736f,0.359635f,-0.0773866f},{0.370621f,-0.103174f,0.19856f},{0.0443297f,0.398135f,-0.130356f}, -{-0.347979f,0.195595f,0.310697f},{-0.188872f,0.111746f,0.168046f},{-0.302122f,0.0224752f,0.262448f}, -{-0.19581f,0.158921f,0.094595f},{-0.474637f,0.189756f,0.11262f},{-0.328218f,0.118562f,0.327571f}, -{0.302302f,-0.353873f,0.261619f},{0.337844f,-0.355133f,0.222398f},{0.287023f,0.0218385f,0.224835f}, -{-0.330565f,0.168226f,0.307302f},{0.43289f,-0.351185f,0.201994f},{0.470535f,-0.351847f,0.165847f}, -{-0.129517f,0.3041f,0.0381531f},{-0.495852f,0.115186f,0.132401f},{-0.371998f,-0.281168f,0.0942992f}, -{0.320964f,0.00302242f,0.202135f},{-0.066895f,0.346728f,-0.0293945f},{-0.0516607f,0.323623f,-0.0016398f}, -{-0.305247f,0.172001f,0.264429f},{-0.369978f,0.442159f,-0.334922f},{-0.273551f,0.213196f,0.231227f}, -{-0.0336999f,0.398508f,-0.0774766f},{-0.297016f,0.176271f,0.248076f},{0.191695f,-0.341108f,0.339211f}, -{0.210138f,-0.341057f,0.326305f},{0.230517f,-0.340343f,0.322015f},{0.244433f,-0.338542f,0.315752f}, -{0.252831f,-0.341102f,0.306717f},{0.262657f,-0.338806f,0.296859f},{0.271904f,-0.341185f,0.289078f}, -{0.285769f,-0.339462f,0.279714f},{0.29328f,-0.344915f,0.271271f},{0.306579f,-0.339539f,0.265554f}, -{0.326128f,-0.340896f,0.248629f},{0.334359f,-0.345429f,0.234443f},{0.342423f,-0.340285f,0.225851f}, -{0.349587f,-0.343204f,0.214932f},{-0.295216f,0.28457f,-0.205325f},{0.340031f,-0.0957268f,0.244892f}, -{-0.453384f,0.0383525f,0.308678f},{-0.206524f,0.09455f,0.209112f},{0.435783f,-0.33696f,0.202939f}, -{0.446336f,-0.339204f,0.197138f},{0.457866f,-0.337822f,0.187351f},{0.466059f,-0.338111f,0.176547f}, -{0.471904f,-0.338459f,0.167892f},{0.481846f,-0.338864f,0.153969f},{0.303202f,-0.0957333f,0.280055f}, -{0.0814218f,-0.0515803f,0.29255f},{-0.292264f,0.345217f,-0.341024f},{-0.0167551f,0.356053f,-0.0587505f}, -{-0.19363f,0.107617f,0.182425f},{-0.164204f,0.243098f,0.0192984f},{-0.247487f,0.230038f,0.203376f}, -{-0.124462f,0.283644f,0.0264107f},{-0.219212f,0.247761f,0.0982477f},{-0.21082f,0.130903f,0.203293f}, -{-0.292605f,0.211903f,0.251201f},{-0.310257f,0.172207f,0.274229f},{-0.241192f,0.170798f,0.20827f}, -{-0.218337f,0.132022f,0.212688f},{0.319665f,-0.335674f,0.258641f},{0.337111f,-0.336053f,0.238623f}, -{-0.324443f,0.16811f,0.299051f},{-0.310984f,0.0778753f,0.329893f},{-0.319781f,0.0780104f,0.33977f}, -{-0.212723f,0.247503f,0.0867303f},{-0.111903f,0.327655f,0.00719593f},{-0.287132f,0.171544f,0.23987f}, -{-0.195708f,0.242571f,0.0661265f},{0.317562f,-0.076139f,0.257664f},{-0.106804f,0.318067f,0.0255683f}, -{-0.302739f,0.130337f,0.282878f},{-0.310894f,0.135976f,0.290222f},{-0.191585f,0.28338f,0.0687952f}, -{0.194016f,-0.319443f,0.337095f},{0.211733f,-0.321552f,0.328806f},{0.231353f,-0.322774f,0.323301f}, -{0.24642f,-0.322466f,0.316903f},{0.256098f,-0.322536f,0.308241f},{0.267371f,-0.321765f,0.298537f}, -{0.273506f,-0.326838f,0.293785f},{0.287344f,-0.322485f,0.285579f},{0.307743f,-0.323861f,0.269805f}, -{0.323073f,-0.32143f,0.26149f},{0.332546f,-0.323867f,0.251092f},{0.340134f,-0.320414f,0.243246f}, -{0.347445f,-0.324067f,0.22879f},{0.353149f,-0.328247f,0.21652f},{-0.298476f,0.095341f,0.302948f}, -{-0.291113f,0.0951159f,0.290724f},{-0.48919f,0.0783126f,0.230668f},{0.457493f,-0.320871f,0.190232f}, -{0.467326f,-0.324928f,0.17838f},{0.474811f,-0.320138f,0.16993f},{0.483763f,-0.321134f,0.157011f}, -{0.488161f,-0.321031f,0.148625f},{-0.0857175f,0.396045f,-0.0339217f},{0.345233f,-0.114582f,0.246526f}, -{-0.0343365f,0.360728f,-0.0558889f},{-0.277596f,0.193653f,0.228842f},{-0.455699f,-0.0891225f,0.038719f}, -{0.402235f,-0.13053f,0.0563583f},{-0.488714f,0.0780746f,0.192135f},{0.346564f,-0.1702f,-0.0924986f}, -{-0.360197f,0.287618f,-0.207794f},{0.169702f,-0.313784f,0.354754f},{0.299865f,-0.318048f,0.275464f}, -{0.355612f,-0.314749f,0.220244f},{-0.177753f,0.242481f,0.0468217f},{0.448632f,-0.315919f,0.196881f}, -{0.311498f,0.00544677f,0.212662f},{-0.243262f,0.14869f,0.227414f},{-0.0769911f,0.379383f,-0.04405f}, -{-0.314482f,0.133552f,-0.0457734f},{-0.427822f,0.00120256f,0.0205267f},{-0.297923f,0.24859f,-0.113122f}, -{-0.236767f,0.180811f,0.193653f},{-0.285808f,0.376689f,-0.360123f},{-0.288335f,0.304633f,-0.13287f}, -{-0.354223f,-0.222089f,0.246018f},{0.206987f,-0.310447f,0.33343f},{0.219893f,-0.301328f,0.329514f}, -{0.23089f,-0.301251f,0.3228f},{0.244728f,-0.30273f,0.315688f},{0.254548f,-0.299733f,0.308582f}, -{0.269043f,-0.300884f,0.298859f},{0.289016f,-0.300582f,0.288184f},{0.30128f,-0.300659f,0.277631f}, -{0.308932f,-0.302312f,0.272866f},{0.325871f,-0.299572f,0.263927f},{0.333214f,-0.309154f,0.255915f}, -{0.343516f,-0.299733f,0.246076f},{0.351194f,-0.306865f,0.232899f},{-0.324096f,0.127372f,0.316569f}, -{0.458355f,-0.303045f,0.188367f},{0.474715f,-0.303276f,0.172342f},{0.484348f,-0.303739f,0.158034f}, -{0.488881f,-0.300743f,0.148433f},{-0.185644f,0.247124f,0.0580239f},{-0.318411f,0.0184432f,0.285946f}, -{-0.0494679f,0.415948f,-0.0680621f},{-0.266908f,0.231768f,0.224417f},{0.375901f,-0.0972251f,-0.0192984f}, -{-0.310476f,0.0367319f,0.308395f},{0.325941f,-0.0720298f,0.247214f},{-0.0904505f,0.342626f,-0.0160445f}, -{0.323137f,-0.0387383f,0.22861f},{-0.34477f,0.182007f,0.315257f},{-0.482824f,0.0947237f,0.0602039f}, -{0.172461f,-0.296769f,0.359423f},{0.180094f,-0.302177f,0.350683f},{0.192299f,-0.297347f,0.346175f}, -{0.209636f,-0.297097f,0.337314f},{0.358738f,-0.296884f,0.225099f},{-0.231481f,0.144838f,0.218501f}, -{-0.174866f,0.25187f,0.0510595f},{0.0382849f,0.358741f,-0.0940355f},{0.00948199f,0.40337f,-0.105437f}, -{-0.0533199f,0.355944f,-0.0437928f},{-0.329292f,0.154535f,0.309013f},{-0.299132f,0.0402945f,0.28493f}, -{-0.469062f,0.0256133f,0.0585576f},{-0.0876338f,0.318446f,0.0195621f},{-0.282431f,0.21445f,0.244815f}, -{-0.185753f,0.0938748f,0.170605f},{-0.2486f,0.162773f,0.222147f},{-0.409804f,-0.0203466f,-0.0172149f}, -{0.246278f,-0.0565512f,0.297617f},{0.31135f,-0.282692f,0.272609f},{0.371734f,-0.293926f,0.198457f}, -{0.274052f,-0.011035f,0.254854f},{0.462734f,-0.28037f,0.176682f},{0.473396f,-0.283309f,0.168239f}, -{0.482065f,-0.280004f,0.154928f},{0.488502f,-0.286955f,0.147256f},{0.355336f,-0.0938298f,0.221742f}, -{-0.385644f,-0.0936176f,-0.070255f},{-0.229443f,0.266911f,0.112292f},{-0.28103f,0.232713f,0.246024f}, -{-0.0279059f,0.436661f,-0.0857271f},{-0.0987525f,0.336832f,-0.00780037f},{-0.132468f,0.287444f,0.033761f}, -{0.192711f,-0.279515f,0.352574f},{0.201521f,-0.279393f,0.348388f},{0.211668f,-0.279393f,0.340433f}, -{0.22242f,-0.27938f,0.333378f},{0.233243f,-0.279367f,0.326395f},{0.245172f,-0.27783f,0.31727f}, -{0.253358f,-0.280332f,0.307932f},{0.268136f,-0.279386f,0.297643f},{0.288328f,-0.279059f,0.287335f}, -{0.303903f,-0.277464f,0.277837f},{0.32661f,-0.278718f,0.263561f},{0.345934f,-0.278891f,0.24623f}, -{0.36021f,-0.279412f,0.227253f},{0.36857f,-0.279464f,0.207698f},{0.372068f,-0.285174f,0.199029f}, -{-0.499177f,0.0955082f,0.153455f},{-0.482046f,0.209968f,0.133494f},{-0.0162342f,0.337552f,-0.0352014f}, -{-0.076258f,0.309418f,0.0135044f},{-0.0918524f,0.0832128f,-0.0219671f},{-0.349998f,0.15015f,0.330182f}, -{-0.290624f,0.0768914f,0.291476f},{0.281312f,-0.0972187f,0.295515f},{-0.0157326f,0.436661f,-0.096402f}, -{-0.016067f,0.313353f,-0.0512716f},{-0.266927f,0.0447767f,0.256918f},{-0.324392f,0.0462815f,0.338529f}, -{-0.298624f,0.0591621f,0.303161f},{0.353098f,-0.102164f,0.229716f},{-0.21318f,0.261574f,0.0861387f}, -{0.492849f,-0.283226f,0.134684f},{0.0356741f,0.375403f,-0.101309f},{0.269242f,-0.0938169f,0.302961f}, -{0.379361f,-0.150484f,-0.0398829f},{0.270863f,-0.0711231f,0.289502f},{0.362139f,-0.151886f,-0.0719526f}, -{-0.462303f,0.0608019f,0.0229896f},{-0.0906884f,0.305135f,0.0184882f},{-0.0543552f,0.337352f,-0.0225845f}, -{-0.2624f,0.148439f,0.243992f},{-0.293184f,0.131089f,0.270634f},{-0.197296f,0.094132f,0.193865f}, -{-0.279531f,0.0439793f,0.261503f},{-0.1169f,0.271001f,0.0107649f},{0.190441f,-0.262172f,0.355063f}, -{0.201984f,-0.261895f,0.349217f},{0.213565f,-0.261863f,0.343372f},{0.227301f,-0.261754f,0.334973f}, -{0.236838f,-0.263168f,0.327996f},{0.24894f,-0.260178f,0.320993f},{0.256567f,-0.266352f,0.309225f}, -{0.266528f,-0.260603f,0.301051f},{0.273293f,-0.266474f,0.293804f},{0.286933f,-0.261959f,0.285431f}, -{0.304257f,-0.261676f,0.276583f},{0.313299f,-0.261484f,0.27275f},{0.326166f,-0.261477f,0.263066f}, -{0.345298f,-0.261664f,0.245465f},{0.360191f,-0.262101f,0.227369f},{0.368622f,-0.262718f,0.211286f}, -{0.373535f,-0.263258f,0.201196f},{0.355747f,-0.0973281f,-0.0497219f},{-0.153548f,0.343011f,0.0336388f}, -{0.475203f,-0.262641f,0.15096f},{0.484431f,-0.260873f,0.133886f},{0.296695f,-0.0675219f,0.272589f}, -{0.0291791f,0.36586f,-0.0880936f},{-0.252953f,0.0538568f,0.254911f},{-0.296611f,0.305817f,-0.244442f}, -{0.394196f,-0.149301f,-0.00137614f},{-0.294939f,0.0174657f,0.250101f},{-0.0417382f,0.337487f,-0.0269187f}, -{-0.111884f,0.285277f,0.0182438f},{-0.300199f,-0.305321f,0.170843f},{-0.310874f,0.195203f,0.273663f}, -{-0.00157232f,0.374972f,-0.0819909f},{-0.467641f,-0.114054f,0.135192f},{-0.445532f,-0.0192534f,0.13469f}, -{-0.48319f,0.0278319f,0.0975724f},{0.335234f,-0.16685f,-0.104138f},{-0.446426f,0.0595158f,0.0026816f}, -{-0.0854732f,-0.131076f,-0.165879f},{-0.210762f,0.14786f,0.186386f},{-0.0732292f,0.438963f,-0.0937912f}, -{-0.352095f,0.359474f,-0.285496f},{-0.0802643f,0.422379f,-0.0257162f},{-0.00456257f,0.356265f,-0.0636635f}, -{0.257931f,-0.0343397f,0.272988f},{-0.107009f,0.301945f,0.0255362f},{-0.00114789f,0.3377f,-0.0415099f}, -{-0.0524774f,0.437343f,-0.0565962f},{0.0514549f,0.383396f,-0.136047f},{-0.292032f,0.0369249f,0.266107f}, -{-0.306997f,0.0260635f,0.278821f},{0.191142f,-0.244854f,0.356233f},{0.203566f,-0.244513f,0.351693f}, -{0.214048f,-0.244507f,0.344246f},{0.231854f,-0.244236f,0.33615f},{0.252522f,-0.244571f,0.323925f}, -{0.270097f,-0.244931f,0.304042f},{0.288315f,-0.245921f,0.287566f},{0.302289f,-0.242121f,0.279554f}, -{0.3109f,-0.245703f,0.273117f},{0.325864f,-0.244674f,0.265188f},{0.345368f,-0.244359f,0.245671f}, -{0.36014f,-0.244777f,0.227472f},{0.36967f,-0.245246f,0.212874f},{0.375084f,-0.245651f,0.203595f}, -{0.381914f,-0.246275f,0.190669f},{0.38936f,-0.245638f,0.174753f},{0.291145f,-0.0359409f,0.253278f}, -{0.254272f,-0.0530337f,0.29037f},{-0.28575f,0.144632f,0.258808f},{0.0141571f,0.329494f,-0.0638436f}, -{-0.414929f,0.245169f,0.0165204f},{-0.317208f,0.131674f,0.303855f},{-0.204415f,-0.261458f,0.263316f}, -{-0.423675f,-0.108736f,-0.0320054f},{0.29573f,0.0261407f,0.214739f},{-0.307177f,0.0458571f,0.313128f}, -{0.244658f,-0.239465f,0.332022f},{0.264008f,-0.239696f,0.314607f},{0.281171f,-0.240037f,0.294113f}, -{0.33515f,-0.239632f,0.25931f},{-0.475133f,0.157525f,0.0939584f},{-0.381605f,0.418109f,-0.31127f}, -{-0.317819f,-0.314434f,0.132928f},{0.387007f,-0.149873f,-0.0206167f},{-0.213379f,0.0719012f,0.221864f}, -{-0.300649f,0.284679f,-0.225845f},{-0.0719495f,0.00154982f,-0.110222f},{-0.294026f,0.342208f,-0.359886f}, -{-0.416755f,-0.208431f,0.173589f},{-0.397791f,0.244089f,-0.00489371f},{-0.0996592f,0.290222f,0.0133694f}, -{-0.0757886f,0.290743f,-0.00540174f},{-0.0452944f,0.384206f,-0.0660557f},{-0.0610817f,0.441446f,-0.0430918f}, -{-0.307685f,0.144851f,0.27774f},{0.38801f,-0.112652f,-0.00266871f},{0.336725f,-0.000199339f,0.183357f}, -{0.230157f,0.0578695f,-0.0557795f},{0.193065f,-0.22724f,0.359236f},{0.207109f,-0.22553f,0.353204f}, -{0.214093f,-0.228404f,0.348246f},{0.231925f,-0.226526f,0.34206f},{0.245539f,-0.226372f,0.333423f}, -{0.25296f,-0.226436f,0.327153f},{0.264831f,-0.2256f,0.31826f},{0.273602f,-0.228938f,0.305939f}, -{0.2842f,-0.224437f,0.298788f},{0.293023f,-0.228031f,0.292685f},{0.307209f,-0.227182f,0.283605f}, -{0.325337f,-0.226662f,0.267792f},{0.33742f,-0.225176f,0.258924f},{0.347478f,-0.227542f,0.246391f}, -{0.360371f,-0.227433f,0.227928f},{0.370146f,-0.227825f,0.213839f},{0.375457f,-0.228237f,0.204347f}, -{0.382949f,-0.225581f,0.190965f},{0.389721f,-0.227414f,0.176367f},{-0.464149f,0.17485f,0.191557f}, -{0.335317f,-0.00309312f,-0.0148612f},{-0.294605f,0.246108f,-0.0770907f},{-0.231636f,0.247857f,0.147918f}, -{-0.257378f,0.195544f,0.212797f},{-0.300174f,0.149108f,0.266191f},{-0.266483f,0.126832f,0.258397f}, -{-0.184467f,0.073078f,-0.0691939f},{0.316778f,-0.222109f,0.278094f},{0.393463f,-0.22135f,0.167634f}, -{0.398994f,-0.222141f,0.152883f},{0.40428f,-0.223215f,0.133481f},{-0.224337f,0.188322f,0.154188f}, -{0.0944117f,-0.00196778f,-0.126137f},{-0.141645f,0.261509f,0.0257677f},{-0.153027f,0.289978f,0.0494518f}, -{-0.202595f,0.225678f,0.0589692f},{-0.350725f,0.323347f,-0.265856f},{0.371689f,-0.0461207f,0.136742f}, -{-0.287788f,0.306292f,-0.147879f},{0.193508f,-0.20555f,0.359879f},{0.21318f,-0.209279f,0.354638f}, -{0.230407f,-0.209041f,0.345648f},{0.243481f,-0.20899f,0.33624f},{0.254413f,-0.208913f,0.329443f}, -{0.267898f,-0.208861f,0.320684f},{0.276869f,-0.209016f,0.310929f},{0.288103f,-0.209697f,0.301347f}, -{0.308038f,-0.2089f,0.288222f},{0.319832f,-0.207517f,0.278834f},{0.32796f,-0.209993f,0.269477f}, -{0.338552f,-0.209286f,0.258751f},{0.349098f,-0.209562f,0.245799f},{0.361194f,-0.205698f,0.22924f}, -{0.370628f,-0.206161f,0.21452f},{0.37565f,-0.206508f,0.204926f},{0.381772f,-0.204598f,0.19265f}, -{-0.18529f,0.230616f,0.0361275f},{-0.192518f,0.233105f,0.0540176f},{-0.26629f,0.193145f,0.221073f}, -{-0.309517f,0.153905f,0.275007f},{0.00359793f,-0.0376451f,-0.136844f},{0.400395f,-0.112588f,0.056339f}, -{0.377425f,-0.112543f,0.18883f},{-0.27231f,0.227221f,0.233259f},{-0.392177f,0.323874f,-0.150098f}, -{0.392782f,-0.0995724f,0.0242693f},{0.297447f,-0.204656f,0.295566f},{0.389238f,-0.203325f,0.179113f}, -{0.393997f,-0.203846f,0.168702f},{0.400254f,-0.203286f,0.152606f},{0.404016f,-0.205543f,0.137488f}, -{0.406575f,-0.203736f,0.0958555f},{0.373728f,-0.0370471f,0.0916627f},{-0.285036f,0.196302f,0.239285f}, -{-0.49265f,0.113205f,0.172702f},{0.391894f,-0.0905887f,0.0307064f},{-0.0491335f,0.400045f,-0.0677341f}, -{0.387496f,-0.131507f,0.172104f},{-0.30445f,0.042571f,0.302254f},{-0.289537f,0.331526f,-0.205775f}, -{0.210852f,-0.192984f,0.353641f},{0.230388f,-0.186656f,0.3435f},{0.2464f,-0.187447f,0.334999f}, -{0.256336f,-0.189357f,0.329636f},{0.26829f,-0.187139f,0.321404f},{0.277544f,-0.187287f,0.312067f}, -{0.287859f,-0.187396f,0.302119f},{0.297582f,-0.195955f,0.295823f},{0.3078f,-0.187319f,0.288036f}, -{0.320893f,-0.187293f,0.278641f},{0.330063f,-0.187415f,0.269316f},{0.336108f,-0.187647f,0.261021f}, -{0.3465f,-0.187949f,0.247799f},{0.405495f,-0.20337f,0.114061f},{-0.463545f,0.155307f,0.0387769f}, -{0.349606f,-0.0372335f,0.194515f},{-0.25541f,0.153847f,0.234912f},{0.335838f,-0.0763834f,0.238951f}, -{0.275666f,0.0441979f,0.211537f},{-0.40626f,0.244191f,0.00486803f},{-0.247198f,0.214655f,0.203582f}, -{-0.194151f,0.251947f,0.0684094f},{-0.393611f,-0.26093f,0.0749301f},{-0.336989f,0.11408f,0.337558f}, -{0.193643f,-0.184219f,0.35469f},{0.214215f,-0.182181f,0.348728f},{0.363619f,-0.184116f,0.227555f}, -{0.372885f,-0.184528f,0.21245f},{0.377219f,-0.183409f,0.203685f},{0.383579f,-0.18629f,0.191351f}, -{0.389901f,-0.185685f,0.179049f},{0.393913f,-0.185467f,0.168824f},{0.399412f,-0.186483f,0.153088f}, -{0.403026f,-0.186547f,0.134369f},{0.153992f,-0.0128613f,-0.119212f},{0.342526f,-0.0724093f,0.226012f}, -{0.351702f,-0.0712453f,0.212816f},{-0.323607f,0.0270281f,0.316819f},{-0.0144658f,0.347044f,-0.0496318f}, -{0.24024f,0.0426288f,0.236269f},{-0.410202f,0.0403524f,0.321244f},{0.295923f,-0.178888f,0.293463f}, -{-0.380415f,0.441587f,-0.323456f},{0.315099f,-0.0676699f,0.254069f},{0.255937f,0.0257355f,0.23643f}, -{-0.233983f,0.153783f,0.214951f},{-0.433906f,-0.109958f,-0.0181473f},{-0.293139f,0.346458f,-0.282949f}, -{-0.47429f,0.245143f,0.0948394f},{-0.298727f,0.325096f,-0.339359f},{0.270522f,0.0224816f,0.232616f}, -{-0.0683805f,0.449986f,-0.0894955f},{0.160712f,-0.171879f,0.369146f},{0.174441f,-0.167917f,0.363262f}, -{0.187348f,-0.165776f,0.355075f},{0.197418f,-0.167114f,0.348883f},{0.24514f,-0.170104f,0.333404f}, -{0.25141f,-0.16494f,0.328877f},{0.266342f,-0.165725f,0.318806f},{0.277287f,-0.165692f,0.311874f}, -{0.28674f,-0.165789f,0.302878f},{0.294534f,-0.16611f,0.291585f},{0.306186f,-0.165937f,0.285791f}, -{0.320392f,-0.165744f,0.278126f},{0.329388f,-0.165905f,0.268461f},{0.335632f,-0.166104f,0.26041f}, -{0.346127f,-0.166381f,0.247375f},{0.363381f,-0.166792f,0.227176f},{0.372846f,-0.167236f,0.212366f}, -{0.376017f,-0.167487f,0.205871f},{0.38365f,-0.16858f,0.191942f},{0.389933f,-0.166516f,0.179422f}, -{-0.392833f,0.0234912f,0.319732f},{-0.494894f,0.0964214f,0.174059f},{-0.0558921f,0.396836f,-0.0624288f}, -{-0.253506f,0.117868f,0.254564f},{-0.0270828f,0.450976f,-0.084441f},{-0.0342787f,0.379268f,-0.11507f}, -{-0.381399f,-0.0122504f,-0.0409311f},{0.369933f,-0.151256f,-0.0590527f},{0.0296164f,0.38456f,-0.104524f}, -{-0.0463297f,0.431909f,-0.0671232f},{-0.310083f,0.0582618f,0.327507f},{0.331279f,-0.00854636f,0.198232f}, -{0.35731f,-0.0743127f,0.205871f},{-0.392602f,-0.0367319f,0.227928f},{-0.215926f,0.0532652f,0.217864f}, -{-0.286309f,0.0630462f,0.280576f},{-0.46703f,0.191994f,0.0951931f},{-0.369458f,-0.277586f,0.132684f}, -{0.392743f,-0.117739f,0.00504166f},{-0.0631459f,0.365101f,-0.0467509f},{-0.325035f,0.00603198f,0.262551f}, -{-0.314392f,-0.0357866f,-0.090563f},{-0.0242726f,0.346928f,-0.0468859f},{0.394499f,-0.131205f,0.00184562f}, -{0.353773f,-0.0515031f,0.196663f},{0.173123f,-0.150137f,0.36467f},{0.190126f,-0.14977f,0.355461f}, -{0.199875f,-0.149822f,0.346921f},{0.265705f,-0.148503f,0.31808f},{0.276772f,-0.148452f,0.311302f}, -{0.285705f,-0.148632f,0.301598f},{0.294502f,-0.148818f,0.29165f},{0.306527f,-0.148613f,0.286537f}, -{0.321633f,-0.148272f,0.280094f},{0.330391f,-0.148478f,0.270075f},{0.337838f,-0.147269f,0.26014f}, -{0.347072f,-0.149712f,0.246455f},{0.360615f,-0.149519f,0.228887f},{0.370171f,-0.14995f,0.214572f}, -{0.375168f,-0.150304f,0.204784f},{0.381952f,-0.150812f,0.19184f},{0.298502f,-0.0759397f,0.275194f}, -{0.33124f,-0.0341532f,0.215356f},{-0.271448f,0.0951159f,0.273721f},{-0.0428379f,0.374792f,-0.062506f}, -{0.22062f,-0.145429f,0.331745f},{0.114508f,0.00446288f,-0.119282f},{-0.457262f,0.227337f,0.0693869f}, -{0.333793f,-0.0678563f,0.235941f},{-0.282194f,0.0950195f,0.280801f},{-0.353799f,0.226996f,-0.10954f}, -{-0.372088f,0.422546f,-0.321089f},{0.278161f,-0.0846404f,0.290981f},{0.373618f,-0.150953f,-0.0526349f}, -{-0.309517f,0.113656f,0.309482f},{0.197817f,-0.131153f,0.347841f},{0.210472f,-0.132478f,0.339745f}, -{0.219572f,-0.132677f,0.330292f},{0.266393f,-0.1328f,0.315308f},{0.27321f,-0.129957f,0.310016f}, -{0.284489f,-0.131507f,0.299926f},{0.294437f,-0.131539f,0.291804f},{0.306829f,-0.131243f,0.287161f}, -{0.321067f,-0.13107f,0.279361f},{0.33014f,-0.131211f,0.26985f},{0.33868f,-0.131423f,0.259509f}, -{0.348288f,-0.131822f,0.245246f},{0.359657f,-0.132337f,0.22787f},{0.369187f,-0.132099f,0.209877f}, -{0.373663f,-0.137539f,0.202727f},{0.379676f,-0.133372f,0.18964f},{-0.393232f,0.266429f,-0.0018713f}, -{-0.386332f,0.318556f,-0.0768207f},{-0.384435f,0.284216f,-0.00197419f},{-0.234812f,0.117643f,0.236436f}, -{-0.23489f,0.0535288f,0.23578f},{-0.374834f,0.170168f,-0.0319604f},{-0.0530176f,0.034687f,-0.0872898f}, -{-0.391007f,0.326273f,-0.111803f},{-0.105858f,0.346156f,-0.0124497f},{-0.284901f,-0.307379f,0.175287f}, -{0.0462268f,0.397987f,-0.147699f},{0.396698f,-0.112768f,0.114164f},{-0.294573f,0.346574f,-0.205781f}, -{-0.382042f,0.248281f,-0.0404103f},{0.301756f,-0.0592071f,0.263098f},{-0.451204f,0.0230218f,0.0365069f}, -{-0.496013f,0.0583776f,0.113443f},{-0.367014f,0.453825f,-0.336015f},{0.265088f,0.0171763f,0.238275f}, -{-0.350133f,0.114054f,-0.0474583f},{0.0793125f,-0.0969293f,-0.202637f},{-0.184801f,0.230391f,0.0214463f}, -{-0.297061f,0.264165f,-0.167287f},{0.0243175f,0.418411f,-0.166252f},{-0.467223f,0.19274f,0.230018f}, -{0.262966f,-0.118594f,0.314202f},{0.319414f,-0.118298f,0.277052f},{0.335613f,-0.118517f,0.260802f}, -{-0.214363f,0.270905f,0.0846661f},{-0.301241f,0.247413f,-0.132774f},{-0.216234f,0.117546f,0.218051f}, -{-0.340494f,0.127443f,0.332504f},{-0.486219f,0.134652f,0.095341f},{-0.0820585f,0.412855f,-0.0283914f}, -{-0.112675f,-0.091489f,-0.140169f},{-0.0356548f,0.30491f,-0.0375936f},{0.033642f,0.347982f,-0.0946079f}, -{-0.289055f,0.321347f,-0.218642f},{-0.289184f,0.180727f,0.236848f},{-0.334507f,-0.0908009f,-0.0943185f}, -{-0.380448f,0.248204f,-0.0540368f},{0.0440211f,0.38148f,-0.149088f},{-0.373059f,-0.0920935f,-0.0786277f}, -{-0.315627f,-0.0169255f,-0.0797981f},{0.00336643f,0.327083f,-0.0718112f},{-0.425436f,0.207395f,0.0221344f}, -{0.24876f,-0.472712f,-0.00379407f},{0.237996f,-0.475419f,-0.0214655f},{0.232973f,-0.473644f,-0.0391434f}, -{0.229333f,-0.47401f,-0.0584097f},{0.226768f,-0.473483f,-0.0764348f},{0.21536f,-0.483161f,-0.0790199f}, -{0.215553f,-0.479669f,-0.0921128f},{0.243217f,-0.466917f,0.259413f},{0.246272f,-0.467946f,0.247426f}, -{0.2504f,-0.468242f,0.230372f},{-0.357651f,0.244089f,-0.170348f},{-0.296708f,0.346574f,-0.186476f}, -{-0.284097f,0.395949f,-0.37966f},{-0.317807f,-0.306826f,0.154715f},{-0.27665f,-0.0892061f,-0.114967f}, -{0.377882f,-0.452609f,0.0563905f},{0.365676f,-0.455542f,0.0379345f},{0.36284f,-0.450699f,0.0208804f}, -{0.350294f,-0.457143f,0.0219286f},{0.246008f,-0.467168f,-0.0164175f},{0.223842f,-0.470146f,-0.0938298f}, -{0.212466f,-0.469425f,-0.113649f},{0.177528f,0.0819909f,-0.0581396f},{0.250445f,-0.0753995f,-0.128144f}, -{-0.287994f,0.321437f,-0.18647f},{0.257706f,-0.456783f,0.246899f},{0.266753f,-0.453702f,0.228102f}, -{-0.463313f,-0.0535996f,0.0963442f},{-0.292862f,0.266171f,-0.115655f},{-0.297691f,0.418154f,-0.340291f}, -{-0.486406f,0.0608212f,0.211479f},{-0.392788f,0.092788f,-0.0334844f},{-0.333645f,0.073824f,-0.0471689f}, -{0.401514f,-0.441831f,0.0767628f},{0.397302f,-0.441947f,0.0568471f},{0.388287f,-0.44295f,0.0376966f}, -{0.378776f,-0.444076f,0.0248802f},{0.359496f,-0.445253f,0.00628921f},{0.344159f,-0.450371f,0.0042957f}, -{-0.201231f,0.169287f,0.0771036f},{0.25568f,-0.458268f,-0.0205074f},{0.248497f,-0.453471f,-0.0392013f}, -{0.238356f,-0.459477f,-0.0585383f},{0.236433f,-0.456005f,-0.0791228f},{0.233108f,-0.455432f,-0.0939584f}, -{0.228137f,-0.453645f,-0.108517f},{0.22152f,-0.46122f,-0.110086f},{0.207739f,-0.462738f,-0.12325f}, -{0.193013f,-0.469998f,-0.129411f},{0.0398026f,-0.0865888f,-0.191074f},{-0.467647f,0.0190926f,0.246281f}, -{-0.292798f,0.305984f,-0.22515f},{-0.0710363f,-0.0359988f,-0.136619f},{-0.496019f,0.056204f,0.13433f}, -{0.261358f,-0.447111f,0.256468f},{0.26712f,-0.446609f,0.243651f},{-0.469294f,0.0183531f,0.0758561f}, -{-0.355683f,0.217601f,-0.0730137f},{-0.206736f,0.169075f,0.134896f},{-0.298148f,0.43724f,-0.361525f}, -{-0.29227f,0.266262f,-0.096357f},{-0.286824f,0.396965f,-0.360117f},{-0.429559f,0.152137f,1.28796e-05f}, -{0.417263f,-0.431394f,0.113746f},{0.418292f,-0.432346f,0.0939777f},{0.421462f,-0.43025f,0.0760104f}, -{0.417102f,-0.430546f,0.0568278f},{0.411803f,-0.430751f,0.0441787f},{0.405071f,-0.431832f,0.0345455f}, -{0.39608f,-0.428835f,0.0193756f},{0.381856f,-0.434423f,0.0154336f},{0.364422f,-0.435478f,-0.00126682f}, -{0.289216f,-0.0535674f,-0.0970258f},{-0.453339f,0.134864f,0.0193306f},{0.269724f,-0.452873f,-0.0171763f}, -{0.244555f,-0.449497f,-0.0585769f},{0.241179f,-0.449799f,-0.0713803f},{0.212524f,-0.450153f,-0.127932f}, -{0.155471f,0.0844796f,-0.0584097f},{-0.462837f,-0.0924729f,0.15249f},{-0.481685f,0.0599273f,0.0604418f}, -{-0.47656f,0.0597601f,0.0508215f},{-0.294315f,0.376772f,-0.302241f},{0.0440661f,0.419118f,-0.17339f}, -{-0.20855f,0.188798f,0.0578245f},{-0.287113f,0.417118f,-0.380277f},{-0.370043f,-0.258249f,0.186502f}, -{-0.210177f,0.16521f,0.154014f},{-0.401611f,-0.0144818f,0.216019f},{0.439886f,-0.415434f,0.114472f}, -{0.44069f,-0.416218f,0.0951867f},{0.440446f,-0.415112f,0.0759204f},{0.43597f,-0.415356f,0.0566927f}, -{0.423385f,-0.421093f,0.0375679f},{0.421539f,-0.41407f,0.020308f},{0.405296f,-0.4218f,0.0159866f}, -{0.315569f,-0.0725507f,-0.0834893f},{-0.108765f,0.0418508f,-0.0803318f},{0.302238f,-0.0549371f,-0.0891289f}, -{0.271486f,-0.43169f,-0.0343847f},{0.256265f,-0.438925f,-0.0425581f},{0.251686f,-0.436108f,-0.0600173f}, -{0.248471f,-0.43623f,-0.0766277f},{0.24631f,-0.434648f,-0.0921128f},{0.237391f,-0.440835f,-0.109984f}, -{0.230446f,-0.433742f,-0.127115f},{0.215707f,-0.436205f,-0.134716f},{0.00438248f,-0.0895598f,-0.188193f}, -{-0.293428f,0.266049f,-0.131738f},{-0.300553f,0.380226f,-0.282229f},{-0.296058f,0.326035f,-0.282981f}, -{-0.150725f,0.37847f,-0.061072f},{-0.45377f,0.0130671f,0.153905f},{-0.431726f,0.0403845f,0.320234f}, -{-0.458683f,0.0119096f,0.140979f},{-0.353413f,0.305341f,-0.246449f},{-0.204119f,0.169069f,0.0578631f}, -{-0.109042f,0.272705f,-0.00145331f},{0.449043f,-0.409749f,0.0951416f},{0.436105f,-0.410643f,0.0375422f}, -{0.40271f,-0.413234f,0.000861727f},{0.306546f,-0.074287f,-0.0900743f},{0.269499f,-0.0541912f,-0.108228f}, -{0.100129f,0.070165f,-0.0682357f},{0.262104f,-0.428867f,-0.0521269f},{0.243442f,-0.431086f,-0.110164f}, -{0.218157f,-0.0130735f,-0.101431f},{-0.108019f,-0.476364f,-0.188161f},{-0.335703f,-0.278917f,0.190425f}, -{-0.375515f,0.270152f,-0.130504f},{-0.431944f,0.190862f,0.0184432f},{-0.487537f,0.078184f,0.211369f}, -{-0.289775f,0.331468f,-0.186476f},{0.0238481f,0.341397f,-0.0924857f},{-0.288521f,0.39191f,-0.34404f}, -{-0.446143f,0.0075689f,0.264294f},{-0.225732f,0.208109f,0.13487f},{0.0427799f,0.363577f,-0.128607f}, -{0.458786f,-0.395499f,0.133726f},{0.461525f,-0.396122f,0.115688f},{0.459699f,-0.399807f,0.0951031f}, -{0.460323f,-0.397119f,0.0742484f},{0.458426f,-0.395183f,0.056577f},{0.446169f,-0.400977f,0.0373943f}, -{0.439462f,-0.396843f,0.0184432f},{0.428928f,-0.402225f,0.0122118f},{0.419314f,-0.399698f,-0.000353668f}, -{0.40662f,-0.403916f,-0.00723448f},{0.0976528f,0.0429054f,-0.0970322f},{0.287975f,-0.41598f,-0.036629f}, -{0.275512f,-0.417671f,-0.0584611f},{0.266586f,-0.418668f,-0.0745378f},{0.253018f,-0.421536f,-0.091161f}, -{0.24723f,-0.417035f,-0.110479f},{0.231848f,-0.41652f,-0.131038f},{0.307492f,-0.0907044f,-0.0960162f}, -{0.440838f,-0.2645f,0.0228546f},{0.459384f,-0.319617f,0.00039872f},{-0.03415f,-0.0165011f,-0.131044f}, -{-0.296032f,0.326208f,-0.12925f},{-0.259333f,-0.27547f,0.242835f},{-0.303955f,0.309939f,-0.303907f}, -{-0.239005f,0.247696f,0.173621f},{-0.208993f,0.152182f,0.0179416f},{-0.192061f,0.145751f,0.059818f}, -{-0.209662f,0.208521f,0.0578181f},{-0.0908363f,-0.0219285f,-0.124105f},{-0.300752f,0.304575f,-0.264204f}, -{-0.128597f,0.261561f,-0.000932427f},{-0.292573f,0.2663f,-0.0770715f},{0.468425f,-0.389859f,0.107919f}, -{0.469159f,-0.389807f,0.095058f},{0.46856f,-0.389717f,0.0790007f},{0.457275f,-0.390682f,0.03742f}, -{0.449937f,-0.391357f,0.0247388f},{0.432722f,-0.392901f,0.00583906f},{0.41172f,-0.394187f,-0.0133114f}, -{0.304617f,-0.411684f,-0.0309572f},{0.286933f,-0.407781f,-0.058609f},{0.280965f,-0.40809f,-0.0777981f}, -{0.272824f,-0.408469f,-0.0935468f},{0.13452f,0.0551622f,-0.0911482f},{0.00276838f,-0.0574065f,-0.142613f}, -{0.0986881f,-0.111392f,-0.208566f},{-0.0535256f,-0.0160316f,-0.128793f},{-0.480194f,0.112318f,0.0601846f}, -{-0.291717f,0.331552f,-0.167159f},{-0.291486f,0.376772f,-0.321514f},{0.0521751f,0.396354f,-0.154664f}, -{-0.466503f,0.262262f,0.0949037f},{-0.304456f,0.303926f,-0.282345f},{-0.230684f,0.208173f,0.154329f}, -{-0.438227f,-0.0888203f,-0.00416705f},{-0.317356f,-0.279991f,0.207871f},{-0.309556f,0.298486f,-0.301161f}, -{-0.394203f,0.00450149f,0.299174f},{-0.497608f,0.0648661f,0.118202f},{0.474933f,-0.375789f,0.133629f}, -{0.47793f,-0.375473f,0.114311f},{0.479036f,-0.375467f,0.0950195f},{0.47784f,-0.375454f,0.0757275f}, -{0.474194f,-0.375776f,0.0564869f},{0.470213f,-0.374702f,0.0414842f},{0.4642f,-0.378284f,0.0329765f}, -{0.456767f,-0.376547f,0.0194078f},{0.447642f,-0.382708f,0.0118903f},{0.439333f,-0.378206f,0.000366566f}, -{0.427507f,-0.384714f,-0.00714445f},{0.417784f,-0.379435f,-0.0165654f},{-0.0898074f,0.0744092f,-0.0384811f}, -{0.174776f,-0.0560882f,-0.130272f},{0.295061f,-0.127295f,-0.121662f},{0.306707f,-0.393621f,-0.0401016f}, -{0.294945f,-0.398193f,-0.0587891f},{0.292759f,-0.395338f,-0.0759461f},{0.289241f,-0.393987f,-0.0908781f}, -{0.272901f,-0.395241f,-0.112292f},{0.255384f,-0.402244f,-0.11734f},{0.326739f,-0.0737533f,-0.0754767f}, -{0.0427671f,0.0614836f,-0.0778946f},{0.024787f,0.0598694f,-0.0759268f},{0.0609787f,-0.0979068f,-0.204971f}, -{0.370113f,-0.108202f,-0.0410212f},{-0.293151f,0.346593f,-0.225067f},{-0.349182f,-0.294312f,0.142934f}, -{-0.198035f,0.154304f,0.0579017f},{-0.460979f,0.0270666f,0.192534f},{-0.284065f,0.227549f,-0.0155815f}, -{-0.211939f,0.163828f,0.0225845f},{0.263307f,0.0682615f,-0.015575f},{-0.144294f,-0.489791f,-0.179949f}, -{0.302778f,-0.387962f,-0.0587505f},{0.298405f,-0.388778f,-0.0717211f},{0.283737f,-0.389698f,-0.106762f}, -{0.306045f,0.0186232f,-0.0359667f},{-0.0324716f,0.064043f,-0.0604032f},{-0.0153082f,0.0546413f,-0.0698948f}, -{0.270367f,0.0232468f,-0.0589048f},{0.058818f,-0.471593f,-0.152047f},{-0.238632f,0.0343269f,-0.0881515f}, -{0.251802f,0.0835021f,0.000527333f},{0.052143f,0.412617f,-0.165088f},{-0.468483f,0.0215491f,0.265831f}, -{-0.231687f,0.203267f,0.167236f},{-0.221269f,0.170843f,0.173268f},{-0.335838f,-0.487309f,-0.0170734f}, -{-0.317948f,0.209016f,-0.0551107f},{-0.236909f,0.268364f,0.153243f},{-0.355079f,0.287393f,-0.246384f}, -{-0.217675f,0.171081f,0.0178065f},{-0.439738f,0.0120318f,0.289688f},{0.4833f,-0.35786f,0.13487f}, -{0.484611f,-0.361365f,0.114292f},{0.485865f,-0.361275f,0.0949809f},{0.484656f,-0.35912f,0.0740555f}, -{0.481518f,-0.357223f,0.0563648f},{0.474387f,-0.357886f,0.0371307f},{0.462078f,-0.359905f,0.0167197f}, -{0.453493f,-0.358374f,0.00308674f},{0.444111f,-0.362361f,-0.0054146f},{0.0754349f,0.029954f,-0.102312f}, -{-0.474747f,0.0408347f,0.0529051f},{0.323382f,-0.376927f,-0.03742f},{0.314842f,-0.377467f,-0.045722f}, -{0.310508f,-0.375879f,-0.0588663f},{0.30654f,-0.373197f,-0.0730652f},{0.299865f,-0.373756f,-0.0897206f}, -{0.29492f,-0.379743f,-0.0974952f},{0.289422f,-0.375679f,-0.110389f},{0.271101f,-0.378528f,-0.12743f}, -{0.00521203f,0.0642294f,-0.0609819f},{0.321961f,0.00183919f,-0.0339667f},{0.286959f,-0.0164046f,-0.0771872f}, -{0.420176f,-0.265104f,0.0233819f},{0.0740008f,-0.0641651f,-0.143892f},{-0.0716794f,0.0824154f,-0.0214269f}, -{-0.29319f,0.346394f,-0.302228f},{-0.280541f,-0.282036f,0.227324f},{-0.146101f,0.253818f,0.0192406f}, -{-0.390807f,-0.220514f,0.206148f},{0.0528182f,0.402739f,-0.162246f},{-0.233102f,0.193158f,0.179949f}, -{0.486489f,-0.352252f,0.127153f},{0.487975f,-0.352124f,0.114273f},{0.489042f,-0.352079f,0.0949487f}, -{0.488078f,-0.352059f,0.0788785f},{0.468322f,-0.354085f,0.0241922f},{0.0194559f,0.0802225f,-0.0425388f}, -{0.0245297f,0.0399794f,-0.0934954f},{-0.482663f,0.0772772f,0.0602553f},{0.330353f,-0.362123f,-0.0421208f}, -{0.317839f,-0.368535f,-0.0525771f},{0.280033f,-0.371969f,-0.123237f},{0.00321209f,0.0560947f,-0.074467f}, -{-0.0921032f,-0.0124755f,-0.115996f},{0.155805f,0.0435163f,-0.0979968f},{0.0239831f,0.0742355f,-0.0537089f}, -{-0.30209f,0.342954f,-0.148047f},{-0.376994f,-0.248468f,0.193524f},{-0.414832f,-0.0382303f,-0.0205588f}, -{0.489524f,-0.338581f,0.133584f},{0.492798f,-0.338304f,0.114247f},{0.494219f,-0.338182f,0.0949166f}, -{0.492907f,-0.338272f,0.0756117f},{0.488952f,-0.337687f,0.0576573f},{0.484521f,-0.343552f,0.0499148f}, -{0.48103f,-0.339385f,0.0371307f},{0.471615f,-0.340298f,0.0210733f},{0.465313f,-0.340876f,0.0115109f}, -{0.455661f,-0.337333f,-0.00201921f},{0.448323f,-0.346883f,-0.00728592f},{0.229906f,0.0176136f,-0.0870004f}, -{0.341992f,-0.359969f,-0.0333044f},{0.32272f,-0.355056f,-0.0600366f},{0.312495f,-0.356863f,-0.0761004f}, -{0.303948f,-0.356149f,-0.0911996f},{0.291717f,-0.357255f,-0.110556f},{0.279017f,-0.362921f,-0.123044f}, -{-0.0522717f,0.0835278f,-0.0215491f},{-0.0338478f,0.0893026f,-0.0163596f},{0.156378f,0.0574451f,-0.0872576f}, -{0.267853f,-0.168811f,-0.147146f},{-0.126996f,0.0363654f,-0.0887431f},{0.0581042f,0.100196f,-0.0409376f}, -{-0.486476f,0.112498f,0.0762162f},{-0.293994f,0.326189f,-0.263683f},{-0.396801f,-0.208456f,0.211575f}, -{-0.43289f,-0.204662f,0.135134f},{-0.458406f,-0.0975531f,0.0515611f},{-0.216016f,0.173004f,0.154812f}, -{-0.235005f,0.268229f,0.138819f},{0.487081f,-0.334253f,0.146368f},{-0.0743738f,-0.469959f,-0.181248f}, -{-0.301569f,0.0376644f,-0.0603903f},{-0.497852f,0.0824411f,0.166387f},{0.346326f,-0.34215f,-0.0371949f}, -{0.332333f,-0.343796f,-0.058474f},{0.319626f,-0.349854f,-0.0715218f},{0.272406f,-0.359423f,-0.128658f}, -{0.26303f,-0.355448f,-0.142593f},{-0.0144658f,-0.115945f,-0.219247f},{-0.0125495f,0.0629755f,-0.0593807f}, -{-0.444941f,0.172072f,0.0224495f},{0.00631167f,-0.0170863f,-0.127764f},{-0.0145301f,-0.106228f,-0.209845f}, -{-0.45222f,0.0166683f,0.285078f},{-0.477821f,0.0350407f,0.274229f},{-0.23015f,0.22796f,0.134928f}, -{-0.207681f,0.188823f,0.0963763f},{-0.218221f,0.208353f,0.11563f},{-0.0711649f,-0.482081f,0.33824f}, -{-0.374094f,-0.00108035f,0.286422f},{0.36958f,-0.0675798f,0.176342f},{0.492753f,-0.320472f,0.133578f}, -{0.496836f,-0.320125f,0.114241f},{0.498785f,-0.319958f,0.0948909f},{0.498148f,-0.320028f,0.0755539f}, -{0.493563f,-0.320356f,0.056249f},{0.488553f,-0.319424f,0.0412334f},{0.484058f,-0.322781f,0.0328607f}, -{0.473416f,-0.322298f,0.0177486f},{-0.22552f,-0.03306f,-0.116273f},{0.339709f,-0.333494f,-0.0574579f}, -{0.326713f,-0.335603f,-0.0747114f},{0.308263f,-0.338452f,-0.0923764f},{0.291325f,-0.340073f,-0.111836f}, -{0.280914f,-0.338613f,-0.125436f},{0.272721f,-0.342388f,-0.13397f},{0.265339f,-0.34143f,-0.145802f}, -{0.174396f,-0.105939f,-0.17647f},{0.265249f,-0.0190926f,-0.0887624f},{-0.0135334f,0.0801711f,-0.0390084f}, -{-0.110829f,-0.0155043f,-0.117257f},{-0.321427f,-0.122806f,-0.102132f},{-0.431456f,0.226842f,0.037002f}, -{-0.292598f,0.346593f,-0.244365f},{-0.289524f,0.376715f,-0.334407f},{-0.442336f,-0.0914504f,0.00441145f}, -{0.155136f,0.0992123f,-0.0394971f},{-0.220401f,0.0890261f,-0.0467252f},{-0.297453f,0.226758f,-0.0571235f}, -{-0.469004f,0.175049f,0.230147f},{-0.48101f,0.026893f,0.136169f},{-0.225771f,-0.290621f,0.23369f}, -{-0.47629f,0.208f,0.173692f},{-0.47476f,0.13559f,0.0549565f},{0.364159f,-0.322453f,-0.020726f}, -{0.357233f,-0.317565f,-0.0383332f},{0.351915f,-0.325732f,-0.0437799f},{0.321292f,-0.331642f,-0.0844281f}, -{0.298476f,-0.334195f,-0.104402f},{0.31126f,-0.0140253f,-0.0577152f},{0.2842f,-0.11408f,-0.124851f}, -{-0.493222f,0.0603582f,0.0957654f},{-0.39111f,-0.0106042f,0.244256f},{-0.332321f,0.414868f,-0.355223f}, -{-0.287962f,0.37674f,-0.343995f},{-0.288611f,0.321456f,-0.167165f},{0.191849f,0.0695348f,-0.0683f}, -{-0.292753f,0.346343f,-0.321507f},{0.272162f,0.0412913f,-0.0399923f},{-0.364384f,-0.290068f,0.113553f}, -{-0.290245f,0.303585f,-0.207402f},{-0.438266f,0.0121475f,0.198039f},{-0.353182f,-0.258943f,0.20755f}, -{-0.0692872f,-0.478042f,0.349088f},{0.493981f,-0.302543f,0.133571f},{0.49845f,-0.302164f,0.114215f}, -{0.5f,-0.302022f,0.0948523f},{0.499408f,-0.302125f,0.075451f},{0.494373f,-0.30255f,0.0561654f}, -{0.488656f,-0.304537f,0.0410662f},{0.483975f,-0.30199f,0.0326163f},{0.472972f,-0.30226f,0.0202695f}, -{-0.390042f,-0.0561139f,-0.0530401f},{-0.404878f,-0.0396f,-0.0322047f},{-0.261004f,0.172316f,-0.0231825f}, -{0.346963f,-0.318073f,-0.058892f},{0.339401f,-0.315096f,-0.0698112f},{0.331613f,-0.317353f,-0.078454f}, -{0.323736f,-0.317096f,-0.089862f},{0.31263f,-0.323109f,-0.0999839f},{0.305659f,-0.318221f,-0.10846f}, -{0.294913f,-0.320723f,-0.117089f},{0.286123f,-0.320543f,-0.12869f},{0.27793f,-0.3268f,-0.13651f}, -{0.267532f,-0.319366f,-0.146092f},{0.227559f,0.0757082f,-0.0364232f},{-0.203444f,0.0201601f,-0.0971351f}, -{0.243847f,0.07048f,-0.0308672f},{-0.289602f,0.281271f,-0.115675f},{-0.290766f,0.231555f,-0.0258319f}, -{0.384582f,-0.301264f,-0.00464292f},{-0.262683f,-0.4823f,0.299836f},{-0.372847f,-0.242108f,0.20863f}, -{-0.354024f,-0.299405f,0.114273f},{-0.411032f,-0.225543f,0.151416f},{-0.226414f,0.170818f,0.00573617f}, -{-0.409308f,0.226379f,0.00172344f},{-0.458477f,-0.115012f,0.0517025f},{0.367078f,-0.304923f,-0.0234912f}, -{0.363471f,-0.29817f,-0.0387833f},{0.35414f,-0.310646f,-0.0525321f},{0.440221f,-0.285418f,0.00548537f}, -{-0.489634f,0.0610013f,0.230771f},{-0.332147f,0.289515f,-0.319668f},{-0.256098f,-0.294389f,0.219202f}, -{-0.293325f,0.361718f,-0.28291f},{-0.292663f,0.32653f,-0.147854f},{-0.3932f,-0.261503f,0.116517f}, -{-0.28883f,0.301283f,-0.122131f},{-0.400505f,-0.231021f,0.173641f},{-0.429925f,0.00713804f,0.209775f}, -{0.498077f,-0.284345f,0.114189f},{0.499132f,-0.284261f,0.0948201f},{0.496688f,-0.284467f,0.075451f}, -{0.491164f,-0.284962f,0.0561461f},{0.487203f,-0.289791f,0.0432977f},{0.482676f,-0.28275f,0.0357609f}, -{0.473917f,-0.282885f,0.0238256f},{-0.447249f,0.22717f,0.0597537f},{-0.438143f,0.226983f,0.0499534f}, -{-0.489145f,0.0429632f,0.095849f},{0.357027f,-0.296839f,-0.0525642f},{0.350564f,-0.299006f,-0.0612585f}, -{0.342082f,-0.295997f,-0.0719462f},{0.333517f,-0.303662f,-0.0786791f},{0.326456f,-0.299733f,-0.091444f}, -{0.317511f,-0.300447f,-0.104061f},{0.306643f,-0.302846f,-0.112331f},{0.285698f,-0.30264f,-0.128067f}, -{-0.472245f,0.174682f,0.152979f},{-0.469969f,0.152953f,0.230263f},{-0.483094f,0.0261792f,0.114871f}, -{0.233037f,-0.0750651f,-0.134279f},{-0.497949f,0.10864f,0.137256f},{-0.28955f,0.281232f,-0.131738f}, -{0.309447f,-0.150008f,-0.116639f},{-0.378332f,-0.206643f,0.233356f},{-0.374178f,0.0174464f,0.323186f}, -{-0.154873f,0.253696f,0.0322498f},{-0.379097f,0.268429f,-0.0550014f},{-0.217025f,0.18946f,0.136144f}, -{-0.400029f,0.226224f,-0.00787111f},{0.371573f,-0.287991f,-0.0247452f},{0.294225f,-0.297347f,-0.119456f}, -{-0.418485f,0.228025f,0.0135044f},{-0.42152f,0.239954f,0.0242179f},{-0.146127f,0.0584097f,-0.0732259f}, -{-0.394048f,0.187267f,-0.0230346f},{-0.35032f,0.454493f,-0.352638f},{0.193405f,0.0027459f,-0.107791f}, -{0.081589f,0.100608f,-0.0416835f},{-0.0187743f,-0.00719588f,-0.126941f},{-0.292534f,0.361622f,-0.302228f}, -{-0.111498f,-0.470692f,0.322247f},{-0.395161f,0.417421f,-0.282634f},{-0.278509f,-0.48138f,0.29565f}, -{-0.452034f,0.0168805f,0.170657f},{0.249912f,-0.148297f,-0.151339f},{-0.473769f,0.209099f,0.18973f}, -{-0.337304f,-0.228623f,0.251394f},{-0.381907f,-0.26976f,0.114736f},{0.489659f,-0.269393f,0.131989f}, -{0.491434f,-0.262898f,0.113945f},{0.492939f,-0.262699f,0.0949745f},{0.491229f,-0.263754f,0.0761712f}, -{0.488727f,-0.26875f,0.0603775f},{0.482374f,-0.260397f,0.0549307f},{0.476316f,-0.262924f,0.0415485f}, -{-0.336732f,0.341301f,-0.320755f},{-0.370255f,0.226462f,-0.0519211f},{-0.486875f,0.0963699f,0.264159f}, -{-0.129002f,-0.0141925f,-0.118453f},{-0.473975f,0.0342111f,0.171956f},{0.384988f,-0.284827f,0.000218661f}, -{0.375277f,-0.280518f,-0.0187839f},{0.368731f,-0.277721f,-0.0397479f},{0.359631f,-0.277663f,-0.057773f}, -{0.353272f,-0.283605f,-0.0653548f},{0.346391f,-0.279721f,-0.0750522f},{0.32944f,-0.28219f,-0.0926465f}, -{0.319466f,-0.282113f,-0.104003f},{0.31234f,-0.282724f,-0.110183f},{0.29427f,-0.284422f,-0.118093f}, -{0.285814f,-0.285123f,-0.126459f},{0.275236f,-0.28192f,-0.137121f},{-0.299846f,0.416623f,-0.384965f}, -{-0.348873f,0.287103f,-0.285007f},{-0.481731f,0.112466f,0.261445f},{-0.490721f,0.0610913f,0.246835f}, -{-0.482721f,0.133417f,0.076885f},{-0.331993f,0.323031f,-0.336889f},{-0.361419f,-0.286872f,0.133931f}, -{0.0434166f,0.0389441f,-0.0937719f},{-0.381882f,-0.226649f,0.213209f},{-0.335645f,0.242629f,-0.188026f}, -{-0.464934f,0.0268287f,0.171313f},{-0.212331f,0.183621f,0.128427f},{-0.356551f,-0.2654f,0.192315f}, -{-0.464811f,-0.0710202f,0.0771808f},{0.0998135f,0.0067136f,-0.119469f},{-0.369374f,0.251902f,-0.150503f}, -{0.384724f,-0.263773f,-0.00166552f},{0.379303f,-0.262139f,-0.0197357f},{0.338102f,-0.275991f,-0.0849683f}, -{-0.260818f,0.0960612f,-0.036674f},{0.229462f,-0.0564998f,-0.129989f},{-0.0901997f,0.0448153f,-0.0784219f}, -{0.275017f,0.0672905f,0.000250814f},{-0.208537f,0.342838f,-0.0226938f},{-0.218665f,0.33842f,-0.0145654f}, -{-0.393907f,0.361911f,-0.225819f},{-0.288753f,0.291296f,-0.115675f},{-0.357632f,0.0262114f,0.336015f}, -{-0.2802f,-0.319816f,0.151204f},{0.00395806f,0.491913f,-0.130401f},{-0.108546f,0.0785827f,-0.037928f}, -{0.375007f,-0.257644f,-0.0355551f},{0.370068f,-0.261085f,-0.0441015f},{0.363824f,-0.260159f,-0.0559853f}, -{0.357625f,-0.260693f,-0.0655927f},{0.348629f,-0.261451f,-0.0752387f},{0.33897f,-0.262281f,-0.0850198f}, -{0.329677f,-0.263091f,-0.0945757f},{0.319382f,-0.263979f,-0.103945f},{0.305614f,-0.265239f,-0.113938f}, -{0.287537f,-0.265188f,-0.132986f},{0.0602585f,-0.0592071f,-0.144002f},{-0.374506f,0.339243f,-0.209807f}, -{-0.48773f,0.113192f,0.191936f},{-0.337098f,0.00798691f,0.287521f},{-0.0892158f,-0.452095f,-0.183222f}, -{-0.147966f,0.251985f,0.00030869f},{-0.317626f,-0.201383f,0.276441f},{-0.429514f,0.00733738f,0.2843f}, -{-0.456201f,0.191775f,0.0726279f},{-0.368409f,0.306633f,-0.168027f},{0.371798f,-0.0463908f,0.0113694f}, -{-0.449712f,-0.0191184f,0.115456f},{0.388711f,-0.241812f,-0.000347237f},{0.29854f,-0.261246f,-0.123199f}, -{0.193322f,0.0785634f,-0.0559982f},{-0.445076f,0.208418f,0.0577345f},{-0.446632f,0.114652f,0.000135062f}, -{-0.291299f,0.361577f,-0.321514f},{-0.143825f,0.0790135f,-0.0590656f},{-0.375097f,-0.0163917f,0.247973f}, -{-0.363078f,0.304755f,-0.189846f},{-0.384164f,0.248281f,-0.0467959f},{-0.486393f,0.0956818f,0.230578f}, -{0.395592f,-0.243368f,0.0176072f},{0.382673f,-0.240442f,-0.0205845f},{0.375734f,-0.24106f,-0.0366226f}, -{0.370049f,-0.241542f,-0.0461528f},{0.361844f,-0.24133f,-0.0578631f},{0.35668f,-0.247207f,-0.0655027f}, -{0.344455f,-0.24369f,-0.075348f},{0.336545f,-0.248879f,-0.0850455f},{0.329247f,-0.244101f,-0.0926529f}, -{0.319954f,-0.245812f,-0.104106f},{0.310488f,-0.246629f,-0.113681f},{0.302045f,-0.247388f,-0.123456f}, -{0.292071f,-0.244236f,-0.134555f},{0.191746f,-0.131372f,-0.183711f},{-0.0560657f,0.0633034f,-0.05722f}, -{-0.33852f,-0.267425f,0.209106f},{-0.408189f,-0.0210411f,0.207968f},{-0.355092f,0.00830841f,0.306119f}, -{-0.28775f,0.412212f,-0.363345f},{-0.0922511f,0.398026f,-0.094878f},{-0.470445f,0.153024f,0.249542f}, -{-0.306122f,0.290994f,-0.258841f},{0.394518f,-0.131931f,0.151461f},{0.0388572f,0.456101f,-0.170921f}, -{0.403649f,-0.224996f,0.0363525f},{0.398505f,-0.222951f,0.0189062f},{0.211135f,-0.130671f,-0.169917f}, -{0.0247484f,0.09219f,-0.0328735f},{-0.217874f,-0.35478f,0.114993f},{-0.148172f,0.0707695f,-0.0669753f}, -{-0.445616f,0.0105785f,0.0410791f},{-0.395753f,-0.226346f,0.190772f},{-0.289807f,0.311373f,-0.128562f}, -{-0.413726f,-0.00173626f,0.226334f},{-0.473853f,0.17447f,0.114408f},{-0.372769f,-0.278968f,0.115f}, -{0.407103f,-0.224147f,0.0562876f},{0.393553f,-0.221459f,0.00189706f},{0.389463f,-0.221806f,-0.00772964f}, -{0.383238f,-0.222353f,-0.0206103f},{0.376756f,-0.222925f,-0.0331693f},{0.369998f,-0.223485f,-0.0430468f}, -{0.360358f,-0.224282f,-0.0560239f},{0.344854f,-0.2256f,-0.0719269f},{0.329452f,-0.226874f,-0.0912253f}, -{0.318147f,-0.227851f,-0.107347f},{0.311839f,-0.228333f,-0.116691f},{0.302617f,-0.2256f,-0.126182f}, -{-0.126938f,0.0753609f,-0.0523327f},{-0.418189f,-0.0564933f,-0.0256004f},{-0.201379f,0.320523f,-0.0340053f}, -{0.289576f,0.0437799f,-0.0211054f},{-0.289962f,0.361538f,-0.33761f},{0.389624f,-0.0725443f,0.0563262f}, -{-0.276998f,-0.313218f,0.167654f},{-0.40718f,-0.221736f,0.171834f},{0.0390244f,0.449098f,-0.179878f}, -{-0.332185f,0.305341f,-0.333899f},{-0.312926f,-0.273162f,0.222655f},{0.408614f,-0.223125f,0.0928395f}, -{0.407874f,-0.22135f,0.0749108f},{-0.428935f,-0.0908717f,-0.0191826f},{-0.0479631f,0.471458f,-0.091399f}, -{-0.425977f,-0.0560368f,-0.0160638f},{0.0831967f,-0.0666924f,-0.148786f},{-0.288489f,0.361519f,-0.347256f}, -{-0.129748f,-0.0760812f,-0.133899f},{-0.479653f,0.210064f,0.146323f},{-0.343356f,0.357937f,-0.306935f}, -{-0.486457f,0.0412077f,0.153989f},{0.391669f,-0.126678f,0.159185f},{-0.362853f,0.219581f,-0.0601395f}, -{0.0237516f,-0.097611f,-0.205505f},{-0.359548f,0.440365f,-0.343513f},{0.250683f,0.061297f,-0.0380052f}, -{-0.352397f,0.2565f,-0.259509f},{0.406704f,-0.202302f,0.075721f},{0.405707f,-0.202399f,0.0564484f}, -{0.403431f,-0.202592f,0.0372078f},{0.399534f,-0.202932f,0.0179673f},{0.395135f,-0.203305f,0.00197423f}, -{0.390936f,-0.203665f,-0.00767819f},{0.383875f,-0.204238f,-0.0204431f},{0.376171f,-0.204868f,-0.0333237f}, -{0.36902f,-0.205453f,-0.0429439f},{0.359419f,-0.205299f,-0.057683f},{0.346622f,-0.20825f,-0.0732967f}, -{0.338899f,-0.207903f,-0.0846403f},{0.33007f,-0.208643f,-0.0942606f},{0.320938f,-0.209492f,-0.107334f}, -{0.31209f,-0.207247f,-0.117662f},{0.304186f,-0.208276f,-0.124137f},{-0.348384f,0.342317f,-0.284036f}, -{-0.463435f,0.174162f,0.0758754f},{-0.0486512f,0.452526f,-0.109765f},{-0.437288f,-0.036912f,0.0178515f}, -{-0.287653f,0.361377f,-0.357017f},{-0.356146f,0.241433f,-0.151095f},{-0.195598f,0.155313f,0.075914f}, -{-0.148108f,-0.0737147f,-0.130735f},{0.14133f,-0.107103f,-0.194894f},{-0.468625f,0.0943635f,0.0377994f}, -{-0.200338f,0.221523f,0.0386161f},{-0.221958f,0.0961384f,-0.0375936f},{-0.434401f,-0.0554902f,-3.21349e-05f}, -{-0.375329f,0.247966f,-0.0918041f},{-0.489807f,0.0955532f,0.192039f},{-0.465647f,-0.0924215f,0.135082f}, -{-0.476965f,0.210109f,0.155982f},{-0.439147f,-0.0508151f,0.012752f},{0.133317f,0.083007f,-0.0597923f}, -{-0.302971f,0.361506f,-0.204521f},{-0.319453f,-0.286955f,0.19263f},{-0.214652f,0.193659f,0.122118f}, -{0.404177f,-0.184483f,0.114234f},{0.405186f,-0.184412f,0.0949552f},{0.406189f,-0.184335f,0.0756825f}, -{0.405534f,-0.184406f,0.0564291f},{0.403225f,-0.184631f,0.0372078f},{0.398781f,-0.185023f,0.017948f}, -{0.393939f,-0.18692f,0.00299671f},{0.390113f,-0.184129f,-0.00556893f},{0.384145f,-0.18618f,-0.0205524f}, -{0.376242f,-0.186766f,-0.0365133f},{0.37111f,-0.187139f,-0.0461786f},{0.366667f,-0.187512f,-0.0558181f}, -{0.358789f,-0.187203f,-0.0704929f},{0.350661f,-0.193286f,-0.078184f},{0.343761f,-0.18836f,-0.0895662f}, -{0.333304f,-0.194669f,-0.0972444f},{0.325401f,-0.188663f,-0.107752f},{0.308463f,-0.187685f,-0.11752f}, -{-0.433809f,0.209929f,0.0358059f},{-0.345034f,0.306595f,-0.289315f},{-0.382981f,0.261805f,-0.0373814f}, -{-0.341838f,0.341352f,-0.304601f},{-0.388113f,0.346079f,-0.204952f},{-0.398852f,0.0174142f,-0.00798686f}, -{-0.412035f,0.0197743f,-0.00122181f},{-0.296122f,-0.0897206f,-0.106923f},{-0.301948f,0.364516f,-0.223478f}, -{-0.386737f,-0.241124f,0.18856f},{-0.319112f,0.290537f,-0.321147f},{-0.338076f,0.206218f,-0.0533487f}, -{-0.12697f,-0.407267f,-0.133867f},{-0.337954f,0.304826f,-0.320568f},{-0.419134f,0.21025f,0.0134851f}, -{-0.388872f,0.226096f,-0.0177036f},{-0.388595f,0.345294f,-0.132086f},{0.117434f,0.0805762f,-0.0601845f}, -{-0.29901f,0.363352f,-0.24279f},{-0.311588f,-0.313225f,0.14451f},{-0.214331f,0.203376f,0.0319475f}, -{0.393611f,-0.167204f,0.168843f},{0.398113f,-0.166876f,0.152773f},{0.40091f,-0.166696f,0.133513f}, -{0.402305f,-0.166606f,0.114221f},{0.403534f,-0.166528f,0.094923f},{0.404768f,-0.166451f,0.0756503f}, -{0.404312f,-0.166496f,0.0564226f},{0.401148f,-0.166773f,0.037195f},{0.395868f,-0.167249f,0.017993f}, -{0.392692f,-0.165918f,0.00290668f},{0.390479f,-0.169133f,-0.00570398f},{0.328179f,-0.168355f,-0.107971f}, -{-0.242484f,0.0954567f,-0.0339667f},{0.0977235f,-0.07684f,-0.168927f},{-0.184415f,0.0829427f,-0.0602038f}, -{-0.228298f,-0.255497f,0.259722f},{-0.126128f,0.11471f,0.0564998f},{-0.146963f,0.11898f,0.0773223f}, -{-0.430079f,0.282325f,0.0953989f},{-0.335414f,0.294782f,0.073824f},{-0.366808f,0.23007f,-0.0692132f}, -{-0.0931578f,0.0893219f,0.149326f},{-0.305775f,0.448204f,-0.372451f},{-0.316032f,0.450011f,-0.373281f}, -{-0.188209f,0.132562f,0.150548f},{-0.206929f,0.154124f,0.168522f},{-0.317549f,0.453014f,-0.358863f}, -{-0.130333f,0.0906209f,0.167557f},{-0.303402f,0.433298f,-0.345352f},{-0.308443f,0.443632f,-0.350227f}, -{-0.179335f,0.124279f,0.0366934f},{-0.191168f,0.128189f,0.0249896f},{-0.313228f,0.437652f,-0.336478f}, -{-0.322366f,0.450899f,-0.34361f},{-0.444799f,0.276518f,0.0951288f},{-0.337523f,0.455567f,-0.337385f}, -{-0.356281f,0.455972f,-0.341931f},{-0.311697f,0.42108f,-0.317887f},{-0.321691f,0.43542f,-0.323424f}, -{-0.337471f,0.449105f,-0.326665f},{-0.389502f,0.308234f,-0.129102f},{-0.298617f,0.296402f,0.132041f}, -{-0.215308f,0.160136f,0.179551f},{-0.392595f,0.260873f,0.244687f},{-0.335825f,0.441696f,-0.317353f}, -{-0.355593f,0.452333f,-0.320601f},{-0.167567f,0.0814058f,0.173416f},{-0.355805f,0.274969f,0.230449f}, -{-0.163104f,0.121951f,0.0571043f},{-0.172686f,0.125867f,0.0598116f},{-0.183509f,0.13296f,0.0551494f}, -{-0.438111f,0.274165f,0.0738883f},{-0.39037f,0.280261f,0.206212f},{-0.286933f,0.295437f,0.09891f}, -{-0.189541f,0.367107f,0.0278641f},{-0.310167f,0.405755f,-0.299785f},{-0.318315f,0.4167f,-0.302633f}, -{-0.324835f,0.428173f,-0.309591f},{-0.337414f,0.432629f,-0.303334f},{-0.36994f,0.449928f,-0.321591f}, -{0.230948f,0.0913283f,0.187473f},{-0.372377f,0.296679f,0.116266f},{0.270329f,-0.11226f,-0.131115f}, -{-0.109241f,0.0828205f,0.172181f},{-0.36284f,0.28774f,-0.188508f},{-0.352358f,0.287277f,-0.265683f}, -{-0.200942f,0.153596f,0.15177f},{0.00113499f,-0.0836629f,0.330485f},{-0.317067f,0.296203f,0.0975274f}, -{-0.397412f,0.274454f,0.215987f},{-0.429121f,0.278949f,0.07693f},{-0.323337f,0.296878f,-0.0186875f}, -{0.0342465f,0.466442f,-0.171712f},{0.0799106f,0.0706215f,-0.0687952f},{-0.341639f,0.218289f,-0.0877785f}, -{-0.431449f,0.283406f,0.132639f},{-0.330237f,0.42272f,-0.296106f},{-0.355143f,0.44095f,-0.302074f}, -{-0.338597f,0.314241f,-0.0275489f},{0.0233915f,-0.0809749f,0.338073f},{-0.0720588f,0.068403f,0.18575f}, -{-0.37576f,0.276531f,0.223311f},{-0.127504f,0.0984277f,0.151005f},{-0.354069f,0.0557667f,-0.0424938f}, -{-0.371419f,0.295662f,0.151609f},{-0.415745f,0.27138f,0.0370792f},{-0.370236f,0.315739f,-0.039973f}, -{-0.16884f,0.110607f,0.128999f},{-0.0144401f,0.113746f,0.11509f},{-0.160699f,0.0890775f,0.163107f}, -{-0.307247f,0.393351f,-0.284814f},{-0.315491f,0.401235f,-0.281521f},{-0.32171f,0.412205f,-0.289958f}, -{-0.369342f,0.447079f,-0.307064f},{-0.376493f,0.441323f,-0.300775f},{-0.387566f,0.438835f,-0.315012f}, -{-0.0306775f,0.108562f,0.111765f},{-0.451262f,0.26457f,0.0748851f},{-0.294997f,0.272962f,0.232475f}, -{-0.394325f,0.290004f,0.07675f},{-0.279422f,0.286518f,0.190367f},{-0.320758f,0.295894f,0.168618f}, -{-0.342372f,0.27374f,0.234976f},{-0.0900518f,0.0837143f,0.156786f},{-0.0354748f,0.100672f,0.136857f}, -{-0.109858f,0.0888846f,0.162252f},{0.176268f,0.121777f,0.172683f},{-0.166596f,0.0948201f,0.152947f}, -{-0.0411016f,0.104318f,0.115881f},{-0.149034f,0.107829f,0.128915f},{-0.186428f,-0.134111f,-0.131449f}, -{0.240864f,0.0891547f,0.184547f},{-0.266072f,0.309135f,0.0362561f},{-0.353317f,0.293238f,0.0387062f}, -{0.015141f,0.485644f,-0.152741f},{0.325215f,-0.0565898f,-0.0726407f},{-0.335562f,0.417601f,-0.281727f}, -{-0.35414f,0.431452f,-0.287849f},{0.15632f,0.109533f,0.200926f},{-0.111652f,0.107849f,0.112041f}, -{0.171162f,0.125732f,0.164606f},{0.264869f,0.0522877f,-0.0369055f},{0.400203f,-0.28601f,0.00717664f}, -{-0.319388f,0.279194f,0.223626f},{-0.409752f,0.281322f,0.0571364f},{-0.433713f,0.267953f,0.0543648f}, -{-0.267326f,0.278653f,0.208997f},{-0.0725668f,0.100846f,0.0960612f},{-0.261191f,0.290402f,0.133031f}, -{-0.183837f,0.113469f,0.152259f},{-0.464696f,0.244044f,0.0771615f},{0.260529f,0.0686216f,0.202148f}, -{-0.0344844f,0.0789814f,-0.0375743f},{-0.450934f,-0.0369441f,0.0577474f},{-0.196942f,0.340021f,-0.0344555f}, -{0.0789781f,0.0928973f,-0.0507379f},{0.214067f,0.0979454f,0.190264f},{0.205669f,0.10882f,0.181866f}, -{0.00593869f,0.48718f,-0.148947f},{-0.279383f,0.27774f,0.218797f},{-0.309968f,0.385808f,-0.260873f}, -{-0.320372f,0.399363f,-0.266821f},{-0.353239f,0.425633f,-0.278313f},{-0.371496f,0.433343f,-0.284197f}, -{-0.38938f,0.434545f,-0.300672f},{-0.380595f,0.294466f,0.150002f},{-0.14542f,-0.415112f,-0.13224f}, -{-0.0912929f,0.076422f,0.171576f},{0.155104f,0.127051f,0.16802f},{-0.335671f,0.296556f,0.0937076f}, -{-0.351838f,0.295617f,0.0773287f},{-0.243693f,0.319585f,0.0538697f},{0.137073f,0.132883f,0.152182f}, -{-0.47013f,0.156355f,0.0566799f},{-0.462323f,-0.0917205f,0.0598438f},{0.11935f,0.132227f,0.153474f}, -{-0.440922f,-0.0770072f,0.00667504f},{-0.146082f,0.0971866f,-0.0368348f},{-0.355728f,0.131931f,-0.0438699f}, -{-0.479653f,0.0475676f,0.192245f},{-0.35839f,0.294383f,0.0687695f},{-0.146603f,0.0898878f,0.168136f}, -{0.0804765f,0.132845f,0.132523f},{-0.33106f,0.404347f,-0.259246f},{-0.340597f,0.41281f,-0.265162f}, -{-0.355246f,0.418919f,-0.262332f},{-0.386293f,0.430526f,-0.2861f},{-0.461538f,-0.072152f,0.0592135f}, -{-0.288309f,0.0437028f,-0.0627182f},{-0.343336f,0.296164f,0.08347f},{0.0623806f,0.130375f,0.135288f}, -{0.0797948f,-0.0629498f,0.318909f},{-0.230877f,0.263702f,0.128967f},{-0.365876f,0.310183f,-0.182168f}, -{-0.464966f,-0.0927365f,0.0772773f},{-0.47721f,0.0314074f,0.22461f},{-0.42026f,0.00966527f,0.0123597f}, -{-0.406125f,0.187711f,-0.0143918f},{-0.177888f,0.0991286f,0.151969f},{0.027237f,0.126073f,0.112279f}, -{0.0190058f,0.122922f,0.118691f},{0.00530206f,0.119572f,0.112807f},{-0.3051f,0.373756f,-0.243593f}, -{-0.313459f,0.384123f,-0.244114f},{-0.322089f,0.394482f,-0.249677f},{-0.374557f,0.421697f,-0.264667f}, -{-0.378088f,0.427452f,-0.273914f},{0.219044f,0.102254f,0.177596f},{-0.387206f,0.269207f,-0.0319604f}, -{-0.48074f,0.0297547f,0.0799074f},{-0.393991f,0.286853f,0.0585898f},{0.0944375f,0.0846982f,0.234976f}, -{0.0764445f,0.126478f,0.16584f},{-0.388441f,-0.110948f,-0.0707823f},{-0.364101f,0.229986f,-0.0788528f}, -{-0.480361f,0.227729f,0.152683f},{-0.388557f,0.290627f,-0.0904215f},{0.308257f,0.0406997f,0.00110609f}, -{-0.400929f,-0.07048f,-0.0452718f},{-0.408286f,-0.0569885f,-0.0353236f},{-0.411064f,0.00485518f,0.00178774f}, -{-0.375721f,0.00127326f,-0.0385518f},{-0.385296f,0.295219f,0.110813f},{-0.0561622f,0.103682f,0.0916241f}, -{-0.467249f,0.209781f,0.0951224f},{-0.335041f,0.401756f,-0.24441f},{-0.355632f,0.412006f,-0.246732f}, -{-0.391798f,0.414746f,-0.265683f},{0.470805f,-0.247876f,0.0585576f},{-0.238587f,0.32462f,0.00147907f}, -{-0.109151f,0.110074f,0.0755603f},{-0.360043f,0.257895f,0.258191f},{0.101537f,0.0912768f,0.225864f}, -{-0.167053f,0.116504f,0.115141f},{0.287023f,0.0577538f,-0.0010739f},{0.284856f,0.0531816f,-0.0135301f}, -{-0.468876f,0.174335f,0.0951802f},{-0.399045f,-0.0575158f,-0.0449503f},{-0.400093f,0.378727f,-0.226436f}, -{-0.374956f,0.293463f,0.0760297f},{-0.425462f,0.277631f,0.0640816f},{-0.147458f,0.119385f,0.0581653f}, -{-0.307588f,0.374297f,-0.229079f},{-0.317787f,0.383943f,-0.225871f},{-0.325491f,0.393126f,-0.235574f}, -{-0.350609f,0.407144f,-0.240352f},{-0.372808f,0.413678f,-0.247793f},{0.47703f,-0.246468f,0.0764284f}, -{0.457545f,-0.244719f,0.054577f},{-0.392794f,0.206263f,-0.0201601f},{-0.318044f,0.274557f,0.233832f}, -{-0.19529f,0.141005f,0.15885f},{-0.418903f,-0.00291306f,0.195994f},{-0.110251f,0.109939f,0.0938877f}, -{0.336957f,0.0148291f,0.024996f},{0.329703f,0.0246037f,0.0209897f},{0.321279f,0.0350921f,0.0179866f}, -{0.312546f,0.0445259f,0.0194785f},{0.300553f,0.0499855f,0.00521528f},{-0.0685219f,-0.132896f,-0.203331f}, -{-0.244992f,0.32716f,0.0155172f},{-0.446407f,-0.0366998f,0.153982f},{-0.306334f,0.295019f,0.0873348f}, -{-0.336578f,0.396997f,-0.226526f},{-0.354583f,0.403067f,-0.225382f},{0.457339f,-0.237819f,0.0758818f}, -{0.439282f,-0.242822f,0.055696f},{-0.147137f,0.104035f,0.139082f},{-0.0884827f,0.102627f,0.0958747f}, -{-0.0929713f,0.0635414f,0.192791f},{0.201521f,0.0841066f,0.217446f},{-0.199193f,0.357339f,0.0339603f}, -{0.302103f,0.0538632f,0.0212405f},{0.290585f,0.0616122f,0.0160509f},{0.26568f,0.0744992f,0.000971048f}, -{-0.43916f,-0.103328f,-0.00632775f},{-0.442478f,-0.111842f,0.00203854f},{-0.497402f,0.0911225f,0.166406f}, -{-0.402846f,0.203852f,-0.0139802f},{-0.457789f,-0.0685766f,0.15732f},{0.264181f,0.0370149f,-0.0539018f}, -{-0.352989f,0.266654f,-0.266223f},{-0.349895f,0.305231f,-0.265753f},{-0.392872f,0.00293882f,-0.0182309f}, -{-0.483062f,0.0447574f,0.171904f},{-0.24251f,-0.278364f,0.244037f},{-0.461667f,-0.114781f,0.0613742f}, -{-0.0333334f,0.476094f,-0.111418f},{-0.308463f,0.37058f,-0.211029f},{-0.317376f,0.379827f,-0.208926f}, -{-0.372178f,0.404051f,-0.227247f},{-0.379489f,0.405768f,-0.237549f},{-0.299357f,0.269027f,-0.00139544f}, -{0.477088f,-0.244282f,0.0955082f},{0.439153f,-0.236635f,0.0765249f},{0.421128f,-0.237825f,0.0749429f}, -{0.419314f,-0.242944f,0.0557153f},{-0.460374f,0.110331f,0.0227003f},{-0.103575f,0.065895f,0.19373f}, -{-0.261287f,0.298331f,0.0754188f},{-0.243089f,0.300878f,0.0763898f},{-0.236362f,0.293277f,0.0843896f}, -{-0.454072f,0.27439f,0.134825f},{0.354757f,-0.00544677f,0.0437092f},{0.339497f,0.0163017f,0.0414006f}, -{0.332623f,0.0255554f,0.0390341f},{0.32326f,0.0375487f,0.037285f},{0.283171f,0.0696569f,0.0240378f}, -{0.269686f,0.0779203f,0.0181924f},{0.245751f,0.0899457f,0.00502237f},{-0.405611f,-0.0968008f,-0.0510208f}, -{-0.438028f,-0.0347256f,0.172837f},{-0.383103f,0.00792259f,-0.0261085f},{-0.338809f,0.360342f,-0.318999f}, -{-0.489891f,0.0399794f,0.133591f},{0.0094627f,-0.081798f,0.332973f},{-0.329896f,0.387981f,-0.203415f}, -{-0.340217f,0.394778f,-0.20973f},{-0.355574f,0.314614f,-0.0240507f},{-0.377991f,0.305109f,-0.0350792f}, -{0.460464f,-0.236353f,0.0941063f},{-0.275962f,0.296003f,0.0702357f},{0.100617f,0.108286f,0.205749f}, -{-0.0984117f,0.10646f,0.0950516f},{0.356628f,-0.00610268f,0.058384f},{0.349535f,0.00374265f,0.0549243f}, -{0.339934f,0.017022f,0.0585833f},{0.315807f,0.0460242f,0.0391756f},{0.306816f,0.0548278f,0.0411177f}, -{0.294232f,0.0638886f,0.0342047f},{0.250484f,0.0926272f,0.0191312f},{0.233706f,0.102003f,0.0171892f}, -{-0.147465f,0.036166f,-0.0884216f},{-0.396781f,0.341796f,-0.169486f},{-0.445191f,0.0280056f,0.0249381f}, -{-0.455976f,-0.0343011f,0.117044f},{-0.399013f,0.00875856f,-0.00724091f},{-0.127176f,0.0845696f,-0.0427317f}, -{-0.198408f,0.156471f,0.135269f},{0.115016f,-0.0638114f,0.317102f},{-0.304714f,0.35912f,-0.186592f}, -{-0.31072f,0.367512f,-0.188766f},{-0.320218f,0.377171f,-0.190232f},{-0.355548f,0.397447f,-0.206238f}, -{-0.373445f,0.395544f,-0.207402f},{0.477088f,-0.245683f,0.114575f},{0.451506f,-0.234211f,0.100293f}, -{0.441243f,-0.234005f,0.0964471f},{0.431976f,-0.235073f,0.0881644f},{0.412736f,-0.234275f,0.0805955f}, -{0.0239703f,0.103148f,0.190881f},{0.332636f,0.0271889f,0.0590271f},{0.32333f,0.0394714f,0.0564226f}, -{0.284232f,0.0735796f,0.0411948f},{0.27004f,0.0828591f,0.03506f},{0.212665f,0.113f,0.0187711f}, -{-0.478534f,0.0301598f,0.255979f},{-0.479448f,0.196611f,0.117495f},{-0.356821f,0.305463f,-0.227144f}, -{-0.460966f,0.191904f,0.0822739f},{-0.367432f,0.287933f,-0.149931f},{-0.45667f,-0.0321533f,0.0962156f}, -{0.248201f,0.0532009f,-0.0508022f},{-0.0157262f,0.109566f,0.133494f},{-0.284592f,0.29538f,0.113746f}, -{-0.0297643f,0.486023f,-0.0808334f},{-0.333722f,0.385505f,-0.187061f},{-0.342976f,0.390939f,-0.191402f}, -{-0.355657f,0.392547f,-0.189936f},{0.458824f,-0.236513f,0.115424f},{0.421507f,-0.235311f,0.0960162f}, -{-0.25921f,0.294865f,0.0855085f},{0.355419f,-0.00317029f,0.0764863f},{0.349342f,0.00503524f,0.0742613f}, -{0.307035f,0.0570336f,0.0588727f},{0.295138f,0.0672519f,0.0544034f},{0.262233f,0.0901515f,0.0422559f}, -{0.250394f,0.0972316f,0.0371307f},{0.228137f,0.107701f,0.0250796f},{0.19574f,0.119154f,0.0164239f}, -{-0.312656f,0.361332f,-0.372072f},{-0.481377f,0.209865f,0.117417f},{-0.443989f,-0.0430726f,0.168753f}, -{-0.459654f,-0.0406611f,0.112292f},{-0.44478f,0.278126f,0.137809f},{-0.390061f,0.280788f,0.0173564f}, -{-0.128552f,0.115482f,0.0745571f},{-0.371072f,0.297926f,-0.00272658f},{-0.304694f,0.354104f,-0.169692f}, -{-0.314495f,0.36494f,-0.168612f},{-0.32263f,0.3724f,-0.170059f},{-0.369805f,0.39173f,-0.192058f}, -{-0.394872f,0.379126f,-0.208585f},{0.474046f,-0.249818f,0.134298f},{0.453641f,-0.23443f,0.115418f}, -{0.440137f,-0.234076f,0.110331f},{0.420954f,-0.237388f,0.115302f},{0.413598f,-0.233452f,0.100183f}, -{0.25294f,-0.111566f,-0.137037f},{0.0383942f,0.104601f,0.196084f},{0.115466f,0.108762f,0.204881f}, -{0.34041f,0.0172792f,0.0793672f},{0.333317f,0.0269252f,0.0777274f},{0.324096f,0.0392913f,0.075078f}, -{0.286187f,0.0757339f,0.0602232f},{0.274708f,0.0836243f,0.0544677f},{0.264985f,0.0908846f,0.0569564f}, -{0.240156f,0.103527f,0.038539f},{0.229713f,0.109469f,0.0399409f},{0.210678f,0.118607f,0.039465f}, -{0.178737f,0.124163f,0.0155043f},{-0.478348f,0.214565f,0.168824f},{-0.0894087f,-0.0338703f,-0.131456f}, -{0.0999292f,-0.0885438f,-0.188676f},{-0.339047f,0.283894f,-0.305527f},{0.0879553f,-0.0823446f,0.351108f}, -{0.225797f,0.0867239f,0.198463f},{0.122147f,0.12426f,0.179261f},{-0.335253f,0.38092f,-0.170773f}, -{-0.348378f,0.389055f,-0.179621f},{-0.377785f,0.384843f,-0.184393f},{-0.389978f,0.37728f,-0.190778f}, -{0.459808f,-0.240565f,0.131944f},{0.439822f,-0.235362f,0.119745f},{0.411418f,-0.231735f,0.108935f}, -{0.407669f,-0.22553f,0.113996f},{0.305698f,0.0594129f,0.0766921f},{0.287164f,0.0762033f,0.0766535f}, -{0.249706f,0.100743f,0.0565255f},{0.196254f,0.123835f,0.0345841f},{0.186711f,0.125617f,0.0280377f}, -{0.172474f,0.127231f,0.0207132f},{0.154731f,0.12907f,0.017665f},{-0.374281f,-0.0746278f,-0.0723256f}, -{-0.498122f,0.0952895f,0.121231f},{-0.163258f,0.379737f,-0.0499984f},{0.162281f,0.123822f,0.175261f}, -{-0.44386f,-0.127134f,0.185685f},{-0.316205f,0.359931f,-0.151564f},{-0.354854f,0.385492f,-0.168085f}, -{-0.374268f,0.380804f,-0.170631f},{0.440259f,-0.239105f,0.134111f},{-0.0803994f,0.0880743f,0.144413f}, -{0.339741f,0.0176715f,0.098492f},{0.332796f,0.0273818f,0.0974567f},{0.322424f,0.0410083f,0.0941771f}, -{0.316019f,0.0491302f,0.0851934f},{0.274972f,0.0856821f,0.0744221f},{0.266425f,0.0920099f,0.0758175f}, -{0.231353f,0.11098f,0.0588534f},{0.212369f,0.120221f,0.0584097f},{0.188364f,0.127661f,0.0408733f}, -{0.17457f,0.130658f,0.0373557f},{0.136275f,0.130671f,0.0183531f},{0.11834f,0.0629433f,-0.0799717f}, -{-0.380486f,0.225883f,-0.0275361f},{-0.479396f,0.130022f,0.0632584f},{-0.477133f,0.0945629f,0.0505965f}, -{-0.367663f,0.295219f,0.084216f},{-0.0727276f,0.458262f,-0.0540883f},{-0.085576f,0.449574f,-0.0604868f}, -{-0.338063f,0.376001f,-0.154259f},{0.456767f,-0.248269f,0.14977f},{0.419372f,-0.244224f,0.134716f}, -{0.407443f,-0.240468f,0.132735f},{0.306257f,0.058847f,0.095251f},{0.287801f,0.0757339f,0.0952188f}, -{0.252381f,0.101f,0.075168f},{0.200768f,0.124543f,0.0515546f},{0.191335f,0.128581f,0.0587441f}, -{0.156165f,0.134021f,0.0397479f},{0.136558f,0.135256f,0.0385776f},{0.118996f,0.130954f,0.0188997f}, -{0.100482f,0.129096f,0.0171442f},{-0.0688242f,-0.0185718f,-0.127745f},{-0.458008f,-0.0671618f,0.0515482f}, -{0.420054f,-0.285148f,0.00508667f},{-0.350346f,0.442442f,-0.351911f},{-0.452863f,-0.0364875f,0.134729f}, -{-0.095042f,0.443433f,-0.0547635f},{-0.0495f,-0.189582f,0.356001f},{-0.303575f,0.339359f,-0.132311f}, -{-0.31009f,0.346568f,-0.131603f},{-0.320289f,0.356259f,-0.132285f},{-0.330321f,0.368245f,-0.145224f}, -{-0.354294f,0.378142f,-0.14941f},{-0.37131f,0.375396f,-0.154053f},{0.456825f,-0.25558f,0.159062f}, -{0.438388f,-0.247921f,0.153198f},{0.423404f,-0.248301f,0.148227f},{-0.40898f,0.277001f,0.0416578f}, -{-0.045976f,0.106029f,0.0999646f},{-0.103595f,0.104698f,0.116903f},{0.34005f,0.0165011f,0.116993f}, -{0.333021f,0.0263915f,0.116016f},{0.322456f,0.0400566f,0.114016f},{0.275718f,0.0854314f,0.0930131f}, -{0.266522f,0.0921321f,0.096775f},{0.242156f,0.106968f,0.0805376f},{0.231269f,0.112427f,0.0765956f}, -{0.213617f,0.120929f,0.0772001f},{0.17329f,0.133198f,0.055188f},{0.116591f,0.13552f,0.0403331f}, -{0.0802193f,0.127379f,0.0192598f},{-0.493428f,0.0950774f,0.0955275f},{0.2484f,0.0440115f,-0.0601652f}, -{-0.370294f,0.253812f,-0.169512f},{-0.111022f,0.432783f,-0.0540754f},{-0.341767f,0.371763f,-0.140233f}, -{0.00490979f,0.107778f,0.165281f},{0.354532f,-0.00598052f,0.126903f},{0.306489f,0.0576638f,0.11372f}, -{0.251905f,0.101791f,0.0923829f},{0.155001f,0.136703f,0.0576573f},{0.0638982f,0.126054f,0.0237292f}, -{-0.471158f,0.227446f,0.0947944f},{0.210871f,-0.0339346f,-0.115122f},{-0.364416f,0.301225f,-0.175711f}, -{-0.415199f,0.171673f,-0.00596764f},{-0.0313398f,0.106003f,0.124022f},{-0.373933f,-0.114942f,0.265239f}, -{-0.30726f,0.337359f,-0.118234f},{-0.354751f,0.372734f,-0.135635f},{-0.365773f,0.371879f,-0.139565f}, -{-0.377734f,0.368914f,-0.148497f},{-0.249732f,0.278743f,0.182431f},{0.414472f,-0.255606f,0.157571f}, -{-0.366409f,0.244616f,0.275818f},{0.0588116f,0.123977f,0.0193756f},{-0.0135591f,-0.0344555f,-0.136722f}, -{-0.334996f,-0.0174078f,-0.070943f},{-0.331845f,0.0327707f,-0.0486544f},{-0.296154f,0.189544f,-0.0344876f}, -{-0.311447f,0.0182952f,-0.068628f},{-0.411861f,0.00317034f,0.28592f},{-0.336385f,0.0394071f,-0.0446609f}, -{-0.373824f,0.149577f,-0.0365519f},{-0.206145f,-0.0328928f,-0.118819f},{-0.164853f,0.36213f,-0.0554644f}, -{-0.0502331f,0.364876f,-0.104202f},{0.0241696f,0.436738f,-0.172361f},{-0.0166265f,0.37692f,-0.118337f}, -{-0.0686377f,0.380663f,-0.106048f},{-0.29883f,-0.487836f,0.113443f},{-0.294437f,-0.484492f,0.132182f}, -{-0.308141f,-0.482139f,0.178213f},{-0.315858f,-0.470853f,0.190759f},{-0.322353f,-0.472705f,0.211215f}, -{-0.321221f,-0.473354f,0.227131f},{-0.318231f,-0.473683f,0.247111f},{-0.312199f,-0.470326f,0.264217f}, -{-0.261795f,-0.470602f,0.309167f},{-0.445468f,-0.10873f,0.186689f},{-0.0117649f,0.455272f,-0.144748f}, -{-0.143323f,0.321115f,-0.0665766f},{-0.0528568f,-0.072287f,-0.145269f},{-0.388891f,0.147744f,-0.0298704f}, -{-0.309575f,0.112421f,-0.0459663f},{-0.2584f,0.111939f,-0.0322755f},{-0.130366f,0.321269f,-0.0709109f}, -{-0.0524003f,-0.48237f,0.339783f},{-0.446195f,0.0441143f,0.316884f},{0.0216617f,-0.0345262f,-0.137951f}, -{-0.352847f,-0.483708f,0.0576445f},{-0.356075f,-0.469773f,0.0596958f},{-0.350429f,-0.475136f,0.0710717f}, -{-0.341156f,-0.469335f,0.0783448f},{-0.33214f,-0.475084f,0.0933861f},{-0.323581f,-0.473946f,0.103637f}, -{-0.313916f,-0.47374f,0.112247f},{-0.304296f,-0.473528f,0.120806f},{-0.295865f,-0.474049f,0.132092f}, -{-0.309215f,-0.47648f,0.173525f},{-0.388344f,-0.183197f,0.240886f},{-0.309209f,0.0606862f,-0.0464551f}, -{-0.144937f,-0.469689f,0.286795f},{-0.1356f,-0.476428f,0.291116f},{-0.127562f,-0.46976f,0.302588f}, -{-0.0715572f,-0.470249f,0.35494f},{-0.409167f,-0.16748f,0.227555f},{-0.387206f,-0.136735f,0.256403f}, -{-0.392647f,-0.167596f,0.24468f},{-0.37884f,0.348703f,-0.110453f},{-0.3565f,-0.472139f,0.0207839f}, -{-0.357188f,-0.468531f,0.0413749f},{-0.287049f,-0.46821f,0.139822f},{-0.307768f,-0.464139f,0.169345f}, -{-0.312887f,-0.453194f,0.195717f},{-0.313858f,-0.451362f,0.207813f},{-0.316077f,-0.453792f,0.227613f}, -{-0.314012f,-0.451928f,0.247651f},{-0.309286f,-0.455181f,0.261207f},{-0.304244f,-0.449902f,0.266995f}, -{-0.295235f,-0.449838f,0.283444f},{-0.286007f,-0.449561f,0.292402f},{-0.277171f,-0.450313f,0.299952f}, -{-0.374519f,-0.186734f,0.249908f},{-0.331883f,-0.183576f,0.278467f},{-0.462709f,0.150928f,0.280904f}, -{-0.433076f,0.152747f,0.323128f},{-0.104116f,-0.464307f,0.334298f},{-0.0812482f,-0.461503f,0.352503f}, -{-0.0733385f,-0.451188f,0.354908f},{-0.336172f,-0.166644f,0.281759f},{-0.43777f,-0.108312f,0.197183f}, -{-0.147838f,-0.133494f,-0.137751f},{-0.0286004f,-0.225665f,0.353288f},{-0.408935f,0.226353f,0.280621f}, -{-0.429083f,0.225813f,0.264442f},{-0.370602f,-0.166496f,0.26077f},{-0.298154f,-0.314164f,0.152426f}, -{-0.0732806f,0.0510787f,-0.0722163f},{-0.334481f,-0.451728f,0.0750458f},{-0.328919f,-0.46104f,0.0899135f}, -{-0.3187f,-0.451317f,0.0951738f},{-0.312122f,-0.457619f,0.107006f},{-0.298617f,-0.453034f,0.113488f}, -{-0.291473f,-0.460133f,0.125867f},{-0.279428f,-0.454069f,0.132092f},{-0.29737f,-0.452873f,0.171982f}, -{-0.45276f,0.174856f,0.284865f},{-0.44431f,0.173737f,0.29774f},{-0.427289f,0.16712f,0.318903f}, -{-0.406575f,-0.18373f,0.22281f},{-0.366802f,-0.217016f,0.238655f},{-0.141523f,-0.451227f,0.283952f}, -{-0.127375f,-0.449658f,0.302408f},{-0.113157f,-0.44805f,0.322588f},{-0.103524f,-0.449651f,0.334819f}, -{-0.0899618f,-0.448269f,0.342323f},{0.271126f,-0.130645f,-0.13741f},{-0.0707276f,-0.203961f,0.30428f}, -{0.00260761f,-0.072017f,0.302408f},{-0.455802f,-0.0919906f,0.169216f},{-0.44559f,-0.0912961f,0.186283f}, -{-0.0584965f,-0.210964f,0.323957f},{0.173792f,0.00269444f,-0.113758f},{-0.348648f,-0.455509f,0.0179094f}, -{-0.349555f,-0.452879f,0.0386161f},{-0.350937f,-0.451349f,0.0576959f},{-0.284753f,-0.445658f,0.118749f}, -{-0.308392f,-0.440108f,0.208173f},{-0.310733f,-0.437607f,0.229247f},{-0.309234f,-0.439041f,0.247343f}, -{-0.298547f,-0.434102f,0.265612f},{-0.291383f,-0.432648f,0.279033f},{-0.282592f,-0.432314f,0.288492f}, -{-0.272618f,-0.43661f,0.296852f},{-0.458715f,0.178895f,0.272531f},{-0.0676602f,-0.18647f,0.32253f}, -{-0.437976f,-0.0909038f,0.196875f},{-0.136584f,-0.445799f,0.288981f},{-0.0789525f,-0.443819f,0.349481f}, -{-0.428742f,-0.091116f,0.208373f},{-0.0783094f,-0.204212f,0.290229f},{-0.0325874f,-0.208662f,0.359738f}, -{-0.476387f,0.095849f,0.29264f},{-0.464033f,0.192155f,0.248481f},{-0.355021f,-0.18438f,0.264718f}, -{-0.421417f,-0.0858814f,0.216456f},{0.211874f,-0.0764349f,-0.137063f},{-0.419778f,-0.133899f,0.216379f}, -{-0.345446f,-0.44749f,0.0345069f},{-0.342796f,-0.444474f,0.0628726f},{-0.323922f,-0.444275f,0.0805248f}, -{-0.304701f,-0.443548f,0.102254f},{-0.445847f,0.190984f,0.282139f},{-0.304759f,-0.432591f,0.208778f}, -{-0.471949f,0.22553f,0.189505f},{-0.305209f,-0.42996f,0.245233f},{-0.472509f,0.133822f,0.267766f}, -{-0.0580335f,-0.23016f,0.305907f},{-0.412189f,0.111244f,-0.0244944f},{-0.350809f,-0.201775f,0.259194f}, -{-0.0508891f,-0.209247f,0.341642f},{-0.132706f,-0.43178f,0.286441f},{-0.123234f,-0.432751f,0.30037f}, -{-0.114218f,-0.430378f,0.308453f},{-0.106373f,-0.431169f,0.321893f},{-0.0908621f,-0.431697f,0.335636f}, -{-0.0644835f,-0.435356f,0.353127f},{-0.380763f,-0.0849297f,0.253034f},{-0.449288f,0.15413f,0.303514f}, -{-0.427443f,0.0979583f,0.336549f},{-0.438742f,-0.157519f,0.176856f},{-0.482116f,0.0947301f,0.28201f}, -{-0.358661f,-0.0896756f,0.271914f},{-0.463943f,0.11282f,0.299669f},{-0.446722f,0.114215f,0.321578f}, -{-0.450188f,0.0614321f,0.31981f},{-0.335607f,-0.433182f,0.0214527f},{-0.335639f,-0.43232f,0.0373557f}, -{-0.335767f,-0.432803f,0.0577666f},{-0.328237f,-0.435549f,0.0709881f},{-0.317929f,-0.430771f,0.0761326f}, -{-0.310128f,-0.435304f,0.0892769f},{-0.296978f,-0.432571f,0.0957654f},{-0.276869f,-0.433388f,0.110524f}, -{-0.261345f,-0.428771f,0.115553f},{-0.452278f,-0.129121f,0.171351f},{-0.387547f,0.358644f,-0.150857f}, -{-0.446857f,-0.147513f,0.169577f},{-0.295409f,-0.417614f,0.246751f},{-0.29301f,-0.420887f,0.262281f}, -{-0.283827f,-0.413819f,0.267406f},{-0.276895f,-0.417755f,0.282338f},{-0.426626f,-0.151667f,0.205633f}, -{-0.419507f,-0.151211f,0.216675f},{-0.464561f,0.244564f,0.187544f},{-0.0957429f,-0.426546f,0.329423f}, -{-0.427842f,-0.109006f,0.208855f},{-0.0315842f,-0.131005f,0.356342f},{-0.221398f,0.341102f,0.0392399f}, -{-0.436317f,0.0953217f,0.328613f},{-0.44842f,0.0965886f,0.319385f},{-0.0449986f,-0.204238f,0.353802f}, -{-0.409996f,-0.111668f,0.228552f},{-0.448921f,0.0793415f,0.320652f},{-0.413983f,-0.189016f,0.209865f}, -{-0.418858f,-0.170207f,0.213517f},{-0.393039f,-0.149989f,0.249072f},{-0.472271f,0.114196f,0.286049f}, -{-0.0770361f,-0.184045f,0.303456f},{-0.0587087f,-0.111366f,0.307225f},{-0.466773f,0.13143f,0.28448f}, -{-0.304373f,-0.426906f,0.08338f},{-0.283203f,-0.42724f,0.0985177f},{-0.470818f,0.0794573f,0.303206f}, -{0.0180348f,-0.0658371f,0.300537f},{-0.472207f,0.0373171f,0.287296f},{-0.424388f,-0.0574644f,0.203434f}, -{-0.427327f,-0.186952f,0.188206f},{-0.355272f,0.247703f,-0.205633f},{-0.460972f,0.221845f,0.219196f}, -{-0.220324f,0.282094f,-0.0189769f},{-0.424035f,-0.167602f,0.206501f},{-0.124147f,-0.416437f,0.282898f}, -{-0.109241f,-0.416295f,0.30163f},{-0.100746f,-0.418707f,0.315951f},{-0.0343944f,-0.111752f,0.340491f}, -{-0.428613f,-0.0390084f,0.190444f},{-0.435346f,-0.151584f,0.188849f},{-0.433398f,0.177049f,0.306505f}, -{-0.292097f,0.0731423f,-0.0469374f},{-0.477171f,0.117597f,0.271355f},{-0.0671586f,-0.220334f,0.299341f}, -{-0.435584f,0.21434f,0.271271f},{-0.447121f,0.208231f,0.264737f},{-0.454374f,0.194328f,0.267734f}, -{-0.428761f,0.208746f,0.282788f},{-0.0505161f,-0.112524f,0.320318f},{-0.319511f,-0.419511f,0.057175f}, -{-0.30845f,-0.41908f,0.0689946f},{-0.295852f,-0.417035f,0.0745828f},{-0.280985f,-0.413292f,0.0778046f}, -{-0.276342f,-0.419292f,0.0914569f},{-0.260008f,-0.414514f,0.0950452f},{-0.254246f,-0.419215f,0.105797f}, -{-0.240407f,-0.41562f,0.111405f},{-0.461442f,-0.128395f,0.151854f},{-0.430112f,0.0803511f,0.327166f}, -{-0.05822f,-0.191975f,0.341243f},{-0.205334f,0.361525f,0.0194656f},{-0.462625f,0.20989f,0.229748f}, -{-0.464291f,0.225054f,0.206225f},{-0.280007f,-0.405132f,0.244384f},{-0.278727f,-0.404682f,0.250751f}, -{-0.273512f,-0.404321f,0.2605f},{-0.410048f,0.0592521f,0.327919f},{-0.420376f,-0.116427f,0.216385f}, -{-0.0372239f,-0.191145f,0.365609f},{-0.0676474f,-0.147635f,0.320208f},{-0.334912f,-0.035658f,-0.0790007f}, -{-0.11571f,-0.410964f,0.289772f},{-0.0967975f,-0.410778f,0.307231f},{-0.459918f,0.0791679f,0.313257f}, -{-0.462799f,0.173641f,0.266088f},{-0.37394f,-0.132311f,0.265773f},{-0.45458f,0.131385f,0.306106f}, -{-0.410099f,-0.133423f,0.229388f},{-0.458336f,0.0964535f,0.311083f},{-0.432144f,-0.168991f,0.189698f}, -{-0.434587f,0.197093f,0.28893f},{-0.384557f,0.377666f,-0.178637f},{-0.4486f,-0.0571364f,0.170059f}, -{-0.300611f,-0.412051f,0.061027f},{-0.268567f,-0.411479f,0.0835214f},{-0.245236f,-0.411138f,0.101141f}, -{-0.430729f,0.114665f,0.337526f},{-0.18547f,0.381428f,0.0018006f},{-0.446433f,0.225388f,0.245452f}, -{-0.259577f,-0.398058f,0.244584f},{-0.0629658f,-0.182476f,0.334748f},{-0.455841f,-0.10945f,0.169776f}, -{-0.354686f,-0.167313f,0.270351f},{0.021816f,0.453555f,-0.172824f},{-0.435938f,0.256969f,0.215987f}, -{-0.0266197f,-0.19027f,0.371377f},{-0.108488f,-0.400058f,0.282358f},{-0.0891708f,-0.400842f,0.300203f}, -{-0.0369474f,-0.167924f,0.367345f},{-0.480599f,0.0447832f,0.280563f},{-0.428247f,-0.131031f,0.205395f}, -{-0.471255f,0.0615029f,0.30219f},{-0.467905f,0.0962027f,0.302376f},{-0.0124852f,-0.112241f,0.356728f}, -{-0.0659497f,-0.201543f,0.315546f},{-0.43069f,0.0579081f,0.325719f},{-0.391721f,0.361043f,-0.168503f}, -{-0.0402592f,-0.108016f,0.328118f},{-0.0692936f,-0.165249f,0.322337f},{-0.415758f,0.231973f,0.269123f}, -{-0.0491078f,-0.168175f,0.356812f},{-0.411855f,-0.150805f,0.227131f},{-0.276252f,-0.403736f,0.0591621f}, -{-0.263139f,-0.393949f,0.0586862f},{-0.256587f,-0.398482f,0.0750908f},{-0.238754f,-0.400064f,0.0943507f}, -{-0.221173f,-0.398187f,0.111971f},{-0.0518022f,-0.0313495f,-0.13678f},{-0.461873f,0.126678f,0.295373f}, -{-0.0625993f,-0.164754f,0.334028f},{-0.469712f,0.248879f,0.172548f},{-0.316585f,0.30408f,-0.337539f}, -{-0.0603357f,-0.142793f,0.331031f},{-0.453995f,0.254313f,0.193306f},{-0.450413f,0.248108f,0.208013f}, -{-0.407579f,-0.202386f,0.205923f},{-0.0902254f,-0.390258f,0.286531f},{-0.454368f,0.227427f,0.228777f}, -{-0.458053f,0.230726f,0.216012f},{-0.0643806f,-0.130118f,0.316434f},{-0.0579306f,-0.16876f,0.342966f}, -{-0.386557f,0.300614f,-0.0578695f},{-0.39601f,0.0348349f,0.328883f},{-0.413051f,0.214733f,0.289624f}, -{-0.0550433f,-0.147391f,0.341378f},{-0.396743f,0.361866f,-0.187402f},{-0.0361757f,-0.0912382f,0.305373f}, -{-0.246677f,-0.390277f,0.0792386f},{-0.226819f,-0.3942f,0.100441f},{-0.26366f,-0.134787f,-0.126446f}, -{-0.436922f,-0.132131f,0.193434f},{-0.0280152f,-0.167911f,0.37211f},{-0.277692f,0.11217f,-0.0390727f}, -{-0.0964053f,-0.386515f,0.274377f},{-0.0776663f,-0.386161f,0.292003f},{-0.36648f,0.256198f,-0.207614f}, -{-0.396286f,-0.190219f,0.229266f},{-0.454702f,0.211504f,0.249484f},{-0.0332691f,-0.0973731f,0.320819f}, -{-0.241224f,-0.374187f,0.0783962f},{-0.236639f,-0.385737f,0.087277f},{-0.224665f,-0.375756f,0.0965114f}, -{-0.214909f,-0.377351f,0.114614f},{-0.360847f,-0.149674f,0.271348f},{-0.226536f,-0.378438f,0.208411f}, -{-0.211958f,-0.374168f,0.234558f},{-0.0197968f,-0.0909424f,0.325385f},{-0.0126588f,-0.0958169f,0.341037f}, -{-0.485203f,0.0782483f,0.283611f},{-0.0904955f,-0.378817f,0.263721f},{-0.0708563f,-0.373782f,0.263747f}, -{-0.435166f,0.231472f,0.252204f},{-0.44177f,-0.0567249f,0.181435f},{-0.433931f,-0.0563455f,0.191724f}, -{-0.478322f,0.0742806f,0.295245f},{-0.445044f,0.130986f,0.32208f},{-0.0440468f,-0.116491f,0.332086f}, -{-0.358898f,0.270249f,-0.244905f},{-0.415553f,-0.0548728f,0.211466f},{-0.195482f,0.374914f,0.00135046f}, -{-0.398286f,0.398322f,-0.265959f},{-0.422491f,-0.182303f,0.20245f},{-0.0459182f,-0.146323f,0.352953f}, -{-0.25505f,-0.376264f,0.0585705f},{-0.221964f,-0.359371f,0.208373f},{-0.216093f,-0.359487f,0.222231f}, -{-0.21026f,-0.356882f,0.230481f},{-0.457905f,0.155063f,0.288119f},{-0.427893f,0.242931f,0.244635f}, -{-0.0752998f,-0.37139f,0.253111f},{-0.360834f,-0.114736f,0.274769f},{-0.0265812f,-0.115848f,0.350857f}, -{-0.460439f,0.205389f,0.24441f},{-0.416607f,-0.0167583f,0.196129f},{-0.350076f,-0.14824f,0.277245f}, -{-0.411231f,-0.0384168f,0.209408f},{-0.315588f,0.00127969f,-0.0730394f},{0.172898f,-0.129436f,-0.189807f}, -{-0.0764638f,-0.166014f,0.30682f},{-0.428452f,0.19211f,0.298402f},{-0.250825f,-0.368805f,0.0646989f}, -{-0.389058f,0.322427f,-0.0952188f},{-0.356712f,-0.206849f,0.252834f},{-0.0465419f,-0.357403f,0.278377f}, -{-0.224099f,0.347449f,0.0191119f},{-0.404106f,-0.150387f,0.237523f},{-0.43651f,0.136484f,0.328948f}, -{-0.465236f,0.0237292f,0.280358f},{-0.0378927f,-0.229034f,0.34296f},{-0.225662f,-0.354555f,0.0966657f}, -{-0.218459f,-0.360895f,0.133224f},{-0.222896f,-0.359718f,0.149725f},{-0.226658f,-0.35885f,0.169487f}, -{-0.446072f,0.241349f,0.225652f},{-0.208961f,-0.338079f,0.231587f},{-0.199334f,-0.338716f,0.243671f}, -{-0.190434f,-0.338407f,0.253085f},{-0.430259f,0.0928652f,-0.0149255f},{-0.370763f,-0.20236f,0.24396f}, -{-0.428697f,0.131423f,0.336812f},{-0.134944f,-0.137848f,-0.140883f},{-0.380165f,-0.168901f,0.253413f}, -{-0.452137f,-0.0750715f,0.171486f},{-0.394569f,-0.13215f,0.248159f},{-0.223205f,-0.347867f,0.118093f}, -{-0.228395f,-0.3415f,0.153513f},{-0.229205f,-0.337693f,0.171049f},{-0.226941f,-0.341288f,0.187949f}, -{-0.222208f,-0.337764f,0.206135f},{-0.216453f,-0.335346f,0.219665f},{-0.0562201f,-0.340066f,0.26477f}, -{-0.045288f,-0.339288f,0.281103f},{-0.0397254f,-0.338864f,0.28927f},{-0.0306775f,-0.338214f,0.302916f}, -{-0.0162857f,-0.338002f,0.322864f},{-0.443153f,-0.0753416f,0.186393f},{-0.436272f,-0.0714447f,0.194534f}, -{-0.443584f,0.144947f,0.317508f},{-0.489775f,0.132587f,0.152317f},{-0.427597f,-0.0741005f,0.205923f}, -{-0.417887f,-0.0715154f,0.215511f},{-0.426838f,0.145391f,0.332716f},{-0.409778f,-0.0735732f,0.224424f}, -{-0.243153f,-0.337134f,0.138073f},{-0.238452f,-0.33559f,0.146426f},{-0.234761f,0.336902f,0.0319668f}, -{-0.373387f,0.055458f,-0.0377222f},{-0.00782935f,-0.332369f,0.334369f},{-0.399386f,-0.0709559f,0.233349f}, -{-0.39073f,-0.0730523f,0.24169f},{0.0324137f,-0.332806f,0.353249f},{-0.376943f,-0.0711102f,0.251529f}, -{-0.465454f,0.0420951f,0.300209f},{-0.354879f,0.254474f,-0.242256f},{-0.368152f,-0.0732902f,0.259702f}, -{-0.41426f,0.194174f,0.307849f},{-0.175792f,0.340015f,-0.0504935f},{-0.335864f,0.00357545f,0.269503f}, -{-0.247333f,-0.325314f,0.159545f},{-0.240471f,-0.322408f,0.170895f},{-0.229861f,-0.320549f,0.193357f}, -{-0.223835f,-0.318286f,0.208328f},{-0.216009f,-0.317411f,0.22324f},{-0.208305f,-0.316961f,0.233716f}, -{-0.200177f,-0.316536f,0.243838f},{-0.191431f,-0.316221f,0.253355f},{-0.181309f,-0.316112f,0.261619f}, -{-0.387148f,-0.0592585f,0.240423f},{-0.0554613f,-0.321855f,0.268049f},{-0.0459503f,-0.321289f,0.281219f}, -{-0.0403621f,-0.32089f,0.289322f},{-0.0314427f,-0.320228f,0.303116f},{-0.0189415f,-0.319321f,0.322369f}, -{-0.0096428f,-0.318704f,0.335745f},{-0.0709527f,-0.0763191f,-0.143185f},{-0.412138f,0.0923057f,-0.0229381f}, -{-0.315684f,0.037748f,-0.054159f},{-0.371953f,0.0373943f,-0.032089f},{-0.0837626f,-0.0820745f,-0.141339f}, -{-0.31917f,0.112447f,-0.0468409f},{-0.383554f,0.306099f,-0.0502749f},{-0.14951f,0.301977f,-0.0557538f}, -{-0.146989f,0.359506f,-0.0680235f},{-0.0904248f,0.416559f,-0.0912253f},{-0.242909f,0.281901f,-0.00522811f}, -{-0.14686f,0.340272f,-0.0684029f},{-0.277113f,0.00260441f,-0.0934632f},{-0.20972f,-0.303701f,0.234783f}, -{-0.192158f,-0.302948f,0.253696f},{-0.184525f,-0.297354f,0.261445f},{-0.056831f,-0.303765f,0.26886f}, -{-0.0474165f,-0.303135f,0.28221f},{-0.0416996f,-0.302781f,0.290126f},{-0.0336099f,-0.302768f,0.302871f}, -{-0.0201698f,-0.301997f,0.324903f},{-0.0113919f,-0.300704f,0.336915f},{-0.0915244f,-0.0767114f,-0.138401f}, -{-0.31216f,-0.0945757f,-0.104903f},{-0.456374f,0.113887f,0.308447f},{-0.401116f,-0.172303f,0.235144f}, -{-0.0199254f,-0.107077f,0.34858f},{-0.373367f,0.0742934f,-0.0393878f},{-0.379554f,0.0314266f,-0.0254075f}, -{-0.244844f,0.00772325f,-0.102247f},{0.118289f,-0.0103276f,-0.120999f},{-0.165966f,0.320832f,-0.0557924f}, -{0.00993857f,0.455458f,-0.164033f},{-0.233404f,0.301f,-0.0111057f},{-0.0537764f,0.398206f,-0.11527f}, -{-0.0713321f,0.322536f,-0.07711f},{-0.28993f,-0.0385711f,-0.105804f},{-0.0270956f,-0.0990386f,0.332851f}, -{-0.00941129f,-0.0826083f,0.319334f},{-0.255114f,0.31945f,0.0384232f},{-0.0271278f,-0.296923f,0.316292f}, -{-0.00624098f,-0.065567f,0.292544f},{-0.244638f,0.304627f,0.000353705f},{0.00179091f,-0.0658114f,0.293675f}, -{-0.461127f,0.187479f,0.260963f},{-0.360635f,-0.270557f,0.17285f},{-0.277834f,0.149751f,-0.0346741f}, -{-0.459937f,0.0661715f,0.313636f},{-0.356075f,0.252288f,-0.226777f},{-0.300714f,0.0763063f,-0.046275f}, -{-0.386563f,0.341648f,-0.116253f},{-0.0601685f,-0.287084f,0.268679f},{-0.0514228f,-0.285534f,0.283702f}, -{-0.0382014f,-0.284692f,0.306009f},{-0.0291856f,-0.282936f,0.322395f},{-0.0161056f,-0.28219f,0.341063f}, -{-0.00232471f,-0.286537f,0.350111f},{-0.335253f,-0.258924f,0.224443f},{-0.385155f,0.333037f,-0.0948522f}, -{-0.0333591f,0.43542f,-0.127803f},{-0.411855f,-0.207029f,0.191672f},{-0.446426f,0.022861f,0.300524f}, -{-0.277055f,0.170085f,-0.031208f},{-0.258972f,0.00383911f,-0.100222f},{-0.317266f,-0.245445f,0.248603f}, -{-0.272728f,0.300087f,0.0339153f},{0.230388f,-0.091444f,-0.138401f},{-0.0138677f,-0.131848f,-0.228597f}, -{-0.201257f,-0.274763f,0.258956f},{-0.0455002f,-0.279547f,0.297772f},{-0.225276f,0.00369118f,-0.1068f}, -{-0.370486f,0.256436f,-0.188766f},{-0.382705f,0.288885f,-0.0146748f},{0.00393876f,0.417485f,-0.150645f}, -{-0.385271f,0.287875f,-0.0345519f},{-0.260792f,-0.0337803f,-0.108704f},{-0.244831f,-0.0334458f,-0.111713f}, -{0.134803f,-0.116003f,-0.199814f},{-0.392602f,0.0739076f,-0.032269f},{-0.239179f,0.224848f,0.00285523f}, -{-0.334828f,0.0558953f,-0.0452461f},{-0.372088f,-0.0197486f,-0.0509951f},{-0.460844f,0.239163f,0.200495f}, -{-0.0567988f,-0.266589f,0.285836f},{-0.0479953f,-0.264763f,0.302518f},{-0.0426835f,-0.269921f,0.308286f}, -{-0.0364136f,-0.265336f,0.322581f},{-0.0279445f,-0.261644f,0.338645f},{-0.0204399f,-0.265175f,0.346375f}, -{-0.0110511f,-0.263548f,0.353577f},{-0.0415196f,-0.213491f,0.350619f},{-0.366557f,-0.114839f,-0.0851419f}, -{-0.387206f,0.286878f,-0.0535867f},{-0.0459696f,-0.223099f,0.337192f},{-0.23932f,0.111945f,-0.0249381f}, -{-0.368429f,-0.18074f,0.257278f},{-0.39747f,0.150677f,-0.024115f},{-0.40736f,0.0371628f,-0.0137487f}, -{-0.279833f,0.0576059f,-0.0560432f},{-0.18682f,-0.0372271f,-0.123777f},{-0.200994f,0.287045f,-0.0307f}, -{-0.405437f,0.0665188f,0.332163f},{-0.392486f,-0.00592905f,0.264339f},{-0.167876f,-0.0127777f,-0.115559f}, -{-0.431706f,0.110852f,-0.014887f},{-0.383843f,0.297264f,-0.0405903f},{-0.359869f,-0.136562f,0.274609f}, -{-0.205707f,-0.134285f,-0.130022f},{-0.379097f,-0.128182f,-0.07911f},{-0.167509f,-0.0371756f,-0.123816f}, -{-0.148236f,0.00388414f,-0.109051f},{-0.108071f,-0.0344876f,-0.125636f},{-0.130231f,-0.0316775f,-0.120556f}, -{-0.12252f,-0.0370213f,-0.122819f},{-0.390344f,-0.203717f,0.223781f},{-0.060863f,-0.248262f,0.289296f}, -{-0.053069f,-0.248204f,0.302363f},{-0.0462461f,-0.24533f,0.317038f},{-0.0402077f,-0.246346f,0.327642f}, -{-0.0311919f,-0.245748f,0.34132f},{-0.0216617f,-0.250088f,0.350182f},{-0.479345f,0.10862f,0.276891f}, -{-0.0165558f,0.416456f,-0.13696f},{-0.240613f,0.00181343f,-0.105263f},{-0.251307f,-0.00141475f,-0.104061f}, -{-0.243983f,-0.345249f,0.0791357f},{-0.37976f,-0.146928f,-0.0790264f},{-0.284489f,0.186753f,-0.0306292f}, -{-0.166853f,-0.488621f,-0.151378f},{-0.176988f,-0.48165f,-0.146484f},{-0.182602f,-0.485354f,-0.132883f}, -{-0.182563f,-0.469779f,-0.130819f},{-0.188415f,-0.472615f,-0.114112f},{-0.192512f,-0.473065f,-0.0986913f}, -{-0.196087f,-0.475657f,-0.0901064f},{-0.20235f,-0.47093f,-0.0717211f},{0.132764f,-0.0231825f,-0.122986f}, -{0.039944f,-0.48882f,-0.149474f},{0.0224976f,-0.0872319f,-0.190502f},{0.135433f,-0.056204f,-0.131603f}, -{-0.343092f,-0.463438f,0.00420567f},{-0.487267f,0.130806f,0.17258f},{-0.163702f,-0.472956f,-0.165364f}, -{-0.171027f,-0.467946f,-0.152497f},{0.0600398f,0.0716697f,-0.0695862f},{0.0408508f,-0.0974438f,-0.205595f}, -{0.300392f,-0.193556f,-0.123572f},{-0.335619f,-0.449535f,0.00314461f},{-0.173612f,0.381512f,-0.0386097f}, -{-0.186685f,0.381075f,-0.0166104f},{-0.482695f,0.130813f,0.191782f},{0.00456896f,0.0809042f,-0.037928f}, -{-0.322411f,0.376715f,-0.357763f},{-0.327215f,0.382174f,-0.349963f},{-0.33297f,0.377602f,-0.33707f}, -{-0.342153f,0.376753f,-0.319134f},{-0.351407f,0.377486f,-0.301778f},{-0.358731f,0.376528f,-0.286988f}, -{-0.278682f,-0.454268f,0.148587f},{-0.289023f,-0.458513f,0.162754f},{-0.480489f,0.126414f,0.211106f}, -{-0.478753f,0.126446f,0.223967f},{-0.314533f,0.396926f,-0.373435f},{-0.337992f,0.395717f,-0.337192f}, -{-0.372744f,0.393184f,-0.287315f},{-0.145664f,0.399228f,-0.0548149f},{-0.369689f,0.404225f,-0.30208f}, -{-0.341741f,0.412334f,-0.341507f},{-0.47602f,0.131777f,0.231665f},{-0.175091f,-0.462834f,-0.138176f}, -{-0.181431f,-0.450474f,-0.112922f},{-0.187457f,-0.452378f,-0.0945114f},{-0.198215f,-0.457599f,-0.0711102f}, -{-0.322347f,-0.449432f,-0.0207646f},{-0.342114f,-0.444552f,0.0145719f},{-0.475576f,0.130928f,0.249651f}, -{-0.388409f,0.328401f,-0.169358f},{-0.372094f,0.323552f,-0.188772f},{-0.360223f,0.323527f,-0.227272f}, -{-0.346783f,0.324787f,-0.280885f},{-0.306334f,-0.447471f,0.184972f},{-0.377014f,0.354587f,-0.231073f}, -{-0.0322337f,0.0547957f,-0.0699784f},{-0.213797f,0.357223f,0.0104113f},{-0.489724f,0.134935f,0.133899f}, -{-0.388544f,0.426584f,-0.314903f},{-0.360107f,0.341494f,-0.246744f},{-0.362088f,0.26956f,-0.22697f}, -{-0.144899f,-0.453497f,-0.168876f},{-0.161966f,-0.451529f,-0.151211f},{-0.168705f,-0.448545f,-0.137327f}, -{-0.177663f,-0.450487f,-0.128858f},{-0.191148f,-0.446744f,-0.0748786f},{-0.31416f,-0.436713f,-0.0157422f}, -{-0.320385f,-0.433047f,0.000713822f},{-0.331632f,-0.436893f,0.00825056f},{-0.398807f,0.272673f,0.0160702f}, -{-0.259255f,0.306582f,0.0174271f},{-0.16639f,0.0193627f,-0.0963892f},{-0.2655f,-0.443079f,0.133751f}, -{-0.267403f,-0.442867f,0.143391f},{-0.274734f,-0.442063f,0.153011f},{-0.281171f,-0.433812f,0.169056f}, -{-0.295209f,-0.439838f,0.175518f},{-0.299312f,-0.434674f,0.188206f},{-0.183753f,0.0188611f,-0.0958747f}, -{-0.145092f,0.0895598f,-0.0480499f},{-0.0156812f,-0.0939005f,-0.187737f},{-0.357644f,0.287502f,-0.227073f}, -{-0.388158f,0.288332f,-0.0727115f},{-0.436201f,0.137925f,-0.000482281f},{-0.443339f,0.13341f,0.00564614f}, -{-0.152873f,-0.447098f,-0.158869f},{-0.205546f,-0.434385f,-0.0600752f},{0.249809f,-0.0934632f,-0.132144f}, -{0.117897f,0.0717212f,-0.0700427f},{-0.460078f,-0.0407382f,0.096267f},{-0.299132f,-0.431536f,-0.0201794f}, -{-0.373547f,0.270056f,-0.149796f},{-0.371355f,0.26994f,-0.169081f},{-0.256085f,-0.435066f,0.130497f}, -{-0.260657f,-0.432256f,0.151358f},{-0.307132f,-0.429189f,0.226957f},{-0.410871f,0.260808f,0.0192406f}, -{-0.105749f,0.430977f,-0.0668081f},{-0.476682f,0.187891f,0.13361f},{-0.328989f,0.397312f,-0.352194f}, -{-0.146269f,-0.434886f,-0.151243f},{-0.163432f,-0.433066f,-0.131983f},{-0.169901f,-0.431382f,-0.113977f}, -{-0.172757f,-0.428777f,-0.0962863f},{-0.178994f,-0.435002f,-0.0914054f},{-0.182042f,-0.430301f,-0.075168f}, -{-0.188068f,-0.430121f,-0.0630205f},{-0.286296f,-0.426526f,-0.0209511f},{-0.295679f,-0.423536f,-0.0106942f}, -{-0.299158f,-0.419125f,0.00205783f},{-0.30964f,-0.421794f,0.00842418f},{-0.319067f,-0.420539f,0.0211762f}, -{-0.317787f,-0.415877f,0.0403717f},{-0.241513f,-0.42742f,0.130504f},{-0.246574f,-0.426957f,0.146503f}, -{-0.265088f,-0.424977f,0.165782f},{-0.278605f,-0.41899f,0.188264f},{-0.289878f,-0.422186f,0.194675f}, -{-0.296367f,-0.421485f,0.207543f},{-0.296624f,-0.416861f,0.226842f},{-0.214041f,0.35705f,0.000868158f}, -{-0.372178f,0.360188f,-0.245767f},{-0.126732f,-0.431999f,-0.168876f},{-0.137542f,-0.430205f,-0.159088f}, -{-0.150487f,-0.428944f,-0.139693f},{-0.107415f,0.0218128f,-0.0993151f},{-0.107826f,-0.0982734f,-0.142163f}, -{-0.260014f,-0.410617f,-0.0196071f},{-0.275139f,-0.418797f,-0.0182245f},{-0.280573f,-0.410868f,0.00176845f}, -{-0.301145f,-0.413131f,0.0196264f},{-0.478277f,0.24097f,0.165397f},{-0.479788f,0.243169f,0.150992f}, -{-0.23289f,-0.419176f,0.124035f},{-0.22716f,-0.414501f,0.131655f},{-0.237886f,-0.41652f,0.151256f}, -{-0.245224f,-0.411183f,0.167319f},{-0.258143f,-0.416636f,0.172162f},{-0.261242f,-0.410231f,0.188219f}, -{-0.279152f,-0.410733f,0.208804f},{-0.234761f,0.338857f,0.0169963f},{-0.109099f,-0.452146f,-0.183042f}, -{-0.12879f,-0.415852f,-0.150034f},{-0.137793f,-0.420694f,-0.146503f},{-0.160075f,-0.418713f,-0.114035f}, -{-0.16293f,-0.414913f,-0.093386f},{-0.167233f,-0.411961f,-0.0760554f},{0.137401f,0.0762162f,-0.0700106f}, -{0.193206f,0.0219222f,-0.0992637f},{0.117524f,0.0372528f,-0.107186f},{-0.242619f,-0.416353f,-0.0356644f}, -{-0.269223f,-0.407247f,-0.0048487f},{-0.283293f,-0.406013f,0.0177808f},{-0.290901f,-0.405099f,0.0402945f}, -{-0.286155f,-0.405035f,0.0532973f},{-0.477178f,0.13523f,0.211067f},{-0.359001f,0.238642f,-0.130349f}, -{-0.36293f,0.23879f,-0.11426f},{-0.227366f,-0.410913f,0.117514f},{-0.229591f,-0.410585f,0.1464f}, -{-0.251204f,-0.408251f,0.181776f},{-0.265866f,-0.406694f,0.201074f},{-0.277969f,-0.405363f,0.226771f}, -{-0.344474f,0.321842f,-0.289502f},{-0.364229f,0.372869f,-0.272808f},{-0.39909f,0.359654f,-0.208148f}, -{-0.167573f,0.0368927f,-0.0891675f},{-0.149921f,-0.409479f,-0.111752f},{-0.155606f,-0.408765f,-0.0957525f}, -{-0.171252f,-0.408855f,-0.0626539f},{-0.128803f,0.0930517f,-0.0337481f},{-0.236954f,-0.399897f,-0.031761f}, -{-0.245462f,-0.39474f,-0.0222887f},{-0.253468f,-0.396849f,-0.0136394f},{-0.260998f,-0.394527f,0.00144692f}, -{-0.266863f,-0.393839f,0.0208096f},{-0.271139f,-0.397891f,0.0370406f},{-0.266123f,-0.39137f,0.0419858f}, -{-0.218028f,-0.398206f,0.130208f},{-0.225591f,-0.397363f,0.149455f},{-0.230806f,-0.39528f,0.164496f}, -{-0.234845f,-0.397846f,0.173094f},{-0.239385f,-0.395852f,0.188129f},{-0.240941f,-0.393396f,0.2058f}, -{-0.255069f,-0.398714f,0.210662f},{-0.260741f,-0.398077f,0.226726f},{0.422581f,-0.303431f,-0.008855f}, -{-0.252979f,0.320176f,0.0204238f},{0.00404165f,0.0687116f,-0.0526414f},{0.0234815f,0.028057f,-0.100048f}, -{-0.0830745f,0.449953f,-0.0670911f},{-0.121877f,-0.402958f,-0.124716f},{-0.132301f,-0.403363f,-0.111636f}, -{-0.142712f,-0.403344f,-0.095984f},{-0.159342f,-0.401923f,-0.0683258f},{-0.166024f,-0.395119f,-0.0611942f}, -{0.0255393f,-0.0174078f,-0.13015f},{0.210421f,0.0209189f,-0.0930066f},{0.233301f,-0.11307f,-0.146889f}, -{-0.430722f,0.244603f,0.0369442f},{-0.476554f,0.228989f,0.109829f},{-0.47928f,0.226076f,0.118395f}, -{-0.480772f,0.227626f,0.133404f},{-0.236536f,-0.391434f,0.223472f},{-0.231886f,-0.391839f,0.233137f}, -{-0.374023f,0.377255f,-0.266467f},{-0.392621f,0.402617f,-0.285676f},{-0.36331f,0.354966f,-0.253329f}, -{-0.360352f,0.305559f,-0.207871f},{-0.0127617f,0.0691425f,-0.0529565f},{0.225211f,-0.100518f,-0.143616f}, -{0.22833f,-0.0351178f,-0.111739f},{0.400203f,-0.263914f,0.0221408f},{0.286573f,-0.0366419f,-0.0902029f}, -{-0.107479f,0.0613164f,-0.058474f},{-0.0914923f,-0.401138f,-0.148098f},{-0.0929006f,-0.395145f,-0.13352f}, -{-0.104617f,-0.399666f,-0.133211f},{-0.110173f,-0.396367f,-0.114093f},{-0.107247f,-0.390348f,-0.0948522f}, -{-0.127697f,-0.397434f,-0.09228f},{-0.128777f,-0.393499f,-0.074049f},{-0.146777f,-0.391113f,-0.0637793f}, -{0.0422655f,-0.00248225f,-0.127166f},{-0.0146008f,0.0365648f,-0.0938812f},{-0.234967f,-0.384721f,-0.0298961f}, -{-0.244812f,-0.378399f,-0.0178837f},{-0.255571f,-0.377197f,0.00137618f},{-0.26114f,-0.376528f,0.0207518f}, -{-0.260188f,-0.376483f,0.0402431f},{-0.477473f,0.209826f,0.107881f},{-0.34704f,0.303643f,-0.280718f}, -{-0.216215f,-0.381248f,0.131378f},{-0.222665f,-0.379615f,0.149326f},{-0.227957f,-0.378978f,0.168689f}, -{-0.229198f,-0.378753f,0.188039f},{-0.421314f,0.195351f,0.0116652f},{-0.157689f,0.393672f,-0.0470981f}, -{-0.358873f,0.35858f,-0.267483f},{-0.394415f,0.342664f,-0.187473f},{0.250214f,0.0217163f,-0.0747114f}, -{-0.0781615f,-0.389061f,-0.137552f},{-0.0940581f,-0.38829f,-0.114215f},{-0.0967204f,-0.388026f,-0.101341f}, -{-0.110759f,-0.386779f,-0.0755217f},{-0.224793f,-0.379332f,-0.0364618f},{0.309421f,-0.0351564f,-0.0752451f}, -{-0.354301f,0.212225f,-0.053233f},{-0.356635f,0.2038f,-0.0401016f},{-0.212697f,-0.371692f,0.11727f}, -{-0.0316228f,-0.0987171f,-0.188586f},{0.100437f,0.099045f,-0.0386418f},{-0.376178f,0.319128f,-0.169448f}, -{-0.362467f,0.319096f,-0.211157f},{-0.300559f,0.395724f,-0.384277f},{-0.365618f,0.363963f,-0.259812f}, -{0.286451f,0.0156522f,-0.0540175f},{-0.110263f,0.00234718f,-0.109418f},{-0.067493f,-0.378502f,-0.149243f}, -{-0.0773962f,-0.376142f,-0.133758f},{-0.0834796f,-0.375563f,-0.11426f},{-0.0887785f,-0.374985f,-0.094968f}, -{-0.0947783f,-0.374297f,-0.0758946f},{0.327723f,-0.0941063f,-0.0786534f},{-0.261332f,0.0396836f,-0.0784283f}, -{0.0601363f,0.00210928f,-0.129205f},{-0.234491f,-0.361545f,-0.0312144f},{-0.24433f,-0.360458f,-0.0179544f}, -{-0.250625f,-0.359802f,-0.00518309f},{-0.254902f,-0.359339f,0.00448862f},{-0.258381f,-0.358934f,0.0206553f}, -{-0.256709f,-0.359005f,0.0401981f},{-0.252696f,-0.359326f,0.0564162f},{-0.248773f,-0.359622f,0.0660429f}, -{-0.226395f,-0.361004f,0.187975f},{-0.43997f,0.24032f,0.0500048f},{-0.185708f,0.0393235f,-0.0903636f}, -{0.399167f,-0.275515f,0.0147327f},{-0.0604257f,-0.373454f,-0.159667f},{0.021726f,0.00198706f,-0.117398f}, -{-0.447256f,0.245632f,0.0579596f},{0.192859f,-0.110691f,-0.169872f},{-0.224626f,0.343153f,-0.00208995f}, -{-0.0538279f,0.437452f,-0.112003f},{-0.46213f,0.169589f,0.056577f},{-0.0297193f,0.454834f,-0.127893f}, -{0.174493f,0.040108f,-0.0943442f},{0.0798784f,0.0608919f,-0.0775023f},{-0.128925f,0.00378121f,-0.110685f}, -{0.306341f,-0.131018f,-0.115533f},{-0.0521945f,-0.359069f,-0.170985f},{-0.0679753f,-0.35905f,-0.153082f}, -{-0.0764767f,-0.358188f,-0.136973f},{-0.0822835f,-0.357609f,-0.127276f},{-0.085396f,-0.357255f,-0.114395f}, -{-0.0885663f,-0.356863f,-0.0950709f},{-0.0949005f,-0.355339f,-0.0771744f},{-0.244137f,0.0433684f,-0.0812385f}, -{0.00293558f,0.00318962f,-0.117385f},{-0.224826f,-0.359513f,-0.0394714f},{-0.238709f,-0.335687f,-0.0346741f}, -{-0.246516f,-0.342497f,-0.0181602f},{-0.250452f,-0.346484f,-0.00528599f},{-0.254458f,-0.340947f,0.00241795f}, -{-0.259416f,-0.341108f,0.0204624f},{-0.262072f,-0.339925f,0.0405711f},{-0.260541f,-0.339442f,0.0580367f}, -{-0.250715f,-0.346066f,0.0657085f},{-0.229764f,-0.34777f,0.0946079f},{-0.478084f,0.143294f,0.0695798f}, -{-0.0194624f,0.454918f,-0.137661f},{0.230504f,0.0393814f,-0.0744413f},{-0.0131475f,0.00237936f,-0.119089f}, -{-0.261159f,-0.336709f,0.0775474f},{-0.336951f,0.323102f,-0.320594f},{-0.482161f,0.146793f,0.15314f}, -{-0.36412f,0.292286f,-0.172464f},{-0.341118f,0.323173f,-0.304447f},{-0.154821f,0.402887f,-0.0399472f}, -{-0.480985f,0.14397f,0.17247f},{-0.373953f,0.305714f,-0.150085f},{0.0102794f,0.469335f,-0.163043f}, -{-0.047185f,-0.340516f,-0.185473f},{-0.0574934f,-0.341931f,-0.17566f},{-0.0636925f,-0.339854f,-0.168181f}, -{-0.0706248f,-0.340658f,-0.15314f},{-0.0778142f,-0.339886f,-0.136979f},{-0.0816469f,-0.339539f,-0.127417f}, -{-0.0869393f,-0.338999f,-0.114536f},{-0.0922639f,-0.33842f,-0.0952124f},{-0.0962638f,-0.33887f,-0.0771679f}, -{-0.249024f,-0.326324f,-0.0227131f},{-0.257783f,-0.31788f,-0.0144175f},{-0.261165f,-0.323372f,-0.000257208f}, -{-0.266278f,-0.326858f,0.0179351f},{-0.2693f,-0.329141f,0.0326421f},{-0.14104f,0.379949f,-0.068075f}, -{0.217597f,-0.0904601f,-0.14069f},{-0.478329f,0.144021f,0.185338f},{-0.297132f,0.16867f,-0.03742f}, -{-0.349812f,0.27331f,-0.282345f},{-0.0403556f,0.45639f,-0.116228f},{0.00156584f,0.473284f,-0.154117f}, -{-0.185734f,0.0511109f,-0.0847947f},{-0.0329411f,0.0695283f,-0.0532716f},{0.281827f,-0.0642809f,-0.104826f}, -{-0.0320729f,0.00306098f,-0.118446f},{0.208871f,-0.118466f,-0.163217f},{0.154847f,-0.090473f,-0.168831f}, -{-0.167374f,-0.073914f,-0.129115f},{-0.072599f,0.340851f,-0.0886917f},{-0.366667f,0.381724f,-0.279457f}, -{-0.230234f,0.324427f,-0.00771678f},{-0.444722f,0.260564f,0.0609241f},{-0.390074f,0.266377f,-0.0179994f}, -{-0.205019f,0.0589885f,-0.0783897f},{0.155696f,0.0757082f,-0.0711424f},{0.289036f,0.00604484f,-0.0610784f}, -{-0.05386f,-0.32471f,-0.188232f},{-0.0694608f,-0.322703f,-0.169332f},{-0.0759301f,-0.322035f,-0.153191f}, -{-0.0800071f,-0.326137f,-0.137089f},{-0.0837948f,-0.318942f,-0.132272f},{-0.0893701f,-0.3208f,-0.114633f}, -{-0.0966689f,-0.319919f,-0.0953024f},{-0.0994277f,-0.324112f,-0.0823703f},{-0.106489f,-0.321019f,-0.0733867f}, -{0.292431f,-0.0723835f,-0.100453f},{-0.149445f,-0.470924f,-0.172438f},{0.0788817f,0.000926046f,-0.129231f}, -{0.0984116f,0.0203595f,-0.112736f},{0.118257f,-0.112266f,-0.202592f},{0.20846f,-0.0947365f,-0.144658f}, -{0.17383f,-0.073406f,-0.137037f},{-0.316964f,-0.304125f,-0.00106747f},{-0.464509f,0.227427f,0.0788464f}, -{-0.42925f,0.260982f,0.0385454f},{-0.163574f,0.397498f,-0.0332915f},{-0.351902f,0.235922f,-0.147539f}, -{-0.22152f,0.0564291f,-0.0771293f},{-0.0656667f,-0.318678f,-0.179255f},{0.252535f,-0.0537153f,-0.117816f}, -{-0.0121893f,-0.0160059f,-0.130941f},{-0.127453f,-0.47147f,-0.182393f},{0.0793254f,0.0197872f,-0.113578f}, -{0.458831f,-0.267097f,0.0243722f},{-0.317376f,-0.295476f,-0.0150156f},{-0.333626f,-0.295296f,0.00389057f}, -{-0.336764f,-0.2979f,0.0185653f},{-0.257429f,0.283187f,0.00455936f},{-0.405932f,-0.241375f,0.133391f}, -{-0.354153f,0.0745571f,-0.0441465f},{-0.419096f,0.153346f,-0.00814763f},{-0.327099f,0.327359f,-0.349841f}, -{-0.322951f,0.394309f,-0.360857f},{-0.37075f,0.287991f,-0.130658f},{-0.36621f,0.267438f,-0.206064f}, -{-0.162898f,0.000514465f,-0.108871f},{-0.0462654f,-0.312871f,-0.199325f},{-0.0594933f,-0.300961f,-0.192058f}, -{-0.0672487f,-0.304775f,-0.182322f},{-0.0766374f,-0.303913f,-0.169435f},{-0.0791132f,-0.30808f,-0.153217f}, -{-0.0874795f,-0.302756f,-0.133976f},{-0.0951449f,-0.30208f,-0.114762f},{-0.0997557f,-0.306196f,-0.101907f}, -{-0.103241f,-0.300428f,-0.0942606f},{-0.11018f,-0.303219f,-0.0795022f},{0.321511f,-0.0410662f,-0.0695154f}, -{-0.0158227f,-0.485991f,-0.167647f},{0.139388f,-0.0693933f,-0.138169f},{-0.333099f,-0.281046f,-0.0147905f}, -{-0.340777f,-0.283181f,-0.00391625f},{-0.351394f,-0.27911f,0.00481658f},{-0.357329f,-0.284029f,0.0211119f}, -{-0.386068f,-0.0377737f,-0.0490209f},{-0.321331f,0.235285f,-0.148297f},{-0.374062f,-0.280004f,0.0586155f}, -{-0.372666f,-0.282261f,0.0763448f},{0.249629f,-0.0174978f,-0.0920742f},{-0.164429f,0.0917784f,-0.0503135f}, -{0.335099f,-0.00899008f,-0.0222115f},{-0.374043f,0.250539f,-0.110157f},{0.213424f,0.0407125f,-0.0809684f}, -{-0.363529f,0.337031f,-0.230636f},{0.214073f,0.0646603f,-0.0599209f},{-0.0494036f,-0.298383f,-0.201749f}, -{-0.0826758f,-0.298711f,-0.153262f},{0.288766f,-0.16813f,-0.13006f},{0.349883f,-0.104794f,-0.0615607f}, -{-0.369618f,-0.275419f,0.0223337f},{-0.372994f,-0.277071f,0.0392592f},{-0.363252f,0.274158f,-0.210945f}, -{-0.371876f,0.252358f,-0.130369f},{-0.166056f,0.0586155f,-0.0782997f},{-0.0469342f,0.0687309f,-0.0523006f}, -{-0.0710235f,-0.281856f,-0.185775f},{-0.0795184f,-0.290126f,-0.172843f},{-0.084097f,-0.283644f,-0.168522f}, -{-0.0888235f,-0.284647f,-0.153436f},{-0.0927912f,-0.284152f,-0.134047f},{-0.0977621f,-0.2852f,-0.119077f}, -{-0.102334f,-0.281837f,-0.110601f},{-0.110096f,-0.283251f,-0.095013f},{0.193167f,-0.0444487f,-0.125932f}, -{0.210254f,-0.0442237f,-0.126176f},{-0.338134f,-0.268429f,-0.02416f},{-0.353317f,-0.261464f,-0.0176714f}, -{-0.356571f,-0.267033f,-0.00273944f},{-0.370892f,-0.259053f,0.00223789f},{-0.378017f,-0.261207f,0.018829f}, -{-0.380563f,-0.266255f,0.036031f},{-0.388769f,-0.257387f,0.0409119f},{-0.393296f,-0.259284f,0.0599917f}, -{-0.224581f,0.0217292f,-0.0973795f},{-0.277493f,0.0697534f,-0.0489566f},{-0.348191f,0.38202f,-0.311495f}, -{0.230028f,-0.150413f,-0.164348f},{-0.174428f,0.365828f,-0.0464615f},{-0.00840811f,0.473888f,-0.144368f}, -{-0.127317f,0.0454583f,-0.0789106f},{-0.0519373f,-0.281245f,-0.207955f},{0.328263f,0.00381982f,-0.0205267f}, -{-0.385071f,-0.255535f,0.0264493f},{-0.403219f,-0.253587f,0.0716247f},{-0.412279f,-0.24295f,0.0788335f}, -{-0.410434f,-0.242712f,0.115668f},{-0.479229f,0.245175f,0.114061f},{-0.48065f,0.245272f,0.133314f}, -{-0.391457f,0.382155f,-0.259612f},{0.0414745f,0.078602f,-0.057355f},{0.097119f,0.032134f,-0.104755f}, -{-0.380975f,0.283476f,-0.0952445f},{-0.297859f,0.0199222f,-0.0754959f},{-0.0166522f,0.476062f,-0.133867f}, -{0.251429f,0.0748529f,-0.0162503f},{-0.0652552f,-0.273599f,-0.199029f},{-0.0789203f,-0.263027f,-0.187409f}, -{-0.0867143f,-0.266744f,-0.16957f},{-0.0926819f,-0.266152f,-0.153474f},{-0.0976142f,-0.267895f,-0.135738f}, -{-0.105775f,-0.264969f,-0.11498f},{-0.11371f,-0.266043f,-0.10136f},{0.223366f,-0.0452654f,-0.125063f}, -{-0.164191f,0.0825826f,-0.0599595f},{-0.25966f,-0.4712f,-0.0566155f},{0.152616f,-0.130073f,-0.200251f}, -{-0.0534999f,-0.0905823f,-0.151551f},{-0.358661f,-0.248108f,-0.036076f},{-0.376686f,-0.248043f,-0.0189383f}, -{-0.392094f,-0.241774f,0.000803851f},{-0.394306f,-0.243728f,0.0184432f},{-0.400145f,-0.245285f,0.03297f}, -{-0.409405f,-0.240314f,0.0406161f},{-0.412511f,-0.241253f,0.0587698f},{-0.476059f,0.249876f,0.155802f}, -{-0.381837f,0.372689f,-0.253587f},{0.0425099f,0.051426f,-0.0864795f},{-0.242034f,0.0572844f,-0.0712903f}, -{-0.0562265f,-0.265136f,-0.213819f},{-0.0698724f,-0.258506f,-0.203993f},{-0.0831645f,-0.258114f,-0.182509f}, -{-0.101318f,-0.260763f,-0.130954f},{-0.0545867f,0.00329893f,-0.113752f},{0.212292f,0.0944536f,-0.0180444f}, -{0.227436f,0.0886209f,-0.0160766f},{-0.371393f,-0.23879f,-0.0384425f},{-0.389373f,-0.238487f,-0.0192598f}, -{-0.405399f,-0.236391f,0.0231697f},{-0.261307f,-0.265336f,0.252268f},{-0.478856f,0.152291f,0.101656f}, -{-0.480149f,0.152413f,0.114511f},{-0.194711f,0.375621f,-0.00891288f},{-0.479936f,0.152529f,0.133803f}, -{-0.374621f,0.285663f,-0.112993f},{-0.382448f,0.336967f,-0.195331f},{-0.260792f,0.0700299f,-0.0518826f}, -{-0.0886049f,-0.241594f,-0.185068f},{-0.0948683f,-0.248005f,-0.166535f},{-0.0981866f,-0.252121f,-0.150317f}, -{-0.105325f,-0.246873f,-0.13424f},{-0.112263f,-0.246918f,-0.116922f},{0.0821356f,-0.110093f,-0.211627f}, -{0.289306f,-0.150799f,-0.128838f},{-0.205109f,0.00398703f,-0.106389f},{0.23579f,0.0818816f,-0.0195878f}, -{0.136121f,-0.081618f,-0.163789f},{-0.00316069f,0.0486287f,-0.0831098f},{-0.378866f,-0.22953f,-0.0397801f}, -{-0.387393f,-0.222649f,-0.0356902f},{-0.396486f,-0.225935f,-0.0234333f},{-0.404749f,-0.22207f,-0.0145719f}, -{-0.408363f,-0.222977f,0.000681669f},{-0.414556f,-0.223279f,0.0187132f},{-0.420665f,-0.226301f,0.0392914f}, -{-0.425784f,-0.221337f,0.0586155f},{-0.420003f,-0.226192f,0.0779525f},{-0.419192f,-0.225961f,0.097238f}, -{-0.417244f,-0.22625f,0.116575f},{-0.41498f,-0.224546f,0.135044f},{0.000530508f,0.43643f,-0.153616f}, -{0.247841f,-0.0313559f,-0.101321f},{-0.0731263f,-0.242809f,-0.209009f},{-0.101801f,-0.242712f,-0.150336f}, -{-0.0732871f,0.0348092f,-0.0873284f},{0.220356f,-0.122761f,-0.158651f},{0.1365f,0.0392913f,-0.106254f}, -{0.155336f,0.0330022f,-0.105945f},{0.100579f,-0.0536767f,-0.136889f},{0.115652f,-0.0799138f,-0.168798f}, -{-0.423469f,-0.217395f,0.0263722f},{-0.427533f,-0.216951f,0.0392463f},{-0.425494f,-0.216983f,0.0779011f}, -{-0.424337f,-0.21688f,0.0971866f},{-0.425662f,-0.216598f,0.116234f},{-0.423797f,-0.216681f,0.12851f}, -{-0.423861f,0.225183f,0.0220893f},{0.100174f,-0.066583f,-0.146233f},{0.117781f,0.100608f,-0.0368284f}, -{-0.0833832f,-0.235883f,-0.199106f},{-0.0978393f,-0.231247f,-0.170998f},{-0.104392f,-0.227542f,-0.162303f}, -{-0.107845f,-0.228681f,-0.150445f},{-0.111389f,-0.228263f,-0.134343f},{-0.116778f,-0.227954f,-0.12181f}, -{0.249667f,-0.128967f,-0.145706f},{0.232472f,0.0238128f,-0.0833221f},{-0.392711f,-0.207087f,-0.0382303f}, -{-0.402485f,-0.210778f,-0.0256197f},{-0.409521f,-0.204836f,-0.0176264f},{-0.417019f,-0.205781f,-0.000688062f}, -{-0.421044f,-0.208868f,0.0135237f},{-0.426826f,-0.203151f,0.0212534f},{-0.433874f,-0.203408f,0.0392656f}, -{-0.436709f,-0.205222f,0.0569371f},{-0.434806f,-0.20726f,0.077856f},{-0.434021f,-0.208842f,0.115675f}, -{-0.426948f,-0.203672f,0.15186f},{-0.419392f,-0.211967f,0.157686f},{-0.347349f,0.218392f,-0.0859072f}, -{-0.14086f,0.412385f,-0.0475226f},{0.154384f,0.0215427f,-0.112858f},{-0.243057f,0.0221793f,-0.0944857f}, -{-0.0784766f,-0.222494f,-0.212701f},{-0.0877432f,-0.221594f,-0.20236f},{-0.0960066f,-0.220906f,-0.18609f}, -{-0.184673f,0.00709305f,-0.102762f},{0.00357221f,0.0290087f,-0.101013f},{-0.358982f,-0.204495f,-0.0763319f}, -{-0.374499f,-0.206366f,-0.0561397f},{-0.107196f,-0.404501f,-0.146388f},{-0.421803f,-0.200129f,0.00706088f}, -{-0.441404f,-0.198405f,0.0617279f},{-0.441841f,-0.198167f,0.0778239f},{-0.442954f,-0.198026f,0.097103f}, -{-0.442626f,-0.197916f,0.116363f},{-0.424305f,-0.199215f,0.171094f},{-0.42233f,-0.199756f,0.181563f}, -{-0.033552f,-0.110974f,-0.208964f},{-0.32481f,0.410244f,-0.363647f},{-0.0341886f,-0.0863831f,-0.153114f}, -{0.215347f,0.00317677f,-0.0975853f},{-0.10544f,-0.206263f,-0.166702f},{-0.111595f,-0.210225f,-0.150535f}, -{-0.114463f,-0.209916f,-0.134433f},{-0.116205f,-0.214244f,-0.121559f},{-0.0201055f,0.0293688f,-0.101296f}, -{0.205476f,0.0341211f,-0.0879907f},{0.173072f,0.0181537f,-0.109257f},{-0.361824f,-0.192013f,-0.0803061f}, -{-0.369959f,-0.185345f,-0.0759332f},{-0.376383f,-0.192547f,-0.0622745f},{0.0600784f,0.0621138f,-0.0787177f}, -{-0.397058f,-0.190901f,-0.0428603f},{-0.40473f,-0.187197f,-0.0339732f},{-0.413649f,-0.188984f,-0.0203209f}, -{-0.420009f,-0.191859f,-0.00282304f},{-0.425642f,-0.184708f,0.00212857f},{-0.429642f,-0.186438f,0.0198643f}, -{-0.437494f,-0.185814f,0.0391563f},{-0.44478f,-0.185177f,0.0584419f},{-0.447198f,-0.184791f,0.0777853f}, -{-0.448767f,-0.184624f,0.0970323f},{-0.447564f,-0.184586f,0.116279f},{-0.443822f,-0.183865f,0.134227f}, -{-0.439828f,-0.189216f,0.141912f},{-0.434227f,-0.185383f,0.154863f},{-0.432086f,-0.185505f,0.170991f}, -{-0.372679f,0.204006f,-0.0321276f},{-0.380731f,0.208058f,-0.0269509f},{-0.385669f,0.292717f,-0.108125f}, -{-0.384955f,0.275155f,-0.0501334f},{-0.457513f,0.0372528f,0.0313302f},{-0.0781293f,-0.209074f,-0.214385f}, -{-0.0885985f,-0.202334f,-0.204315f},{-0.0979165f,-0.200945f,-0.190463f},{-0.100585f,-0.203717f,-0.181891f}, -{-0.290669f,0.41126f,-0.387428f},{0.246542f,-0.0402495f,-0.109823f},{-0.388872f,-0.187074f,-0.0538118f}, -{-0.421507f,-0.183107f,-0.0125269f},{-0.376924f,0.270249f,-0.111244f},{0.135272f,0.0239992f,-0.115713f}, -{-0.221777f,0.0372528f,-0.0892061f},{0.458972f,-0.281965f,0.0151571f},{-0.0687985f,-0.207048f,-0.221607f}, -{-0.11216f,-0.187557f,-0.147654f},{-0.125125f,-0.188746f,-0.129906f},{0.136224f,-0.0950966f,-0.185917f}, -{-0.159561f,0.0490338f,-0.0826726f},{-0.377965f,-0.167352f,-0.077065f},{-0.39329f,-0.17031f,-0.0587762f}, -{-0.408022f,-0.171068f,-0.038436f},{-0.418806f,-0.170213f,-0.0255233f},{-0.427141f,-0.169647f,-0.0158773f}, -{-0.435854f,-0.168728f,0.000495179f},{-0.437925f,-0.172734f,0.0198257f},{-0.447076f,-0.167744f,0.0390856f}, -{-0.448728f,-0.167544f,0.0583583f},{-0.449712f,-0.167326f,0.0776695f},{-0.450297f,-0.167146f,0.0969229f}, -{-0.449378f,-0.167216f,0.116215f},{-0.447352f,-0.167255f,0.135494f},{-0.444323f,-0.165081f,0.153101f}, -{-0.437745f,-0.172175f,0.158059f},{-0.437012f,-0.167917f,0.170966f},{-0.128308f,0.265824f,-0.0182373f}, -{-0.376872f,0.270306f,-0.0919713f},{-0.345265f,0.336864f,-0.291669f},{-0.0700781f,-0.189023f,-0.223221f}, -{-0.080573f,-0.185692f,-0.212334f},{-0.0877818f,-0.185081f,-0.202456f},{-0.096013f,-0.184386f,-0.189428f}, -{-0.10144f,-0.183943f,-0.179705f},{-0.104682f,-0.183647f,-0.166747f},{-0.146892f,0.0471175f,-0.0806276f}, -{-0.107704f,0.0503778f,-0.0712196f},{-0.0904633f,0.050918f,-0.071869f},{-0.445179f,-0.163641f,0.0197807f}, -{-0.441044f,0.20481f,0.0434584f},{-0.463165f,0.257715f,0.0824154f},{-0.436195f,0.124215f,-0.00681005f}, -{-0.463442f,0.258603f,0.168477f},{-0.0122279f,0.490132f,-0.127771f},{0.192447f,-0.0923057f,-0.150741f}, -{-0.3861f,-0.159468f,-0.0706472f},{-0.397045f,-0.146979f,-0.0587698f},{-0.403296f,-0.153828f,-0.0512009f}, -{-0.41109f,-0.150014f,-0.0392527f},{-0.42851f,-0.152034f,-0.0189962f},{-0.438639f,-0.152702f,-0.00389053f}, -{-0.442375f,-0.149513f,0.00473942f},{-0.449436f,-0.150426f,0.0197421f},{-0.456413f,-0.15069f,0.0377351f}, -{-0.456812f,-0.153821f,0.0583325f},{-0.458169f,-0.153641f,0.0776052f},{-0.456612f,-0.153764f,0.0968458f}, -{-0.455628f,-0.153757f,0.116144f},{-0.455841f,-0.151474f,0.137005f},{-0.4526f,-0.149384f,0.154612f}, -{-0.457108f,0.24904f,0.0697727f},{-0.435938f,0.174599f,0.0144369f},{-0.0689142f,-0.16804f,-0.222166f}, -{-0.0786438f,-0.167577f,-0.212385f},{-0.0840327f,-0.167126f,-0.202559f},{-0.0928748f,-0.166419f,-0.186303f}, -{-0.102688f,-0.166516f,-0.165609f},{-0.111601f,-0.165641f,-0.149005f},{-0.387663f,-0.146169f,-0.0707115f}, -{-0.460053f,-0.145236f,0.0454391f},{-0.460496f,-0.145031f,0.0583261f},{-0.462857f,-0.144896f,0.0775538f}, -{-0.462085f,-0.144812f,0.0968072f},{-0.461165f,-0.144761f,0.116106f},{-0.460696f,-0.144613f,0.132137f}, -{0.20037f,0.0470274f,-0.0826468f},{-0.377708f,0.301283f,-0.134021f},{-0.0979422f,-0.161397f,-0.173499f}, -{-0.119028f,-0.15995f,-0.142497f},{0.0999871f,0.079528f,-0.0589499f},{-0.413495f,-0.129668f,-0.0401402f}, -{-0.432227f,-0.131147f,-0.0199608f},{-0.438915f,-0.133674f,-0.00619914f},{-0.441867f,-0.13098f,0.00160125f}, -{-0.448889f,-0.133185f,0.0197421f},{-0.45678f,-0.132594f,0.0357674f},{-0.46004f,-0.132388f,0.0454262f}, -{-0.462721f,-0.132111f,0.0582489f},{-0.465982f,-0.131777f,0.0775023f},{-0.466663f,-0.131616f,0.0967493f}, -{-0.466638f,-0.131533f,0.116028f},{-0.464985f,-0.131501f,0.135288f},{-0.457262f,-0.136041f,0.157654f}, -{-0.299678f,-0.473072f,-0.0419022f},{-0.066014f,-0.152439f,-0.219549f},{-0.0736086f,-0.147384f,-0.208488f}, -{-0.0819427f,-0.153545f,-0.199479f},{-0.0862963f,-0.14867f,-0.186367f},{-0.0939488f,-0.148085f,-0.166966f}, -{-0.109556f,-0.148574f,-0.150355f},{-0.221694f,-0.48738f,-0.0727243f},{-0.388229f,-0.128594f,-0.0705443f}, -{-0.396473f,-0.128941f,-0.0591492f},{-0.423617f,-0.126382f,-0.0322497f},{-0.282952f,0.025549f,-0.0794444f}, -{-0.439114f,0.213549f,0.0500113f},{0.213347f,0.0806791f,-0.0397029f},{-0.402633f,-0.123334f,-0.0517282f}, -{0.279788f,-0.0226423f,-0.084949f},{0.00770069f,-0.0975017f,-0.202469f},{-0.463043f,0.028475f,0.0439793f}, -{-0.438684f,0.159937f,0.012154f},{-0.0821935f,-0.135037f,-0.183261f},{0.112443f,0.0452011f,-0.0996109f}, -{-0.440008f,0.0363911f,0.0118517f},{0.0788109f,-0.0764541f,-0.171068f},{-0.0513071f,0.0541204f,-0.0704157f}, -{-0.0725218f,0.0608791f,-0.0584676f},{0.138854f,-0.0875727f,-0.173519f},{0.262078f,-0.0821195f,-0.124337f}, -{-0.0899425f,0.0356066f,-0.0881129f},{0.26658f,-0.0933218f,-0.125514f},{0.276104f,-0.0914312f,-0.121025f}, -{0.401579f,-0.301399f,-0.00446929f},{0.289235f,-0.0925565f,-0.113353f},{-0.0525868f,0.045259f,-0.0791357f}, -{0.0232886f,-0.079618f,-0.172843f},{0.0404006f,-0.114704f,-0.220147f},{-0.127575f,0.0222308f,-0.0996624f}, -{-0.091055f,-0.415993f,-0.167731f},{0.461493f,-0.258995f,0.0334973f},{0.0801485f,0.0388862f,-0.0953474f}, -{0.0859811f,0.0112665f,-0.121064f},{0.211128f,-0.0580817f,-0.13316f},{-0.0155011f,0.0200122f,-0.109476f}, -{0.13569f,0.0984984f,-0.0425517f},{0.209334f,0.0733224f,-0.0531558f},{0.37383f,-0.297662f,-0.0146426f}, -{0.174473f,-0.0865953f,-0.153281f},{-0.0290248f,-0.00725378f,-0.126877f},{0.264291f,0.0159287f,-0.0684544f}, -{0.30427f,-0.0999389f,-0.105508f},{0.312405f,-0.103913f,-0.101238f},{0.325838f,-0.111083f,-0.093624f}, -{-0.0629594f,-0.448423f,-0.178367f},{0.153825f,0.00549181f,-0.117688f},{0.0600527f,0.0406289f,-0.0930709f}, -{0.193785f,-0.0587441f,-0.134587f},{0.232806f,0.00174273f,-0.0917398f},{0.176403f,0.0629755f,-0.0804797f}, -{0.440729f,-0.274448f,0.0136845f},{0.185399f,0.0156072f,-0.10664f},{0.32742f,-0.0140767f,-0.0403781f}, -{0.119909f,-0.0675284f,-0.140188f},{-0.120462f,-0.417369f,-0.160014f},{-0.184846f,0.0625961f,-0.0775216f}, -{0.334127f,-0.108717f,-0.0832449f},{0.339111f,-0.118543f,-0.0857078f},{0.348841f,-0.12961f,-0.0804411f}, -{-0.278059f,0.0395357f,-0.0715282f},{0.212832f,0.054352f,-0.0712839f},{0.303788f,0.0003923f,-0.0545191f}, -{-0.0927848f,-0.471593f,-0.185357f},{0.438767f,-0.321842f,-0.0139288f},{0.0999292f,0.0890518f,-0.0499019f}, -{-0.279441f,-0.470139f,-0.048963f},{0.0730555f,0.0125012f,-0.122363f},{0.00391304f,0.0395164f,-0.0928394f}, -{-0.260947f,0.0601653f,-0.0610141f},{-0.205894f,-0.449568f,-0.0642744f},{0.19574f,0.0603518f,-0.0749622f}, -{0.119163f,-0.094087f,-0.189229f},{-0.0131282f,-0.0585062f,-0.143738f},{0.250722f,-0.165963f,-0.157017f}, -{-0.260921f,0.0503457f,-0.0701842f},{0.268876f,-0.184875f,-0.148606f},{-0.105344f,0.0338253f,-0.0893669f}, -{0.455017f,-0.300942f,0.00419281f},{0.156976f,-0.110363f,-0.188618f},{-0.074033f,0.0204431f,-0.097939f}, -{-0.10908f,-0.418257f,-0.165628f},{0.273441f,-0.298261f,-0.137044f},{-0.109234f,-0.428674f,-0.175023f}, -{0.406022f,-0.243195f,0.03742f},{0.00558501f,-0.131558f,-0.23043f},{0.025385f,-0.152947f,-0.238134f}, -{0.41743f,-0.248706f,0.0421723f},{0.0629336f,0.012572f,-0.12242f},{0.0616732f,0.0293945f,-0.101669f}, -{0.0579434f,0.0198579f,-0.113565f},{0.269679f,0.00122184f,-0.0735732f},{0.0437703f,-0.146934f,-0.230874f}, -{-0.242703f,0.0852513f,-0.042333f},{-0.186017f,-0.00108035f,-0.107206f},{-0.0730748f,0.0450918f,-0.0788142f}, -{0.264979f,-0.303926f,-0.144748f},{-0.0814283f,0.433549f,-0.0899842f},{0.420144f,-0.274981f,0.0141282f}, -{0.00217032f,-0.46875f,-0.16359f},{0.0806758f,-0.0558438f,-0.1386f},{0.230292f,-0.165487f,-0.167686f}, -{-0.0914344f,-0.485078f,-0.183917f},{0.079737f,0.0510144f,-0.0862352f},{0.059519f,0.0513617f,-0.086531f}, -{-0.0636282f,0.435066f,-0.105038f},{-0.0721102f,0.311488f,-0.0673805f},{0.0599562f,-0.0869232f,-0.19056f}, -{-0.0704897f,-0.490711f,-0.165313f},{0.1921f,0.0920035f,-0.034687f},{0.17421f,-0.0966528f,-0.167056f}, -{0.321433f,0.0167261f,-0.0155172f},{0.0605029f,-0.0743577f,-0.167403f},{0.0802386f,0.0808591f,-0.0602617f}, -{0.0422526f,0.0701264f,-0.0677534f},{-0.127317f,0.0551558f,-0.0697598f},{0.156667f,-0.0688402f,-0.134427f}, -{0.287216f,-0.00226358f,-0.0682293f},{0.137787f,0.0655992f,-0.0798302f},{0.0426642f,-0.0758882f,-0.168644f}, -{0.0249027f,0.0505129f,-0.0853477f},{-0.0142793f,0.0467831f,-0.0810392f},{-0.112752f,0.40072f,-0.0819266f}, -{-0.0764188f,0.420405f,-0.10026f},{-0.148532f,0.021099f,-0.0983505f},{-0.0322337f,0.0449889f,-0.0789685f}, -{0.0228963f,0.47257f,-0.16847f},{0.344397f,-0.112003f,-0.0732838f},{0.334835f,-0.0549564f,-0.0632262f}, -{0.00402235f,-0.0809749f,-0.165081f},{0.0234044f,-0.0553422f,-0.143532f},{0.193618f,0.0389377f,-0.0904022f}, -{-0.0916209f,-0.427208f,-0.176412f},{-0.292843f,0.400572f,-0.387647f},{-0.277351f,-0.432546f,-0.0328735f}, -{0.0236101f,-0.130761f,-0.229671f},{0.0407672f,0.0189962f,-0.109791f},{0.232697f,-0.13069f,-0.155558f}, -{-0.0537443f,0.0202373f,-0.097791f},{-0.255513f,-0.419279f,-0.0314331f},{0.17466f,0.0740234f,-0.0699334f}, -{-0.270593f,0.296801f,0.0237677f},{-0.176981f,0.35514f,-0.0475869f},{-0.0332369f,0.0160252f,-0.107681f}, -{0.341156f,-0.0549757f,-0.0554966f},{0.171097f,0.0880808f,-0.0495739f},{0.322231f,-0.020308f,-0.0531044f}, -{-0.0737501f,-0.486299f,-0.181094f},{-0.0327803f,-0.0931031f,-0.173191f},{0.258316f,0.0655092f,-0.025459f}, -{0.244568f,-0.00190989f,-0.0878557f},{0.0420533f,-0.0569692f,-0.145031f},{-0.033552f,-0.0750973f,-0.145648f}, -{-0.299814f,0.281284f,0.0215106f},{-0.279737f,0.283412f,0.0196843f},{-0.209373f,0.327385f,-0.0267129f}, -{0.196408f,0.0842545f,-0.0456062f},{-0.0161635f,-0.0777531f,-0.149191f},{-0.2435f,-0.47057f,-0.0622038f}, -{0.00624094f,-0.0729365f,-0.149339f},{0.0225748f,-0.0716054f,-0.151667f},{0.151915f,-0.0584418f,-0.128607f}, -{0.302399f,-0.0201666f,-0.0695926f},{0.235443f,-0.146613f,-0.15968f},{0.202723f,0.00639853f,-0.103077f}, -{-0.0153082f,-0.470872f,-0.168438f},{0.022652f,0.0167455f,-0.107334f},{-0.219732f,0.0707759f,-0.0663708f}, -{0.0407607f,-0.0696055f,-0.151082f},{0.0616411f,-0.0680557f,-0.152548f},{-0.279319f,-0.487778f,-0.0510337f}, -{-0.293659f,-0.489888f,-0.0501784f},{0.00330855f,0.0187904f,-0.109469f},{0.0112504f,0.0501527f,-0.0848847f}, -{-0.30555f,0.276789f,0.00826342f},{-0.296746f,0.274049f,0.0108936f},{-0.283763f,0.27257f,0.0122118f}, -{-0.280612f,0.265593f,0.00686153f},{0.26386f,-0.137719f,-0.142786f},{0.269647f,-0.0361596f,-0.0978554f}, -{0.260156f,-0.0403396f,-0.104575f},{-0.203038f,0.0361982f,-0.0896177f},{0.417604f,-0.298164f,-0.00448858f}, -{-0.205939f,-0.073959f,-0.131282f},{-0.0925919f,-0.436269f,-0.180843f},{-0.0775634f,-0.436153f,-0.17975f}, -{0.116546f,0.024758f,-0.115083f},{0.20718f,-0.00464937f,-0.10401f},{0.285299f,-0.0771229f,-0.109115f}, -{-0.0350568f,0.0268866f,-0.0985177f},{-0.0529211f,-0.469638f,-0.17683f},{0.115234f,-0.073078f,-0.15377f}, -{0.192241f,-0.0755088f,-0.13833f},{0.0680782f,-0.0558631f,-0.140079f},{0.134211f,-0.0758111f,-0.150696f}, -{-0.129465f,-0.447863f,-0.175904f},{-0.110122f,-0.437568f,-0.179467f},{-0.146391f,-0.399132f,-0.0756053f}, -{-0.090174f,0.0221536f,-0.0997267f},{0.296984f,-0.0316839f,-0.0818816f},{0.0440661f,0.0283978f,-0.100518f}, -{0.153336f,-0.0782933f,-0.147989f},{0.173522f,0.02861f,-0.10127f},{-0.245719f,0.0662872f,-0.0612649f}, -{-0.279467f,0.248005f,-0.0012411f},{-0.260773f,0.24596f,-0.000218624f},{0.321485f,-0.129147f,-0.106768f}, -{0.023713f,-0.114099f,-0.220867f},{0.24413f,-0.0576059f,-0.124697f},{-0.0915759f,-0.406855f,-0.157082f}, -{-0.296058f,-0.270261f,0.234983f},{0.00615734f,0.0945629f,-0.0194463f},{0.168081f,-0.0794766f,-0.144581f}, -{0.252497f,0.00464294f,-0.0807627f},{0.24822f,0.0340825f,-0.0687502f},{0.313916f,0.00494521f,-0.0416064f}, -{0.0403749f,-0.469702f,-0.154934f},{-0.293164f,0.254763f,-0.00702226f},{0.0280087f,-0.0414585f,-0.142111f}, -{0.0618211f,0.0931031f,-0.0507122f},{-0.17102f,0.00729881f,-0.103051f},{-0.25896f,0.0220122f,-0.0907302f}, -{-0.0683676f,-0.430282f,-0.176702f},{0.143471f,0.0490145f,-0.0974759f},{0.154763f,0.0894312f,-0.0509244f}, -{-0.245468f,-0.429954f,-0.0434134f},{-0.0755121f,-0.0124948f,-0.121404f},{-0.261712f,-0.45576f,-0.0506865f}, -{0.188447f,0.0503714f,-0.0862159f},{-0.0160284f,0.0915083f,-0.0186553f},{-0.288245f,0.242037f,-0.0126362f}, -{0.439166f,-0.300878f,-0.00482298f},{-0.0333334f,0.0365197f,-0.0880615f},{0.317967f,-0.0967814f,-0.0894826f}, -{0.0200926f,0.0669368f,-0.0639915f},{-0.281396f,-0.450725f,-0.0420436f},{0.161168f,-0.0859651f,-0.159204f}, -{-0.013334f,-0.0866789f,-0.168876f},{-0.260336f,-0.435716f,-0.0411498f},{-0.299878f,-0.48938f,-0.0368348f}, -{0.292592f,-0.109083f,-0.117334f},{-0.275538f,0.230571f,-0.006212f},{0.331504f,-0.140124f,-0.101926f}, -{0.305942f,-0.112993f,-0.110987f},{-0.242639f,-0.437381f,-0.049381f},{0.317446f,-0.113977f,-0.103482f}, -{-0.0706248f,-0.414482f,-0.167506f},{0.0406385f,0.0091251f,-0.118633f},{0.252342f,-0.320954f,-0.156136f}, -{0.331214f,-0.127102f,-0.098209f},{-0.286836f,0.4f,-0.387441f},{-0.00711554f,-0.0828655f,-0.163146f}, -{0.323568f,-0.148651f,-0.108871f},{-0.205218f,0.0724285f,-0.0683129f},{-0.223134f,-0.454969f,-0.0629433f}, -{0.38266f,-0.335706f,-0.0232275f},{-0.27431f,0.21917f,-0.00699654f},{-0.260381f,0.211685f,-0.00508663f}, -{0.390312f,-0.260422f,0.0117103f},{0.337832f,-0.0386418f,-0.05059f},{0.117459f,0.0530465f,-0.0919584f}, -{0.0412752f,-0.0419022f,-0.14186f},{-0.227938f,0.0485451f,-0.0817144f},{0.0407221f,-0.1673f,-0.236796f}, -{-0.194158f,-0.250577f,0.273869f},{-0.184525f,0.0924215f,-0.0508601f},{0.0057715f,-0.0839266f,-0.174837f}, -{0.0450371f,0.0886145f,-0.0488473f},{0.0313655f,0.0688788f,-0.0662808f},{0.160294f,0.06794f,-0.079335f}, -{-0.299466f,-0.441446f,-0.0306742f},{0.11807f,-0.0567377f,-0.135372f},{0.176113f,-0.472351f,-0.135089f}, -{-0.126842f,0.0658114f,-0.0616507f},{0.1534f,-0.100363f,-0.182406f},{0.245191f,-0.114536f,-0.141526f}, -{-0.202826f,-0.490389f,-0.073779f},{-0.267294f,0.205112f,-0.012932f},{-0.240606f,0.205492f,0.00168485f}, -{0.327459f,-0.0332272f,-0.058564f},{0.235661f,0.0680685f,-0.041034f},{0.0310183f,-0.140105f,-0.232719f}, -{0.046066f,-0.16876f,-0.235111f},{-0.205585f,0.0910453f,-0.0491688f},{0.0606829f,-0.108337f,-0.213601f}, -{0.0407607f,-0.107411f,-0.2147f},{0.0204913f,-0.107128f,-0.215125f},{0.00281983f,-0.105373f,-0.210572f}, -{0.00645958f,-0.114749f,-0.220302f},{-0.147851f,-0.488614f,-0.17031f},{-0.123697f,-0.451297f,-0.179313f}, -{0.204485f,0.089592f,-0.0321211f},{0.11699f,0.0893798f,-0.0503521f},{0.134745f,0.0903315f,-0.0517154f}, -{0.440002f,-0.250082f,0.0402109f},{0.459384f,-0.251735f,0.0420758f},{-0.259615f,0.192746f,-0.0167261f}, -{-0.241024f,0.190868f,-0.00066877f},{-0.0119771f,-0.0980033f,-0.198862f},{0.0374296f,-0.153371f,-0.236552f}, -{0.276483f,-0.150227f,-0.137668f},{-0.111543f,-0.408559f,-0.15114f},{0.289222f,-0.204649f,-0.134684f}, -{0.271126f,-0.203061f,-0.148297f},{0.419784f,-0.320067f,-0.0175557f},{0.466393f,-0.311077f,0.0125913f}, -{0.103788f,-0.127289f,-0.213157f},{0.0621813f,-0.0796309f,-0.178985f},{0.213032f,-0.148741f,-0.175615f}, -{-0.276123f,0.19364f,-0.0243014f},{-0.237057f,0.175345f,-0.000983873f},{-0.051217f,-0.0594772f,-0.143346f}, -{-0.0341115f,-0.0593293f,-0.144195f},{-0.195013f,0.140182f,0.0354008f},{-0.0339764f,-0.483142f,-0.170406f}, -{0.267313f,-0.151204f,-0.143571f},{0.382132f,-0.321662f,-0.0154464f},{0.40372f,-0.320575f,-0.0174657f}, -{0.157876f,-0.12471f,-0.195923f},{-0.0725218f,-0.447722f,-0.179679f},{-0.0453651f,-0.133153f,-0.221298f}, -{-0.0336806f,-0.13051f,-0.223787f},{0.205791f,-0.147436f,-0.179486f},{-0.243204f,-0.489933f,-0.0578631f}, -{0.235147f,-0.0296067f,-0.103167f},{-0.247056f,0.172014f,-0.0121411f},{-0.221713f,0.154066f,-2.57039e-05f}, -{-0.201141f,0.135912f,0.0175429f},{0.288097f,-0.18638f,-0.132729f},{-0.241725f,-0.454281f,-0.0580045f}, -{-0.223064f,-0.473014f,-0.0674833f},{-0.0658854f,-0.465335f,-0.178657f},{0.252683f,-0.304164f,-0.154522f}, -{0.100559f,-0.0970258f,-0.199235f},{0.172474f,-0.114562f,-0.183679f},{0.0369409f,0.0861901f,-0.0460435f}, -{0.362075f,-0.339404f,-0.0242629f},{-0.0222147f,-0.0861901f,-0.159821f},{-0.233565f,0.161043f,-0.00777465f}, -{-0.213115f,0.148137f,0.00656572f},{0.0732227f,-0.117109f,-0.217337f},{0.18628f,-0.115874f,-0.178978f}, -{-0.123922f,-0.486454f,-0.18665f},{0.398839f,-0.335353f,-0.0244236f},{0.12106f,-0.0842031f,-0.173937f}, -{-0.296405f,0.0342433f,-0.0656313f},{-0.256805f,0.155757f,-0.0229317f},{-0.240356f,0.151571f,-0.0168869f}, -{-0.228626f,0.151365f,-0.0101476f},{-0.215733f,0.136684f,-0.00267514f},{-0.207392f,0.130748f,0.00387771f}, -{0.278091f,-0.176985f,-0.140973f},{0.00451752f,0.111064f,0.0211183f},{0.0224784f,0.115508f,0.018546f}, -{-0.279962f,-0.294164f,0.208308f},{0.317472f,0.0347706f,0.00812194f},{-0.226047f,0.135121f,-0.0132664f}, -{-0.202601f,0.121314f,7.07559e-05f},{-0.184576f,0.116607f,-0.000681631f},{-0.0169223f,0.103913f,0.0169963f}, -{-0.0125623f,0.107128f,0.0231697f},{0.040735f,0.11462f,0.00070096f},{0.060207f,0.119263f,0.00183276f}, -{0.0800906f,0.121507f,0.000392289f},{0.0970676f,0.121469f,-0.00239862f},{0.116057f,0.122093f,-0.00194847f}, -{0.136745f,0.122343f,-0.00261726f},{0.15668f,0.121314f,-0.00171054f},{0.175811f,0.118646f,0.000971048f}, -{0.194151f,0.112221f,-0.000225055f},{0.134372f,0.00556251f,-0.120093f},{-0.115472f,0.0872769f,-0.0327256f}, -{-0.114977f,0.0688852f,-0.0518761f},{-0.0382078f,-0.103366f,-0.193608f},{0.271293f,-0.0128099f,-0.0826275f}, -{-0.252992f,0.138716f,-0.0265072f},{-0.242188f,0.134099f,-0.0231053f},{-0.215167f,0.124703f,-0.00695796f}, -{0.00827945f,0.108106f,0.00857852f},{0.022832f,0.109945f,0.00102249f},{0.212755f,0.107791f,0.00616702f}, -{0.230613f,0.0964599f,0.00186491f},{0.22543f,-0.132883f,-0.161088f},{0.299415f,0.0143018f,-0.0474454f}, -{0.356455f,-0.0437028f,-0.0169641f},{-0.0465548f,0.0114209f,-0.107849f},{0.0974341f,0.052217f,-0.0876628f}, -{-0.221945f,0.114665f,-0.0193305f},{-0.202511f,0.112221f,-0.0181023f},{-0.186158f,0.112742f,-0.0161152f}, -{-0.239404f,-0.484917f,-0.0675219f},{-0.029102f,-0.117887f,-0.217536f},{0.406305f,-0.255284f,0.0327835f}, -{0.419893f,-0.255754f,0.033208f},{-0.0154754f,0.0985306f,-0.000263639f},{0.00136006f,0.101585f,-0.00249508f}, -{0.043005f,0.109611f,-0.0146876f},{0.0620076f,0.11327f,-0.016456f},{0.0792418f,0.113746f,-0.0197807f}, -{0.0978779f,0.113392f,-0.0183852f},{0.117909f,0.112839f,-0.0178644f},{0.137471f,0.114331f,-0.018501f}, -{0.155722f,0.113064f,-0.0185975f},{0.174686f,0.110357f,-0.0158837f},{0.21527f,0.101457f,-0.0032539f}, -{0.462657f,-0.297823f,0.0121604f},{0.440478f,-0.255458f,0.0329186f},{0.240201f,-0.104659f,-0.139391f}, -{-0.169046f,0.108524f,-0.0214012f},{-0.149214f,0.106916f,-0.0149063f},{0.0234172f,0.101907f,-0.01753f}, -{0.184396f,0.106157f,-0.0178579f},{0.193778f,0.101367f,-0.0190926f},{-0.133767f,-0.465335f,-0.178547f}, -{0.186409f,-0.0962027f,-0.161062f},{-0.261165f,-0.490434f,-0.0584804f},{-0.070599f,-0.397383f,-0.151481f}, -{-0.247622f,0.108164f,-0.0284299f},{-0.228555f,0.105804f,-0.0256197f},{-0.186595f,0.107688f,-0.0281663f}, -{-0.160519f,0.105386f,-0.025922f},{-0.147664f,0.103579f,-0.0243207f},{-0.0743545f,0.0868204f,-0.00658498f}, -{-0.0456031f,0.0891804f,-0.00969099f},{0.0395839f,0.103418f,-0.0260313f},{0.0621041f,0.107341f,-0.0307257f}, -{0.0794476f,0.107984f,-0.0316067f},{0.0958008f,0.106614f,-0.030282f},{0.126276f,0.106267f,-0.0302498f}, -{0.136899f,0.107109f,-0.0312851f},{0.150571f,0.106961f,-0.0313816f},{0.178949f,0.10244f,-0.0266872f}, -{0.150924f,-0.486299f,-0.125578f},{0.134089f,-0.486807f,-0.128459f},{0.118392f,-0.486319f,-0.133185f}, -{0.0979808f,-0.483766f,-0.142265f},{0.0787209f,-0.484049f,-0.14442f},{0.059982f,-0.483933f,-0.146986f}, -{0.0217517f,-0.486319f,-0.150915f},{0.00719267f,-0.489219f,-0.149513f},{-0.0549082f,-0.482345f,-0.175068f}, -{0.199855f,-0.476094f,-0.120543f},{0.157419f,-0.473052f,-0.139314f},{0.136558f,-0.470429f,-0.144278f}, -{0.117253f,-0.470191f,-0.1475f},{0.0979615f,-0.470023f,-0.149558f},{0.0786759f,-0.469998f,-0.151043f}, -{-0.22442f,-0.0713611f,-0.131063f},{0.0219896f,-0.470287f,-0.158329f},{-0.0307547f,-0.468165f,-0.172586f}, -{-0.324398f,-0.270171f,0.217665f},{0.0275329f,0.382361f,-0.144728f},{-0.0119193f,0.384026f,-0.123764f}, -{-0.243462f,-0.0706344f,-0.1266f},{-0.0151732f,0.39838f,-0.130722f},{-0.0697823f,0.398154f,-0.107617f}, -{-0.260908f,-0.0702357f,-0.11772f},{-0.276946f,-0.0708402f,-0.111238f},{-0.204202f,0.277444f,-0.0249509f}, -{-0.316591f,-0.489946f,-0.0348027f},{-0.321048f,-0.491084f,-0.0186618f},{0.152622f,-0.465959f,-0.142356f}, -{0.0141957f,-0.464461f,-0.161101f},{-0.29283f,-0.0713353f,-0.105617f},{-0.302418f,-0.0715925f,-0.101791f}, -{-0.315376f,-0.0719334f,-0.0965306f},{-0.334584f,-0.0724543f,-0.0895598f},{-0.112591f,0.302691f,-0.0615093f}, -{-0.349574f,-0.0743063f,-0.0856757f},{-0.358185f,-0.0715411f,-0.0805247f},{0.00820872f,0.399987f,-0.144671f}, -{-0.178859f,0.320749f,-0.0490531f},{-0.104971f,0.307752f,-0.0656828f},{-0.0410694f,0.441092f,-0.121565f}, -{-0.319614f,-0.474319f,-0.0342883f},{-0.333967f,-0.471162f,-0.0213819f},{-0.348937f,-0.484627f,0.00558826f}, -{0.265435f,-0.471522f,0.00476514f},{-0.0139835f,0.35932f,-0.107906f},{-0.0550175f,0.357673f,-0.0990772f}, -{0.194409f,-0.452731f,-0.134549f},{0.17511f,-0.452397f,-0.138684f},{0.162223f,-0.452275f,-0.140079f}, -{0.152564f,-0.452101f,-0.141938f},{0.136455f,-0.451857f,-0.144909f},{0.117151f,-0.451567f,-0.1486f}, -{0.0978714f,-0.451336f,-0.151744f},{0.0785859f,-0.45113f,-0.154561f},{0.0592939f,-0.451008f,-0.156516f}, -{0.0399955f,-0.450892f,-0.158567f},{0.0270891f,-0.455387f,-0.159744f},{0.0193981f,-0.449664f,-0.162477f}, -{0.00133434f,-0.450146f,-0.167326f},{-0.0147359f,-0.449799f,-0.171467f},{-0.0307868f,-0.449561f,-0.174721f}, -{-0.0500788f,-0.44942f,-0.176952f},{-0.242336f,-0.482878f,0.298177f},{-0.319247f,0.126562f,-0.0472203f}, -{-0.431095f,0.0555095f,-0.0061284f},{-0.287203f,-0.468345f,-0.044796f},{-0.38992f,0.13053f,-0.0323076f}, -{-0.349137f,-0.474191f,0.00606413f},{0.324231f,-0.464403f,0.0193563f},{0.323909f,-0.455207f,0.00261087f}, -{0.305087f,-0.4565f,-0.00248222f},{0.28811f,-0.462313f,-0.00134399f},{0.278348f,-0.461175f,-0.00605123f}, -{0.00435675f,0.360104f,-0.113617f},{-0.0341886f,0.364934f,-0.107283f},{-0.318012f,0.189827f,-0.0402752f}, -{-0.274509f,-0.458886f,-0.0477541f},{-0.300212f,-0.455368f,-0.037285f},{-0.316141f,-0.456108f,-0.0309186f}, -{0.297441f,-0.450699f,-0.00994178f},{0.287891f,-0.450957f,-0.0121411f},{-0.399508f,0.13024f,-0.0256133f}, -{0.200846f,-0.438417f,-0.139552f},{0.193019f,-0.432301f,-0.144613f},{0.175001f,-0.433189f,-0.146098f}, -{0.155702f,-0.433298f,-0.145513f},{0.136423f,-0.433311f,-0.146619f},{0.117144f,-0.433201f,-0.148548f}, -{0.0978393f,-0.432976f,-0.151384f},{0.0785666f,-0.432841f,-0.155043f},{0.0592167f,-0.432655f,-0.156818f}, -{0.039944f,-0.432616f,-0.158156f},{0.0271084f,-0.432443f,-0.159699f},{0.0174431f,-0.432198f,-0.162393f}, -{0.00134721f,-0.431812f,-0.166644f},{-0.014768f,-0.43144f,-0.170869f},{-0.0308511f,-0.431214f,-0.173673f}, -{-0.0501495f,-0.431182f,-0.175242f},{-0.0301823f,0.399897f,-0.12462f},{-0.268213f,-0.449658f,-0.046365f}, -{-0.33625f,0.00163985f,-0.0621202f},{0.345535f,-0.441259f,-0.00639849f},{0.34068f,-0.43333f,-0.0138259f}, -{0.323073f,-0.435671f,-0.0155429f},{0.305042f,-0.436352f,-0.0183467f},{0.289531f,-0.43389f,-0.0237677f}, -{0.274978f,-0.440031f,-0.0245394f},{0.207283f,-0.428874f,-0.142137f},{-0.277486f,0.0933989f,-0.0426095f}, -{-0.322244f,-0.0305328f,-0.0829812f},{-0.223347f,-0.434533f,-0.0549436f},{-0.259757f,-0.0169448f,-0.105681f}, -{-0.0928941f,0.310215f,-0.0684094f},{-0.166165f,0.340118f,-0.0569049f},{-0.188499f,0.320652f,-0.0430661f}, -{0.381329f,-0.429542f,0.00839203f},{0.355034f,-0.431163f,-0.0114594f},{0.219919f,-0.41499f,-0.139725f}, -{0.210324f,-0.414636f,-0.144092f},{0.194286f,-0.414263f,-0.149654f},{0.174924f,-0.414083f,-0.152683f}, -{0.155638f,-0.414045f,-0.154741f},{0.136391f,-0.418938f,-0.155474f},{0.117054f,-0.41861f,-0.158818f}, -{0.104251f,-0.418964f,-0.159448f},{0.0964117f,-0.411627f,-0.171467f},{0.0784058f,-0.417138f,-0.171377f}, -{0.0591203f,-0.417003f,-0.173808f},{0.0398283f,-0.417382f,-0.171075f},{0.0205492f,-0.417742f,-0.169647f}, -{0.00121859f,-0.412887f,-0.172342f},{-0.0148709f,-0.413151f,-0.169705f},{-0.0309347f,-0.413254f,-0.168895f}, -{-0.050201f,-0.413459f,-0.16784f},{-0.376846f,0.0291824f,0.336182f},{-0.0667085f,-0.0604096f,-0.141764f}, -{-0.0752677f,-0.0574966f,-0.139732f},{-0.0910935f,-0.0558696f,-0.135616f},{-0.10962f,-0.0549243f,-0.132491f}, -{-0.05377f,0.417266f,-0.115745f},{-0.128083f,-0.054069f,-0.128986f},{0.377477f,-0.422443f,-0.00421206f}, -{0.361381f,-0.416212f,-0.0185396f},{0.343838f,-0.418379f,-0.0225073f},{0.322964f,-0.420443f,-0.025041f}, -{0.310077f,-0.420385f,-0.0269252f},{0.136333f,-0.408276f,-0.167114f},{0.11697f,-0.407775f,-0.172985f}, -{0.0783544f,-0.407157f,-0.180187f},{0.059056f,-0.407177f,-0.181647f},{0.0397575f,-0.40746f,-0.180001f}, -{0.0204591f,-0.407492f,-0.179583f},{-0.372737f,0.188187f,-0.0315874f},{-0.396814f,-0.245272f,0.151635f}, -{0.0300472f,0.402907f,-0.161988f},{-0.185033f,-0.415022f,-0.0589884f},{-0.20417f,-0.415749f,-0.0533873f}, -{-0.219167f,-0.417845f,-0.0483007f},{-0.227629f,-0.415363f,-0.0426931f},{-0.380833f,-0.271683f,0.093952f}, -{-0.0345552f,0.417343f,-0.126768f},{0.380705f,-0.411922f,-0.0144947f},{0.339015f,-0.410701f,-0.028102f}, -{0.3229f,-0.410675f,-0.0285714f},{-0.251223f,-0.065387f,-0.121064f},{0.250477f,-0.395171f,-0.128118f}, -{0.234034f,-0.397981f,-0.133552f},{0.219848f,-0.400971f,-0.140954f},{0.212215f,-0.39481f,-0.148793f}, -{0.194312f,-0.399916f,-0.156046f},{0.174834f,-0.394283f,-0.166696f},{0.155542f,-0.394161f,-0.168837f}, -{0.13742f,-0.394341f,-0.175608f},{0.1169f,-0.392913f,-0.18292f},{0.0975756f,-0.39274f,-0.185345f}, -{0.0782643f,-0.392868f,-0.186013f},{0.0589916f,-0.392888f,-0.186933f},{0.0396804f,-0.392952f,-0.187254f}, -{0.0203884f,-0.392933f,-0.187499f},{0.00426672f,-0.393312f,-0.1851f},{-0.0102666f,-0.391357f,-0.18229f}, -{-0.0150188f,-0.398688f,-0.177518f},{-0.0311083f,-0.394534f,-0.172586f},{-0.0471593f,-0.395293f,-0.164104f}, -{-0.0565931f,-0.395942f,-0.15894f},{-0.153072f,0.320954f,-0.0621009f},{-0.107093f,0.396296f,-0.0868846f}, -{-0.167715f,0.302543f,-0.0497283f},{-0.185103f,0.30145f,-0.0428025f},{-0.108058f,0.345346f,-0.0850583f}, -{0.398556f,-0.396341f,-0.019292f},{0.382325f,-0.399434f,-0.0228417f},{0.364673f,-0.401614f,-0.0251117f}, -{0.359734f,-0.394f,-0.0299476f},{0.342192f,-0.396418f,-0.030507f},{0.322829f,-0.396495f,-0.030925f}, -{0.226369f,-0.391762f,-0.141198f},{0.194119f,-0.389749f,-0.1642f},{0.129658f,-0.388296f,-0.181383f}, -{-0.432073f,0.00232147f,0.247658f},{-0.184923f,-0.396682f,-0.0553037f},{-0.202884f,-0.398251f,-0.0495482f}, -{-0.223424f,-0.398296f,-0.0397093f},{-0.328552f,-0.0035883f,-0.0680685f},{-0.376268f,-0.264924f,0.15395f}, -{-0.355079f,-0.00288092f,0.268069f},{-0.0902833f,0.343147f,-0.0872769f},{0.377496f,-0.39182f,-0.0286229f}, -{0.256419f,-0.379737f,-0.13725f},{0.247854f,-0.376026f,-0.146317f},{0.234047f,-0.378007f,-0.152149f}, -{0.216588f,-0.381267f,-0.154972f},{0.211746f,-0.373904f,-0.162381f},{0.194087f,-0.375679f,-0.167885f}, -{0.176081f,-0.376091f,-0.17456f},{0.155464f,-0.379595f,-0.177113f},{0.13915f,-0.379493f,-0.178136f}, -{0.134513f,-0.372406f,-0.181383f},{0.116797f,-0.374348f,-0.184927f},{0.0975113f,-0.374059f,-0.189145f}, -{0.0783351f,-0.373814f,-0.193357f},{0.0589724f,-0.378483f,-0.194155f},{0.0395968f,-0.37856f,-0.195595f}, -{0.0202984f,-0.378599f,-0.19418f},{0.0030449f,-0.375711f,-0.194624f},{-0.0119836f,-0.374612f,-0.189846f}, -{-0.0269284f,-0.373711f,-0.182599f},{-0.0354426f,-0.377313f,-0.176271f},{-0.0504003f,-0.376695f,-0.166818f}, -{-0.210794f,-0.392843f,-0.0463393f},{-0.341433f,0.0888203f,-0.0460564f},{-0.0527925f,0.340221f,-0.0890389f}, -{0.401373f,-0.380669f,-0.0243658f},{0.380589f,-0.377705f,-0.0326999f},{0.361471f,-0.377859f,-0.0330021f}, -{0.341986f,-0.37784f,-0.0325327f},{0.226298f,-0.371924f,-0.160329f},{0.168332f,-0.370245f,-0.179705f}, -{0.1554f,-0.370136f,-0.181595f},{0.0589402f,-0.368676f,-0.200817f},{0.0395839f,-0.368554f,-0.203395f}, -{0.0202212f,-0.369062f,-0.199428f},{0.00733414f,-0.36921f,-0.1989f},{-0.354249f,0.0934375f,-0.0446931f}, -{-0.398344f,-0.251227f,0.136806f},{-0.108051f,-0.377563f,-0.0586862f},{-0.127337f,-0.377679f,-0.058384f}, -{-0.146635f,-0.377589f,-0.0602488f},{-0.165844f,-0.377673f,-0.060146f},{-0.185091f,-0.378174f,-0.0551172f}, -{-0.201019f,-0.378895f,-0.0484357f},{-0.2108f,-0.379229f,-0.0450918f},{-0.360641f,-0.031954f,-0.0637793f}, -{-0.0316164f,0.341442f,-0.0910903f},{0.431693f,-0.3751f,-0.00904149f},{0.396473f,-0.373351f,-0.0290151f}, -{0.253159f,-0.359448f,-0.152561f},{0.232581f,-0.357468f,-0.165924f},{0.213289f,-0.357159f,-0.17094f}, -{0.195167f,-0.35777f,-0.17483f},{0.174718f,-0.356329f,-0.181904f},{0.155329f,-0.356021f,-0.185917f}, -{0.136025f,-0.356169f,-0.185582f},{0.116745f,-0.355873f,-0.189383f},{0.0987331f,-0.356522f,-0.192862f}, -{0.084605f,-0.359815f,-0.197273f},{0.0768625f,-0.354201f,-0.199788f},{0.0588437f,-0.354825f,-0.203505f}, -{0.0395003f,-0.354612f,-0.206887f},{0.0201762f,-0.354831f,-0.206109f},{0.00404809f,-0.355043f,-0.204772f}, -{-0.0103759f,-0.353095f,-0.200675f},{-0.0152053f,-0.360503f,-0.194618f},{-0.0312884f,-0.356683f,-0.187235f}, -{-0.030118f,-0.479399f,0.347571f},{0.0219446f,0.397531f,-0.15269f},{-0.358667f,0.110723f,-0.0458442f}, -{-0.424781f,0.0588084f,-0.0108742f},{0.433861f,-0.359384f,-0.0142889f},{0.418909f,-0.360207f,-0.0223272f}, -{0.406106f,-0.3644f,-0.026983f},{0.398486f,-0.358799f,-0.0295875f},{0.380615f,-0.359686f,-0.0323269f}, -{0.361361f,-0.359853f,-0.0312401f},{-0.0793962f,0.398103f,-0.102235f},{-0.200968f,0.251413f,-0.0134979f}, -{-0.341304f,0.0793994f,-0.0464294f},{0.245494f,-0.353307f,-0.160914f},{0.187605f,-0.351982f,-0.179139f}, -{0.0910099f,-0.350683f,-0.198199f},{-0.0441111f,-0.352735f,-0.180618f},{-0.233243f,0.281978f,-0.0114851f}, -{-0.0771647f,0.377428f,-0.102164f},{-0.108128f,-0.359358f,-0.0574708f},{-0.127408f,-0.359423f,-0.0577023f}, -{-0.146712f,-0.359242f,-0.0606604f},{-0.165985f,-0.359172f,-0.0619658f},{-0.185232f,-0.359538f,-0.0583004f}, -{-0.204511f,-0.360201f,-0.0518568f},{-0.339915f,0.269303f,-0.283605f},{0.254966f,-0.340008f,-0.156072f}, -{0.245442f,-0.339577f,-0.161442f},{0.232549f,-0.339179f,-0.166464f},{0.213154f,-0.338658f,-0.173326f}, -{0.197167f,-0.338439f,-0.176895f},{0.187438f,-0.338214f,-0.179653f},{0.174608f,-0.338008f,-0.182618f}, -{0.155297f,-0.337758f,-0.186746f},{0.135986f,-0.337481f,-0.190971f},{0.116662f,-0.341661f,-0.196309f}, -{0.103813f,-0.341803f,-0.196888f},{0.0960773f,-0.335938f,-0.200688f},{0.0780586f,-0.336568f,-0.204579f}, -{0.0587473f,-0.336491f,-0.206225f},{0.0394489f,-0.336253f,-0.20962f},{0.0217324f,-0.338349f,-0.212752f}, -{0.00291629f,-0.337629f,-0.213241f},{-0.0121379f,-0.336652f,-0.208206f},{-0.0271728f,-0.335816f,-0.201248f}, -{-0.0355584f,-0.339333f,-0.19445f},{0.43806f,-0.342523f,-0.0153435f},{0.418954f,-0.34186f,-0.0241021f}, -{0.399823f,-0.34624f,-0.0280055f},{0.38064f,-0.346413f,-0.0280827f},{0.353471f,-0.346156f,-0.0265007f}, -{-0.412408f,0.130015f,-0.0195942f},{-0.316122f,-0.255265f,0.240365f},{-0.186936f,-0.0145526f,-0.112871f}, -{-0.296907f,0.131153f,-0.0426031f},{0.116668f,-0.332388f,-0.199248f},{0.0168837f,-0.331211f,-0.217305f}, -{0.0071991f,-0.331321f,-0.217118f},{-0.375753f,0.00609625f,0.303244f},{-0.109498f,-0.341667f,-0.0609241f}, -{-0.127491f,-0.340857f,-0.0605575f},{-0.146835f,-0.340677f,-0.0623324f},{-0.164474f,-0.342812f,-0.0642037f}, -{-0.186563f,-0.341648f,-0.063059f},{-0.20453f,-0.341282f,-0.0579338f},{-0.219411f,-0.340561f,-0.0491753f}, -{-0.227919f,-0.344323f,-0.0415485f},{-0.373702f,0.11208f,-0.0423523f},{0.0166908f,0.412739f,-0.157738f}, -{-0.206177f,-0.0147069f,-0.112755f},{0.232414f,-0.321205f,-0.16431f},{0.213135f,-0.320716f,-0.171113f}, -{0.193843f,-0.320343f,-0.176708f},{0.174557f,-0.31999f,-0.182065f},{0.155259f,-0.319797f,-0.186476f}, -{0.139195f,-0.319263f,-0.192142f},{0.129401f,-0.318671f,-0.198527f},{0.116598f,-0.318369f,-0.203492f}, -{0.0972605f,-0.318086f,-0.20764f},{0.0779685f,-0.31772f,-0.212656f},{0.058638f,-0.317707f,-0.21398f}, -{0.0408508f,-0.319945f,-0.214688f},{0.0232758f,-0.317199f,-0.22189f},{0.00712193f,-0.317347f,-0.220906f}, -{-0.00791295f,-0.316041f,-0.218687f},{-0.0164593f,-0.319456f,-0.214546f},{-0.0314813f,-0.318671f,-0.2069f}, -{-0.333761f,0.0945243f,-0.0467638f},{-0.101826f,-0.33561f,-0.0671297f},{-0.169342f,-0.335777f,-0.065985f}, -{-0.178943f,-0.33588f,-0.0656699f},{-0.128867f,0.289489f,-0.0502813f},{-0.389348f,0.055143f,-0.0314395f}, -{0.0361306f,-0.312729f,-0.219633f},{0.0188064f,0.379345f,-0.136735f},{-0.114701f,-0.326723f,-0.0646731f}, -{-0.127568f,-0.326813f,-0.0641008f},{-0.143671f,-0.326723f,-0.0642037f},{-0.148539f,-0.319597f,-0.0669946f}, -{-0.166217f,-0.321642f,-0.0696376f},{-0.185386f,-0.321867f,-0.0692003f},{-0.200408f,-0.320729f,-0.0664802f}, -{-0.20889f,-0.324208f,-0.0617858f},{-0.222549f,-0.322581f,-0.0527636f},{-0.230279f,-0.328845f,-0.0446866f}, -{-0.27829f,-0.0147905f,-0.0996752f},{-0.402839f,-0.255696f,0.0866918f},{-0.156641f,0.359429f,-0.0620752f}, -{-0.259853f,0.129867f,-0.0303977f},{-0.225507f,-0.0148805f,-0.111746f},{0.232311f,-0.302794f,-0.167403f}, -{0.214324f,-0.303141f,-0.175171f},{0.19374f,-0.301759f,-0.182271f},{0.174396f,-0.301206f,-0.189023f}, -{0.15513f,-0.301013f,-0.193872f},{0.142391f,-0.305534f,-0.195479f},{0.134507f,-0.299341f,-0.202058f}, -{0.116527f,-0.299746f,-0.208643f},{0.0971769f,-0.299553f,-0.211813f},{0.081081f,-0.299264f,-0.215794f}, -{0.0714157f,-0.299135f,-0.217761f},{0.0585608f,-0.299129f,-0.218829f},{0.0392624f,-0.298923f,-0.222064f}, -{0.0231922f,-0.298633f,-0.226571f},{0.00704477f,-0.298704f,-0.226906f},{-0.0123372f,-0.299238f,-0.222308f}, -{-0.0332305f,-0.302395f,-0.212347f},{-0.148166f,-0.0508858f,-0.125301f},{-0.127607f,-0.317276f,-0.0687245f}, -{-0.242896f,-0.315733f,-0.0365133f},{-0.167451f,-0.0509308f,-0.126793f},{-0.349825f,-0.274268f,0.182084f}, -{-0.302971f,0.0889425f,-0.0468152f},{-0.18675f,-0.0509437f,-0.127417f},{-0.298257f,0.209826f,-0.0373686f}, -{-0.206067f,-0.0509694f,-0.127006f},{-0.244806f,-0.0151764f,-0.108157f},{-0.296392f,-0.0161731f,-0.0915919f}, -{-0.224112f,-0.0520305f,-0.125938f},{0.245371f,-0.298781f,-0.161191f},{0.20662f,-0.297367f,-0.179917f}, -{-0.0283432f,-0.294974f,-0.218765f},{-0.238362f,-0.0558181f,-0.124401f},{-0.24251f,-0.265773f,0.253985f}, -{-0.244851f,-0.0492267f,-0.118369f},{-0.127684f,-0.302858f,-0.0759525f},{-0.146989f,-0.302871f,-0.0744606f}, -{-0.166287f,-0.302807f,-0.0762933f},{-0.185483f,-0.303051f,-0.0754702f},{-0.203521f,-0.302871f,-0.0691617f}, -{-0.21109f,-0.308685f,-0.0650333f},{-0.223887f,-0.304826f,-0.0569242f},{-0.236465f,-0.31026f,-0.046783f}, -{-0.280856f,-0.314929f,-0.00204493f},{-0.296888f,-0.313347f,0.00282951f},{-0.143819f,0.287103f,-0.0472782f}, -{-0.258921f,-0.0529436f,-0.113276f},{-0.351143f,0.0140575f,-0.0489502f},{-0.276875f,-0.052352f,-0.110086f}, -{-0.294849f,-0.0535738f,-0.106627f},{-0.409984f,0.019472f,0.307707f},{-0.399006f,0.0548214f,-0.0255812f}, -{-0.270586f,-0.020083f,-0.103309f},{0.266541f,-0.281946f,-0.143217f},{0.255744f,-0.286988f,-0.155622f}, -{0.247262f,-0.283284f,-0.164477f},{0.23233f,-0.284312f,-0.171621f},{0.219347f,-0.283901f,-0.176425f}, -{0.209707f,-0.283611f,-0.180534f},{0.193611f,-0.283329f,-0.185049f},{0.174293f,-0.282936f,-0.190077f}, -{0.15821f,-0.282486f,-0.196109f},{0.148584f,-0.282312f,-0.198836f},{0.135748f,-0.282036f,-0.202727f}, -{0.116353f,-0.281586f,-0.208797f},{0.0971448f,-0.28147f,-0.211228f},{0.0778142f,-0.281316f,-0.214578f}, -{0.0584965f,-0.281078f,-0.218199f},{0.0391981f,-0.28075f,-0.222964f},{0.0231729f,-0.28039f,-0.228591f}, -{0.00698689f,-0.280062f,-0.232835f},{-0.0123823f,-0.280383f,-0.230764f},{-0.0317321f,-0.281168f,-0.222803f}, -{-0.315324f,-0.0533874f,-0.0960741f},{-0.238606f,-0.294839f,-0.0495289f},{-0.24714f,-0.29882f,-0.0383653f}, -{-0.261332f,-0.29655f,-0.0361339f},{-0.268985f,-0.302711f,-0.0272724f},{-0.281782f,-0.302974f,-0.0227774f}, -{-0.302392f,-0.29992f,-0.0184303f},{-0.331465f,-0.053979f,-0.086994f},{-0.298386f,-0.24034f,0.26075f}, -{-0.42761f,0.12824f,-0.012797f},{-0.335369f,-0.242693f,0.242372f},{-0.341195f,-0.0541976f,-0.0824604f}, -{-0.353973f,-0.0546413f,-0.0768078f},{-0.368892f,-0.0567249f,-0.0698305f},{-0.127761f,-0.288569f,-0.0824411f}, -{-0.147072f,-0.28855f,-0.0815279f},{-0.166352f,-0.288389f,-0.0835857f},{-0.187238f,-0.28664f,-0.0815858f}, -{-0.204878f,-0.284955f,-0.0752902f},{-0.225694f,-0.288589f,-0.0600302f},{-0.281904f,-0.293039f,-0.0341789f}, -{-0.294656f,-0.293315f,-0.0295875f},{-0.377612f,-0.054069f,-0.0618244f},{-0.1754f,0.296756f,-0.0446545f}, -{-0.2782f,-0.265471f,0.245973f},{-0.362107f,-0.229041f,0.234423f},{0.26858f,-0.260242f,-0.148568f}, -{0.257635f,-0.267091f,-0.157378f},{0.248175f,-0.26648f,-0.165757f},{0.232266f,-0.265863f,-0.174573f}, -{0.219417f,-0.270159f,-0.178419f},{0.211533f,-0.264313f,-0.183132f},{0.193624f,-0.264789f,-0.189801f}, -{0.174178f,-0.264686f,-0.191132f},{0.159162f,-0.265895f,-0.195531f},{0.150596f,-0.262506f,-0.200804f}, -{0.135581f,-0.263824f,-0.203575f},{0.116302f,-0.263651f,-0.206964f},{0.0969904f,-0.263316f,-0.21207f}, -{0.0841355f,-0.267606f,-0.215331f},{0.0764059f,-0.261831f,-0.219999f},{0.0584065f,-0.262641f,-0.222584f}, -{0.0391338f,-0.262339f,-0.227279f},{0.0230957f,-0.261953f,-0.233394f},{0.00694188f,-0.266332f,-0.234957f}, -{-0.0124466f,-0.26421f,-0.234661f},{-0.0317964f,-0.262358f,-0.231047f},{-0.0467992f,-0.261567f,-0.222887f}, -{-0.117704f,0.383499f,-0.0835278f},{-0.0364072f,-0.48212f,0.341198f},{-0.127806f,-0.279161f,-0.0867046f}, -{-0.147137f,-0.279078f,-0.08565f},{-0.16639f,-0.278904f,-0.0886274f},{-0.18246f,-0.279303f,-0.0873605f}, -{-0.220678f,-0.280769f,-0.0675541f},{-0.243526f,-0.282145f,-0.0568277f},{-0.262773f,-0.282698f,-0.0507636f}, -{-0.279988f,-0.276287f,-0.056249f},{-0.285325f,-0.283521f,-0.0440564f},{-0.302797f,-0.281296f,-0.0386161f}, -{-0.321954f,-0.282673f,-0.0228095f},{-0.220665f,0.229311f,0.0031639f},{-0.0906949f,0.286428f,-0.0364425f}, -{0.0101379f,0.436443f,-0.16184f},{0.27719f,-0.263914f,-0.140484f},{0.006884f,-0.257233f,-0.236211f}, -{-0.0124208f,-0.257323f,-0.235844f},{-0.354661f,0.0166168f,0.323713f},{-0.127883f,-0.264937f,-0.0931095f}, -{-0.14724f,-0.264782f,-0.0925758f},{-0.16648f,-0.264699f,-0.0958426f},{-0.185689f,-0.26522f,-0.0914376f}, -{-0.206235f,-0.267007f,-0.0815793f},{-0.224247f,-0.266416f,-0.0773737f},{-0.243558f,-0.266422f,-0.0763512f}, -{-0.262837f,-0.266577f,-0.0745442f},{-0.282033f,-0.272332f,-0.0624996f},{-0.297942f,-0.27293f,-0.0529115f}, -{-0.317356f,-0.274866f,-0.034732f},{-0.347812f,-0.0224109f,-0.0663258f},{0.257731f,-0.244269f,-0.159005f}, -{0.248124f,-0.243896f,-0.163995f},{0.23287f,-0.24587f,-0.172798f},{0.211456f,-0.24796f,-0.183132f}, -{0.193405f,-0.246474f,-0.191087f},{0.177335f,-0.246134f,-0.196154f},{0.167618f,-0.245818f,-0.200322f}, -{0.154744f,-0.245413f,-0.205807f},{0.135478f,-0.245117f,-0.210707f},{0.117485f,-0.245902f,-0.213594f}, -{0.100193f,-0.249503f,-0.215736f},{0.0953442f,-0.242487f,-0.218488f},{0.0776277f,-0.244552f,-0.221131f}, -{0.0583486f,-0.244204f,-0.226707f},{0.0403234f,-0.244847f,-0.231767f},{0.0229349f,-0.24351f,-0.236661f}, -{0.00681327f,-0.243394f,-0.23886f},{-0.0125044f,-0.24351f,-0.238738f},{-0.0306132f,-0.242847f,-0.237137f}, -{-0.0383171f,-0.248609f,-0.233414f},{-0.0510755f,-0.244616f,-0.22661f},{-0.334828f,0.188579f,-0.0405839f}, -{-0.333163f,0.273882f,-0.295952f},{-0.198428f,-0.260988f,-0.0868846f},{-0.282091f,-0.26185f,-0.0785055f}, -{-0.301376f,-0.258152f,-0.0702807f},{-0.307382f,-0.262924f,-0.060416f},{-0.320366f,-0.258976f,-0.0545963f}, -{-0.326694f,-0.26495f,-0.039465f},{-0.33634f,-0.260789f,-0.0343526f},{-0.300212f,-0.249072f,0.252564f}, -{-0.336835f,-0.251272f,0.232552f},{0.283467f,-0.240983f,-0.142163f},{0.270657f,-0.240346f,-0.15069f}, -{0.219115f,-0.242822f,-0.178837f},{0.109749f,-0.240217f,-0.217208f},{0.0324845f,-0.239047f,-0.234745f}, -{-0.0638275f,-0.240713f,-0.219105f},{-0.129581f,-0.248333f,-0.100813f},{-0.146031f,-0.246899f,-0.100344f}, -{-0.166544f,-0.250494f,-0.102704f},{-0.166577f,-0.24351f,-0.105045f},{-0.185843f,-0.246526f,-0.0976367f}, -{-0.205058f,-0.247098f,-0.0892833f},{-0.224453f,-0.246918f,-0.0900935f},{-0.243732f,-0.246777f,-0.0927944f}, -{-0.262985f,-0.246995f,-0.0935661f},{-0.280991f,-0.246468f,-0.091071f},{-0.288643f,-0.252551f,-0.0838687f}, -{-0.301395f,-0.248088f,-0.0803832f},{-0.314218f,-0.253966f,-0.0657406f},{-0.332758f,-0.254088f,-0.051889f}, -{-0.349246f,-0.256423f,-0.031851f},{-0.264111f,-0.0108871f,-0.103058f},{-0.459564f,0.0280763f,0.295232f}, -{-0.222761f,0.242751f,-0.005331f},{0.231121f,-0.22425f,-0.16921f},{0.216517f,-0.223093f,-0.175872f}, -{0.208395f,-0.230565f,-0.181145f},{0.193405f,-0.228655f,-0.186785f},{0.177297f,-0.228102f,-0.194849f}, -{0.167721f,-0.227542f,-0.20317f},{0.154751f,-0.227092f,-0.208739f},{0.13542f,-0.226784f,-0.213588f}, -{0.122597f,-0.231227f,-0.215755f},{0.114803f,-0.225594f,-0.21816f},{0.0968425f,-0.226391f,-0.221073f}, -{0.0775763f,-0.226166f,-0.225266f},{0.0582778f,-0.225826f,-0.230468f},{0.0402527f,-0.226436f,-0.234481f}, -{0.0247612f,-0.224443f,-0.237208f},{0.0067361f,-0.225215f,-0.239786f},{-0.0125752f,-0.225253f,-0.240468f}, -{-0.0319829f,-0.225453f,-0.239336f},{-0.0523938f,-0.227125f,-0.230205f},{-0.067075f,-0.227041f,-0.220314f}, -{-0.302804f,0.325057f,-0.357101f},{-0.12481f,-0.24104f,-0.105932f},{-0.15376f,-0.241272f,-0.103604f}, -{-0.298251f,-0.24297f,-0.0873862f},{-0.320552f,-0.244069f,-0.0723128f},{-0.339349f,-0.244757f,-0.0569306f}, -{-0.0142214f,0.343577f,-0.0948908f},{-0.207077f,0.240359f,-0.00654639f},{0.291029f,-0.222366f,-0.13541f}, -{0.283357f,-0.22733f,-0.142124f},{0.270483f,-0.222147f,-0.150703f},{0.2555f,-0.220122f,-0.157976f}, -{0.247018f,-0.222893f,-0.161422f},{-0.0447735f,-0.22124f,-0.235742f},{-0.128083f,-0.227144f,-0.1088f}, -{-0.147394f,-0.22735f,-0.105675f},{-0.166647f,-0.227285f,-0.108067f},{-0.181682f,-0.22616f,-0.104948f}, -{-0.190016f,-0.228919f,-0.101026f},{-0.203559f,-0.230404f,-0.0983441f},{-0.224517f,-0.232796f,-0.0976946f}, -{-0.243815f,-0.232603f,-0.101527f},{-0.263101f,-0.232841f,-0.102376f},{-0.283988f,-0.23079f,-0.0994694f}, -{-0.300379f,-0.22971f,-0.096685f},{-0.314482f,-0.226816f,-0.0928073f},{-0.3207f,-0.234185f,-0.0835986f}, -{-0.333562f,-0.230108f,-0.0782547f},{-0.336687f,-0.235201f,-0.0708466f},{-0.352545f,-0.236166f,-0.0560239f}, -{-0.28748f,-0.479747f,0.292415f},{0.207797f,-0.204083f,-0.181563f},{0.194273f,-0.208585f,-0.187209f}, -{0.177258f,-0.20991f,-0.195582f},{0.167413f,-0.209408f,-0.202411f},{0.15468f,-0.208964f,-0.208553f}, -{0.13533f,-0.208726f,-0.212643f},{0.122462f,-0.208488f,-0.216462f},{0.112855f,-0.208366f,-0.218623f}, -{0.0967975f,-0.208167f,-0.222334f},{0.0774541f,-0.207652f,-0.229793f},{0.0581364f,-0.207505f,-0.232642f}, -{0.0420469f,-0.207472f,-0.233742f},{0.0324394f,-0.207427f,-0.234951f},{0.0228063f,-0.207376f,-0.236571f}, -{0.00668465f,-0.207363f,-0.237787f},{-0.0126459f,-0.207228f,-0.239786f},{-0.0320472f,-0.207337f,-0.239484f}, -{-0.0447799f,-0.212193f,-0.235697f},{-0.0525289f,-0.207177f,-0.230996f},{-0.208485f,-0.223137f,-0.103862f}, -{-0.224588f,-0.222951f,-0.106312f},{-0.243835f,-0.222919f,-0.108556f},{-0.263159f,-0.223176f,-0.108627f}, -{-0.279229f,-0.223478f,-0.104273f},{-0.333671f,-0.220372f,-0.0866596f},{-0.351207f,-0.220282f,-0.0727115f}, -{-0.358821f,-0.226726f,-0.0594643f},{-0.370667f,-0.222218f,-0.0515289f},{-0.386113f,0.0409569f,-0.0281148f}, -{-0.239307f,0.243812f,-0.00250151f},{0.254394f,-0.203492f,-0.157403f},{0.244806f,-0.203196f,-0.161686f}, -{0.231938f,-0.202772f,-0.167885f},{0.216929f,-0.203704f,-0.176142f},{-0.0388702f,0.396682f,-0.120768f}, -{-0.128173f,-0.208501f,-0.113861f},{-0.147458f,-0.208707f,-0.111475f},{-0.166737f,-0.208662f,-0.112884f}, -{-0.186017f,-0.208906f,-0.110865f},{-0.205341f,-0.208977f,-0.110035f},{-0.224639f,-0.208881f,-0.112807f}, -{-0.243918f,-0.208829f,-0.115173f},{-0.263242f,-0.209112f,-0.11361f},{-0.282496f,-0.209588f,-0.108691f}, -{-0.298579f,-0.209871f,-0.105495f},{-0.315884f,-0.211241f,-0.100067f},{-0.332989f,-0.203653f,-0.0944986f}, -{-0.0356677f,-0.0449182f,-0.141745f},{-0.0517443f,-0.0449503f,-0.141706f},{0.192402f,-0.186624f,-0.187769f}, -{0.177104f,-0.187293f,-0.194682f},{0.167528f,-0.186959f,-0.199293f},{0.154654f,-0.190991f,-0.206353f}, -{0.13533f,-0.190798f,-0.21009f},{0.120314f,-0.192013f,-0.215009f},{0.111633f,-0.188714f,-0.219125f}, -{0.0967203f,-0.189936f,-0.224141f},{0.0773898f,-0.189557f,-0.229999f},{0.0580528f,-0.189344f,-0.233574f}, -{0.0430629f,-0.190888f,-0.233973f},{0.0259123f,-0.189068f,-0.239131f},{0.00660105f,-0.188926f,-0.2416f}, -{-0.0127488f,-0.189068f,-0.24086f},{-0.0320601f,-0.189235f,-0.239555f},{-0.0513328f,-0.18984f,-0.232706f}, -{-0.308193f,-0.205389f,-0.104312f},{-0.348738f,-0.200778f,-0.0857979f},{-0.36502f,-0.2078f,-0.0682293f}, -{0.254374f,-0.185415f,-0.155905f},{0.244761f,-0.185081f,-0.160876f},{0.231841f,-0.184618f,-0.167589f}, -{0.215688f,-0.184026f,-0.176174f},{0.206183f,-0.183673f,-0.180978f},{0.0386965f,-0.184701f,-0.235838f}, -{-0.131459f,-0.194405f,-0.119462f},{-0.147542f,-0.189962f,-0.118614f},{-0.166834f,-0.190007f,-0.118607f}, -{-0.186126f,-0.190116f,-0.117642f},{-0.20381f,-0.192386f,-0.119224f},{-0.224703f,-0.19465f,-0.120864f}, -{-0.242741f,-0.188926f,-0.125308f},{-0.250503f,-0.19483f,-0.12208f},{-0.264966f,-0.192753f,-0.119224f}, -{-0.28265f,-0.190926f,-0.114067f},{-0.298695f,-0.191241f,-0.110492f},{-0.314829f,-0.188631f,-0.106144f}, -{-0.321189f,-0.196579f,-0.102087f},{-0.384666f,-0.200495f,-0.0488087f},{0.154513f,-0.168696f,-0.202257f}, -{0.135208f,-0.168265f,-0.208701f},{0.122231f,-0.167988f,-0.213401f},{0.112617f,-0.172059f,-0.219884f}, -{0.0965724f,-0.171564f,-0.227272f},{0.0772612f,-0.171287f,-0.232134f},{0.057982f,-0.171236f,-0.233568f}, -{0.0258287f,-0.170895f,-0.239851f},{0.0064853f,-0.170785f,-0.242179f},{-0.0128388f,-0.170985f,-0.240468f}, -{-0.0308383f,-0.172142f,-0.238134f},{-0.0514292f,-0.171821f,-0.231722f},{-0.231925f,-0.0466544f,-0.121996f}, -{-0.000286191f,0.396785f,-0.137282f},{-0.208659f,-0.185293f,-0.123424f},{-0.224742f,-0.185152f,-0.125771f}, -{-0.260162f,-0.185505f,-0.123867f},{-0.335362f,-0.183981f,-0.0998939f},{-0.353162f,-0.183698f,-0.0911675f}, -{-0.298759f,0.345281f,-0.371531f},{0.308964f,-0.170007f,-0.116054f},{-0.302694f,-0.0482235f,-0.103032f}, -{0.244555f,-0.171448f,-0.161004f},{0.215681f,-0.16593f,-0.175338f},{0.206035f,-0.165615f,-0.180052f}, -{0.193129f,-0.165281f,-0.185447f},{0.173856f,-0.164792f,-0.192727f},{-0.0385808f,-0.166979f,-0.235182f}, -{-0.128449f,-0.170522f,-0.133179f},{-0.147651f,-0.17112f,-0.126915f},{-0.166924f,-0.171371f,-0.124819f}, -{-0.186222f,-0.171326f,-0.12552f},{-0.205527f,-0.171268f,-0.127623f},{-0.224806f,-0.171326f,-0.128613f}, -{-0.244111f,-0.171416f,-0.128092f},{-0.263435f,-0.171737f,-0.125076f},{-0.281441f,-0.173306f,-0.117405f}, -{-0.296418f,-0.167056f,-0.113283f},{-0.314115f,-0.167384f,-0.10999f},{-0.327723f,-0.178129f,-0.104582f}, -{-0.365856f,-0.179563f,-0.0851162f},{-0.311562f,0.346207f,-0.370239f},{-0.112906f,-0.0277612f,-0.121623f}, -{0.115839f,-0.147288f,-0.212437f},{0.109389f,-0.158542f,-0.219015f},{0.0956914f,-0.150407f,-0.222301f}, -{0.0771711f,-0.149031f,-0.226379f},{0.0586958f,-0.150002f,-0.229555f},{0.00640814f,-0.152928f,-0.239028f}, -{-0.0116234f,-0.154008f,-0.237459f},{-0.0257387f,-0.157808f,-0.236037f},{-0.032999f,-0.148002f,-0.231105f}, -{-0.051455f,-0.149603f,-0.226173f},{-0.315093f,-0.235465f,0.25749f},{-0.327755f,-0.164342f,-0.105354f}, -{-0.337484f,-0.164696f,-0.101244f},{-0.353445f,-0.165262f,-0.0944921f},{-0.368332f,-0.164336f,-0.0870583f}, -{0.193065f,-0.146979f,-0.1862f},{0.173721f,-0.146606f,-0.192502f},{0.154513f,-0.146034f,-0.200945f}, -{0.135137f,-0.145764f,-0.205717f},{-0.0193917f,-0.148838f,-0.233806f},{-0.123883f,-0.149892f,-0.142754f}, -{-0.132726f,-0.153764f,-0.133989f},{-0.147741f,-0.152612f,-0.129636f},{-0.167014f,-0.152793f,-0.128234f}, -{-0.186312f,-0.152735f,-0.130169f},{-0.00889684f,0.422186f,-0.143655f},{0.102977f,-0.140529f,-0.216012f}, -{-0.318225f,-0.223105f,0.263252f},{-0.366892f,-0.00498377f,-0.0479984f},{-0.110251f,-0.491759f,-0.181525f}, -{-0.0913894f,-0.491913f,-0.170451f},{-0.131369f,-0.491315f,-0.169191f},{-0.111292f,-0.49145f,-0.169943f}, -{-0.0513714f,-0.491663f,-0.151969f},{-0.0331983f,-0.491624f,-0.149641f},{-0.0130961f,-0.49174f,-0.150439f}, -{0.0435452f,-0.489901f,-0.13197f},{0.0612102f,-0.489663f,-0.131745f},{0.0793768f,-0.489631f,-0.129423f}, -{0.0996656f,-0.489405f,-0.130517f},{0.155735f,-0.487618f,-0.114164f},{0.174171f,-0.486608f,-0.112215f}, -{0.189656f,-0.484576f,-0.112292f},{-0.165329f,-0.488055f,-0.165667f},{-0.125909f,-0.491836f,-0.151371f}, -{-0.108263f,-0.491585f,-0.151146f},{-0.0900904f,-0.49154f,-0.148818f},{-0.0699945f,-0.491643f,-0.149596f}, -{-0.0160992f,-0.490897f,-0.133668f},{0.00396448f,-0.490171f,-0.130407f},{0.0226391f,-0.4901f,-0.132845f}, -{0.0807787f,-0.488531f,-0.11381f},{0.0982894f,-0.488306f,-0.112389f},{0.114906f,-0.488319f,-0.11154f}, -{0.135118f,-0.488261f,-0.112492f},{0.191971f,-0.48628f,-0.09446f},{0.202884f,-0.484119f,-0.103309f}, -{0.20808f,-0.483258f,-0.0937976f},{-0.147793f,-0.491798f,-0.149712f},{-0.0728047f,-0.490479f,-0.133153f}, -{-0.0527861f,-0.48983f,-0.129809f},{-0.0355262f,-0.490274f,-0.129012f},{0.0236487f,-0.487901f,-0.116549f}, -{0.0419633f,-0.487168f,-0.112414f},{0.0601042f,-0.48718f,-0.110041f},{0.117163f,-0.485644f,-0.097193f}, -{0.135915f,-0.486377f,-0.095849f},{0.15513f,-0.487213f,-0.0912961f},{0.17367f,-0.487496f,-0.0935918f}, -{-0.449989f,0.00813478f,0.248461f},{-0.145728f,-0.491373f,-0.133513f},{-0.128584f,-0.491174f,-0.130298f}, -{-0.10991f,-0.490229f,-0.128678f},{-0.0921225f,-0.489714f,-0.128671f},{-0.031835f,-0.483238f,-0.116736f}, -{-0.0167037f,-0.484808f,-0.116517f},{0.00189381f,-0.484351f,-0.113276f},{0.0818527f,-0.485258f,-0.101489f}, -{0.0984116f,-0.484917f,-0.0985306f},{0.173901f,-0.486576f,-0.0760618f},{0.192023f,-0.486705f,-0.0736632f}, -{-0.168641f,-0.49165f,-0.132992f},{-0.0911964f,-0.483785f,-0.118948f},{-0.0730427f,-0.48464f,-0.120575f}, -{-0.0523617f,-0.482775f,-0.118221f},{0.00335356f,-0.475322f,-0.106074f},{0.0212051f,-0.480087f,-0.106177f}, -{0.0343301f,-0.480049f,-0.103611f},{0.041751f,-0.470757f,-0.0971737f},{0.0607922f,-0.471419f,-0.0942992f}, -{0.0806115f,-0.471117f,-0.0906723f},{0.100894f,-0.474075f,-0.0899521f},{0.119067f,-0.47585f,-0.0877528f}, -{0.133176f,-0.479046f,-0.0850133f},{0.139909f,-0.470962f,-0.0775409f},{0.157799f,-0.481946f,-0.0774637f}, -{0.196035f,-0.486415f,-0.0577216f},{0.211578f,-0.484203f,-0.0575994f},{0.224408f,-0.482055f,-0.0584868f}, -{-0.165348f,-0.491412f,-0.114614f},{-0.14686f,-0.490775f,-0.112742f},{-0.129395f,-0.488351f,-0.109109f}, -{-0.111466f,-0.484775f,-0.113057f},{-0.0891579f,-0.471522f,-0.108466f},{-0.0720395f,-0.471091f,-0.110614f}, -{-0.0527539f,-0.471252f,-0.110929f},{-0.032253f,-0.469728f,-0.108279f},{-0.013842f,-0.471046f,-0.106427f}, -{0.0209929f,-0.468191f,-0.099135f},{0.121511f,-0.465696f,-0.0803254f},{0.155632f,-0.472004f,-0.0701456f}, -{0.167721f,-0.478049f,-0.0589434f},{0.177007f,-0.484441f,-0.0562425f},{-0.184801f,-0.487926f,-0.112749f}, -{-0.104829f,-0.478531f,-0.108537f},{-0.00903832f,-0.46511f,-0.10192f},{0.004241f,-0.464802f,-0.099553f}, -{0.100585f,-0.462332f,-0.0827369f},{0.157169f,-0.467252f,-0.0572972f},{0.176551f,-0.484949f,-0.0377415f}, -{0.193264f,-0.486377f,-0.036121f},{0.212665f,-0.484074f,-0.0356001f},{0.224858f,-0.482512f,-0.0334201f}, -{-0.352043f,-0.278075f,0.16793f},{-0.18556f,-0.490968f,-0.0940098f},{-0.167451f,-0.491032f,-0.0915404f}, -{-0.14724f,-0.489013f,-0.0923507f},{-0.131041f,-0.483663f,-0.0930645f},{-0.112103f,-0.469548f,-0.0943121f}, -{-0.0604193f,-0.461059f,-0.103823f},{-0.0504261f,-0.459426f,-0.0961384f},{-0.0323109f,-0.459471f,-0.0937076f}, -{-0.0139642f,-0.459091f,-0.0916176f},{0.00604159f,-0.459297f,-0.0922414f},{0.0226713f,-0.45886f,-0.0893476f}, -{0.0390823f,-0.45877f,-0.0861644f},{0.0606829f,-0.457098f,-0.0773866f},{0.0806051f,-0.456603f,-0.0738947f}, -{0.0981608f,-0.456506f,-0.0734896f},{0.118192f,-0.457844f,-0.0712967f},{0.133902f,-0.459059f,-0.0670525f}, -{0.137812f,-0.458506f,-0.0571235f},{0.166589f,-0.477091f,-0.0439407f},{0.230665f,-0.482583f,-0.0170991f}, -{-0.196646f,-0.486422f,-0.0956625f},{-0.14614f,-0.484782f,-0.0751744f},{-0.126166f,-0.477297f,-0.0899778f}, -{-0.098611f,-0.46286f,-0.097791f},{-0.0876403f,-0.459458f,-0.0915533f},{-0.071255f,-0.458699f,-0.0931738f}, -{0.00337286f,-0.457902f,-0.0760361f},{0.0219189f,-0.457149f,-0.0742355f},{0.042169f,-0.456937f,-0.0752066f}, -{0.0984052f,-0.455722f,-0.0560882f},{0.116044f,-0.455445f,-0.0558374f},{0.151233f,-0.46104f,-0.049709f}, -{0.157226f,-0.469014f,-0.0381724f},{0.172171f,-0.485952f,-0.0186167f},{0.193097f,-0.486377f,-0.0180573f}, -{0.209939f,-0.485496f,-0.0155172f},{-0.185348f,-0.491637f,-0.0737532f},{-0.164024f,-0.490582f,-0.0734317f}, -{-0.127047f,-0.469368f,-0.0775602f},{-0.101569f,-0.460133f,-0.088936f},{-0.0714929f,-0.458892f,-0.0750972f}, -{-0.0540208f,-0.458911f,-0.0745764f},{-0.0364265f,-0.458705f,-0.0742484f},{-0.015469f,-0.458365f,-0.0733738f}, -{0.0257065f,-0.457432f,-0.0580045f},{0.0419826f,-0.456969f,-0.057175f},{0.0585351f,-0.456648f,-0.0541783f}, -{0.0773255f,-0.456313f,-0.0567248f},{0.136783f,-0.457207f,-0.0380245f},{0.147703f,-0.459304f,-0.0399601f}, -{0.149902f,-0.475174f,-0.0189254f},{0.157439f,-0.483457f,-0.0158194f},{0.174904f,-0.487335f,0.000244383f}, -{0.192376f,-0.487361f,0.000745975f},{0.210267f,-0.48664f,0.000649515f},{0.232549f,-0.483856f,-0.000456558f}, -{0.245937f,-0.48329f,0.00167842f},{-0.18529f,-0.491405f,-0.0561847f},{-0.167104f,-0.490087f,-0.0567055f}, -{-0.151047f,-0.484608f,-0.0584933f},{-0.109993f,-0.460133f,-0.0715025f},{-0.0922768f,-0.458937f,-0.0762226f}, -{-0.0308768f,-0.459117f,-0.0565898f},{-0.0139642f,-0.458551f,-0.0561204f},{0.00377799f,-0.457844f,-0.0550079f}, -{0.0625928f,-0.456969f,-0.0380502f},{0.0804443f,-0.456288f,-0.0380952f},{0.0988939f,-0.455683f,-0.0361532f}, -{0.119369f,-0.455046f,-0.037465f},{0.141034f,-0.465233f,-0.0178001f},{0.153747f,-0.486036f,0.00079742f}, -{0.213f,-0.485727f,0.0189962f},{0.229558f,-0.485804f,0.0199737f},{0.248606f,-0.484119f,0.0210347f}, -{0.26858f,-0.47558f,0.0111829f},{0.288714f,-0.472416f,0.0155494f},{0.306231f,-0.470776f,0.0226167f}, -{0.310443f,-0.463844f,0.00981964f},{-0.224781f,-0.491733f,-0.0549307f},{-0.206305f,-0.491907f,-0.0569756f}, -{-0.135613f,-0.470229f,-0.0626025f},{-0.124019f,-0.461033f,-0.068718f},{-0.0896531f,-0.45994f,-0.0568727f}, -{-0.0721617f,-0.459902f,-0.0563904f},{-0.0514485f,-0.459979f,-0.0551493f},{0.0043246f,-0.458435f,-0.0382045f}, -{0.0226648f,-0.458024f,-0.0361017f},{0.0414231f,-0.457709f,-0.0386097f},{0.0994469f,-0.456223f,-0.0193434f}, -{0.11672f,-0.456378f,-0.0175493f},{0.130005f,-0.457342f,-0.0212147f},{0.132829f,-0.472731f,0.00142119f}, -{0.141529f,-0.484267f,0.00572974f},{0.156886f,-0.488074f,0.0182824f},{0.173599f,-0.487438f,0.0210476f}, -{0.192595f,-0.487026f,0.0232919f},{0.270638f,-0.483528f,0.0369313f},{0.284952f,-0.479406f,0.0300312f}, -{0.310193f,-0.475811f,0.0396836f},{0.339658f,-0.462377f,0.0256391f},{-0.203045f,-0.491862f,-0.0386418f}, -{-0.184647f,-0.491309f,-0.0366355f},{-0.169342f,-0.490061f,-0.0335102f},{-0.155252f,-0.486203f,-0.0400759f}, -{-0.139999f,-0.470178f,-0.0516832f},{-0.127748f,-0.461014f,-0.0536188f},{-0.108225f,-0.459914f,-0.054667f}, -{-0.0706569f,-0.460564f,-0.0393814f},{-0.0535706f,-0.460442f,-0.0360696f},{-0.0367223f,-0.459979f,-0.0354779f}, -{-0.0162921f,-0.459374f,-0.0367126f},{0.0429086f,-0.457979f,-0.0213112f},{0.0609852f,-0.457612f,-0.0168162f}, -{0.0772612f,-0.45713f,-0.0159802f},{0.118276f,-0.459194f,-0.00186487f},{0.136436f,-0.486428f,0.0216328f}, -{0.199257f,-0.484287f,0.0293238f},{0.217154f,-0.481476f,0.0303463f},{0.232845f,-0.483676f,0.0385004f}, -{0.250696f,-0.486023f,0.0412141f},{0.289036f,-0.481714f,0.0449761f},{0.299518f,-0.480499f,0.0459921f}, -{0.327009f,-0.471303f,0.0436513f},{0.343368f,-0.465252f,0.0412077f},{-0.337967f,-0.286254f,0.172303f}, -{-0.260143f,-0.492505f,-0.0377673f},{-0.242118f,-0.492666f,-0.0351628f},{-0.221855f,-0.492312f,-0.0361146f}, -{-0.164705f,-0.489463f,-0.0183659f},{-0.14695f,-0.474859f,-0.036957f},{-0.1267f,-0.460628f,-0.0399087f}, -{-0.110257f,-0.460275f,-0.0357287f},{-0.0942703f,-0.460185f,-0.0367512f},{-0.0310762f,-0.460262f,-0.0180123f}, -{-0.0133469f,-0.459773f,-0.0178515f},{0.00447894f,-0.459111f,-0.0178386f},{0.0255651f,-0.45848f,-0.0171698f}, -{0.0810745f,-0.457406f,0.0002058f},{0.097865f,-0.457046f,0.000855296f},{0.120855f,-0.463786f,0.00681652f}, -{0.118437f,-0.470152f,0.0181152f},{0.12425f,-0.481592f,0.0237549f},{0.1367f,-0.487566f,0.0388476f}, -{0.154005f,-0.486242f,0.0387576f},{0.176743f,-0.48138f,0.0340954f},{0.194634f,-0.478551f,0.0351179f}, -{0.212723f,-0.475374f,0.0358574f},{0.22687f,-0.479457f,0.0424488f},{0.249918f,-0.484319f,0.0566349f}, -{0.26966f,-0.485065f,0.056159f},{0.286888f,-0.483457f,0.0581461f},{0.304309f,-0.481502f,0.0598823f}, -{0.315511f,-0.478956f,0.0598052f},{0.327999f,-0.474049f,0.0578567f},{0.344597f,-0.467297f,0.0551172f}, -{0.358268f,-0.462313f,0.0590335f},{0.366667f,-0.458294f,0.0572715f},{-0.402948f,-0.00846919f,0.222533f}, -{-0.262921f,-0.299225f,0.207421f},{-0.278419f,-0.492003f,-0.036031f},{-0.241172f,-0.49273f,-0.0190412f}, -{-0.22352f,-0.492139f,-0.0177743f},{-0.206788f,-0.491856f,-0.0170091f},{-0.186383f,-0.491251f,-0.0181473f}, -{-0.131356f,-0.46212f,-0.0335487f},{-0.0887399f,-0.460731f,-0.0191055f},{-0.0707727f,-0.460982f,-0.0164432f}, -{-0.0521559f,-0.460898f,-0.0187068f},{0.003823f,-0.460146f,0.000823143f},{0.0216231f,-0.459522f,0.000874589f}, -{0.0395389f,-0.458718f,0.000784559f},{0.0607344f,-0.45787f,0.00129258f},{0.101151f,-0.45832f,0.0177872f}, -{0.111183f,-0.461329f,0.014604f},{0.111813f,-0.474814f,0.0349442f},{0.118945f,-0.484544f,0.0412399f}, -{0.168789f,-0.475779f,0.0393492f},{0.234195f,-0.47585f,0.0525964f},{0.269107f,-0.48583f,0.0746986f}, -{0.288071f,-0.484242f,0.0758882f},{0.30537f,-0.482087f,0.079811f},{0.32416f,-0.47803f,0.0775281f}, -{0.344796f,-0.469792f,0.0765442f},{-0.388422f,-0.255927f,0.150561f},{-0.297801f,-0.492595f,-0.0188868f}, -{-0.28047f,-0.492601f,-0.0171313f},{-0.264644f,-0.492762f,-0.0178772f},{-0.200666f,-0.491412f,-0.000302223f}, -{-0.184525f,-0.491f,-0.00152405f},{-0.166377f,-0.490505f,0.00285523f},{-0.148854f,-0.486319f,-0.00328605f}, -{-0.125253f,-0.46084f,-0.0216392f},{-0.10872f,-0.460551f,-0.0185653f},{-0.0523552f,-0.46113f,-0.000713785f}, -{-0.0344008f,-0.460982f,0.00396774f},{-0.0170895f,-0.46048f,-0.000128595f},{0.045095f,-0.459136f,0.0183596f}, -{0.0618983f,-0.458763f,0.0190219f},{0.0790875f,-0.458423f,0.0222051f},{0.105955f,-0.462815f,0.0268223f}, -{0.118353f,-0.485785f,0.0573294f},{0.132205f,-0.488158f,0.0591107f},{0.148146f,-0.481541f,0.052352f}, -{0.158841f,-0.473869f,0.0475483f},{0.242536f,-0.476377f,0.0667246f},{0.251789f,-0.47801f,0.0780554f}, -{0.256014f,-0.481702f,0.0742999f},{0.361348f,-0.462094f,0.0778367f},{0.371265f,-0.4565f,0.0741841f}, -{0.383393f,-0.450474f,0.0784477f},{0.397643f,-0.443439f,0.0674384f},{-0.411135f,-0.00341467f,0.245548f}, -{-0.258638f,-0.492601f,-0.00105461f},{-0.240375f,-0.492293f,0.00120898f},{-0.222729f,-0.491901f,0.00151122f}, -{-0.147889f,-0.490621f,0.0184046f},{-0.120012f,-0.461149f,-0.00846916f},{-0.107961f,-0.461091f,-0.00315744f}, -{-0.0910678f,-0.460898f,0.00417352f},{-0.0740459f,-0.460847f,0.000559486f},{-0.0140221f,-0.46077f,0.0184882f}, -{0.00419598f,-0.460551f,0.0208032f},{0.0244911f,-0.460107f,0.0198257f},{0.080708f,-0.458995f,0.0389763f}, -{0.0930806f,-0.459606f,0.0371435f},{0.102206f,-0.467586f,0.0423202f},{0.0986688f,-0.470789f,0.0581653f}, -{0.13623f,-0.488184f,0.0748786f},{0.267995f,-0.483624f,0.0962734f},{0.286071f,-0.484467f,0.0948265f}, -{0.30382f,-0.481882f,0.0960741f},{0.314881f,-0.479592f,0.0962284f},{0.329105f,-0.474776f,0.0986657f}, -{0.344635f,-0.468905f,0.0984599f},{0.356056f,-0.463818f,0.0903444f},{0.364062f,-0.459651f,0.0960548f}, -{-0.314405f,-0.492216f,0.000662377f},{-0.297273f,-0.492743f,0.00171057f},{-0.279666f,-0.492441f,0.00209641f}, -{-0.222736f,-0.492036f,0.0190669f},{-0.205077f,-0.491598f,0.0193434f},{-0.187361f,-0.491077f,0.0195557f}, -{-0.166808f,-0.491367f,0.0210669f},{-0.133896f,-0.490949f,0.0273496f},{-0.105106f,-0.461857f,0.00686153f}, -{-0.07121f,-0.461323f,0.0179158f},{-0.0534227f,-0.461078f,0.0195557f},{-0.0327031f,-0.461072f,0.0208225f}, -{0.00517987f,-0.46059f,0.0368284f},{0.0227034f,-0.46023f,0.0383075f},{0.0410372f,-0.459786f,0.040436f}, -{0.0597762f,-0.459394f,0.0380245f},{0.107241f,-0.482544f,0.0744349f},{0.116154f,-0.486184f,0.0766213f}, -{0.25449f,-0.475644f,0.0960805f},{0.288759f,-0.482737f,0.110228f},{0.303235f,-0.480936f,0.106858f}, -{0.308109f,-0.477997f,0.113964f},{0.324732f,-0.473451f,0.110299f},{0.381599f,-0.451188f,0.0953989f}, -{0.396293f,-0.44423f,0.0976946f},{0.405579f,-0.439664f,0.0950002f},{-0.338539f,-0.48983f,0.000366566f}, -{-0.279531f,-0.492312f,0.0194142f},{-0.261969f,-0.492048f,0.0198386f},{-0.244446f,-0.491875f,0.0203273f}, -{-0.181894f,-0.491965f,0.0371692f},{-0.165181f,-0.491675f,0.0379602f},{-0.147992f,-0.491328f,0.0411305f}, -{-0.128456f,-0.491045f,0.0401788f},{-0.118411f,-0.490608f,0.0418379f},{-0.0931128f,-0.461921f,0.0210219f}, -{-0.0829137f,-0.461213f,0.0224623f},{-0.070091f,-0.461676f,0.0254783f},{-0.0473393f,-0.461297f,0.0336259f}, -{-0.0361178f,-0.461374f,0.0379216f},{-0.0264976f,-0.461721f,0.0401852f},{-0.0166458f,-0.460975f,0.0395614f}, -{0.0614803f,-0.459503f,0.0548536f},{0.0783222f,-0.459792f,0.0585255f},{0.096894f,-0.472789f,0.07911f}, -{0.118077f,-0.486344f,0.0929231f},{0.135517f,-0.48875f,0.0974695f},{0.250921f,-0.475547f,0.11089f}, -{0.268162f,-0.483329f,0.113617f},{0.345143f,-0.465252f,0.1168f},{0.354924f,-0.461966f,0.1119f}, -{0.365136f,-0.457162f,0.115501f},{0.3823f,-0.449715f,0.11208f},{-0.298662f,-0.297714f,0.189081f}, -{-0.377451f,-0.269091f,0.135025f},{-0.335613f,-0.491315f,0.0186875f},{-0.318752f,-0.49237f,0.0201859f}, -{-0.301428f,-0.492531f,0.0209575f},{-0.239938f,-0.491727f,0.0356066f},{-0.223681f,-0.491913f,0.0390856f}, -{-0.204672f,-0.492016f,0.0401338f},{-0.147626f,-0.489032f,0.0596766f},{-0.128346f,-0.490955f,0.0575802f}, -{-0.113202f,-0.490486f,0.0582875f},{-0.0844828f,-0.462133f,0.0346163f},{-0.0740201f,-0.4623f,0.0407897f}, -{-0.0580978f,-0.461741f,0.0396258f},{-0.0177004f,-0.461664f,0.0535996f},{-0.00942416f,-0.461098f,0.056712f}, -{0.00554642f,-0.460982f,0.0576895f},{0.0231343f,-0.46068f,0.0580753f},{0.0440918f,-0.46023f,0.0589949f}, -{0.0782129f,-0.46032f,0.0737854f},{0.0864827f,-0.462474f,0.0754703f},{0.105678f,-0.48147f,0.0965178f}, -{0.150828f,-0.487341f,0.112922f},{0.255172f,-0.481136f,0.12071f},{0.268432f,-0.482853f,0.130806f}, -{0.284476f,-0.48138f,0.126877f},{0.290823f,-0.47839f,0.133282f},{0.307112f,-0.474589f,0.132375f}, -{0.326578f,-0.469232f,0.129153f},{0.340249f,-0.464892f,0.129179f},{0.393482f,-0.443285f,0.114183f}, -{0.403733f,-0.438372f,0.117604f},{-0.293917f,-0.294312f,0.19991f},{-0.24359f,-0.287939f,0.232102f}, -{-0.352487f,-0.486274f,0.0193949f},{-0.296714f,-0.49201f,0.0359088f},{-0.280348f,-0.491984f,0.039227f}, -{-0.261236f,-0.491907f,0.0401466f},{-0.205444f,-0.488518f,0.0571493f},{-0.186203f,-0.487148f,0.0540176f}, -{-0.166435f,-0.486878f,0.0577859f},{-0.108617f,-0.490447f,0.0739076f},{-0.0683805f,-0.462699f,0.0558889f}, -{-0.0517765f,-0.462223f,0.0588341f},{-0.0363622f,-0.461889f,0.055831f},{-0.0263046f,-0.461445f,0.0574837f}, -{0.0231086f,-0.460795f,0.075676f},{0.04069f,-0.460532f,0.0761005f},{0.0583614f,-0.460101f,0.0763898f}, -{0.0958972f,-0.471734f,0.0962542f},{0.117408f,-0.484872f,0.114479f},{0.135992f,-0.487939f,0.114344f}, -{0.24377f,-0.476043f,0.125482f},{0.252632f,-0.483894f,0.134382f},{0.348654f,-0.459426f,0.137687f}, -{0.363053f,-0.45412f,0.134652f},{0.381997f,-0.44605f,0.132388f},{0.401579f,-0.43623f,0.133063f}, -{-0.352249f,-0.485689f,0.0385068f},{-0.336179f,-0.490563f,0.0381017f},{-0.317935f,-0.491489f,0.0414971f}, -{-0.260194f,-0.491901f,0.0559918f},{-0.242291f,-0.492235f,0.0587827f},{-0.223681f,-0.491283f,0.0605511f}, -{-0.142507f,-0.487026f,0.0685895f},{-0.129999f,-0.486968f,0.0777146f},{-0.0948298f,-0.48956f,0.0805505f}, -{-0.0349732f,-0.462262f,0.0750973f},{-0.0164529f,-0.461857f,0.0784991f},{-0.0175332f,-0.461394f,0.0708723f}, -{0.00209959f,-0.461381f,0.0748401f},{0.0640912f,-0.460448f,0.0936112f},{0.0788045f,-0.460641f,0.0956111f}, -{0.0865277f,-0.462455f,0.0929745f},{0.0987974f,-0.471065f,0.114922f},{0.136751f,-0.486602f,0.130787f}, -{0.154899f,-0.486119f,0.135205f},{0.170982f,-0.483753f,0.135179f},{0.230079f,-0.475168f,0.13361f}, -{0.233385f,-0.481219f,0.139745f},{0.23325f,-0.484184f,0.150188f},{0.249886f,-0.482955f,0.150516f}, -{0.263995f,-0.481033f,0.151674f},{0.273769f,-0.477727f,0.152632f},{0.289132f,-0.47401f,0.149275f}, -{0.308122f,-0.468699f,0.15069f},{0.326147f,-0.464795f,0.146735f},{0.343587f,-0.456024f,0.155088f}, -{0.416781f,-0.428198f,0.134568f},{0.426806f,-0.422732f,0.130735f},{-0.373091f,-0.224449f,0.226289f}, -{-0.315472f,-0.490749f,0.0568856f},{-0.298354f,-0.49129f,0.058011f},{-0.281107f,-0.491585f,0.0589306f}, -{-0.194756f,-0.478872f,0.0621974f},{-0.184139f,-0.477367f,0.0630012f},{-0.170737f,-0.476776f,0.0651941f}, -{-0.161541f,-0.477914f,0.0680943f},{-0.146069f,-0.477573f,0.0755796f},{-0.109678f,-0.489811f,0.0959969f}, -{-0.0912672f,-0.489155f,0.0983313f},{-0.0687599f,-0.463483f,0.0739848f},{-0.0555513f,-0.463246f,0.076467f}, -{-0.00233756f,-0.461567f,0.0857722f},{0.00869102f,-0.461381f,0.093669f},{0.0229478f,-0.461175f,0.0934825f}, -{0.0410951f,-0.460885f,0.0969101f},{0.0883026f,-0.463213f,0.105714f},{0.11344f,-0.475991f,0.135925f}, -{0.122109f,-0.482808f,0.134105f},{0.178042f,-0.484891f,0.15222f},{0.193663f,-0.485393f,0.151783f}, -{0.210858f,-0.485039f,0.154966f},{0.331362f,-0.461181f,0.153352f},{0.363818f,-0.448603f,0.153333f}, -{0.38291f,-0.440153f,0.150812f},{0.400138f,-0.430475f,0.153699f},{-0.428459f,0.0276519f,0.314106f}, -{-0.412016f,-0.00104821f,0.266345f},{-0.337407f,-0.489116f,0.0595544f},{-0.278824f,-0.491193f,0.0745893f}, -{-0.260316f,-0.491592f,0.0776052f},{-0.244568f,-0.491978f,0.0792708f},{-0.222562f,-0.486126f,0.0746729f}, -{-0.204357f,-0.476557f,0.0697534f},{-0.133214f,-0.478042f,0.0855921f},{-0.126983f,-0.477309f,0.0939198f}, -{-0.120919f,-0.481534f,0.0970387f},{-0.0656217f,-0.463863f,0.0924022f},{-0.0524196f,-0.463619f,0.094878f}, -{-0.033687f,-0.46241f,0.0964406f},{-0.0134626f,-0.462062f,0.0955982f},{-0.000260458f,-0.461818f,0.0980676f}, -{0.0259766f,-0.461683f,0.103296f},{0.0439118f,-0.460802f,0.111971f},{0.0603614f,-0.460583f,0.115135f}, -{0.0776984f,-0.460763f,0.115906f},{0.100746f,-0.465863f,0.131996f},{0.138301f,-0.483026f,0.15004f}, -{0.154397f,-0.484685f,0.154805f},{0.213385f,-0.484042f,0.170323f},{0.23134f,-0.483071f,0.170194f}, -{0.247146f,-0.481367f,0.169937f},{0.256587f,-0.478673f,0.17139f},{0.269403f,-0.473072f,0.168972f}, -{0.286984f,-0.466371f,0.170329f},{0.305608f,-0.464628f,0.162876f},{0.324809f,-0.454744f,0.171068f}, -{0.41134f,-0.426051f,0.149371f},{0.422993f,-0.418765f,0.150793f},{-0.31908f,-0.48965f,0.0752645f}, -{-0.301376f,-0.490338f,0.0783705f},{-0.240169f,-0.491553f,0.0943635f},{-0.229887f,-0.491746f,0.0897528f}, -{-0.111742f,-0.488872f,0.114209f},{-0.0909585f,-0.488711f,0.115405f},{-0.0327417f,-0.46257f,0.112479f}, -{-0.0152182f,-0.462204f,0.113977f},{0.00272336f,-0.461792f,0.11417f},{0.00360437f,-0.461529f,0.117983f}, -{0.0219253f,-0.461175f,0.113656f},{0.0347416f,-0.461631f,0.116684f},{0.0799299f,-0.460345f,0.131706f}, -{0.119517f,-0.469618f,0.152793f},{0.131034f,-0.475798f,0.156812f},{0.159869f,-0.482943f,0.169107f}, -{0.17403f,-0.484325f,0.171294f},{0.191412f,-0.484415f,0.172001f},{0.306006f,-0.458043f,0.174535f}, -{0.343889f,-0.447998f,0.173319f},{0.361008f,-0.444462f,0.167795f},{0.383148f,-0.432192f,0.169126f}, -{-0.221604f,-0.246654f,0.267053f},{-0.212086f,-0.27158f,0.254243f},{-0.347523f,-0.483804f,0.0699656f}, -{-0.335864f,-0.485766f,0.0786727f},{-0.295048f,-0.489753f,0.0946272f},{-0.2782f,-0.490775f,0.0961513f}, -{-0.259956f,-0.491187f,0.09455f},{-0.121491f,-0.476673f,0.109926f},{-0.119041f,-0.484312f,0.117276f}, -{-0.109614f,-0.488743f,0.130144f},{-0.0914151f,-0.486479f,0.131835f},{-0.0691071f,-0.469805f,0.118343f}, -{-0.0545481f,-0.463676f,0.117726f},{0.0204205f,-0.461355f,0.129018f},{0.0282659f,-0.461664f,0.132832f}, -{0.0416546f,-0.461066f,0.135025f},{0.0579113f,-0.460545f,0.135931f},{0.0933378f,-0.46014f,0.138928f}, -{0.107672f,-0.463901f,0.145211f},{0.138217f,-0.469721f,0.169634f},{0.154571f,-0.477014f,0.175306f}, -{0.19381f,-0.483689f,0.187557f},{0.21271f,-0.48338f,0.189968f},{0.231385f,-0.481907f,0.193621f}, -{0.242246f,-0.481103f,0.188142f},{0.25141f,-0.474898f,0.192212f},{0.269094f,-0.46702f,0.185602f}, -{0.293344f,-0.459561f,0.179094f},{0.362461f,-0.439735f,0.175557f},{0.396074f,-0.425543f,0.169737f}, -{0.399997f,-0.420784f,0.174039f},{-0.430259f,0.00304813f,0.26468f},{-0.316598f,-0.265516f,0.229362f}, -{-0.327922f,-0.484139f,0.0914633f},{-0.316308f,-0.486891f,0.0962863f},{-0.259879f,-0.491309f,0.111868f}, -{-0.243944f,-0.492023f,0.115803f},{-0.121466f,-0.482885f,0.132896f},{-0.0500402f,-0.463522f,0.133031f}, -{-0.0322401f,-0.462815f,0.133121f},{-0.0136877f,-0.461934f,0.134967f},{0.00335356f,-0.4614f,0.13332f}, -{0.0129867f,-0.461741f,0.135603f},{0.0622906f,-0.460062f,0.151121f},{0.080663f,-0.459496f,0.153217f}, -{0.0981094f,-0.459451f,0.153834f},{0.111459f,-0.460969f,0.155018f},{0.171084f,-0.474621f,0.19274f}, -{0.175554f,-0.481579f,0.186605f},{0.286907f,-0.455587f,0.193036f},{0.306296f,-0.449124f,0.1871f}, -{0.32598f,-0.444892f,0.184393f},{0.344127f,-0.435838f,0.190219f},{0.362062f,-0.430269f,0.190386f}, -{0.375483f,-0.42753f,0.184849f},{-0.33396f,0.239008f,-0.169165f},{-0.281917f,-0.48992f,0.114646f}, -{-0.242105f,-0.492582f,0.133816f},{-0.124565f,-0.478551f,0.13415f},{-0.109177f,-0.488544f,0.15204f}, -{-0.092579f,-0.485328f,0.150625f},{-0.0680782f,-0.46468f,0.133256f},{-0.00444683f,-0.461831f,0.143732f}, -{0.0050577f,-0.461207f,0.152079f},{0.0233336f,-0.460853f,0.154329f},{0.0421433f,-0.460275f,0.151847f}, -{0.0987396f,-0.45839f,0.170458f},{0.117716f,-0.458667f,0.170856f},{0.155477f,-0.467522f,0.186187f}, -{0.194383f,-0.483161f,0.209299f},{0.211906f,-0.482981f,0.209807f},{0.230086f,-0.48156f,0.209357f}, -{0.24867f,-0.473457f,0.211678f},{0.260477f,-0.467548f,0.20301f},{0.310321f,-0.438082f,0.194566f}, -{0.386248f,-0.417376f,0.189582f},{-0.335459f,0.246854f,-0.208836f},{-0.402743f,-0.236642f,0.149744f}, -{-0.313723f,-0.482608f,0.110054f},{-0.279338f,-0.489071f,0.129816f},{-0.261487f,-0.490685f,0.133816f}, -{-0.121517f,-0.483174f,0.150477f},{-0.069718f,-0.465033f,0.149481f},{-0.0525546f,-0.463104f,0.153577f}, -{-0.0356162f,-0.462377f,0.154079f},{-0.0186843f,-0.462043f,0.152625f},{-0.00848528f,-0.461329f,0.154066f}, -{0.0423491f,-0.460011f,0.169075f},{0.0605543f,-0.459387f,0.173403f},{0.0767017f,-0.458905f,0.172213f}, -{0.1307f,-0.457689f,0.179287f},{0.136205f,-0.457239f,0.186984f},{0.151439f,-0.458705f,0.193138f}, -{0.173747f,-0.470255f,0.209022f},{0.184351f,-0.479573f,0.209839f},{0.211758f,-0.483374f,0.227562f}, -{0.2268f,-0.481708f,0.226256f},{0.23707f,-0.47875f,0.219896f},{0.37212f,-0.421279f,0.196154f}, -{-0.323961f,-0.233658f,0.25414f},{-0.285865f,-0.251638f,0.255098f},{-0.468824f,0.0225716f,0.22699f}, -{-0.299254f,-0.277387f,0.224662f},{-0.241147f,-0.490351f,0.150297f},{-0.230549f,-0.492048f,0.152844f}, -{-0.127626f,-0.480448f,0.158349f},{-0.123774f,-0.487624f,0.171255f},{-0.108836f,-0.486975f,0.174946f}, -{-0.0972541f,-0.48475f,0.168445f},{-0.0860262f,-0.472049f,0.170927f},{-0.0317193f,-0.462127f,0.16739f}, -{-0.0195074f,-0.461664f,0.163686f},{-0.0138999f,-0.461001f,0.171197f},{0.00345646f,-0.460332f,0.174149f}, -{0.020472f,-0.460217f,0.170593f},{0.0814025f,-0.458352f,0.187203f},{0.0982058f,-0.457516f,0.189885f}, -{0.116713f,-0.456294f,0.193749f},{0.163426f,-0.461734f,0.201215f},{0.172673f,-0.473039f,0.224829f}, -{0.190962f,-0.483579f,0.226391f},{0.3207f,-0.423974f,0.199479f},{-0.350211f,-0.23589f,0.23906f}, -{-0.372802f,-0.0054532f,0.268416f},{-0.354828f,-0.243812f,0.226546f},{-0.445172f,0.00870071f,0.23097f}, -{-0.465107f,0.026012f,0.20773f},{-0.383052f,-0.00770392f,0.261021f},{-0.278547f,-0.488486f,0.151063f}, -{-0.261725f,-0.489521f,0.152651f},{-0.138005f,-0.479644f,0.167017f},{-0.131626f,-0.47994f,0.168599f}, -{-0.0711907f,-0.463959f,0.171358f},{-0.0532813f,-0.462229f,0.17348f},{-0.0302338f,-0.461464f,0.172908f}, -{0.0242275f,-0.459458f,0.188058f},{0.0425677f,-0.458963f,0.190219f},{0.0601042f,-0.458538f,0.191704f}, -{0.137774f,-0.454886f,0.20726f},{0.15459f,-0.455985f,0.208778f},{0.166075f,-0.460931f,0.212662f}, -{0.177631f,-0.48212f,0.233947f},{0.193913f,-0.484312f,0.24506f},{0.212652f,-0.483058f,0.246622f}, -{0.225128f,-0.480923f,0.248449f},{0.233648f,-0.477187f,0.246847f},{-0.355857f,-0.28183f,0.153378f}, -{-0.389238f,-0.260448f,0.134658f},{-0.29737f,-0.260757f,0.243446f},{-0.366872f,-0.275046f,0.145224f}, -{-0.296643f,-0.483894f,0.154587f},{-0.259275f,-0.488955f,0.167995f},{-0.24215f,-0.488672f,0.171326f}, -{-0.226247f,-0.489778f,0.173358f},{-0.173753f,-0.489907f,0.179936f},{-0.164159f,-0.489193f,0.188155f}, -{-0.146957f,-0.487881f,0.188341f},{-0.128861f,-0.487406f,0.192856f},{-0.109312f,-0.485245f,0.189383f}, -{-0.0912736f,-0.46994f,0.193383f},{-0.0498216f,-0.461586f,0.186348f},{-0.0412624f,-0.461799f,0.182515f}, -{-0.0314492f,-0.460648f,0.190425f},{-0.0145751f,-0.460024f,0.191029f},{0.00553356f,-0.459869f,0.190386f}, -{0.0617761f,-0.457394f,0.206656f},{0.0800842f,-0.456963f,0.208874f},{0.0986302f,-0.456082f,0.210733f}, -{0.119144f,-0.455124f,0.209453f},{0.156075f,-0.45668f,0.222276f},{0.1574f,-0.484126f,0.250918f}, -{0.175335f,-0.48446f,0.247175f},{-0.319626f,-0.20782f,0.27165f},{-0.329877f,-0.29554f,0.165345f}, -{-0.318694f,-0.29873f,0.170175f},{-0.451796f,0.0128677f,0.223247f},{-0.303878f,-0.310151f,0.0028488f}, -{-0.280785f,-0.321527f,0.0187711f},{-0.278489f,-0.302846f,0.191081f},{-0.360262f,-0.250693f,0.212096f}, -{-0.298862f,-0.485206f,0.169969f},{-0.280046f,-0.487785f,0.172785f},{-0.223237f,-0.487393f,0.190052f}, -{-0.205553f,-0.488795f,0.189325f},{-0.185952f,-0.488698f,0.193376f},{-0.113517f,-0.484608f,0.203151f}, -{-0.0732742f,-0.462783f,0.191261f},{-0.0518279f,-0.461342f,0.191479f},{0.00290986f,-0.458802f,0.206257f}, -{0.0227742f,-0.458345f,0.209923f},{0.0404006f,-0.457934f,0.210283f},{0.116302f,-0.454487f,0.225697f}, -{0.13398f,-0.453992f,0.225973f},{0.142211f,-0.48338f,0.250995f},{0.15612f,-0.484962f,0.26394f}, -{0.17347f,-0.484872f,0.265689f},{0.192113f,-0.483811f,0.267413f},{0.207804f,-0.482261f,0.267342f}, -{0.217199f,-0.479657f,0.268879f},{-0.414048f,-0.00264297f,0.20955f},{-0.455635f,0.0113823f,0.240758f}, -{-0.401682f,-0.00607055f,0.25549f},{-0.316006f,-0.307752f,0.0176329f},{-0.299061f,-0.317032f,0.0229575f}, -{-0.281904f,-0.324832f,0.0377994f},{-0.261352f,-0.487695f,0.187943f},{-0.241513f,-0.487174f,0.191672f}, -{-0.165979f,-0.486139f,0.206688f},{-0.146667f,-0.486634f,0.211189f},{-0.128224f,-0.486563f,0.209337f}, -{-0.106476f,-0.478358f,0.212508f},{-0.0748819f,-0.461889f,0.204566f},{-0.0675123f,-0.461014f,0.207228f}, -{-0.052889f,-0.460262f,0.208797f},{-0.0343944f,-0.459464f,0.210733f},{-0.0158484f,-0.45931f,0.208643f}, -{0.0431722f,-0.456564f,0.225253f},{0.0604064f,-0.456101f,0.228379f},{0.0771647f,-0.45569f,0.22915f}, -{0.0974213f,-0.455252f,0.228295f},{0.117942f,-0.484197f,0.266962f},{0.133774f,-0.484261f,0.266236f}, -{0.319678f,-0.462101f,0.0100833f},{-0.443185f,0.00970388f,0.279348f},{-0.382152f,-0.251735f,0.178387f}, -{-0.313729f,-0.311791f,0.0269573f},{-0.312694f,-0.315971f,0.0396258f},{-0.29856f,-0.32015f,0.0378252f}, -{-0.282194f,-0.328124f,0.0543841f},{-0.275146f,-0.331256f,0.0615222f},{-0.298875f,-0.486126f,0.189126f}, -{-0.282123f,-0.487528f,0.192798f},{-0.220871f,-0.486287f,0.207678f},{-0.202588f,-0.485798f,0.20998f}, -{-0.184055f,-0.485541f,0.208038f},{-0.129433f,-0.485984f,0.226739f},{-0.117099f,-0.484383f,0.226829f}, -{-0.0914215f,-0.464364f,0.209132f},{-0.0150767f,-0.458095f,0.225035f},{0.0032764f,-0.457169f,0.22915f}, -{0.0200283f,-0.456757f,0.229909f},{0.0820456f,-0.4543f,0.243561f},{0.100437f,-0.453754f,0.239143f}, -{0.101254f,-0.48284f,0.26522f},{0.139619f,-0.48448f,0.283238f},{0.155567f,-0.484357f,0.282377f}, -{0.174236f,-0.482827f,0.286017f},{0.19356f,-0.481251f,0.28282f},{0.213694f,-0.473342f,0.284544f}, -{-0.242465f,-0.257683f,0.258429f},{-0.335754f,-0.305109f,0.0369313f},{-0.32342f,-0.309578f,0.0344619f}, -{-0.300225f,-0.323256f,0.0579403f},{-0.311357f,-0.484068f,0.191132f},{-0.277576f,-0.487013f,0.207569f}, -{-0.25948f,-0.486852f,0.210135f},{-0.241854f,-0.486299f,0.210591f},{-0.185361f,-0.485168f,0.225523f}, -{-0.167522f,-0.485534f,0.228469f},{-0.149304f,-0.485862f,0.22697f},{-0.100997f,-0.468261f,0.221974f}, -{-0.0878911f,-0.461992f,0.219286f},{-0.0706183f,-0.459451f,0.225189f},{-0.0522459f,-0.4585f,0.229279f}, -{-0.0360921f,-0.45814f,0.230366f},{0.0267998f,-0.455291f,0.245587f},{0.0428314f,-0.45495f,0.244558f}, -{0.0601749f,-0.454275f,0.24751f},{0.0805086f,-0.483103f,0.272724f},{0.100457f,-0.484537f,0.283888f}, -{0.11845f,-0.48464f,0.286525f},{0.194846f,-0.476898f,0.290769f},{-0.349381f,-0.00533103f,0.254024f}, -{-0.417945f,0.0292209f,0.315366f},{-0.35014f,-0.296383f,0.0380181f},{-0.328983f,-0.311906f,0.0467638f}, -{-0.319491f,-0.316652f,0.0564419f},{-0.299132f,-0.326459f,0.075496f},{-0.28065f,-0.331513f,0.0751037f}, -{-0.259783f,-0.338375f,0.0941963f},{-0.314077f,-0.483554f,0.206939f},{-0.300154f,-0.486422f,0.211247f}, -{-0.241365f,-0.485901f,0.227195f},{-0.223919f,-0.485676f,0.227915f},{-0.206376f,-0.48529f,0.228481f}, -{-0.145735f,-0.485734f,0.244552f},{-0.127813f,-0.485907f,0.247388f},{-0.113614f,-0.485888f,0.249619f}, -{-0.0850616f,-0.460905f,0.230385f},{-0.0312048f,-0.45677f,0.244764f},{-0.0144465f,-0.456352f,0.245529f}, -{0.00379085f,-0.455651f,0.249831f},{0.0451786f,-0.482885f,0.284441f},{0.0596797f,-0.483939f,0.285316f}, -{0.0820391f,-0.484435f,0.285759f},{0.135118f,-0.482891f,0.295347f},{0.152448f,-0.480988f,0.297219f}, -{0.155619f,-0.473052f,0.30219f},{0.175303f,-0.470782f,0.298473f},{-0.256394f,-0.259394f,0.256828f}, -{-0.341291f,-0.307823f,0.0568599f},{-0.331067f,-0.314022f,0.0603389f},{-0.315787f,-0.320806f,0.0768979f}, -{-0.290624f,-0.329906f,0.0832063f},{-0.278303f,-0.333411f,0.0946529f},{-0.297794f,-0.486184f,0.226649f}, -{-0.280695f,-0.486621f,0.22787f},{-0.263139f,-0.486177f,0.228424f},{-0.201752f,-0.485181f,0.243426f}, -{-0.185348f,-0.484968f,0.246744f},{-0.16666f,-0.485489f,0.248352f},{-0.109061f,-0.485309f,0.264403f}, -{-0.0923604f,-0.485817f,0.270088f},{-0.0695573f,-0.45857f,0.245883f},{-0.0523038f,-0.456828f,0.247941f}, -{0.0218867f,-0.454416f,0.258217f},{0.0355583f,-0.453278f,0.26003f},{0.0248191f,-0.483174f,0.288042f}, -{0.0613839f,-0.48466f,0.301817f},{0.0791196f,-0.483997f,0.302061f},{0.0968168f,-0.483444f,0.302344f}, -{0.118443f,-0.481592f,0.302299f},{0.136578f,-0.474036f,0.304775f},{-0.285788f,-0.286988f,0.217832f}, -{-0.361201f,-0.288962f,0.044198f},{-0.353516f,-0.299328f,0.0592907f},{-0.334938f,-0.313469f,0.075631f}, -{-0.300444f,-0.327224f,0.0950195f},{-0.289094f,-0.33123f,0.0962799f},{-0.26431f,-0.335848f,0.111283f}, -{-0.312752f,-0.483721f,0.229716f},{-0.258432f,-0.485978f,0.243246f},{-0.242124f,-0.485926f,0.24668f}, -{-0.223096f,-0.4852f,0.249008f},{-0.165155f,-0.484962f,0.263406f},{-0.147092f,-0.48484f,0.26603f}, -{-0.129935f,-0.485161f,0.267162f},{-0.0487541f,-0.456423f,0.25695f},{-0.0353011f,-0.455644f,0.259033f}, -{-0.0153146f,-0.454911f,0.262506f},{0.00496123f,-0.453651f,0.265573f},{0.00542424f,-0.483746f,0.291965f}, -{0.0242018f,-0.484139f,0.303103f},{0.0405871f,-0.484306f,0.304479f},{0.101897f,-0.480113f,0.309109f}, -{-0.335484f,0.250577f,-0.225986f},{-0.362898f,-0.290209f,0.0564741f},{-0.354339f,-0.30028f,0.0768464f}, -{-0.334616f,-0.314601f,0.0951159f},{-0.31888f,-0.321205f,0.0966464f},{-0.298135f,-0.325674f,0.114292f}, -{-0.278232f,-0.331443f,0.114922f},{-0.298148f,-0.485489f,0.24551f},{-0.279885f,-0.486229f,0.248931f}, -{-0.220935f,-0.485341f,0.264673f},{-0.203469f,-0.485058f,0.265387f},{-0.185444f,-0.485007f,0.268075f}, -{-0.126944f,-0.483637f,0.281663f},{-0.108611f,-0.48428f,0.285001f},{-0.0926562f,-0.484164f,0.286441f}, -{-0.0740266f,-0.484402f,0.286891f},{-0.0540337f,-0.483515f,0.290383f},{-0.0409344f,-0.48338f,0.293058f}, -{-0.0318029f,-0.483586f,0.301965f},{-0.0139385f,-0.483849f,0.304878f},{0.00431173f,-0.484074f,0.303334f}, -{0.0427028f,-0.482505f,0.318678f},{0.0602649f,-0.482962f,0.314331f},{0.0708948f,-0.481316f,0.315218f}, -{0.0968618f,-0.47529f,0.315025f},{-0.306276f,-0.2129f,0.274448f},{-0.368274f,-0.235009f,0.223163f}, -{-0.343388f,-0.30862f,0.0938362f},{-0.316758f,-0.31979f,0.114929f},{-0.283467f,-0.329102f,0.11871f}, -{-0.263911f,-0.331243f,0.130414f},{-0.311948f,-0.482968f,0.245992f},{-0.279628f,-0.485631f,0.266242f}, -{-0.260149f,-0.485907f,0.265136f},{-0.242015f,-0.48565f,0.267689f},{-0.183419f,-0.483496f,0.282338f}, -{-0.167593f,-0.48246f,0.280197f},{-0.148552f,-0.481676f,0.279997f},{-0.0880133f,-0.48347f,0.301084f}, -{-0.0700074f,-0.483457f,0.30381f},{-0.0527539f,-0.483599f,0.304813f},{0.00475545f,-0.483721f,0.320067f}, -{0.0216552f,-0.482628f,0.322813f},{-0.315678f,-0.293425f,0.183177f},{-0.3545f,-0.298074f,0.0959712f}, -{-0.331002f,-0.314266f,0.112832f},{-0.299164f,-0.320819f,0.132941f},{-0.279917f,-0.325578f,0.134388f}, -{-0.309144f,-0.482165f,0.257034f},{-0.299048f,-0.483946f,0.266159f},{-0.240542f,-0.485373f,0.28266f}, -{-0.223237f,-0.485193f,0.284589f},{-0.204627f,-0.483972f,0.28646f},{-0.123247f,-0.481599f,0.296454f}, -{-0.107987f,-0.482968f,0.305257f},{-0.0522073f,-0.483193f,0.321269f},{-0.0351532f,-0.483669f,0.322601f}, -{-0.0178998f,-0.483727f,0.323604f},{0.0305231f,-0.480197f,0.328266f},{-0.328674f,-0.273869f,0.208707f}, -{-0.40064f,-0.25104f,0.0488023f},{-0.362519f,-0.289849f,0.0907431f},{-0.341458f,-0.307572f,0.116331f}, -{-0.455841f,0.0126491f,0.268384f},{-0.279165f,-0.484795f,0.283148f},{-0.261506f,-0.485431f,0.286383f}, -{-0.184827f,-0.479534f,0.292415f},{-0.117035f,-0.480132f,0.307701f},{-0.0909135f,-0.482885f,0.320941f}, -{-0.0729848f,-0.482994f,0.32379f},{-0.0158548f,-0.482525f,0.33678f},{0.00325711f,-0.481226f,0.334362f}, -{-0.38266f,-0.270782f,0.0813672f},{-0.332115f,-0.310569f,0.126498f},{-0.307389f,-0.476396f,0.27412f}, -{-0.294328f,-0.482017f,0.281894f},{-0.222954f,-0.482865f,0.298061f},{-0.101678f,-0.480898f,0.322433f}, -{-0.186711f,0.248082f,-0.0135751f},{-0.337054f,0.254307f,-0.24396f},{-0.202891f,0.23162f,0.00283594f}, -{-0.286515f,0.364336f,-0.372927f},{-0.335414f,0.260551f,-0.265149f},{-0.052098f,0.307945f,-0.0569499f}, -{-0.164152f,0.26057f,-0.024578f},{-0.305337f,0.251098f,-0.166741f},{-0.313472f,0.285663f,-0.283026f}, -{-0.302617f,0.215832f,-0.0542812f},{-0.316019f,0.243555f,-0.169171f},{-0.300804f,0.227684f,-0.0737082f}, -{-0.181181f,0.274711f,-0.031671f},{-0.0531462f,0.322594f,-0.0754188f},{-0.312958f,0.259509f,-0.210025f}, -{-0.302566f,0.23205f,-0.0907302f},{0.0233979f,0.356484f,-0.115662f},{-0.316771f,0.22252f,-0.0919199f}, -{0.00642742f,0.340221f,-0.0927558f},{-0.319633f,0.270544f,-0.262069f},{-0.31789f,0.215247f,-0.0716247f}, -{-0.182493f,0.241632f,-0.00751742f},{-0.145638f,0.259972f,-0.0193563f},{-0.318405f,0.226957f,-0.111032f}, -{-0.165168f,0.271027f,-0.0328992f},{-0.109562f,0.2732f,-0.0165396f},{-0.107003f,0.281837f,-0.0365711f}, -{-0.323716f,0.274055f,-0.296479f},{-0.16659f,0.243259f,0.0006045f},{-0.319781f,0.265651f,-0.243709f}, -{-0.148924f,0.270326f,-0.0333044f},{-0.0362722f,0.324607f,-0.0756438f},{-0.311234f,0.220604f,-0.0803125f}, -{-0.3227f,0.271239f,-0.284229f},{-0.323588f,0.256815f,-0.22843f},{-0.220781f,0.206829f,0.0185396f}, -{-0.167914f,0.251284f,-0.0151699f},{-0.0329861f,0.310312f,-0.0527443f},{-0.127337f,0.273367f,-0.0322948f}, -{-0.317382f,0.284158f,-0.302556f},{-0.127871f,0.280666f,-0.0416578f},{-0.187341f,0.234301f,0.00378125f}, -{0.0259895f,0.366509f,-0.128723f},{0.0123822f,0.333057f,-0.0819716f},{-0.313787f,0.265008f,-0.224777f}, -{-0.309061f,0.301977f,-0.319835f},{-0.303871f,0.269368f,-0.2069f},{-0.0717501f,0.30253f,-0.055368f}, -{-0.333034f,0.229555f,-0.136619f},{-0.316327f,0.232745f,-0.128478f},{-0.338886f,0.200733f,-0.0441529f}, -{0.00223463f,0.350227f,-0.103682f},{0.025295f,0.350658f,-0.108054f},{-0.0903219f,0.299785f,-0.0571364f}, -{-0.209681f,0.219363f,0.0212341f},{-0.337054f,0.234758f,-0.152272f},{-0.301788f,0.250449f,-0.149892f}, -{-0.313421f,0.313733f,-0.349333f},{-0.353355f,0.231812f,-0.127121f},{-0.0154754f,0.325109f,-0.0739269f}, -{-0.312546f,0.202521f,-0.0423137f},{-0.109736f,0.29165f,-0.0513167f},{-0.0731263f,0.292106f,-0.0378766f}, -{-0.305575f,0.235472f,-0.111611f},{-0.311228f,0.241394f,-0.150471f},{-0.305884f,0.31271f,-0.343847f}, -{-0.336295f,0.224366f,-0.114556f},{-0.0516286f,0.299514f,-0.0367383f},{-0.343401f,0.237722f,-0.161197f}, -{-0.0322787f,0.314794f,-0.0613163f},{-0.321163f,0.251079f,-0.204977f},{-0.309453f,0.279605f,-0.247323f}, -{-0.316295f,0.249214f,-0.188206f},{-0.0175589f,0.332697f,-0.0845503f},{-0.305434f,0.309495f,-0.323842f}, -{-0.21671f,0.219761f,0.014752f},{-0.306656f,0.273541f,-0.222578f},{-0.334147f,0.213974f,-0.0735667f}, -{-0.173252f,0.237356f,0.018829f},{-0.202177f,0.223048f,0.0189447f},{-0.311614f,0.284152f,-0.265889f}, -{-0.332655f,0.221189f,-0.0998553f},{-0.0605351f,0.294479f,-0.0306485f},{-0.305781f,0.256326f,-0.181872f}, -{-0.0967461f,0.291045f,-0.0472396f} -}; -F32 normals [8127][3] = { -{-0.832532f,-0.483226f,0.270894f},{-0.606785f,-0.758191f,0.23866f},{-0.859166f,-0.504979f,0.0826439f}, -{-0.240595f,0.95358f,-0.181105f},{-0.265911f,0.923509f,-0.276446f},{-0.24535f,0.952364f,-0.181124f}, -{-0.25194f,0.962547f,-0.100147f},{-0.246923f,0.963593f,-0.102551f},{-0.246718f,0.967484f,-0.0557298f}, -{-0.256239f,0.966543f,-0.0116836f},{-0.268399f,0.963145f,0.0176902f},{-0.202139f,0.974793f,-0.094442f}, -{-0.233286f,0.967463f,-0.0979436f},{-0.222973f,0.972356f,-0.0693283f},{-0.216571f,0.976026f,-0.0216751f}, -{-0.248769f,0.966837f,-0.0577895f},{-0.251386f,0.966483f,-0.0521194f},{-0.221256f,0.940455f,-0.258053f}, -{-0.203433f,0.958112f,-0.201585f},{-0.185273f,0.9538f,-0.236513f},{-0.202063f,0.969567f,-0.138239f}, -{-0.277194f,0.958376f,0.0684025f},{-0.323528f,0.932333f,0.16151f},{-0.301745f,0.944805f,0.127648f}, -{-0.263034f,0.964572f,0.0203178f},{-0.298731f,0.932268f,0.204049f},{-0.339448f,0.915328f,0.21668f}, -{-0.256592f,0.921503f,0.291534f},{-0.336811f,0.892243f,0.300767f},{-0.288256f,0.886991f,0.36077f}, -{-0.129143f,0.959514f,-0.25031f},{-0.104011f,0.980522f,-0.166606f},{-0.0715617f,0.949967f,-0.304043f}, -{-0.193212f,0.979873f,0.0501861f},{-0.264442f,0.963268f,0.0467423f},{-0.202161f,0.973002f,0.111346f}, -{0.780632f,0.608123f,0.144219f},{0.893498f,0.412557f,0.177367f},{0.918654f,0.348847f,0.185421f}, -{-0.235108f,0.898248f,0.371314f},{-0.0326766f,0.912646f,0.407443f},{-0.281134f,0.890492f,0.357753f}, -{-0.717587f,-0.696125f,-0.0218705f},{-0.848457f,-0.528571f,-0.0270921f},{-0.865329f,-0.500314f,-0.029859f}, -{-0.121792f,0.898055f,0.422685f},{0.101699f,0.854369f,0.509619f},{-0.140896f,0.896477f,0.420093f}, -{-0.808979f,-0.581233f,0.0878659f},{-0.770083f,-0.637941f,0.00173141f},{-0.756549f,-0.652533f,0.0428222f}, -{0.0971026f,0.799445f,0.592839f},{-0.145356f,0.83366f,0.532806f},{-0.00267177f,0.775686f,0.631113f}, -{-4.50738e-05f,-0.710945f,-0.703248f},{-0.0235271f,-0.794254f,-0.60713f},{0.259285f,-0.884284f,-0.388348f}, -{-0.945709f,0.157642f,0.284225f},{-0.904527f,0.212372f,0.36977f},{-0.885759f,0.334308f,0.321977f}, -{-0.263036f,0.950565f,0.16504f},{-0.323719f,0.90817f,0.265394f},{-0.28809f,0.926484f,0.242139f}, -{-0.95459f,0.0441123f,-0.29464f},{-0.969511f,-0.169456f,-0.177012f},{-0.954454f,-0.223864f,-0.197238f}, -{0.611328f,0.777271f,0.148758f},{0.684309f,0.653679f,0.323149f},{0.915668f,0.320355f,0.242746f}, -{0.819723f,0.357047f,0.447853f},{0.422096f,0.860388f,0.285599f},{0.187582f,0.923427f,0.334806f}, -{0.432844f,0.790824f,0.432717f},{0.0680594f,-0.941994f,0.328655f},{-0.290907f,-0.832029f,0.472335f}, -{0.146264f,-0.741517f,0.654797f},{-0.735765f,-0.280452f,0.616439f},{-0.722188f,-0.547927f,0.422161f}, -{-0.768976f,-0.134488f,0.624971f},{-0.453323f,0.851967f,-0.262013f},{-0.381382f,0.908381f,-0.171438f}, -{-0.417129f,0.849952f,-0.321845f},{0.254919f,0.880365f,0.399968f},{-0.190589f,0.854832f,0.482637f}, -{-0.210229f,0.889628f,0.405419f},{0.708171f,0.617f,0.343227f},{0.614328f,0.678828f,0.402236f}, -{0.720949f,0.588198f,0.36641f},{-0.346537f,0.869928f,0.350909f},{-0.60894f,0.719521f,0.333889f}, -{-0.33076f,0.856751f,0.395696f},{0.0127889f,0.924737f,0.380393f},{-0.142866f,0.666357f,0.731818f}, -{-0.034274f,0.677512f,0.734712f},{-0.0935795f,0.661009f,0.74452f},{-0.509054f,0.763082f,0.398208f}, -{0.224064f,-0.899254f,-0.375683f},{-0.272324f,-0.820453f,-0.50269f},{0.575326f,-0.786607f,-0.224161f}, -{-0.0317741f,0.983694f,0.177022f},{-0.208638f,0.977128f,-0.0411155f},{-0.0326322f,0.9994f,-0.0116285f}, -{-0.959056f,-0.281756f,0.0287399f},{-0.968295f,-0.230842f,0.0954859f},{-0.932971f,-0.284521f,-0.220485f}, -{-0.936459f,-0.146232f,-0.318844f},{-0.385196f,0.795521f,0.467728f},{-0.571132f,0.811969f,-0.120481f}, -{-0.285455f,0.884252f,0.369613f},{0.770701f,0.508164f,0.384433f},{0.653749f,0.544785f,0.525187f}, -{0.911702f,0.212638f,0.351546f},{-0.149382f,0.141765f,-0.978564f},{-0.215627f,0.158924f,-0.963456f}, -{-0.172656f,0.332476f,-0.927173f},{-0.11137f,0.20172f,-0.973091f},{-0.120247f,0.218757f,-0.968342f}, -{-0.116053f,0.208667f,-0.971077f},{-0.110441f,0.873446f,0.474232f},{-0.120825f,0.884438f,0.450746f}, -{-0.869758f,0.377088f,0.318317f},{-0.925243f,0.175597f,0.33629f},{-0.919523f,0.0685275f,0.387016f}, -{-0.482565f,0.874002f,0.0570216f},{-0.328802f,0.876258f,0.352222f},{-0.120162f,0.895601f,0.428322f}, -{0.118699f,0.915735f,0.38385f},{-0.89304f,0.449975f,0.00125259f},{-0.956562f,0.289896f,0.0308044f}, -{-0.950694f,0.305572f,-0.0529737f},{-0.202962f,0.974794f,-0.0926428f},{-0.149628f,0.983888f,-0.0978547f}, -{-0.14631f,0.98241f,-0.116032f},{0.694537f,0.621044f,0.363211f},{0.620447f,0.729884f,0.286908f}, -{0.765911f,0.603359f,0.22212f},{0.852062f,0.457413f,0.254488f},{0.752783f,0.532628f,0.386814f}, -{-0.239568f,0.74193f,0.626216f},{-0.075257f,0.613884f,0.785801f},{0.123843f,0.376122f,0.918257f}, -{-0.474381f,0.23936f,-0.847154f},{-0.455168f,-0.811384f,-0.366713f},{-0.213933f,-0.514973f,-0.830082f}, -{-0.254102f,0.948463f,-0.189341f},{-0.367517f,0.829036f,0.421461f},{-0.361859f,0.854456f,0.372778f}, -{-0.322071f,0.851882f,0.412998f},{-0.13554f,0.98971f,-0.045867f},{-0.160853f,0.986362f,-0.0348832f}, -{-0.131247f,0.991314f,0.00835482f},{-0.542619f,0.828757f,0.136845f},{-0.343869f,0.809416f,0.476025f}, -{-0.462981f,0.852059f,0.244222f},{-0.263369f,0.901217f,0.344157f},{-0.338921f,0.884725f,0.319992f}, -{-0.511586f,0.803891f,0.303379f},{0.874238f,0.377572f,0.305199f},{0.829018f,0.495984f,0.25832f}, -{0.792623f,0.48816f,0.365306f},{0.195735f,0.962956f,0.18548f},{0.116284f,0.964873f,0.235578f}, -{0.190608f,0.956302f,0.221709f},{-0.25398f,0.966403f,-0.0394976f},{-0.378434f,0.83816f,0.39278f}, -{0.662297f,0.72069f,0.204862f},{0.530429f,0.822517f,0.205209f},{0.684042f,0.704221f,0.190155f}, -{-0.0569504f,0.997668f,-0.0376106f},{0.0157645f,0.999316f,-0.0334653f},{0.0157935f,0.995784f,-0.0903618f}, -{-0.422862f,-0.852884f,-0.306229f},{-0.12403f,-0.948113f,-0.292743f},{-0.622856f,-0.765261f,-0.162564f}, -{-0.901512f,-0.161439f,0.401515f},{-0.83239f,-0.442392f,0.333789f},{-0.279616f,0.315223f,-0.90689f}, -{-0.187629f,0.239955f,-0.952479f},{-0.201018f,0.207097f,-0.957446f},{-0.351005f,0.870672f,0.344566f}, -{-0.356193f,0.83271f,0.423934f},{-0.930524f,0.364666f,-0.0338037f},{-0.934408f,0.34659f,-0.0822029f}, -{-0.581141f,-0.79047f,-0.193474f},{-0.401732f,-0.866777f,-0.295481f},{0.219798f,0.943023f,0.249793f}, -{0.441648f,0.744463f,0.500721f},{-0.170662f,0.962922f,-0.208942f},{-0.140103f,0.977176f,-0.15968f}, -{-0.174618f,0.973903f,-0.14499f},{-0.816847f,-0.468775f,-0.336171f},{-0.897091f,0.0904234f,-0.432495f}, -{-0.65512f,-0.498546f,-0.567689f},{-0.207628f,0.956946f,0.202842f},{-0.168441f,0.72412f,0.668788f}, -{-0.0670168f,0.91956f,0.387192f},{0.311933f,0.593536f,0.741898f},{0.17352f,0.787655f,0.591177f}, -{0.180038f,0.58603f,0.790035f},{-0.861929f,-0.365565f,0.351341f},{-0.914147f,-0.309319f,0.262025f}, -{-0.791212f,-0.558632f,0.248825f},{-0.053992f,0.998524f,0.00585528f},{0.654485f,0.747701f,0.112219f}, -{0.34414f,0.92576f,0.15664f},{-0.219221f,0.914674f,0.339579f},{-0.258173f,0.858933f,0.442246f}, -{-0.143065f,0.905573f,0.399337f},{0.84601f,0.500754f,0.183061f},{0.317856f,0.577094f,0.752283f}, -{0.161512f,0.786348f,0.596297f},{0.21221f,0.640586f,0.737981f},{-0.166751f,0.982628f,-0.0814596f}, -{-0.188703f,0.980337f,-0.0577052f},{-0.17194f,0.985102f,-0.00323838f},{-0.234144f,0.969227f,0.0759959f}, -{-0.208683f,0.971131f,0.115569f},{-0.17246f,0.983756f,0.0498251f},{-0.837886f,-0.545703f,0.0124777f}, -{-0.881945f,-0.46478f,0.0784393f},{-0.936872f,-0.341756f,-0.073981f},{-0.152191f,0.98821f,0.0167007f}, -{0.529805f,0.839465f,0.12085f},{0.35177f,0.933835f,0.0648909f},{0.645035f,0.758214f,0.0950878f}, -{0.897254f,0.430807f,0.0966417f},{0.82479f,0.54689f,0.143639f},{0.833868f,0.533647f,0.141017f}, -{0.398204f,0.869206f,-0.293111f},{0.368214f,0.912358f,-0.178942f},{0.460623f,0.862636f,-0.209012f}, -{0.757324f,0.632608f,0.162072f},{-0.196495f,0.847757f,0.492644f},{-0.281075f,0.806466f,0.520201f}, -{-0.178493f,0.831846f,0.525522f},{-0.965141f,0.251922f,-0.070975f},{-0.968395f,0.204029f,-0.143468f}, -{-0.98048f,0.122575f,-0.153733f},{-0.181622f,0.862125f,0.473026f},{-0.24619f,0.905469f,0.345711f}, -{-0.228317f,0.86714f,0.44265f},{-0.366278f,0.419914f,-0.830369f},{-0.283198f,0.181294f,-0.94177f}, -{-0.125999f,0.144635f,-0.98143f},{-0.139033f,0.985514f,-0.0971168f},{-0.689549f,0.612864f,0.385901f}, -{-0.466431f,0.7979f,0.381836f},{-0.429588f,0.835885f,0.341687f},{0.92412f,0.353599f,-0.144809f}, -{0.860566f,0.471663f,-0.192248f},{0.897956f,0.425678f,-0.111685f},{0.207155f,0.859726f,0.466859f}, -{0.500149f,-0.865185f,-0.036124f},{0.196539f,-0.87016f,-0.451878f},{0.407742f,-0.874513f,-0.262628f}, -{-0.165294f,0.961411f,0.219924f},{-0.174258f,0.925978f,0.334962f},{0.0209707f,0.954479f,-0.297539f}, -{-0.0411579f,0.958112f,-0.28342f},{-0.0430633f,0.986192f,-0.15991f},{-0.138388f,0.984372f,0.108905f}, -{-0.0864297f,0.979549f,0.181694f},{0.355448f,-0.675269f,-0.646272f},{0.982785f,-0.167672f,0.0775822f}, -{0.964467f,-0.220328f,0.145802f},{-0.106177f,0.990299f,-0.0896399f},{0.585177f,0.809954f,0.0392717f}, -{0.351387f,0.916776f,0.189866f},{0.28604f,0.941601f,-0.177678f},{-0.330406f,0.875489f,0.352634f}, -{0.421234f,0.845704f,0.327638f},{-0.000578385f,0.935843f,0.352418f},{0.797729f,0.521056f,0.303528f}, -{0.851595f,0.355876f,0.384888f},{0.833935f,0.461972f,0.301884f},{-0.281361f,0.950692f,0.130465f}, -{0.494345f,0.869264f,0.0014269f},{0.323062f,0.915374f,0.240255f},{0.236605f,0.903551f,0.357229f}, -{0.326762f,0.897894f,0.29498f},{-0.797988f,-0.554353f,0.236451f},{-0.715613f,-0.675862f,0.176376f}, -{-0.604376f,-0.751052f,0.265801f},{-0.986977f,-0.121592f,-0.105315f},{-0.980444f,-0.196796f,-0.000786544f}, -{-0.991928f,-0.0157392f,-0.12582f},{-0.164281f,0.191446f,-0.967657f},{-0.0978269f,0.992432f,0.074216f}, -{-0.0896928f,0.987081f,0.132768f},{-0.0518716f,0.987449f,0.149177f},{-0.0994765f,0.995001f,0.00874661f}, -{-0.0983143f,0.994234f,-0.0428241f},{-0.151126f,0.986293f,0.0662396f},{-0.105553f,0.987126f,0.120173f}, -{0.969847f,-0.00525719f,-0.243657f},{0.986459f,0.017394f,-0.163085f},{0.977914f,0.0433675f,-0.204458f}, -{0.785811f,0.528888f,0.32059f},{0.773372f,0.522143f,0.35953f},{0.866441f,0.410223f,0.2846f}, -{-0.51235f,0.858582f,0.0183004f},{0.220746f,0.613517f,0.7582f},{0.359838f,0.596592f,0.717353f}, -{0.263219f,0.954822f,-0.137951f},{0.236716f,0.968405f,-0.0784723f},{0.0393797f,0.987006f,-0.155785f}, -{-0.100373f,0.924854f,0.366837f},{-0.0789204f,0.886723f,0.455514f},{-0.0325974f,0.953865f,0.298462f}, -{-0.0996998f,0.958219f,0.268097f},{-0.124818f,0.990033f,0.0652242f},{0.858404f,0.470083f,0.20534f}, -{-0.351088f,0.90292f,0.247937f},{-0.266096f,0.623714f,0.734965f},{0.0546192f,0.518634f,0.85325f}, -{-0.00627665f,0.528708f,0.848781f},{0.0310592f,0.974423f,0.222564f},{0.225176f,0.961336f,0.158522f}, -{0.238458f,0.899672f,0.365688f},{0.112761f,0.816349f,0.566444f},{0.0456267f,0.831381f,0.553826f}, -{0.0552438f,0.806235f,0.589011f},{0.00507421f,0.703522f,0.710656f},{0.0903773f,0.728552f,0.679002f}, -{-0.417529f,0.874211f,0.247839f},{-0.503292f,0.783758f,0.363895f},{-0.760404f,-0.626818f,-0.169957f}, -{0.528696f,0.762456f,0.373016f},{-0.0576661f,0.99596f,0.0688321f},{-0.0702293f,0.979726f,0.187628f}, -{-0.050923f,0.994669f,-0.0896719f},{0.550602f,-0.79647f,0.249946f},{0.435275f,-0.856718f,0.276713f}, -{0.503614f,-0.851182f,0.147859f},{0.924068f,0.378481f,-0.0533867f},{0.91027f,0.413033f,-0.0285087f}, -{0.909985f,0.413706f,0.027824f},{0.151382f,0.614505f,0.774252f},{0.121735f,0.71707f,0.686288f}, -{-0.0654101f,0.661894f,0.746738f},{0.449607f,0.836161f,-0.314146f},{0.410327f,0.856681f,0.312616f}, -{-0.296897f,0.85146f,0.432283f},{0.657107f,-0.725019f,0.206298f},{0.302314f,-0.951098f,0.0633903f}, -{0.376669f,-0.920947f,0.0998864f},{0.358164f,0.823977f,0.439068f},{0.708367f,0.624326f,0.329293f}, -{0.265183f,0.860485f,0.435022f},{0.264323f,0.827217f,0.495829f},{-0.208083f,0.974072f,-0.088802f}, -{-0.0406154f,0.999099f,-0.0123014f},{-0.21748f,0.975297f,-0.0387011f},{0.811224f,0.532897f,0.240699f}, -{0.325329f,0.935848f,0.135462f},{0.298507f,0.933061f,0.200724f},{0.370731f,0.911821f,0.176466f}, -{0.177805f,0.850282f,0.495384f},{0.0782578f,0.861702f,0.501344f},{-0.862905f,-0.0410319f,0.503697f}, -{-0.780384f,-0.483438f,0.396596f},{-0.920067f,-0.0587012f,0.387339f},{0.120623f,0.907232f,0.402964f}, -{0.0912084f,0.872958f,0.479193f},{-0.223768f,0.248002f,-0.942562f},{-0.006037f,0.829609f,0.558313f}, -{-0.086073f,0.83628f,0.541505f},{-0.0751572f,0.794053f,0.603184f},{-0.1793f,0.932707f,0.312905f}, -{-0.35696f,0.931368f,0.0716437f},{0.723383f,0.662743f,0.193622f},{0.748428f,0.357617f,0.558539f}, -{0.382063f,0.804684f,0.454436f},{0.41987f,0.797587f,0.433088f},{0.60187f,0.723171f,0.338786f}, -{0.465439f,0.84667f,0.257909f},{0.604528f,0.760774f,0.236153f},{-0.14065f,0.878178f,0.457187f}, -{-0.156203f,0.926759f,0.341641f},{0.30724f,0.899647f,0.310225f},{0.983246f,0.063408f,-0.1709f}, -{0.96155f,0.0864831f,-0.260656f},{0.979863f,0.0529409f,-0.192523f},{0.0766483f,-0.724763f,-0.684722f}, -{0.0795982f,-0.728566f,-0.680335f},{0.240247f,-0.855735f,-0.458256f},{-0.168843f,0.172447f,-0.97044f}, -{-0.0397846f,0.99753f,-0.0578866f},{-0.187576f,0.976181f,-0.109024f},{-0.315613f,0.922592f,0.221838f}, -{-0.344408f,0.911946f,0.223021f},{-0.0535464f,0.762474f,0.6448f},{-0.150055f,0.814483f,0.560447f}, -{-0.11104f,0.754474f,0.646868f},{-0.838926f,0.210014f,-0.502093f},{-0.83238f,0.28807f,-0.473454f}, -{-0.797072f,0.470878f,-0.378087f},{-0.86169f,0.262894f,-0.434025f},{-0.815344f,0.425554f,-0.392578f}, -{0.57735f,0.57735f,0.57735f},{0.421857f,0.686834f,0.591857f},{-0.249799f,0.940143f,0.231799f}, -{-0.296301f,0.880261f,0.370604f},{0.0118961f,0.905903f,0.423318f},{0.0313234f,0.355953f,0.933979f}, -{0.0352841f,0.306272f,0.95129f},{-0.0893656f,0.270821f,0.958473f},{-0.713881f,0.490776f,-0.499512f}, -{-0.410273f,0.869831f,-0.273989f},{-0.894055f,0.352175f,-0.276838f},{-0.817393f,0.308118f,-0.486757f}, -{-0.875796f,0.121223f,-0.467212f},{0.669572f,-0.707121f,-0.227273f},{0.818913f,-0.535545f,-0.206332f}, -{0.84874f,-0.466955f,-0.248178f},{0.00732999f,0.884841f,0.465835f},{0.756543f,0.624106f,0.19528f}, -{0.00141355f,0.916707f,0.399559f},{0.0128935f,0.936489f,0.35046f},{0.555117f,-0.0206778f,-0.831515f}, -{0.733425f,-0.110287f,-0.670765f},{-0.336867f,0.804122f,0.489804f},{-0.547861f,0.721964f,-0.42263f}, -{-0.517719f,0.852632f,0.0706092f},{-0.659477f,0.748223f,0.0724769f},{0.00701106f,0.622457f,0.782623f}, -{-0.00356288f,0.708901f,0.705299f},{-0.0351258f,0.774387f,0.631736f},{-0.385602f,0.794284f,-0.469494f}, -{-0.409104f,0.75301f,-0.515373f},{-0.343588f,0.739178f,-0.579278f},{0.44348f,0.409973f,0.797024f}, -{0.172274f,0.553567f,0.814791f},{0.444401f,0.516545f,0.731907f},{-0.899018f,0.315509f,-0.303678f}, -{-0.0287092f,0.99401f,-0.105451f},{0.0238513f,0.996213f,-0.0836077f},{0.0498361f,0.992292f,-0.113461f}, -{-0.243806f,0.954737f,0.170399f},{0.935547f,0.345553f,-0.0731101f},{0.866464f,0.488525f,-0.10288f}, -{0.887404f,0.427894f,-0.171524f},{0.919118f,0.358308f,0.163822f},{-0.939902f,-0.308644f,0.146026f}, -{-0.985943f,-0.128784f,0.106447f},{-0.968025f,-0.242516f,0.0641434f},{-0.319472f,-0.322908f,0.890881f}, -{-0.212183f,-0.00597968f,0.977212f},{-0.460175f,-0.0230708f,0.887528f},{-0.311636f,0.272517f,0.910284f}, -{0.148652f,-0.861322f,-0.485827f},{0.249015f,-0.75173f,-0.61065f},{0.283906f,-0.838223f,-0.465596f}, -{-0.0533076f,-0.660568f,-0.748871f},{0.102555f,-0.808587f,-0.579369f},{0.78009f,0.447597f,0.437169f}, -{0.659098f,0.426598f,0.619358f},{0.700411f,0.468918f,0.538089f},{0.981422f,-0.0277144f,-0.189847f}, -{0.990634f,0.0115244f,-0.136058f},{0.969545f,-0.000610817f,-0.244911f},{-0.999433f,0.0331006f,-0.00624168f}, -{-0.969336f,0.0523667f,-0.240095f},{-0.985831f,-0.0135757f,-0.167188f},{-0.11484f,-0.497945f,-0.859571f}, -{0.145066f,-0.756207f,-0.638049f},{-0.992501f,0.0955116f,-0.0762813f},{0.0307977f,0.813263f,0.581081f}, -{-0.252137f,0.914982f,0.315017f},{0.0936196f,0.978662f,0.182908f},{0.0174373f,0.996305f,-0.0841026f}, -{0.0180337f,0.991815f,-0.126402f},{0.044532f,-0.527634f,-0.848304f},{0.0660403f,-0.585473f,-0.807998f}, -{0.100115f,-0.56197f,-0.821077f},{-0.359698f,0.0989121f,-0.927811f},{-0.43688f,0.0954944f,-0.894437f}, -{-0.37905f,0.204351f,-0.902531f},{0.000580824f,0.0870738f,-0.996202f},{0.128226f,0.0453576f,-0.990707f}, -{0.0914407f,-0.0043354f,-0.995801f},{-0.651647f,0.621586f,-0.434727f},{-0.803714f,0.589137f,-0.0834296f}, -{-0.559601f,0.820384f,0.117543f},{0.759113f,0.438907f,0.480737f},{0.573133f,0.785088f,0.234854f}, -{0.738396f,0.63573f,0.224987f},{-0.340618f,-0.160374f,0.926423f},{-0.0783287f,-0.180108f,0.980523f}, -{-0.46722f,-0.379277f,0.798658f},{-0.083493f,-0.271426f,0.958831f},{0.0491597f,-0.0662771f,0.996589f}, -{0.0134786f,0.189284f,0.98183f},{0.00493481f,0.319204f,0.947673f},{-0.0212024f,0.401033f,0.915818f}, -{-0.385416f,0.416591f,0.823351f},{-0.0488352f,0.466255f,0.883301f},{-0.290291f,0.499278f,0.816365f}, -{-0.128063f,0.542822f,0.830026f},{-0.129216f,0.549796f,0.825244f},{-0.32094f,0.562335f,0.762087f}, -{-0.267665f,0.633191f,0.72624f},{-0.033667f,0.973168f,0.227618f},{0.0168639f,0.985589f,0.168313f}, -{-0.566884f,0.712608f,0.413319f},{0.108542f,0.994073f,0.0061294f},{0.125559f,0.990888f,-0.0487381f}, -{0.0163092f,0.994743f,0.101096f},{-0.807412f,-0.589942f,-0.00735334f},{-0.838698f,-0.540232f,0.0688061f}, -{-0.881405f,-0.469341f,0.0533315f},{0.783992f,-0.593224f,-0.182874f},{0.992591f,-0.109235f,-0.0532095f}, -{0.818459f,-0.442588f,-0.366388f},{-0.974179f,-0.225775f,0.000958332f},{-0.958019f,-0.275422f,-0.0796435f}, -{0.707968f,-0.265502f,0.654438f},{0.636608f,-0.281028f,0.71816f},{0.661075f,-0.188496f,0.726257f}, -{0.0874356f,-0.56697f,-0.819085f},{0.0433353f,-0.476473f,-0.87812f},{0.11842f,-0.528335f,-0.840737f}, -{0.129623f,0.104684f,-0.986022f},{-0.998419f,-0.0542573f,-0.0146808f},{-0.688453f,0.673068f,-0.270208f}, -{0.0156894f,0.999522f,0.0266441f},{-0.868316f,-0.494385f,0.0401279f},{-0.18112f,0.613563f,0.768594f}, -{-0.15902f,0.663238f,0.73132f},{-0.271218f,0.702918f,0.657531f},{-0.257402f,0.951051f,-0.171013f}, -{0.981363f,0.0833966f,-0.173124f},{0.99075f,0.0716342f,-0.115248f},{0.973192f,0.181782f,-0.140896f}, -{0.945709f,0.233387f,-0.226198f},{0.914622f,0.287571f,-0.2842f},{0.942306f,0.247063f,-0.225875f}, -{-0.938596f,-0.343675f,-0.030422f},{-0.261763f,0.960149f,-0.097945f},{0.948742f,0.313295f,0.0416476f}, -{-0.95564f,-0.294067f,0.0166649f},{-0.957934f,-0.285956f,0.0243055f},{-0.972972f,-0.208945f,-0.0983253f}, -{-0.979352f,-0.200837f,-0.0230909f},{-0.991689f,-0.0808817f,-0.100057f},{-0.945654f,-0.320158f,-0.0568986f}, -{0.690643f,-0.557553f,-0.460594f},{-0.432122f,-0.506947f,-0.745839f},{0.275703f,-0.688974f,-0.6703f}, -{0.0354541f,0.98518f,-0.167817f},{-0.32858f,-0.451626f,0.829499f},{-0.404259f,-0.441563f,0.800997f}, -{-0.36329f,-0.46504f,0.807315f},{-0.505347f,-0.18888f,-0.841991f},{-0.461011f,-0.138001f,-0.876598f}, -{-0.492927f,-0.276201f,-0.825068f},{0.846028f,0.49353f,0.201657f},{-0.417774f,-0.370217f,0.829701f}, -{-0.372866f,-0.459566f,0.806083f},{-0.301297f,-0.340957f,0.890487f},{0.0386461f,0.5845f,0.810473f}, -{-0.117987f,0.798897f,0.589782f},{-0.252652f,0.769314f,0.586791f},{-0.0898694f,0.716685f,0.691582f}, -{0.984322f,0.159456f,0.0753966f},{0.981936f,0.164752f,0.0930547f},{0.991128f,0.103448f,0.0834458f}, -{0.288081f,0.922413f,0.257223f},{0.196528f,0.928668f,0.314568f},{-0.276998f,0.950331f,0.141926f}, -{-0.947481f,0.302294f,-0.104397f},{-0.880527f,0.290802f,-0.374307f},{-0.982123f,0.082863f,-0.16902f}, -{0.0308069f,0.690279f,0.722888f},{-0.136452f,0.749634f,0.647634f},{-0.0115687f,0.611309f,0.791308f}, -{0.235361f,0.812168f,0.533844f},{0.42321f,0.747665f,0.511752f},{-0.00294655f,0.777584f,0.628772f}, -{-0.0585491f,0.0909536f,-0.994133f},{0.139261f,0.0860385f,-0.986511f},{0.0998423f,0.12309f,-0.98736f}, -{0.103544f,0.953622f,-0.282637f},{0.124829f,0.977293f,-0.171217f},{0.194063f,0.963728f,-0.183217f}, -{-0.464984f,0.339376f,-0.817688f},{-0.437427f,0.436841f,-0.78602f},{-0.428677f,0.450404f,-0.783181f}, -{-0.197968f,0.136253f,-0.970692f},{-0.334069f,0.160007f,-0.928868f},{-0.237943f,0.127333f,-0.962896f}, -{-0.520129f,0.00462802f,-0.854075f},{-0.455464f,0.0948686f,-0.885185f},{-0.332832f,0.0880139f,-0.93887f}, -{-0.481026f,-0.475911f,-0.73629f},{-0.438014f,-0.337269f,-0.833302f},{-0.347452f,-0.547715f,-0.761108f}, -{-0.461713f,-0.302499f,-0.833856f},{-0.29253f,-0.428292f,0.854981f},{-0.254224f,-0.27951f,0.925875f}, -{-0.528736f,-0.202208f,0.824349f},{-0.27128f,-0.0983893f,0.957458f},{-0.119153f,0.0275033f,0.992495f}, -{-0.263646f,0.0184969f,0.964442f},{-0.203003f,-0.0257421f,0.97884f},{0.0881956f,0.0331346f,0.995552f}, -{0.289706f,0.260591f,0.920958f},{0.238046f,0.369706f,0.898138f},{0.186732f,0.437215f,0.879758f}, -{0.160958f,0.506869f,0.846863f},{0.14827f,0.502056f,0.85203f},{-0.00055618f,0.615531f,0.788112f}, -{-0.00716591f,0.635817f,0.771807f},{0.956568f,0.250869f,-0.148464f},{-0.0660797f,0.638031f,-0.76717f}, -{-0.0601667f,0.665157f,-0.744276f},{-0.140985f,0.719068f,-0.680488f},{0.783289f,-0.583404f,-0.214702f}, -{0.948733f,-0.302305f,-0.092287f},{0.965091f,-0.248812f,-0.0818032f},{-0.276455f,0.810676f,0.516117f}, -{-0.396968f,0.850953f,0.343942f},{-0.229114f,0.779813f,0.582579f},{0.119628f,0.98719f,-0.105573f}, -{0.212732f,0.971432f,-0.105193f},{-0.380376f,0.529341f,-0.758362f},{0.0247164f,-0.999286f,-0.0285692f}, -{0.0221136f,-0.999343f,-0.0287203f},{0.0171425f,-0.999755f,-0.01398f},{0.0309597f,-0.415753f,-0.908951f}, -{0.00724507f,-0.383477f,-0.923522f},{0.0188414f,-0.424607f,-0.905182f},{0.210939f,0.157303f,0.964759f}, -{-0.0297303f,0.747411f,0.663697f},{0.933011f,0.289119f,-0.214245f},{0.925733f,0.281444f,-0.252602f}, -{0.903201f,0.364361f,-0.226868f},{0.861819f,-0.100476f,0.497165f},{0.91382f,0.0166522f,0.405778f}, -{0.85081f,0.0456878f,0.523484f},{-0.922116f,0.28202f,-0.264888f},{-0.924562f,0.232143f,-0.302149f}, -{-0.916155f,0.231573f,-0.327161f},{0.801727f,0.22916f,-0.552014f},{0.806146f,0.340978f,-0.483593f}, -{0.844248f,0.252886f,-0.472539f},{-0.900107f,0.432791f,-0.0499879f},{-0.929252f,0.170879f,-0.327554f}, -{-0.889537f,0.200244f,-0.410641f},{-0.909881f,0.119352f,-0.397331f},{0.319048f,-0.927929f,0.19276f}, -{-0.0570574f,-0.998339f,0.00799306f},{-0.837236f,0.0170867f,-0.546575f},{-0.766305f,-0.107681f,-0.633389f}, -{-0.831586f,0.0795901f,-0.549664f},{0.377541f,0.316521f,0.870217f},{0.332509f,0.499481f,0.799972f}, -{0.460076f,0.517386f,0.721555f},{0.79541f,-0.566159f,-0.216304f},{0.911327f,-0.362557f,-0.195027f}, -{-0.74796f,-0.0695523f,-0.660089f},{-0.662762f,-0.235216f,-0.710929f},{-0.539195f,-0.222657f,-0.812214f}, -{0.0218027f,-0.433793f,0.900749f},{-0.00311731f,-0.163603f,0.986521f},{-0.0173914f,0.0456827f,0.998805f}, -{0.0400381f,0.178126f,0.983193f},{0.283483f,0.312944f,0.906479f},{0.134246f,-0.174071f,0.975539f}, -{0.212289f,-0.161507f,0.963768f},{0.229441f,-0.18882f,0.954832f},{0.412163f,0.305418f,0.858395f}, -{0.328776f,0.398539f,0.856197f},{0.424166f,0.363353f,0.829492f},{0.265865f,0.453263f,0.850804f}, -{0.18611f,0.546428f,0.816566f},{0.143454f,0.625752f,0.766718f},{0.120938f,0.656564f,0.744512f}, -{0.932122f,0.322601f,-0.16455f},{0.804729f,0.514737f,-0.29573f},{0.834634f,0.525578f,-0.164783f}, -{-0.988431f,0.0168326f,-0.150736f},{-0.992003f,-0.00163991f,-0.126204f},{-0.967043f,-0.0141034f,-0.254221f}, -{-0.00142562f,-0.579066f,-0.815279f},{-0.125423f,-0.384951f,-0.914375f},{-0.103741f,-0.44905f,-0.887464f}, -{-0.553529f,0.736759f,0.388319f},{-0.678903f,0.627379f,0.381427f},{-0.0588021f,0.897443f,0.437193f}, -{-0.943585f,-0.29927f,-0.141721f},{-0.965152f,-0.168369f,-0.200336f},{0.581388f,-0.170418f,-0.795579f}, -{0.894217f,0.330236f,-0.302192f},{0.891125f,-0.205523f,-0.404545f},{0.210297f,0.767182f,0.605977f}, -{0.00638082f,0.857806f,0.513935f},{0.470693f,0.834009f,0.287883f},{0.370541f,0.871789f,0.320441f}, -{0.440424f,0.862366f,0.249702f},{-0.873822f,-0.484636f,0.0395298f},{-0.891498f,-0.450702f,0.0458181f}, -{-0.87457f,-0.484822f,-0.00871369f},{0.197942f,0.935148f,-0.293798f},{0.197289f,-0.730094f,-0.654248f}, -{0.22188f,-0.765928f,-0.603426f},{0.238886f,-0.773997f,-0.586398f},{-0.683216f,-0.224521f,-0.694842f}, -{-0.127828f,0.30359f,-0.944189f},{-0.0162157f,0.431431f,-0.902f},{-0.193427f,0.498023f,-0.845316f}, -{-0.280182f,-0.707712f,-0.64857f},{-0.079535f,-0.668278f,-0.739648f},{-0.392839f,-0.472588f,-0.788884f}, -{0.176156f,0.338308f,0.924401f},{-0.581431f,0.267686f,-0.768298f},{-0.594621f,0.186383f,-0.782104f}, -{-0.642564f,0.383097f,-0.663587f},{0.0191206f,-0.600232f,0.799598f},{0.100352f,-0.466051f,0.879049f}, -{0.187243f,-0.175769f,0.96646f},{0.209566f,-0.253734f,0.944299f},{0.111776f,-0.225572f,0.967793f}, -{-0.420204f,-0.794529f,-0.438352f},{-0.0541604f,-0.944389f,-0.324339f},{-0.958418f,0.269381f,0.0941702f}, -{-0.924451f,0.370113f,0.0916944f},{-0.950281f,0.306645f,-0.0541689f},{0.980787f,-0.180823f,0.0732094f}, -{0.981284f,-0.17298f,0.0846207f},{-0.0940962f,0.884837f,0.4563f},{-0.534859f,0.744233f,0.400053f}, -{0.718215f,0.189478f,-0.669526f},{0.713162f,0.106936f,-0.692795f},{0.801152f,-0.0516452f,-0.596229f}, -{0.560765f,-0.485962f,-0.67036f},{0.647819f,-0.462094f,-0.60564f},{0.552192f,-0.596363f,-0.582611f}, -{0.461443f,-0.823847f,-0.329161f},{0.839854f,0.511735f,0.181034f},{0.824616f,0.534256f,0.185955f}, -{-0.439976f,0.866796f,0.234702f},{-0.118575f,0.752426f,0.647916f},{0.149029f,0.629448f,0.762618f}, -{0.037462f,0.830588f,0.555625f},{-0.327739f,0.0394449f,0.943944f},{-0.516321f,0.0528115f,0.854765f}, -{-0.414224f,-0.0682792f,0.90761f},{0.288967f,0.0433499f,-0.956357f},{0.275983f,-0.147043f,-0.949848f}, -{0.598083f,-0.304596f,-0.741294f},{0.293406f,-0.917829f,-0.267401f},{0.601447f,-0.775694f,-0.191208f}, -{0.0463522f,0.74153f,0.669317f},{-0.704225f,-0.683019f,-0.193784f},{-0.708969f,-0.696362f,-0.111547f}, -{-0.680494f,-0.689726f,-0.247398f},{-0.443656f,0.340732f,0.828898f},{-0.338882f,0.238957f,0.909977f}, -{-0.467223f,0.237607f,0.851614f},{-0.443441f,-0.0478543f,-0.895025f},{-0.542019f,0.148455f,-0.827149f}, -{-0.496647f,0.0266507f,-0.867543f},{0.452023f,0.320446f,0.83246f},{0.187312f,-0.289498f,0.938672f}, -{0.817561f,0.484433f,-0.311319f},{0.119843f,0.692326f,0.711563f},{-0.5423f,0.839989f,-0.0181133f}, -{-0.589584f,0.802126f,-0.0947837f},{0.272709f,0.847446f,0.455483f},{-0.999451f,0.0035897f,0.0329507f}, -{0.0652443f,0.925068f,0.374155f},{-0.417802f,0.0621403f,0.906411f},{-0.299806f,0.0578951f,0.952242f}, -{-0.230259f,-0.156221f,0.960508f},{-0.482247f,-0.62297f,0.615911f},{-0.72808f,-0.351511f,0.588506f}, -{-0.223557f,0.145718f,0.963737f},{-0.284359f,0.277931f,0.917548f},{-0.394802f,0.167585f,0.903353f}, -{-0.36651f,-0.490079f,-0.790881f},{0.958509f,-0.237533f,-0.157604f},{-0.340748f,-0.792406f,0.505947f}, -{-0.800663f,-0.422511f,0.424763f},{-0.793826f,-0.330462f,0.510524f},{-0.345477f,0.371662f,0.861692f}, -{-0.35377f,0.384884f,0.852474f},{-0.235416f,0.24056f,0.941653f},{-0.00349561f,-0.229967f,0.973192f}, -{-0.452241f,0.131272f,-0.882182f},{0.213681f,-0.17502f,0.961097f},{0.385113f,-0.504767f,0.772592f}, -{0.241816f,0.0985017f,0.96531f},{0.245202f,0.25789f,0.934542f},{0.141131f,0.377939f,0.91501f}, -{0.123254f,0.47787f,0.869741f},{-0.0193965f,0.480999f,0.876507f},{0.220321f,0.498587f,0.838373f}, -{0.158681f,0.595297f,0.787681f},{0.214315f,0.598022f,0.772294f},{0.103356f,-0.545978f,0.8314f}, -{0.198197f,-0.0823329f,0.976698f},{0.65635f,-0.1957f,-0.728633f},{0.628686f,-0.318384f,-0.709497f}, -{0.490731f,-0.0500569f,-0.869872f},{0.996762f,0.0511583f,-0.0620418f},{0.308099f,0.64451f,0.699773f}, -{0.424921f,0.473751f,0.771364f},{0.435549f,0.496107f,0.751116f},{-0.0848771f,-0.255893f,-0.962972f}, -{0.354992f,0.509584f,0.783776f},{0.394104f,0.427023f,0.813839f},{0.585515f,-0.690378f,-0.424912f}, -{0.527878f,-0.549372f,-0.647716f},{0.884681f,-0.463029f,-0.0542522f},{0.022149f,-0.999754f,0.000742555f}, -{-0.0122399f,-0.999713f,0.0206051f},{0.040471f,-0.998944f,0.0217503f},{-0.170834f,0.582988f,-0.794317f}, -{-0.178266f,0.547618f,-0.817518f},{-0.212052f,0.610169f,-0.763366f},{0.825517f,0.493208f,-0.274349f}, -{0.801331f,0.529124f,-0.279101f},{0.818077f,0.552458f,-0.159812f},{0.467831f,-0.658629f,-0.589357f}, -{0.435167f,-0.759272f,-0.483876f},{0.236562f,-0.797224f,-0.555402f},{-0.644491f,0.666855f,0.374081f}, -{-0.00960394f,0.452187f,0.891871f},{-0.177981f,0.559222f,0.809687f},{-0.199909f,0.532918f,0.822213f}, -{0.337658f,0.462369f,0.819879f},{0.229458f,0.26022f,0.937888f},{0.416462f,0.423903f,0.804279f}, -{0.76476f,0.595295f,0.246506f},{-0.929246f,0.137717f,-0.342835f},{-0.875507f,-0.151751f,-0.458759f}, -{-0.894451f,0.21627f,-0.391389f},{0.310225f,0.947793f,0.0738153f},{0.231035f,0.95555f,0.183157f}, -{-0.296947f,0.852665f,0.429865f},{-0.985861f,0.0887629f,-0.142124f},{0.0185413f,0.943008f,0.332254f}, -{0.057313f,0.886239f,0.459669f},{-0.679383f,-0.0801837f,-0.729389f},{0.113925f,-0.311895f,-0.943262f}, -{-0.139823f,0.0525498f,0.988781f},{-0.218846f,0.661597f,0.717214f},{-0.148582f,-0.206342f,-0.967133f}, -{0.7509f,-0.182971f,-0.634563f},{0.420695f,-0.203165f,0.88416f},{-0.420831f,-0.473534f,-0.773736f}, -{-0.229455f,-0.26095f,-0.937686f},{-0.246277f,-0.0434649f,-0.968224f},{0.13588f,0.282837f,0.949495f}, -{0.176315f,0.366131f,0.913707f},{0.116814f,0.371617f,0.921008f},{-0.00480627f,0.35768f,0.933832f}, -{0.0834085f,0.119904f,0.989276f},{0.161637f,-0.054116f,0.985365f},{0.00341052f,0.0398947f,0.999198f}, -{-0.0800531f,-0.726618f,0.682362f},{0.0654456f,-0.609214f,0.790301f},{-0.0633954f,-0.615952f,0.785229f}, -{-0.0539942f,-0.764143f,0.642783f},{0.00401556f,-0.756327f,0.654181f},{0.0838838f,-0.339017f,0.937033f}, -{0.0587523f,-0.4979f,0.865242f},{0.148705f,0.00212254f,0.988879f},{0.182487f,0.0571239f,0.981547f}, -{0.53245f,-0.726799f,-0.43389f},{0.571984f,-0.776758f,-0.263593f},{0.490454f,-0.797822f,-0.350621f}, -{0.914028f,0.298546f,-0.274632f},{0.908921f,0.0880075f,-0.407576f},{0.96965f,0.0520819f,-0.238887f}, -{-0.0686965f,0.325763f,-0.942952f},{-0.109446f,0.392498f,-0.913218f},{-0.132643f,0.414957f,-0.900121f}, -{0.465453f,-0.78761f,-0.403763f},{0.43965f,-0.708592f,-0.551911f},{0.469105f,-0.777133f,-0.419529f}, -{0.453067f,-0.76698f,-0.454393f},{0.454134f,-0.76286f,-0.460225f},{0.876326f,-0.436944f,-0.202812f}, -{0.900929f,-0.413532f,-0.131602f},{0.921355f,-0.355754f,-0.156663f},{-0.0920299f,0.658693f,0.746762f}, -{-0.155912f,0.746973f,0.646315f},{-0.28089f,0.68316f,0.674087f},{-0.0731005f,0.675791f,0.733459f}, -{-0.128286f,0.631681f,0.76454f},{0.210613f,0.314174f,0.925709f},{-0.449802f,0.403711f,-0.796678f}, -{-0.396683f,0.413545f,-0.819526f},{-0.273958f,0.956358f,0.101619f},{0.11902f,0.990924f,0.0624892f}, -{0.108584f,0.967612f,0.227895f},{0.0300621f,0.972509f,0.230917f},{-0.32827f,0.355206f,0.875253f}, -{0.278549f,0.478117f,0.832955f},{0.288245f,0.594488f,0.750666f},{0.0643547f,0.0265242f,0.997575f}, -{0.207224f,-0.0685004f,0.975892f},{0.0639272f,0.178665f,0.981831f},{-0.0313133f,-0.861465f,-0.506851f}, -{0.132764f,-0.817868f,-0.55988f},{0.122697f,-0.893873f,-0.431204f},{0.988041f,0.149777f,-0.036627f}, -{0.970806f,0.237743f,-0.0318535f},{0.982795f,0.17944f,0.0437546f},{0.252469f,0.598346f,0.760422f}, -{0.26065f,0.585606f,0.767547f},{0.264146f,0.574259f,0.774889f},{0.906751f,-0.385086f,-0.171788f}, -{0.684151f,-0.723747f,0.0901569f},{0.773584f,-0.525695f,0.353853f},{0.990162f,-0.133992f,0.0403111f}, -{-0.989415f,0.0943284f,0.110271f},{-0.493016f,-0.774648f,-0.39605f},{0.19466f,0.662258f,0.723548f}, -{0.559884f,0.373378f,0.739675f},{0.320414f,0.527874f,0.786564f},{0.974845f,-0.221106f,0.0280791f}, -{0.987799f,-0.15154f,0.0359129f},{0.948007f,-0.317943f,-0.0139217f},{0.807472f,-0.295769f,-0.510401f}, -{0.831477f,-0.257606f,-0.492224f},{0.830739f,-0.29772f,-0.470357f},{0.629038f,-0.619501f,-0.469605f}, -{0.731654f,-0.44459f,-0.516742f},{0.663327f,-0.609815f,-0.43373f},{-0.888495f,-0.373328f,0.266838f}, -{-0.853903f,-0.411981f,0.317996f},{-0.871296f,-0.349591f,0.344428f},{0.173781f,0.830788f,-0.528764f}, -{0.214551f,0.837516f,-0.502528f},{0.326037f,0.775801f,-0.540215f},{-0.109706f,-0.228527f,0.967336f}, -{-0.147056f,-0.079098f,0.98596f},{-0.19074f,0.0999919f,0.976535f},{0.678873f,-0.52574f,-0.512571f}, -{0.362062f,-0.744174f,-0.561351f},{-0.991329f,0.122094f,0.0485786f},{-0.974345f,0.217247f,-0.0587819f}, -{-0.287749f,0.942918f,0.167646f},{-0.360444f,0.226196f,0.90494f},{-0.212829f,0.253452f,0.943645f}, -{-0.1543f,0.180708f,0.971358f},{-0.240401f,0.248335f,0.938369f},{-0.281255f,0.382109f,0.880277f}, -{-0.291117f,0.434942f,0.852101f},{-0.241476f,0.380203f,0.892824f},{-0.138281f,0.282514f,0.949244f}, -{-0.118735f,0.0590326f,0.99117f},{0.794851f,-0.419047f,-0.438875f},{0.232186f,0.0291142f,0.972236f}, -{0.121233f,-0.0318358f,0.992113f},{0.199799f,0.0839047f,0.976238f},{0.346783f,-0.915641f,-0.203328f}, -{0.193206f,-0.847024f,-0.495199f},{0.289267f,-0.947851f,-0.133803f},{0.348006f,0.499509f,0.793336f}, -{0.208545f,0.31167f,0.927023f},{0.176429f,0.45395f,0.873386f},{0.131126f,-0.651578f,0.747162f}, -{0.477843f,0.446816f,0.756321f},{0.344739f,0.568001f,0.747349f},{0.900389f,-0.107033f,-0.421715f}, -{0.929053f,-0.117313f,-0.350853f},{0.924176f,-0.147349f,-0.352402f},{-0.0313202f,0.13272f,0.990659f}, -{-0.119674f,0.169113f,0.978304f},{0.0505059f,-0.0361727f,0.998068f},{0.178549f,0.161106f,0.970652f}, -{0.30095f,0.0349999f,0.952997f},{0.886396f,0.461951f,0.030055f},{0.869061f,0.492341f,-0.0483173f}, -{0.857969f,0.51363f,0.0086094f},{0.914986f,-0.377543f,-0.142346f},{0.93273f,-0.351435f,-0.0806737f}, -{0.927026f,-0.374765f,-0.0131579f},{0.946514f,-0.00024888f,-0.322663f},{-0.276014f,0.950969f,-0.139548f}, -{-0.264043f,0.963609f,-0.0416947f},{-0.23099f,0.971773f,0.0479709f},{-0.156866f,0.9795f,0.126387f}, -{-0.314375f,0.932833f,0.176042f},{-0.0245953f,0.890615f,0.454092f},{-0.448809f,-0.0923177f,0.888846f}, -{-0.502441f,-0.0916905f,0.859736f},{0.276028f,0.933338f,-0.229541f},{0.314576f,0.894929f,-0.316455f}, -{0.285181f,0.94836f,-0.13887f},{0.110223f,0.0102139f,0.993854f},{0.211547f,0.0628589f,0.975344f}, -{0.321092f,-0.0486882f,0.945795f},{-0.0376397f,0.660927f,0.749506f},{-0.00832555f,-0.522454f,0.852627f}, -{-0.132767f,-0.384428f,0.913558f},{0.223466f,0.216042f,0.950468f},{0.238549f,0.376728f,0.895081f}, -{0.238472f,0.243627f,0.940094f},{0.302267f,0.125011f,0.94499f},{0.248175f,0.366485f,0.896715f}, -{0.168671f,0.349832f,0.921503f},{0.199354f,0.22033f,0.954836f},{0.273515f,0.176255f,0.945581f}, -{0.191339f,0.153628f,0.969427f},{-0.0112707f,0.119995f,0.99271f},{0.0725509f,0.159063f,0.984599f}, -{-0.00629055f,0.274279f,0.96163f},{0.277965f,0.117253f,0.953408f},{0.110563f,-0.343456f,0.932638f}, -{0.216365f,-0.123f,0.968534f},{0.900057f,0.245717f,0.359889f},{0.863173f,0.257873f,0.43409f}, -{0.881976f,0.160588f,0.443091f},{0.370564f,-0.353545f,0.858888f},{0.336535f,-0.0878704f,0.937562f}, -{0.256114f,-0.421237f,0.870037f},{0.905595f,0.0066398f,-0.424091f},{0.932738f,0.00768876f,-0.360474f}, -{0.937288f,0.0876965f,-0.337345f},{-0.0369066f,-0.945463f,0.323632f},{-0.118818f,-0.685618f,0.718199f}, -{-0.0967924f,-0.804577f,0.585907f},{0.916949f,0.263347f,-0.299756f},{0.898078f,0.264743f,-0.351236f}, -{-0.75019f,0.547434f,0.370853f},{-0.604395f,0.689198f,0.399641f},{-0.672897f,0.729871f,0.120408f}, -{-0.245761f,-0.73762f,-0.628903f},{-0.470701f,-0.346268f,-0.811504f},{0.0348372f,-0.579103f,-0.81451f}, -{-0.230634f,-0.210479f,0.950003f},{-0.274659f,-0.0711949f,0.958902f},{-0.350123f,-0.292919f,0.889726f}, -{-0.320295f,0.106153f,0.941352f},{-0.450114f,0.11922f,0.884977f},{0.136917f,0.164934f,0.976755f}, -{0.20114f,-0.423575f,0.883248f},{0.269589f,0.227421f,0.935736f},{0.256735f,0.173565f,0.950769f}, -{0.297017f,0.215377f,0.930266f},{0.300127f,-0.148128f,0.942328f},{-0.16051f,-0.429314f,-0.888778f}, -{-0.0358626f,-0.295419f,-0.954694f},{-0.0163357f,-0.445626f,-0.89507f},{0.458862f,-0.882519f,-0.10298f}, -{0.414609f,-0.88476f,-0.212836f},{0.489972f,-0.830752f,-0.264156f},{-0.079701f,-0.146064f,0.986059f}, -{-0.0857675f,-0.0777074f,0.99328f},{0.00161508f,-0.337113f,0.941463f},{0.280664f,-0.42611f,0.860034f}, -{-0.643998f,-0.577076f,-0.502246f},{-0.0959296f,-0.748871f,-0.655736f},{0.986673f,0.113871f,0.116232f}, -{0.948721f,0.230491f,0.21634f},{0.944986f,0.307393f,0.111848f},{0.960212f,-0.067786f,-0.27092f}, -{0.960641f,-0.049122f,-0.273417f},{0.967143f,-0.0398146f,-0.251094f},{0.91918f,0.127727f,-0.37255f}, -{0.949064f,0.123437f,-0.289897f},{0.568969f,0.205887f,0.796169f},{0.844097f,0.53266f,-0.0614229f}, -{0.137129f,0.880111f,0.454534f},{0.246395f,0.858197f,0.450319f},{-0.269803f,0.959994f,0.0749557f}, -{0.234905f,0.788011f,0.569085f},{-0.389489f,0.854769f,0.343027f},{-0.959211f,0.275599f,0.0629244f}, -{-0.953233f,0.301814f,0.0159892f},{-0.949614f,0.309566f,0.0490065f},{0.403744f,0.911277f,-0.0810251f}, -{0.923159f,0.364994f,0.120653f},{-0.62943f,-0.776664f,0.0247036f},{-0.652388f,-0.757587f,-0.0212481f}, -{-0.44652f,-0.894258f,-0.030358f},{-0.0901651f,-0.339501f,0.936274f},{-0.0379441f,-0.271751f,0.961619f}, -{-0.332831f,-0.401591f,0.853199f},{-0.0344199f,-0.209496f,0.977203f},{-0.126661f,-0.114418f,0.985325f}, -{-0.148426f,0.0111855f,0.98886f},{-0.295706f,0.235843f,0.925708f},{-0.369193f,0.300019f,0.879594f}, -{-0.309604f,0.364565f,0.878201f},{-0.187306f,0.220824f,0.957159f},{-0.158949f,0.314932f,0.93571f}, -{-0.161938f,0.456189f,0.875024f},{-0.148022f,0.444858f,0.883284f},{0.739283f,-0.653128f,-0.163966f}, -{0.86335f,-0.487178f,-0.131467f},{0.933787f,0.353346f,-0.0564575f},{-0.0460242f,-0.614627f,-0.787474f}, -{-0.113948f,-0.561688f,-0.819465f},{0.0168824f,-0.095401f,0.995296f},{-0.274895f,-0.200561f,0.940323f}, -{0.0946811f,0.635809f,0.766018f},{0.231209f,-0.764021f,0.60234f},{0.142163f,-0.126555f,0.98172f}, -{0.25344f,0.386675f,0.886708f},{0.250599f,0.501617f,0.827998f},{0.195129f,0.482999f,0.853602f}, -{0.0557201f,0.685491f,0.725946f},{-0.0774665f,0.667998f,0.74012f},{-0.0840826f,0.594974f,0.799335f}, -{0.01558f,0.551834f,0.833808f},{0.00736914f,0.617291f,0.786701f},{-0.0983184f,0.553799f,0.826825f}, -{0.18891f,0.283061f,-0.940314f},{0.178401f,0.241742f,-0.9538f},{0.100226f,0.273544f,-0.956623f}, -{0.769923f,-0.243603f,0.58981f},{0.77465f,-0.286361f,0.563839f},{0.69038f,-0.0458631f,0.721991f}, -{-0.327666f,0.777839f,0.536285f},{-0.342358f,0.791542f,0.506214f},{-0.327755f,0.859105f,0.393083f}, -{0.883778f,0.438968f,0.162f},{0.877874f,0.383199f,0.287219f},{0.0517423f,0.993679f,-0.0996198f}, -{0.13168f,0.990813f,-0.0308326f},{-0.229953f,-0.378124f,0.896741f},{0.140701f,0.329084f,0.93376f}, -{0.173597f,0.234941f,0.956382f},{0.286773f,-0.404816f,0.868266f},{0.409235f,-0.270151f,0.871519f}, -{-0.379485f,-0.523586f,-0.76279f},{-0.483885f,-0.460032f,-0.744464f},{-0.429615f,-0.568608f,-0.70151f}, -{0.165898f,0.0505138f,0.984848f},{0.185924f,0.175633f,0.96674f},{0.14884f,0.141895f,0.978628f}, -{0.0918044f,0.142985f,0.985458f},{0.0755089f,0.581447f,0.810073f},{0.333992f,-0.909345f,-0.248074f}, -{0.442823f,-0.869149f,-0.220199f},{0.669263f,-0.711774f,-0.213223f},{0.329347f,-0.663973f,0.671319f}, -{0.307978f,-0.627619f,0.715013f},{0.2937f,-0.525645f,0.798397f},{0.459327f,-0.888265f,0.00217148f}, -{0.553339f,-0.766244f,0.32663f},{0.416483f,-0.890913f,-0.18115f},{0.448413f,-0.472512f,0.758722f}, -{0.463214f,-0.583903f,0.666701f},{0.0228558f,0.153535f,0.987879f},{0.108558f,0.236491f,0.96555f}, -{0.728112f,-0.605165f,-0.321914f},{0.858305f,-0.313243f,-0.406437f},{0.599198f,0.0898905f,0.795539f}, -{0.819297f,0.491738f,0.294864f},{0.243573f,-0.893407f,-0.377487f},{0.196902f,-0.829986f,-0.521874f}, -{0.788151f,-0.606299f,0.105922f},{-0.0230661f,0.00367931f,-0.999727f},{0.0283941f,0.0276503f,-0.999214f}, -{0.0669312f,0.0129073f,-0.997674f},{-0.334345f,-0.481378f,0.81024f},{-0.309593f,-0.428943f,0.848622f}, -{-0.302578f,-0.400369f,0.864958f},{-0.254114f,0.379369f,0.889666f},{0.498502f,0.24239f,0.832312f}, -{0.615686f,0.102185f,0.781338f},{0.553289f,0.0582414f,0.830951f},{-0.00204334f,-0.480179f,0.877168f}, -{-0.0856082f,-0.206093f,0.97478f},{0.327397f,-0.357655f,0.874582f},{0.215444f,-0.466779f,0.85773f}, -{0.162921f,-0.132008f,0.977768f},{0.0647925f,0.233047f,0.970305f},{0.111038f,0.205046f,0.972433f}, -{0.0158613f,-0.0419174f,0.998995f},{0.341844f,-0.269747f,0.900211f},{0.116874f,-0.149929f,0.981765f}, -{0.191889f,-0.0992769f,0.976382f},{0.0101111f,0.773999f,0.633107f},{-0.0530789f,0.700445f,0.71173f}, -{0.511712f,-0.845175f,-0.154368f},{0.850173f,-0.499442f,-0.166622f},{0.846485f,-0.503522f,-0.172997f}, -{0.82965f,-0.522815f,-0.195821f},{0.023405f,-0.999625f,-0.0142142f},{0.0242401f,-0.999656f,-0.00998008f}, -{-0.000303005f,-0.999841f,-0.017843f},{-0.933294f,0.332437f,0.135822f},{-0.881595f,0.351294f,0.31525f}, -{-0.928424f,0.283676f,0.239911f},{-0.772711f,0.476617f,-0.41923f},{-0.402891f,0.911185f,-0.0861461f}, -{-0.76101f,0.648736f,0.0022703f},{-0.525614f,0.828955f,-0.191216f},{-0.187238f,0.982224f,-0.0133145f}, -{-0.147426f,0.988429f,-0.0356911f},{-0.248234f,-0.244597f,-0.937311f},{-0.198606f,-0.362544f,-0.910559f}, -{0.3608f,-0.683461f,-0.63459f},{0.0953136f,0.0853679f,-0.99178f},{0.51823f,-0.849414f,-0.0996677f}, -{0.814328f,-0.553142f,-0.175794f},{0.748936f,-0.635619f,-0.187304f},{-0.191851f,-0.439151f,0.87769f}, -{-0.228831f,-0.274946f,0.933831f},{-0.144682f,-0.240387f,0.959834f},{0.0186087f,-0.229308f,0.973176f}, -{0.0844466f,-0.272325f,0.958493f},{0.048156f,-0.214678f,0.975497f},{0.0185073f,-0.0533244f,0.998406f}, -{-0.0645704f,0.122728f,0.990338f},{-0.0960451f,0.353497f,0.930492f},{-0.123316f,0.466299f,0.87599f}, -{-0.101722f,0.334442f,0.93691f},{-0.130158f,0.278541f,0.951564f},{-0.134554f,0.476146f,0.869011f}, -{-0.0530084f,0.525905f,0.84889f},{-0.164811f,0.321452f,0.932473f},{0.0823322f,0.227239f,0.970353f}, -{-0.0657198f,0.130476f,0.989271f},{-0.0768859f,-0.720243f,0.689448f},{0.239307f,0.762061f,0.601661f}, -{0.112851f,0.567339f,0.815715f},{0.141879f,0.648949f,0.747486f},{0.203347f,0.494481f,0.845067f}, -{-0.0796564f,-0.697736f,0.711913f},{-0.0953443f,-0.671122f,0.73519f},{-0.964209f,-0.241382f,0.109707f}, -{-0.972866f,-0.118573f,0.198676f},{-0.962037f,-0.177494f,0.207316f},{0.376109f,0.345327f,0.859821f}, -{0.260354f,0.334831f,0.905596f},{0.413984f,0.0796125f,0.906796f},{0.206149f,0.427033f,0.880423f}, -{0.255093f,0.478282f,0.840342f},{0.186982f,0.425432f,0.885463f},{0.188722f,0.418679f,0.888308f}, -{0.932563f,-0.313456f,-0.179087f},{0.00751608f,-0.992196f,0.124464f},{0.61083f,0.754516f,0.239982f}, -{0.210359f,0.975986f,0.0565786f},{0.237949f,0.971085f,-0.0193416f},{-0.992479f,-0.119535f,-0.0264097f}, -{-0.991905f,0.122125f,-0.0347969f},{-0.994124f,0.0788717f,-0.0741417f},{0.317099f,0.917356f,0.240638f}, -{-0.9839f,0.176112f,-0.0304254f},{-0.229285f,0.931458f,-0.282516f},{-0.249293f,0.95181f,-0.178636f}, -{-0.380595f,-0.0953641f,-0.919811f},{-0.356386f,-0.185595f,-0.91572f},{-0.532308f,0.33788f,-0.7762f}, -{-0.623105f,0.373117f,-0.687404f},{-0.591311f,0.340755f,-0.730915f},{-0.0939356f,0.50456f,-0.858251f}, -{-0.0584824f,0.31504f,-0.947275f},{-0.0717267f,0.392258f,-0.917055f},{-0.409762f,-0.0557136f,-0.91049f}, -{-0.432608f,0.0796261f,-0.898059f},{-0.290013f,-0.0614834f,-0.955046f},{-0.253383f,-0.515742f,0.818418f}, -{-0.147352f,0.43482f,0.88838f},{0.948899f,-0.0521516f,-0.311241f},{0.175427f,0.203394f,-0.963253f}, -{0.284098f,-0.0864908f,0.954886f},{0.156203f,-0.102557f,0.982386f},{-0.0343121f,-0.670962f,0.740697f}, -{0.282425f,0.113884f,0.952505f},{0.252265f,-0.0799734f,0.964348f},{0.608191f,-0.555626f,-0.566907f}, -{-0.281625f,0.0199879f,-0.959316f},{-0.321533f,0.14723f,-0.935382f},{0.00403764f,-0.409977f,0.912087f}, -{0.296786f,0.412455f,0.861278f},{0.314424f,0.491877f,0.811908f},{0.15597f,-0.148834f,0.976484f}, -{-0.265697f,-0.575302f,0.773585f},{-0.0127738f,-0.679576f,0.733494f},{-0.326234f,-0.480712f,0.813933f}, -{-0.872833f,-0.464274f,-0.150372f},{-0.994023f,0.0946819f,-0.0543493f},{-0.550761f,-0.834547f,0.0139191f}, -{0.0263528f,0.37496f,0.926666f},{0.216957f,0.471372f,0.854832f},{0.778666f,0.0794795f,0.622385f}, -{0.595223f,-0.107183f,0.79638f},{0.0160022f,0.466013f,0.884633f},{-0.217392f,0.653551f,0.72499f}, -{-0.331892f,-0.59942f,-0.728384f},{-0.200273f,-0.752239f,-0.627716f},{0.510712f,-0.829747f,-0.225151f}, -{0.546848f,-0.823202f,-0.15263f},{0.255635f,-0.202235f,0.945384f},{0.233842f,-0.286493f,0.929107f}, -{0.308997f,0.326208f,0.893369f},{0.539946f,0.154095f,0.827474f},{0.536519f,0.226703f,0.812867f}, -{-0.013535f,0.996342f,0.0843795f},{-0.430286f,-0.0933455f,-0.897853f},{-0.293771f,-0.0785507f,-0.952643f}, -{-0.316683f,-0.174593f,-0.932325f},{-0.616447f,0.263836f,-0.741878f},{-0.584456f,0.323832f,-0.744006f}, -{-0.533083f,0.332606f,-0.777943f},{-0.470009f,0.0371177f,-0.881881f},{-0.313697f,-0.230665f,-0.92108f}, -{-0.095108f,-0.430469f,0.89758f},{-0.205516f,-0.31961f,0.924993f},{-0.271736f,-0.129682f,0.953594f}, -{-0.16233f,-0.128129f,0.978382f},{-0.103393f,-0.147975f,0.983572f},{0.0371042f,-0.0618592f,0.997395f}, -{0.0800676f,0.0692281f,0.994383f},{0.0655334f,0.326109f,0.943058f},{0.0500331f,0.458989f,0.887032f}, -{-0.012976f,0.250275f,0.968088f},{-0.00278086f,0.254525f,0.967062f},{-0.00602506f,0.403435f,0.914989f}, -{-0.0166253f,0.507921f,0.861243f},{-0.066194f,0.569683f,0.819194f},{0.00612044f,0.50687f,0.862001f}, -{0.087804f,0.358904f,0.929235f},{0.135736f,0.0527765f,0.989338f},{0.219893f,0.0168975f,0.975378f}, -{0.155385f,0.67077f,0.725205f},{0.0911761f,0.307906f,0.947038f},{0.380764f,-0.112959f,0.917747f}, -{0.484482f,-0.25873f,0.835665f},{0.173278f,-0.0255334f,0.984542f},{-0.119044f,0.0165311f,0.992751f}, -{-0.0621672f,-0.226799f,0.971955f},{0.168582f,-0.017391f,0.985534f},{0.192135f,-0.114706f,0.974642f}, -{0.0907603f,0.0712779f,0.993319f},{0.900404f,0.273238f,-0.338546f},{0.867039f,0.330615f,-0.372743f}, -{0.817124f,0.438432f,-0.374281f},{0.272694f,0.0257412f,0.961756f},{-0.264704f,0.876336f,0.402451f}, -{-0.374633f,0.788444f,0.487858f},{-0.239863f,-0.388392f,-0.889729f},{0.322604f,-0.898675f,-0.297171f}, -{0.110378f,0.0512505f,-0.992567f},{0.195878f,0.100581f,-0.975456f},{-0.299195f,0.368799f,-0.88004f}, -{-0.281542f,0.416945f,-0.864229f},{-0.334622f,0.516404f,-0.788261f},{-0.388498f,-0.387132f,-0.836181f}, -{-0.413425f,-0.223328f,-0.882726f},{-0.528806f,-0.229046f,-0.817253f},{-0.567126f,0.252032f,-0.784123f}, -{-0.0622147f,-0.575088f,0.815722f},{-0.262476f,-0.0975698f,0.959993f},{-0.27464f,-0.0410216f,0.960672f}, -{0.863329f,0.259147f,-0.43302f},{0.79449f,0.262755f,-0.547491f},{0.948858f,-0.049514f,-0.311796f}, -{-0.00933192f,0.0898895f,0.995908f},{-0.0154903f,0.0603768f,0.998055f},{0.233006f,0.519745f,0.821933f}, -{0.252677f,0.61801f,0.744458f},{-0.995603f,0.0694375f,-0.062876f},{-0.984647f,0.104033f,-0.140169f}, -{0.834566f,0.388194f,-0.390903f},{0.776226f,0.519924f,-0.356584f},{0.231295f,-0.0027237f,0.97288f}, -{0.123915f,0.171485f,0.977363f},{-0.278264f,0.885621f,0.371812f},{-0.208952f,0.742162f,0.636816f}, -{0.328508f,0.831803f,0.447423f},{-0.790702f,0.415924f,-0.449218f},{-0.592127f,0.348571f,-0.726556f}, -{-0.830674f,0.424403f,-0.360365f},{-0.62552f,0.184799f,-0.758006f},{-0.707192f,0.19258f,-0.680289f}, -{-0.613638f,0.127083f,-0.779293f},{-0.11711f,0.556457f,-0.822582f},{-0.179243f,-0.348841f,0.919881f}, -{0.214004f,0.377502f,0.900941f},{0.205075f,0.336747f,0.918992f},{0.174838f,0.422701f,0.889244f}, -{0.995333f,0.0317781f,-0.0911228f},{0.190036f,0.479935f,0.856475f},{0.231393f,0.433377f,0.871f}, -{0.0713411f,0.536196f,0.841073f},{0.461727f,-0.531031f,0.710503f},{0.642623f,-0.481829f,0.595716f}, -{0.0459413f,-0.172653f,-0.983911f},{-0.0211f,-0.331505f,-0.943218f},{-0.40236f,-0.188535f,-0.895858f}, -{-0.0220802f,0.497801f,0.86701f},{-0.261378f,0.528952f,0.807398f},{-0.310862f,0.246872f,0.917834f}, -{0.0737522f,0.294186f,0.952898f},{-0.0285864f,0.741674f,0.670151f},{0.130811f,0.779388f,0.612734f}, -{-0.329985f,0.70659f,0.625971f},{-0.150434f,0.157564f,-0.975983f},{-0.491554f,0.143916f,-0.858873f}, -{-0.549467f,0.207409f,-0.809362f},{0.0243846f,-0.998918f,-0.0395968f},{0.0154174f,-0.997923f,-0.0625502f}, -{-9.56649e-05f,-0.999511f,-0.031265f},{-0.0736797f,-0.847043f,0.526393f},{0.264565f,-0.526851f,0.807734f}, -{0.0778558f,-0.911717f,0.403374f},{-0.0722179f,-0.489121f,0.869221f},{-0.0497511f,-0.601297f,0.797475f}, -{0.0221068f,-0.414748f,0.909668f},{-0.024475f,-0.345695f,0.938028f},{-0.00234594f,-0.214816f,0.976652f}, -{-0.13038f,-0.0390172f,0.990696f},{-0.113822f,-0.00113113f,0.9935f},{0.00753531f,0.0784319f,0.996891f}, -{0.162659f,0.186062f,0.96898f},{0.197465f,0.373061f,0.90655f},{0.0726495f,0.270119f,0.960082f}, -{-0.00348439f,0.248771f,0.968556f},{0.132326f,0.32448f,0.936591f},{0.125685f,0.424566f,0.896631f}, -{0.153659f,0.430838f,0.889251f},{0.0608871f,0.531499f,0.844868f},{0.0273649f,0.554899f,0.831467f}, -{0.23097f,0.2435f,0.941998f},{0.391681f,-0.408344f,0.824525f},{-0.0899755f,-0.418629f,0.903689f}, -{-0.028856f,-0.230136f,0.972731f},{0.192937f,0.450434f,0.871714f},{0.304815f,0.404069f,0.862448f}, -{0.121643f,0.294766f,0.947795f},{0.0704177f,0.301208f,0.950955f},{-0.0185777f,0.496515f,0.867829f}, -{0.30631f,-0.12352f,0.943884f},{0.0381325f,-0.0587734f,0.997543f},{0.168162f,0.216513f,0.961688f}, -{0.17938f,0.201108f,0.963005f},{0.752987f,-0.233579f,-0.615184f},{0.752213f,-0.142831f,-0.643253f}, -{0.770254f,-0.2229f,-0.597515f},{-0.0432317f,0.381112f,0.923518f},{0.626181f,-0.779599f,0.0110793f}, -{0.621676f,-0.776663f,0.101553f},{0.521547f,-0.846536f,0.106608f},{0.344659f,-0.897823f,-0.274087f}, -{0.170478f,0.931913f,0.320119f},{0.0544409f,0.956743f,0.285794f},{-0.285666f,0.883754f,0.370641f}, -{-0.486945f,0.656165f,0.576482f},{-0.475298f,0.151973f,-0.8666f},{-0.169494f,-0.477562f,-0.862094f}, -{-0.0223069f,-0.554443f,-0.831923f},{0.19763f,0.0676612f,-0.977939f},{0.12502f,0.240439f,-0.96258f}, -{0.096951f,0.348996f,-0.932096f},{0.106352f,0.388327f,0.915364f},{0.186485f,0.465086f,0.865401f}, -{0.085202f,0.629671f,0.772176f},{-0.640431f,-0.404267f,-0.653006f},{-0.780979f,-0.316721f,-0.538294f}, -{-0.865468f,-0.312483f,-0.39156f},{0.0972787f,-0.197405f,0.975483f},{-0.0786699f,0.434336f,0.897309f}, -{-0.076951f,0.450712f,0.889346f},{-0.0668306f,0.439939f,0.895537f},{0.156395f,0.469386f,0.869033f}, -{0.394926f,-0.0689772f,0.91612f},{0.144095f,0.697262f,0.702184f},{0.268524f,0.659339f,0.702259f}, -{0.137937f,0.582651f,0.800932f},{-0.150031f,0.52089f,0.840336f},{-0.157645f,0.567902f,0.807858f}, -{-0.0967734f,0.630328f,0.770274f},{0.622746f,0.181545f,0.761071f},{0.239313f,0.574192f,0.782964f}, -{0.108848f,0.65576f,0.747082f},{0.711315f,0.172817f,0.681297f},{0.874118f,0.338625f,-0.348211f}, -{0.849983f,0.440713f,-0.288621f},{0.82446f,0.469055f,0.316627f},{0.839611f,0.504318f,0.201784f}, -{0.839027f,0.51583f,0.173072f},{-0.0827286f,0.994895f,-0.0577841f},{-0.0780838f,0.996946f,-0.00112269f}, -{-0.0196054f,0.999522f,-0.0238855f},{0.331187f,0.80367f,0.494399f},{0.464725f,0.734652f,0.494285f}, -{-0.657859f,0.081471f,0.748722f},{-0.601514f,-0.443733f,0.66429f},{-0.284661f,-0.303841f,0.909202f}, -{-0.573281f,0.338316f,-0.746251f},{-0.481339f,0.161541f,-0.861521f},{-0.512204f,0.100924f,-0.852913f}, -{-0.362885f,0.109735f,-0.92535f},{-0.104948f,0.555117f,0.825125f},{0.165705f,0.470171f,0.86688f}, -{0.168167f,0.431262f,0.886416f},{0.162941f,-0.206219f,0.964844f},{-0.0583317f,-0.297053f,0.953078f}, -{0.354429f,-0.0278913f,0.934667f},{0.251351f,0.451336f,0.856223f},{0.280874f,0.479454f,0.831405f}, -{-0.140207f,0.763332f,0.630608f},{0.0888948f,0.824089f,0.559442f},{0.236753f,0.565998f,0.78968f}, -{0.276147f,0.490722f,0.826399f},{0.165164f,0.456367f,0.874328f},{0.884691f,0.122447f,0.44981f}, -{0.470696f,0.578142f,0.666482f},{0.885033f,-0.390748f,0.253046f},{0.629966f,-0.274177f,-0.726615f}, -{0.647971f,-0.158293f,-0.745035f},{0.611495f,-0.0616235f,-0.788845f},{0.639939f,-0.751124f,-0.162144f}, -{0.673719f,-0.105217f,-0.731459f},{0.639491f,-0.601652f,0.478608f},{0.513526f,-0.849419f,0.121567f}, -{0.610413f,-0.647956f,0.455575f},{0.334601f,0.299348f,0.893551f},{0.0441093f,0.711599f,0.7012f}, -{0.181251f,0.742361f,0.645018f},{0.00122868f,0.846108f,0.53301f},{-0.281939f,0.868014f,0.408732f}, -{-0.471426f,0.186922f,-0.861869f},{-0.580898f,0.240434f,-0.777656f},{-0.583811f,0.05227f,-0.810205f}, -{0.0320676f,-0.999039f,-0.0298842f},{0.018545f,-0.99914f,-0.0370961f},{0.0146236f,-0.99989f,-0.0025338f}, -{-0.0617785f,-0.382466f,0.921902f},{-0.00404173f,-0.25056f,0.968093f},{0.122372f,-0.278325f,0.95266f}, -{0.0523822f,-0.161823f,0.985429f},{-0.0111141f,-0.0130864f,0.999853f},{0.0363037f,0.192458f,0.980633f}, -{-0.0404656f,0.143099f,0.988881f},{0.0160188f,0.175992f,0.984261f},{-0.210937f,0.0895094f,0.973393f}, -{-0.109152f,0.311871f,0.943834f},{0.0474923f,0.41157f,0.91014f},{0.0645066f,0.39909f,0.91464f}, -{-0.00659182f,0.496609f,0.867949f},{-0.0486732f,0.553081f,0.831704f},{0.0117206f,0.595074f,0.803586f}, -{0.0765092f,0.587289f,0.805753f},{0.347041f,0.370975f,0.861359f},{0.0452194f,0.614496f,0.787623f}, -{0.00440938f,0.620018f,0.784575f},{0.0859346f,0.688023f,0.720583f},{0.0447807f,0.383445f,0.922477f}, -{0.195784f,0.612478f,0.765859f},{0.145692f,0.695086f,0.704009f},{-0.00125758f,0.736867f,0.676037f}, -{0.24172f,0.519188f,0.819766f},{0.285311f,0.497986f,0.818906f},{0.460259f,-0.715681f,-0.525322f}, -{0.983586f,0.0216339f,0.179138f},{0.943684f,0.208261f,0.257076f},{0.981252f,0.0914436f,0.169655f}, -{0.14865f,0.0434738f,0.987934f},{-0.0207364f,0.626854f,0.778861f},{0.0720591f,0.436571f,0.89678f}, -{0.139963f,0.204553f,0.968797f},{-0.995807f,-0.0625395f,0.066763f},{-0.212539f,0.290927f,-0.932839f}, -{-0.418814f,0.226659f,-0.87933f},{0.0559445f,-0.155077f,0.986317f},{-0.202485f,-0.659883f,-0.723571f}, -{0.271867f,0.425229f,0.863289f},{0.235252f,0.505083f,0.83039f},{-0.14351f,0.68616f,0.713155f}, -{-0.393631f,0.778218f,0.489317f},{-0.220183f,0.743723f,0.631186f},{0.00776272f,0.335611f,0.941969f}, -{0.91128f,0.340794f,-0.231146f},{0.876158f,0.161572f,0.454138f},{0.824709f,0.261035f,0.501712f}, -{-0.512031f,0.218737f,0.83065f},{0.299492f,0.57243f,0.763301f},{0.443001f,0.393616f,0.805491f}, -{-0.350699f,0.860797f,0.368836f},{-0.485456f,0.0648393f,-0.871853f},{-0.570127f,0.246992f,-0.78355f}, -{-0.483251f,-0.0510707f,-0.873991f},{-0.510278f,-0.349902f,-0.785611f},{-0.500311f,-0.348015f,-0.792827f}, -{0.121175f,0.0514562f,-0.991297f},{-0.881409f,-0.279087f,-0.381089f},{-0.51307f,-0.43176f,-0.741851f}, -{-0.655812f,-0.39313f,-0.644484f},{-0.156642f,0.119218f,0.980434f},{-0.0217293f,0.0257904f,0.999431f}, -{-0.637142f,0.394017f,0.66242f},{0.108426f,0.88485f,0.453084f},{0.426378f,-0.185955f,0.885225f}, -{-0.0933708f,0.463751f,0.881032f},{-0.0882345f,0.196905f,0.976444f},{0.0172453f,0.226536f,0.97385f}, -{-0.0643816f,0.38211f,0.921871f},{-0.0728973f,0.463505f,0.88309f},{0.99305f,0.0973475f,0.0661499f}, -{0.993768f,0.090838f,0.0645981f},{0.99306f,0.0946657f,0.0697913f},{0.477953f,0.386349f,0.788857f}, -{0.0407022f,0.683789f,0.728544f},{0.0318931f,0.748566f,0.662293f},{0.181964f,-0.732915f,-0.655534f}, -{0.243709f,0.468222f,0.849337f},{0.153119f,0.654531f,0.740367f},{0.0758308f,0.737048f,0.671573f}, -{-0.17887f,0.637327f,0.749546f},{-0.296601f,0.712073f,0.63638f},{-0.541293f,0.466978f,0.699238f}, -{-0.566555f,0.696726f,0.439987f},{-0.134021f,0.932858f,0.334385f},{0.0218045f,-0.997464f,0.0677578f}, -{0.0271397f,-0.997929f,0.0583154f},{0.0252167f,-0.998572f,0.0471037f},{-0.621606f,-0.278433f,0.732176f}, -{-0.570494f,-0.50975f,0.643965f},{-0.681334f,-0.207411f,0.701972f},{-0.559511f,-0.36605f,-0.74361f}, -{0.493383f,0.0945182f,-0.864661f},{0.584445f,-0.0956861f,-0.805772f},{0.611821f,0.0811993f,-0.786817f}, -{0.0579123f,-0.316769f,0.946733f},{-0.0781528f,-0.569633f,0.818175f},{-0.956457f,0.0398561f,0.289139f}, -{-0.992877f,0.118206f,-0.0149156f},{-0.767728f,-0.639771f,0.0358726f},{0.183182f,-0.187221f,0.965087f}, -{0.158643f,-0.200877f,0.966685f},{0.0660394f,-0.240335f,0.968441f},{0.129513f,-0.216463f,0.967662f}, -{0.17963f,0.059801f,0.981915f},{0.216525f,0.230871f,0.948586f},{0.13377f,-0.00599154f,0.990994f}, -{0.13257f,0.0957259f,0.98654f},{0.147001f,0.309975f,0.939311f},{-0.0514512f,0.392173f,0.918452f}, -{-0.0894499f,0.442738f,0.892178f},{-0.184403f,0.382964f,0.905171f},{-0.0898477f,0.43927f,0.893851f}, -{-0.0528206f,0.613729f,0.787748f},{0.0169646f,0.649408f,0.760251f},{0.0341286f,0.644321f,0.763993f}, -{0.163776f,0.613155f,0.772799f},{-0.346824f,0.758038f,0.552352f},{-0.000173428f,0.166072f,0.986114f}, -{0.94866f,-0.152144f,-0.277302f},{0.980893f,-0.150273f,-0.12356f},{0.938342f,-0.31065f,-0.151691f}, -{0.0818533f,-0.546118f,0.833699f},{0.994091f,0.0830656f,0.0698837f},{0.993339f,0.0874817f,0.0749937f}, -{-0.227107f,0.963144f,-0.144138f},{-0.10378f,-0.515128f,0.850807f},{0.315257f,0.0500735f,0.947684f}, -{0.264788f,0.243961f,0.932936f},{0.296313f,0.265407f,0.917473f},{0.328641f,0.479454f,0.813707f}, -{0.229493f,0.231328f,0.945421f},{0.336808f,0.301467f,0.892008f},{0.232176f,0.498203f,0.835397f}, -{0.962198f,0.269438f,0.0397187f},{0.953436f,0.295835f,-0.0586683f},{0.942935f,0.331643f,0.0297584f}, -{0.198719f,0.341757f,0.918538f},{0.44266f,0.233925f,0.865639f},{-0.302218f,-0.92107f,0.245547f}, -{-0.468439f,-0.879868f,0.079976f},{-0.273014f,-0.949768f,-0.152985f},{0.279096f,0.87342f,0.399053f}, -{0.109999f,0.983735f,0.142007f},{0.33597f,0.0460234f,0.940748f},{-0.0755804f,0.557677f,0.82661f}, -{0.469378f,0.32101f,0.822579f},{-0.417018f,0.693837f,0.587099f},{-0.996744f,-0.0371724f,0.071545f}, -{0.202101f,0.433878f,0.878012f},{0.129701f,0.607736f,0.783476f},{0.0245816f,0.617155f,0.786458f}, -{-0.161749f,0.406649f,0.899152f},{-0.370242f,0.314838f,0.873956f},{0.32194f,0.854132f,0.408429f}, -{0.229067f,0.971816f,-0.0556929f},{-0.215353f,-0.504048f,0.836397f},{-0.165197f,-0.256448f,0.952336f}, -{-0.0296231f,-0.105381f,0.993991f},{0.0989861f,-0.0810697f,0.991781f},{0.323746f,-0.196872f,0.925435f}, -{0.343294f,-0.202076f,0.917232f},{0.380756f,0.0343652f,0.924037f},{0.377954f,0.253315f,0.890496f}, -{0.352625f,0.162393f,0.921566f},{0.235176f,0.0282973f,0.971541f},{0.278209f,0.0768769f,0.957439f}, -{0.18879f,0.230847f,0.954499f},{0.100841f,0.209443f,0.972607f},{-0.0516694f,0.294141f,0.954364f}, -{-0.0359873f,0.460162f,0.887105f},{0.0150075f,0.491099f,0.870974f},{0.0174386f,0.594376f,0.803998f}, -{0.0599003f,0.645757f,0.76119f},{0.0237448f,0.664496f,0.746914f},{-0.0117554f,0.643774f,0.765126f}, -{-0.00783735f,0.687184f,0.726442f},{-0.0677373f,0.701206f,0.709734f},{0.14681f,0.639021f,0.755049f}, -{0.161852f,-0.766316f,-0.621742f},{0.313848f,0.615783f,0.722711f},{0.357795f,-0.814972f,-0.455855f}, -{0.577611f,-0.687363f,-0.440337f},{0.0259876f,-0.995169f,0.0946733f},{0.030387f,-0.997499f,0.063819f}, -{0.0198724f,-0.996136f,0.0855424f},{0.368854f,0.251844f,0.894719f},{0.22752f,0.354024f,0.907139f}, -{0.0791086f,0.471746f,0.878178f},{0.827758f,0.36769f,-0.423817f},{0.845807f,0.387535f,-0.366644f}, -{0.240204f,0.227618f,0.943659f},{-0.370066f,0.155968f,0.915819f},{0.022549f,-0.996353f,0.0822977f}, -{0.0262031f,-0.996683f,0.0770459f},{0.416581f,-0.150609f,0.896536f},{0.835817f,-0.534199f,-0.126657f}, -{0.903079f,-0.405958f,-0.140167f},{0.222092f,-0.177756f,0.958686f},{0.0364991f,-0.0694043f,0.996921f}, -{0.0238959f,-0.354001f,0.93494f},{0.230632f,0.323804f,0.917583f},{0.144523f,-0.435178f,0.888669f}, -{-0.1093f,-0.210785f,0.971403f},{0.821085f,0.318833f,-0.47346f},{-0.754431f,0.566074f,-0.332255f}, -{-0.757881f,0.423543f,-0.496214f},{-0.82559f,0.142302f,-0.546032f},{-0.847383f,-0.192788f,-0.494747f}, -{-0.914762f,-0.15749f,-0.372033f},{0.276055f,0.263812f,0.924228f},{-0.0770771f,-0.957563f,-0.277728f}, -{0.139261f,-0.967934f,-0.209068f},{0.321303f,-0.905573f,-0.276951f},{0.431478f,0.0505868f,0.900704f}, -{0.249985f,0.200263f,0.947313f},{0.304387f,0.278311f,0.910984f},{-0.0499762f,-0.111835f,0.992469f}, -{0.246997f,0.369415f,0.895838f},{0.101263f,0.450865f,0.886829f},{0.0237676f,0.496742f,0.867573f}, -{-0.0263901f,0.301213f,0.953192f},{-0.141989f,0.111937f,0.983519f},{-0.179951f,-0.0840402f,0.980079f}, -{-0.385978f,-0.0345515f,0.921861f},{-0.371599f,-0.166121f,0.91341f},{-0.125026f,-0.19002f,0.973787f}, -{-0.373366f,-0.377655f,0.847333f},{-0.2744f,-0.324717f,0.905132f},{-0.0187571f,-0.159511f,0.987018f}, -{-0.0551324f,-0.088822f,0.994521f},{-0.0779111f,0.0233012f,0.996688f},{-0.05431f,0.00554412f,0.998509f}, -{0.0110976f,-0.11894f,0.992839f},{0.116006f,0.0256008f,0.992919f},{-0.00714221f,0.0399637f,0.999176f}, -{0.0629546f,0.0515646f,0.996683f},{0.104175f,0.0657995f,0.99238f},{0.123421f,0.142901f,0.982011f}, -{0.199415f,0.236513f,0.950944f},{0.161276f,0.334805f,0.928383f},{0.278101f,0.368124f,0.887211f}, -{0.249535f,0.469344f,0.847023f},{0.138731f,0.593551f,0.792749f},{0.0456122f,0.613564f,0.788327f}, -{0.00602844f,0.598335f,0.801223f},{-0.0404027f,0.653058f,0.756229f},{-0.113609f,0.70629f,0.698747f}, -{-0.149797f,0.759453f,0.633082f},{-0.0969605f,0.157836f,0.982693f},{0.30952f,0.343163f,0.886812f}, -{0.250895f,0.239551f,0.937905f},{0.364302f,0.214746f,0.906183f},{0.677437f,-0.618769f,-0.39775f}, -{0.403265f,0.340129f,0.849523f},{0.361741f,-0.604613f,-0.709638f},{0.520482f,-0.635742f,-0.570027f}, -{-0.220053f,-0.110282f,0.969234f},{0.664744f,0.0727426f,-0.743522f},{0.69493f,-0.197012f,-0.691562f}, -{0.711349f,0.0990558f,-0.695824f},{0.791779f,-0.192596f,-0.579648f},{0.83793f,0.467497f,-0.281638f}, -{0.803215f,0.569194f,-0.175682f},{0.265927f,-0.221511f,-0.938198f},{0.672927f,-0.206138f,-0.710405f}, -{0.543858f,0.126279f,-0.829622f},{0.543691f,-0.808459f,0.225377f},{0.576513f,-0.710938f,0.402741f}, -{-0.956165f,0.283562f,0.0730865f},{-0.822554f,0.542533f,0.170477f},{-0.703695f,0.6879f,0.177784f}, -{-0.602137f,0.489269f,-0.630909f},{-0.532431f,0.695438f,-0.48258f},{-0.390972f,0.546069f,-0.740911f}, -{-0.255914f,-0.161228f,0.95316f},{-0.384142f,-0.179441f,0.905669f},{0.243979f,0.262092f,0.933693f}, -{0.99634f,-0.0342846f,0.0783019f},{0.709472f,-0.120123f,-0.694421f},{-0.0644449f,0.0727868f,0.995263f}, -{0.775684f,0.125389f,-0.618541f},{-0.107575f,-0.100668f,0.989087f},{0.0138886f,0.527502f,0.84944f}, -{-0.772811f,0.296101f,-0.561326f},{-0.742911f,0.337742f,-0.577939f},{-0.795858f,0.46664f,-0.385819f}, -{0.475773f,0.8358f,-0.274004f},{0.0905323f,0.351765f,0.9317f},{0.141134f,0.3954f,0.907601f}, -{0.181249f,0.353132f,0.917849f},{0.0710616f,0.250557f,0.96549f},{0.0950218f,0.0252217f,0.995156f}, -{0.093489f,-0.137843f,0.986032f},{0.0487989f,-0.207587f,0.976999f},{-0.183824f,-0.148739f,0.97164f}, -{-0.0301569f,-0.227055f,0.973415f},{-0.292098f,-0.143991f,0.945487f},{-0.075602f,-0.179751f,0.980803f}, -{-0.0417652f,-0.0777302f,0.996099f},{0.00792155f,-0.0523368f,0.998598f},{0.0587392f,-0.104993f,0.992737f}, -{0.118203f,-0.133507f,0.983974f},{0.0643076f,-0.145089f,0.987327f},{-0.146965f,-0.0484049f,0.987957f}, -{-0.147134f,-0.0615316f,0.987201f},{-0.108244f,0.067494f,0.991831f},{-0.113617f,0.0485507f,0.992338f}, -{-0.238631f,0.0427924f,0.970167f},{-0.16731f,0.157442f,0.973252f},{-0.0554322f,0.247821f,0.967219f}, -{0.0215249f,0.307941f,0.951162f},{0.089122f,0.370946f,0.924368f},{0.173814f,0.436493f,0.882758f}, -{0.334641f,0.366563f,0.868129f},{0.201333f,0.420597f,0.884626f},{0.107478f,0.499501f,0.859621f}, -{0.0882418f,0.554137f,0.827735f},{0.077174f,0.58413f,0.807983f},{0.0904184f,0.624511f,0.775765f}, -{0.1935f,0.237683f,0.951874f},{0.305689f,0.296056f,0.904934f},{0.327435f,0.184844f,0.926617f}, -{0.269561f,-0.927616f,-0.258583f},{0.193659f,-0.895755f,-0.400149f},{0.394681f,0.163975f,0.904068f}, -{0.258788f,0.468532f,0.844693f},{-0.0718795f,0.684182f,0.72576f},{0.683177f,-0.701106f,-0.204252f}, -{-0.516514f,0.796576f,-0.314133f},{-0.720986f,-0.629455f,-0.289768f},{-0.779838f,-0.545293f,-0.307421f}, -{-0.89702f,-0.302861f,-0.321916f},{-0.483131f,0.87171f,0.081887f},{-0.489306f,0.870408f,-0.0544948f}, -{-0.717503f,0.692303f,0.0768497f},{0.957277f,-0.28916f,0.00262905f},{0.988026f,-0.0837556f,0.129575f}, -{0.24601f,0.323063f,0.913843f},{0.604944f,-0.0749556f,0.792732f},{-0.155861f,0.510953f,0.84536f}, -{0.149976f,0.587202f,0.795425f},{0.0187902f,-0.999677f,-0.0171062f},{0.025801f,-0.999018f,-0.036023f}, -{-0.00739064f,-0.99961f,-0.0269177f},{0.678978f,-0.0969692f,0.727727f},{0.269299f,0.415525f,0.868802f}, -{-0.549574f,0.640399f,-0.536524f},{-0.634002f,0.560561f,-0.532741f},{0.629036f,0.600896f,0.49319f}, -{0.7046f,0.544216f,0.455376f},{0.806775f,0.433922f,0.401032f},{-0.349169f,0.43309f,0.830972f}, -{-0.249238f,0.533495f,0.808247f},{0.223309f,0.158713f,0.96174f},{0.283775f,-0.0974038f,0.953931f}, -{0.297757f,-0.225284f,0.927679f},{0.293836f,-0.261361f,0.91943f},{0.182718f,-0.192612f,0.964113f}, -{0.147264f,-0.0935166f,0.984666f},{0.147869f,-0.0805794f,0.985719f},{0.122862f,-0.0441671f,0.991441f}, -{0.153585f,-0.0603901f,0.986288f},{0.248531f,-0.180208f,0.951713f},{0.192206f,-0.16612f,0.967192f}, -{0.160758f,-0.0170921f,0.986846f},{0.124724f,0.00386966f,0.992184f},{-0.152929f,-0.176901f,0.972275f}, -{-0.334302f,-0.0505609f,0.941109f},{-0.325042f,0.204004f,0.923434f},{-0.273952f,0.324963f,0.905179f}, -{-0.183982f,0.404077f,0.896031f},{-0.12399f,0.480282f,0.868306f},{-0.132311f,0.480545f,0.866931f}, -{-0.0539982f,0.44909f,0.891853f},{0.0186793f,0.528253f,0.848882f},{0.0540516f,0.603218f,0.795742f}, -{0.0574721f,0.58057f,0.812179f},{0.0488323f,0.540287f,0.840063f},{0.107447f,0.574946f,0.811106f}, -{0.836185f,-0.500978f,-0.223194f},{0.706114f,-0.222507f,-0.672231f},{0.73513f,-0.156479f,-0.659619f}, -{0.994869f,-0.0398721f,0.0929814f},{0.990704f,-0.0215186f,0.134325f},{0.601227f,0.0332051f,0.798388f}, -{-0.612229f,0.501538f,-0.611258f},{-0.604453f,0.336919f,-0.721888f},{-0.644079f,0.465962f,-0.606664f}, -{0.389418f,-0.206132f,0.897699f},{-0.210594f,-0.0239807f,0.977279f},{0.823588f,0.444795f,-0.351937f}, -{0.523614f,-0.851564f,-0.0258188f},{0.333779f,-0.101378f,0.937184f},{-0.239351f,0.170456f,0.955853f}, -{-0.191253f,0.418555f,0.887826f},{0.993128f,0.0770358f,-0.0881045f},{0.995817f,0.0332385f,-0.0851114f}, -{0.266118f,-0.0563829f,0.96229f},{-0.0899401f,0.57571f,0.812692f},{0.941752f,-0.336122f,0.0111489f}, -{0.956098f,-0.268499f,0.117412f},{0.972634f,0.227543f,0.0469783f},{0.0213099f,0.745877f,0.665743f}, -{-0.855257f,-0.0444835f,-0.516291f},{-0.204136f,0.966554f,0.155248f},{-0.942272f,0.216219f,0.25568f}, -{-0.980849f,0.182453f,0.0681602f},{-0.936853f,0.329239f,0.117934f},{-0.944458f,0.300396f,0.133269f}, -{0.405896f,0.789675f,0.460067f},{-0.883435f,0.0948705f,-0.458849f},{-0.229111f,-0.238176f,0.943812f}, -{-0.527854f,-0.219852f,0.820387f},{-0.493896f,-0.293839f,0.818368f},{-0.00712655f,-0.57856f,-0.815609f}, -{-0.147518f,0.530632f,0.834666f},{0.0992787f,0.378513f,0.920256f},{0.343353f,-0.0633624f,0.937067f}, -{0.371543f,-0.190139f,0.908737f},{0.393868f,-0.207759f,0.895379f},{0.457386f,-0.212961f,0.863392f}, -{0.399808f,-0.170027f,0.900691f},{0.310284f,-0.131588f,0.941493f},{0.326734f,-0.070236f,0.942503f}, -{0.21877f,-0.0742296f,0.972949f},{0.146588f,-0.114926f,0.982499f},{0.141094f,-0.138347f,0.980282f}, -{0.23755f,-0.115062f,0.964537f},{-0.0402561f,-0.269229f,0.962234f},{-0.0749331f,-0.492771f,0.866927f}, -{-0.0734197f,-0.180458f,0.980839f},{-0.00426604f,-0.0404009f,0.999174f},{-0.139124f,0.0871926f,0.986429f}, -{-0.215771f,0.244843f,0.945249f},{-0.234529f,0.347527f,0.907866f},{-0.224147f,0.450837f,0.864005f}, -{-0.2128f,0.484206f,0.848682f},{-0.219569f,0.479628f,0.849557f},{-0.187117f,0.496056f,0.847889f}, -{-0.188186f,0.459699f,0.867907f},{-0.112351f,0.57933f,0.807313f},{-0.106516f,0.620372f,0.777041f}, -{-0.0679673f,0.612159f,0.787808f},{-0.0326748f,0.580432f,0.813653f},{0.708862f,-0.680962f,-0.183865f}, -{0.847722f,-0.484375f,-0.216214f},{0.712572f,-0.688967f,-0.132536f},{0.645906f,-0.7559f,-0.10687f}, -{0.856818f,-0.487012f,-0.169355f},{0.26561f,0.427572f,0.86408f},{0.141693f,-0.00470907f,0.989899f}, -{0.142388f,-0.0233211f,0.989536f},{0.685045f,-0.0214021f,0.728186f},{-0.0585203f,0.657791f,0.750924f}, -{0.318829f,0.468303f,0.824039f},{-0.90048f,0.294898f,-0.319642f},{0.420585f,-0.898045f,-0.12893f}, -{0.0573068f,-0.998341f,0.0055865f},{0.367788f,-0.911475f,-0.184246f},{0.372103f,-0.184797f,0.909609f}, -{0.397361f,-0.124209f,0.909217f},{0.370408f,-0.452713f,0.811078f},{0.339769f,-0.0340991f,0.939891f}, -{0.375499f,0.00669293f,0.926799f},{0.331121f,0.0276573f,0.943183f},{0.189051f,0.235624f,0.953279f}, -{0.234955f,-0.852191f,-0.467511f},{0.207225f,0.610604f,0.764343f},{0.0281201f,0.611182f,0.79099f}, -{0.592523f,0.330052f,-0.734834f},{0.299147f,-0.110764f,0.947757f},{0.289337f,-0.160901f,0.943607f}, -{-0.184455f,0.301245f,0.935536f},{-0.114346f,0.596484f,0.794438f},{0.892855f,0.450094f,-0.0149891f}, -{0.914416f,0.403767f,0.0285614f},{0.995914f,0.0792773f,0.0432455f},{0.995102f,0.0918383f,0.0365886f}, -{0.0882295f,0.392913f,0.915333f},{0.01841f,0.690734f,0.722874f},{-0.998624f,0.0360211f,-0.0381155f}, -{-0.484736f,-0.873671f,0.0415806f},{-0.28694f,-0.957947f,-0.00188694f},{-0.116894f,-0.567173f,-0.815261f}, -{-0.125439f,-0.579902f,-0.804971f},{-0.241306f,-0.463478f,-0.852619f},{-0.0328103f,-0.946855f,-0.319981f}, -{0.139347f,-0.115985f,0.983428f},{0.116236f,0.0964643f,0.988526f},{0.254626f,-0.170183f,0.951947f}, -{0.391114f,-0.158803f,0.906538f},{0.396983f,-0.203492f,0.894984f},{0.234799f,-0.252738f,0.938612f}, -{0.165006f,-0.21172f,0.9633f},{0.0594331f,-0.20056f,0.977877f},{-0.0990798f,-0.253082f,0.962358f}, -{-0.226912f,-0.176631f,0.957764f},{-0.600585f,-0.199035f,0.774392f},{-0.44706f,-0.174961f,0.877226f}, -{-0.582458f,-0.189821f,0.790386f},{-0.258913f,0.0474452f,0.964735f},{-0.175723f,-0.096949f,0.979654f}, -{-0.0275966f,-0.125996f,0.991647f},{-0.0882985f,0.00297313f,0.99609f},{0.00613423f,0.264642f,0.964327f}, -{-0.0170057f,0.424457f,0.905289f},{-0.110029f,0.389298f,0.914516f},{-0.173889f,0.480406f,0.859635f}, -{-0.174587f,0.499081f,0.848786f},{-0.169377f,0.539228f,0.824951f},{-0.13077f,0.599198f,0.789849f}, -{-0.104141f,0.592033f,0.799156f},{-0.100737f,0.612211f,0.784251f},{0.46098f,-0.118947f,0.879403f}, -{0.507723f,-0.148427f,0.848638f},{0.460838f,-0.157004f,0.873486f},{0.0273984f,0.521382f,0.852883f}, -{-0.0558594f,0.574362f,0.816694f},{-0.230996f,-0.451956f,-0.861612f},{-0.603773f,-0.456419f,-0.653559f}, -{0.0498736f,0.479708f,0.87601f},{0.592333f,0.0544071f,0.803854f},{0.982772f,0.101441f,0.154494f}, -{0.979766f,0.0918827f,0.177808f},{0.690902f,-0.676617f,-0.254645f},{0.680962f,-0.684141f,-0.261232f}, -{0.514943f,-0.723689f,-0.459465f},{0.279941f,0.804335f,-0.524097f},{0.470227f,0.806527f,-0.35833f}, -{0.602172f,0.587103f,-0.541017f},{0.219912f,-0.190058f,0.956827f},{-0.707877f,-0.246572f,0.6619f}, -{0.223647f,-0.190582f,0.955856f},{0.66088f,-0.466033f,0.58826f},{0.78418f,-0.57566f,0.231685f}, -{-0.0963573f,0.66013f,0.744945f},{0.529264f,0.395781f,0.750491f},{-0.0938949f,0.51176f,0.853982f}, -{0.0167492f,0.0845491f,0.996279f},{-0.29642f,0.739859f,0.60394f},{0.770559f,-0.27077f,0.576994f}, -{0.395407f,0.551992f,-0.734138f},{0.426667f,0.671553f,-0.605781f},{-0.678447f,-0.734224f,-0.0250153f}, -{-0.670977f,-0.740986f,-0.0270176f},{0.719373f,0.597154f,0.354838f},{-0.0260727f,-0.794933f,-0.606137f}, -{-0.488692f,-0.0546212f,-0.870745f},{-0.85862f,-0.0460396f,0.510541f},{-0.833654f,-0.028232f,0.551565f}, -{-0.711846f,-0.0760288f,0.698209f},{-0.794342f,0.00412712f,0.607457f},{0.916589f,-0.296311f,-0.268448f}, -{-0.756481f,-0.335536f,0.561384f},{-0.448513f,0.655173f,0.607935f},{-0.491382f,0.649039f,0.580769f}, -{-0.359336f,0.545212f,0.757378f},{-0.454763f,0.408567f,0.791368f},{-0.360103f,0.534543f,0.764585f}, -{-0.419343f,0.270591f,0.866563f},{-0.308274f,-0.158676f,0.937971f},{-0.537672f,-0.0421306f,0.842101f}, -{-0.173191f,-0.228231f,0.958079f},{-0.435517f,-0.276149f,0.856777f},{-0.530407f,-0.286438f,0.797886f}, -{-0.554514f,-0.329894f,0.763992f},{0.785711f,0.574001f,0.230609f},{0.741859f,0.498856f,0.448093f}, -{0.303562f,0.946105f,-0.112852f},{0.307248f,0.93655f,-0.168738f},{0.395085f,-0.646918f,0.652231f}, -{0.259732f,-0.848029f,-0.461938f},{0.238077f,0.968948f,0.0667771f},{0.222715f,0.964406f,0.142547f}, -{0.332458f,0.941366f,0.0574574f},{0.331289f,0.943105f,-0.0283073f},{-0.673966f,0.432063f,0.599243f}, -{-0.361289f,0.120792f,0.924597f},{0.081858f,0.397394f,0.91399f},{-0.0442536f,0.141609f,0.988933f}, -{-0.224349f,0.314769f,0.922273f},{-0.186689f,0.451686f,0.872426f},{-0.208966f,0.483781f,0.849876f}, -{-0.23828f,0.528725f,0.814661f},{-0.226058f,0.597649f,0.769229f},{-0.20108f,0.616536f,0.761216f}, -{-0.186587f,0.626264f,0.756954f},{-0.485704f,0.733153f,-0.476002f},{-0.584897f,0.708289f,-0.395249f}, -{0.91989f,0.0667137f,-0.386461f},{0.955529f,0.0549196f,-0.289737f},{0.911446f,-0.138902f,-0.387263f}, -{0.167664f,-0.966341f,-0.195126f},{0.479603f,-0.758439f,-0.441306f},{0.196735f,0.71953f,0.666013f}, -{0.178837f,0.211949f,0.960778f},{-0.365789f,0.882121f,0.29675f},{0.108296f,-0.661035f,-0.742499f}, -{0.231028f,-0.767635f,-0.597799f},{0.528096f,-0.802825f,-0.276744f},{0.812965f,-0.521272f,-0.259545f}, -{-0.707441f,-0.161392f,0.688099f},{-0.818057f,-0.262473f,0.511752f},{-0.83981f,-0.276777f,0.467027f}, -{-0.78566f,-0.272051f,0.555632f},{0.232743f,0.972491f,0.00962511f},{0.319045f,0.947739f,-0.000587843f}, -{0.355517f,0.91667f,-0.182547f},{0.0257376f,0.844356f,0.535164f},{-0.344861f,0.925942f,0.153956f}, -{-0.322892f,0.577177f,0.750071f},{0.979764f,0.15852f,-0.122203f},{-0.157063f,0.691591f,-0.705006f}, -{-0.217615f,0.649092f,-0.728919f},{-0.115872f,0.61574f,-0.779383f},{-0.156937f,-0.472687f,0.867143f}, -{0.375524f,0.469339f,0.799189f},{0.963422f,-0.262459f,-0.0541521f},{0.543008f,-0.133496f,0.829048f}, -{-0.0294388f,0.115412f,0.992881f},{-0.315051f,0.544746f,0.777171f},{-0.201034f,0.829596f,0.520919f}, -{-0.347545f,0.838266f,0.420146f},{-0.744658f,-0.0792734f,0.662722f},{0.539302f,-0.77313f,0.333802f}, -{0.503749f,-0.7688f,0.393933f},{-0.809059f,-0.0753806f,0.582874f},{-0.776578f,-0.217583f,0.591257f}, -{0.192285f,0.832061f,0.520289f},{0.0294664f,0.792039f,0.60976f},{0.0936467f,0.940049f,0.32793f}, -{0.0481948f,0.903587f,0.425685f},{0.62816f,0.554507f,0.545836f},{0.946447f,-0.0202053f,0.322227f}, -{0.123842f,0.398537f,0.908753f},{0.0566087f,-0.712531f,-0.699353f},{0.00541469f,-0.696924f,-0.717125f}, -{-0.827308f,0.442382f,-0.346208f},{0.945003f,0.288744f,-0.153608f},{-0.164464f,0.501697f,-0.849265f}, -{-0.212151f,0.449517f,-0.867713f},{-0.217853f,0.603f,-0.767418f},{0.777729f,-0.537961f,-0.32517f}, -{-0.350058f,0.556344f,0.753619f},{-0.438878f,0.486298f,0.75558f},{-0.340488f,0.390308f,0.855411f}, -{-0.249393f,0.667711f,0.701402f},{-0.169594f,0.899467f,0.402737f},{-0.40296f,0.798587f,0.447082f}, -{-0.260137f,0.904443f,0.3381f},{0.297284f,0.951307f,0.0814693f},{0.747864f,0.242122f,-0.618124f}, -{0.693854f,0.21889f,-0.686042f},{0.706679f,0.147446f,-0.692f},{0.0362161f,0.811871f,0.582713f}, -{-0.402915f,0.903071f,0.148733f},{-0.611856f,0.758072f,-0.225742f},{-0.60932f,0.783829f,-0.119753f}, -{0.566185f,0.76417f,0.308997f},{-0.331398f,0.274975f,0.902532f},{-0.286723f,-0.182686f,0.940434f}, -{-0.34717f,0.076168f,0.934704f},{-0.172591f,0.212991f,0.96169f},{-0.1893f,0.383452f,0.903953f}, -{-0.231082f,0.432922f,0.871309f},{-0.25959f,0.479614f,0.838202f},{-0.318628f,0.575777f,0.752966f}, -{-0.322619f,0.603173f,0.729451f},{-0.358251f,0.602617f,0.713098f},{-0.390833f,0.610403f,0.688954f}, -{0.388946f,-0.442439f,0.808065f},{0.477906f,0.397443f,0.783355f},{0.661378f,0.162789f,0.732174f}, -{-0.0720481f,0.806311f,0.587088f},{-0.565128f,0.822945f,0.0582318f},{-0.390616f,0.822168f,0.414076f}, -{-0.573525f,0.52527f,0.628618f},{-0.82288f,-0.00567614f,0.568186f},{-0.714775f,0.20468f,0.668733f}, -{0.19947f,0.979005f,0.0419626f},{0.340742f,0.93565f,0.0919395f},{-0.777639f,-0.623126f,-0.0836173f}, -{-0.828711f,-0.559582f,0.0103613f},{-0.771514f,-0.606945f,-0.190748f},{-0.685167f,-0.680435f,-0.259914f}, -{-0.953719f,0.300617f,0.00699773f},{-0.873393f,0.41651f,-0.252396f},{-0.829566f,0.377382f,-0.411587f}, -{0.500125f,0.797272f,0.337983f},{-0.502071f,0.526381f,0.686184f},{-0.419821f,0.617315f,0.665336f}, -{-0.961307f,0.160805f,-0.223676f},{0.989366f,0.0418744f,-0.139286f},{0.958475f,0.210319f,-0.192591f}, -{0.00907638f,0.395259f,0.918525f},{-0.121054f,0.339914f,0.932633f},{-0.0711068f,0.590537f,0.803872f}, -{-0.0363095f,0.710202f,0.703061f},{0.0153851f,0.853133f,0.521466f},{-0.112796f,0.818173f,0.5638f}, -{-0.16988f,0.971006f,-0.168189f},{-0.0077306f,0.996263f,-0.0860288f},{0.243035f,0.943361f,0.22584f}, -{-0.0621356f,0.340509f,0.938186f},{-0.0491563f,0.366334f,0.929184f},{-0.176118f,0.454378f,0.873226f}, -{-0.189273f,0.46869f,0.862847f},{-0.259481f,0.511469f,0.819188f},{-0.449379f,0.578745f,0.680524f}, -{0.0913338f,0.894366f,0.437912f},{0.42565f,-0.422144f,0.800385f},{0.59795f,-0.23884f,0.765122f}, -{0.45527f,-0.177488f,0.872483f},{0.386973f,-0.921255f,-0.0392579f},{0.250819f,-0.869655f,-0.425193f}, -{0.306345f,-0.905818f,-0.292655f},{-0.99852f,-0.0334156f,-0.0429045f},{-0.964216f,0.258421f,0.0592056f}, -{-0.987625f,0.154451f,-0.027243f},{-0.997861f,0.0519454f,-0.0396961f},{-0.83911f,0.481331f,0.253406f}, -{-0.926526f,-0.254974f,-0.276656f},{-0.692555f,0.643989f,0.325032f},{0.99397f,-0.107486f,0.0217039f}, -{-0.218578f,0.93918f,0.264886f},{-0.304393f,0.911539f,0.276481f},{-0.277804f,0.90877f,0.311387f}, -{-0.30602f,0.562103f,0.768369f},{-0.325307f,0.591888f,0.737457f},{-0.367669f,0.600766f,0.709859f}, -{-0.426539f,0.593136f,0.682828f},{-0.357713f,0.671509f,0.648935f},{-0.343895f,0.711826f,0.612406f}, -{0.540354f,0.319822f,0.778288f},{0.319022f,0.317524f,0.892974f},{0.0164285f,-0.758999f,-0.650885f}, -{0.810879f,0.41449f,-0.413125f},{0.402384f,-0.808354f,-0.429711f},{-0.692319f,0.269885f,0.66922f}, -{-0.802128f,-0.0286058f,0.596466f},{0.0118075f,0.999179f,-0.0387475f},{0.039404f,0.998234f,-0.0444579f}, -{-0.255023f,0.966562f,-0.0268538f},{0.181189f,0.943149f,0.278642f},{0.135556f,0.913165f,0.384388f}, -{0.407739f,0.656533f,0.634597f},{0.297586f,0.648132f,0.700976f},{0.384275f,0.922206f,-0.0432202f}, -{-0.0859526f,-0.656785f,-0.749163f},{0.599155f,-0.0773312f,-0.79689f},{0.324199f,0.527672f,0.785148f}, -{-0.932281f,-0.0620485f,-0.356374f},{-0.977376f,0.113279f,-0.178615f},{-0.93158f,0.134419f,-0.337773f}, -{0.140383f,-0.767237f,-0.625812f},{0.213569f,-0.832839f,-0.510654f},{0.532393f,-0.808362f,-0.251216f}, -{0.246787f,0.464288f,0.850607f},{0.193003f,0.739826f,0.644521f},{0.104031f,0.856008f,0.506387f}, -{-0.184839f,0.440609f,0.878464f},{-0.619346f,0.0773028f,0.781304f},{-0.779055f,-0.108587f,0.61748f}, -{-0.72702f,-0.208468f,0.654204f},{-0.693424f,-0.173667f,0.699288f},{-0.0203507f,0.99796f,-0.060504f}, -{-0.116628f,0.989023f,0.0907244f},{-0.138448f,0.974696f,0.175497f},{-0.118911f,0.974713f,0.189194f}, -{0.782602f,0.568475f,0.253714f},{-0.660721f,-0.733755f,-0.158278f},{0.956928f,0.238728f,0.165221f}, -{0.549901f,0.697434f,0.45956f},{0.499327f,0.758075f,0.419517f},{0.607054f,0.674272f,0.420528f}, -{0.512313f,-0.831211f,-0.215926f},{0.697816f,-0.69249f,-0.183061f},{0.0784108f,0.317364f,0.945057f}, -{-0.013652f,0.281661f,0.959417f},{-0.103051f,0.383828f,0.917636f},{-0.184355f,0.471683f,0.862281f}, -{-0.197612f,0.535434f,0.821133f},{-0.240097f,0.582367f,0.776661f},{-0.260232f,0.584369f,0.76863f}, -{-0.342142f,0.66669f,0.662165f},{-0.919643f,0.348874f,-0.180397f},{-0.951161f,0.258725f,-0.168385f}, -{0.196828f,-0.0334996f,0.979865f},{0.93696f,-0.10587f,-0.333013f},{0.898716f,0.0143765f,-0.438296f}, -{0.934906f,-0.162736f,-0.315386f},{-0.0443143f,-0.514988f,-0.856051f},{-0.576905f,-0.302724f,0.758643f}, -{0.999693f,-0.0144882f,0.020096f},{-0.902492f,-0.418109f,-0.103404f},{-0.91035f,-0.370171f,-0.185029f}, -{-0.972665f,0.169551f,-0.158669f},{-0.537973f,0.299744f,0.787869f},{-0.317389f,0.276084f,0.907217f}, -{-0.43221f,0.364523f,0.824814f},{0.530498f,0.182756f,-0.827751f},{0.497767f,0.331848f,-0.801315f}, -{0.59232f,0.276457f,-0.756789f},{0.903917f,-0.0343129f,-0.426329f},{-0.129496f,-0.412196f,-0.901845f}, -{-0.997442f,-0.0199234f,-0.0686405f},{-0.116131f,0.99273f,0.0316319f},{-0.148505f,0.984841f,0.0896363f}, -{-0.107525f,0.991118f,0.0782455f},{0.872192f,0.459426f,0.167954f},{-0.302342f,0.32664f,0.895486f}, -{-0.394453f,0.402819f,0.82592f},{0.988901f,-0.142468f,0.042162f},{-0.28951f,0.597491f,0.747789f}, -{0.886142f,-0.0227338f,-0.462855f},{0.372933f,-0.92439f,-0.080149f},{0.324752f,0.473531f,0.818721f}, -{0.0181762f,0.577834f,0.815952f},{-0.446479f,-0.0219026f,0.894526f},{-0.41044f,-0.340059f,0.846108f}, -{-0.497253f,-0.366512f,0.786389f},{-0.188972f,0.87435f,-0.446992f},{-0.27229f,-0.212348f,0.938492f}, -{-0.260154f,-0.26183f,0.92939f},{-0.424896f,-0.295882f,0.855522f},{-0.201163f,-0.282722f,0.937871f}, -{-0.349685f,-0.362444f,0.863918f},{-0.258599f,-0.400252f,0.879162f},{-0.0663588f,-0.124558f,0.989991f}, -{-0.277381f,-0.292648f,0.915105f},{-0.0129428f,0.051201f,0.998604f},{-0.21943f,0.0640172f,0.973526f}, -{-0.0834486f,0.148989f,0.985311f},{-0.176729f,0.302573f,0.936598f},{-0.303486f,0.374783f,0.876033f}, -{-0.22937f,0.520291f,0.822609f},{-0.399844f,0.536487f,0.743173f},{-0.190027f,0.270728f,0.943714f}, -{-0.0885366f,0.238847f,0.967013f},{-0.208084f,0.301494f,0.930485f},{-0.218262f,0.436112f,0.873022f}, -{-0.209885f,0.518052f,0.829199f},{-0.251104f,0.521023f,0.815771f},{-0.27394f,0.616177f,0.738432f}, -{-0.267678f,0.649952f,0.711275f},{-0.271756f,0.870571f,0.410189f},{-0.248053f,0.886882f,0.389757f}, -{-0.341894f,0.876298f,0.339426f},{0.913529f,-0.0778003f,-0.399265f},{-0.220965f,0.27626f,-0.935337f}, -{0.324672f,0.945114f,-0.0366963f},{-0.549577f,0.390051f,0.7388f},{-0.0404058f,0.453485f,0.890348f}, -{-0.265051f,0.34101f,0.90192f},{0.671957f,0.182503f,-0.717751f},{0.625907f,0.322451f,-0.710116f}, -{0.561647f,-0.442315f,0.699221f},{0.329729f,0.556732f,0.762449f},{0.915737f,0.214104f,-0.339978f}, -{-0.366646f,-0.323675f,0.872241f},{-0.474031f,-0.323003f,0.819124f},{-0.462516f,-0.19931f,0.863918f}, -{-0.60706f,-0.19681f,0.769899f},{-0.413657f,-0.149255f,0.898115f},{-0.551041f,-0.226188f,0.803239f}, -{-0.256732f,-0.2343f,0.937653f},{-0.432891f,0.81967f,0.375162f},{-0.82982f,0.47565f,0.291813f}, -{0.935737f,-0.0667342f,-0.346327f},{0.410462f,-0.898124f,-0.157782f},{0.381093f,0.353227f,0.854399f}, -{0.314514f,0.455215f,0.832983f},{-0.107452f,-0.0516191f,0.992869f},{-0.436083f,-0.386618f,0.812624f}, -{-0.326328f,-0.290193f,0.89961f},{-0.358768f,-0.351906f,0.86455f},{-0.491272f,-0.274142f,0.826739f}, -{-0.249382f,-0.0817001f,0.964953f},{-0.333758f,-0.24729f,0.909644f},{-0.364851f,-0.0687879f,0.928522f}, -{-0.168992f,-0.211946f,0.962559f},{-0.199238f,-0.291946f,0.935453f},{-0.2244f,-0.252274f,0.941277f}, -{-0.152452f,-0.164372f,0.974546f},{-0.112379f,-0.0502458f,0.992394f},{-0.0843327f,0.0708477f,0.993916f}, -{-0.0420862f,0.0883098f,0.995204f},{-0.116689f,0.21632f,0.969324f},{-0.217116f,0.527381f,0.821419f}, -{-0.175943f,0.699574f,0.692561f},{-0.29065f,0.677972f,0.675186f},{-0.207183f,0.94949f,-0.235676f}, -{0.576123f,-0.814343f,-0.0701916f},{-0.330163f,0.771793f,0.543441f},{-0.39642f,0.831665f,0.388823f}, -{-0.396915f,0.639425f,0.658478f},{-0.183854f,0.352624f,0.917526f},{-0.170048f,0.255627f,0.951703f}, -{-0.0999526f,0.132185f,0.986173f},{-0.204507f,0.401786f,0.892605f},{-0.225599f,0.496702f,0.838089f}, -{-0.23613f,0.499564f,0.833474f},{-0.272788f,0.477579f,0.835168f},{-0.255052f,0.575954f,0.776676f}, -{-0.288071f,0.716377f,0.635468f},{0.939666f,0.00962893f,-0.341958f},{0.811251f,-0.550205f,-0.197856f}, -{0.84832f,-0.501184f,-0.170784f},{0.906024f,-0.41817f,-0.0652293f},{0.806224f,0.109341f,0.581419f}, -{0.807168f,0.301015f,0.507808f},{0.391369f,0.919183f,-0.0439765f},{0.259863f,0.0750233f,0.962727f}, -{0.332689f,0.161066f,0.92918f},{0.378018f,0.180702f,0.907992f},{-0.325281f,-0.413715f,0.850313f}, -{0.227168f,-0.359984f,-0.904879f},{0.43349f,-0.686914f,-0.583297f},{0.741767f,0.00615409f,0.670629f}, -{0.519002f,0.52435f,0.67505f},{-0.97891f,0.0906991f,-0.183055f},{0.394563f,0.9161f,0.0712859f}, -{0.389378f,0.920614f,0.0292228f},{0.319017f,0.528083f,0.786992f},{-0.307802f,-0.340839f,0.888306f}, -{-0.126457f,0.361748f,0.92366f},{-0.16985f,0.756014f,0.632134f},{-0.185053f,0.754408f,0.629781f}, -{0.0966245f,-0.689971f,-0.717359f},{0.492416f,-0.869194f,-0.0450272f},{0.996683f,0.0751418f,-0.0312672f}, -{-0.234427f,0.685005f,0.689792f},{0.867339f,0.0838635f,-0.490602f},{0.925486f,0.164947f,-0.34098f}, -{-0.204274f,0.789897f,0.578217f},{0.337036f,-0.144287f,0.93037f},{0.872065f,-0.43883f,-0.216636f}, -{0.723614f,-0.646477f,-0.241765f},{0.303861f,0.202101f,0.931033f},{0.236392f,0.303918f,0.922904f}, -{-0.03706f,-0.379717f,0.92436f},{-0.24061f,-0.442195f,0.864043f},{-0.320437f,-0.327133f,0.88899f}, -{-0.315056f,-0.394821f,0.86305f},{-0.394311f,-0.306347f,0.866412f},{-0.291312f,-0.0705552f,0.954023f}, -{-0.304152f,-0.0144173f,0.952514f},{-0.286319f,-0.243813f,0.926594f},{-0.315406f,-0.311765f,0.896282f}, -{-0.305999f,-0.289459f,0.906961f},{-0.243082f,-0.160769f,0.95659f},{-0.139866f,-0.103768f,0.984718f}, -{-0.0984367f,0.00461992f,0.995133f},{0.000226813f,0.128423f,0.991719f},{-0.0322293f,0.139832f,0.989651f}, -{-0.0463018f,0.159905f,0.986046f},{-0.0349219f,0.332265f,0.942539f},{-0.0872712f,0.549626f,0.83084f}, -{-0.143092f,0.695318f,0.704314f},{0.844038f,0.41268f,0.342484f},{-0.0784911f,0.135579f,0.987653f}, -{-0.151022f,0.495322f,0.855482f},{0.864087f,-0.487038f,-0.127076f},{-0.118199f,0.191062f,0.974435f}, -{-0.128221f,0.381595f,0.915393f},{-0.16414f,0.47926f,0.862188f},{-0.180967f,0.512564f,0.839363f}, -{-0.147203f,0.567275f,0.810266f},{-0.151267f,0.653834f,0.741363f},{-0.188561f,0.726022f,0.661315f}, -{0.824964f,-0.480821f,-0.297061f},{0.905172f,0.260718f,-0.335692f},{-0.751042f,0.593217f,0.289876f}, -{-0.32475f,-0.35033f,-0.878525f},{-0.481899f,-0.260127f,-0.836724f},{-0.624517f,-0.221113f,-0.749058f}, -{-0.103103f,0.445253f,0.889449f},{-0.309203f,-0.277461f,-0.90962f},{-0.294538f,-0.402181f,-0.86689f}, -{0.864967f,0.288401f,-0.410679f},{0.897178f,0.275958f,-0.344845f},{0.767788f,-0.232109f,0.597183f}, -{0.760242f,-0.495563f,0.420059f},{0.808193f,-0.49461f,0.319663f},{0.733594f,0.286807f,-0.616102f}, -{0.640647f,0.238282f,-0.729927f},{-0.281333f,-0.352565f,0.892496f},{-0.232012f,0.873399f,0.428187f}, -{-0.248022f,0.814072f,0.52514f},{0.837728f,-0.0939249f,-0.53795f},{0.870655f,-0.279119f,-0.405033f}, -{-0.881121f,-0.0520004f,-0.470024f},{-0.0155312f,-0.466044f,0.884625f},{-0.129013f,-0.669994f,0.73107f}, -{-0.197947f,-0.475871f,0.85695f},{-0.244171f,-0.34963f,0.90451f},{-0.140039f,-0.330352f,0.933411f}, -{-0.057988f,-0.337569f,0.939513f},{-0.122666f,-0.113582f,0.985927f},{-0.205128f,-0.00877181f,0.978696f}, -{-0.337272f,-0.0746786f,0.938441f},{-0.306237f,-0.258884f,0.916078f},{-0.278592f,-0.259471f,0.924695f}, -{-0.261924f,-0.250819f,0.931926f},{-0.209337f,-0.0287817f,0.97742f},{-0.0601506f,0.0672967f,0.995918f}, -{0.0611062f,0.0532419f,0.99671f},{0.0713627f,0.103608f,0.992055f},{-0.0695355f,0.803765f,0.59087f}, -{-0.644098f,0.273464f,-0.714392f},{0.0732606f,0.601907f,0.795199f},{-0.2022f,0.892853f,0.402403f}, -{-0.116181f,0.690582f,0.713862f},{0.839387f,0.072094f,-0.538733f},{0.906994f,0.157665f,-0.390518f}, -{0.880792f,0.258935f,-0.396433f},{0.849277f,0.279145f,-0.448115f},{0.88698f,-0.0393897f,-0.460125f}, -{-0.256429f,-0.366661f,0.894318f},{0.384314f,-0.129266f,0.914108f},{-0.91019f,-0.38715f,-0.147201f}, -{-0.873766f,-0.460888f,-0.15529f},{0.0533412f,-0.987276f,0.1498f},{-0.0332455f,-0.999425f,-0.00667568f}, -{-0.0177683f,-0.998598f,-0.0498695f},{0.743946f,-0.315207f,-0.589228f},{-0.0300893f,0.428489f,0.903046f}, -{-0.141131f,-0.616613f,0.774513f},{-0.143887f,-0.543126f,0.827231f},{0.151877f,-0.0435705f,0.987439f}, -{0.135903f,0.0967646f,0.985985f},{0.181863f,-0.0316108f,0.982816f},{0.817395f,0.471839f,-0.330504f}, -{0.834915f,0.44021f,-0.330353f},{-0.439625f,0.363522f,-0.821329f},{-0.23135f,-0.491517f,-0.839576f}, -{0.881996f,0.263243f,0.390879f},{0.804092f,0.450491f,-0.387936f},{0.379275f,-0.920389f,-0.0950521f}, -{0.657543f,-0.0898175f,0.748044f},{0.60158f,0.0546622f,0.79694f},{0.424673f,-0.380215f,0.821638f}, -{0.480442f,-0.295344f,0.825801f},{0.296132f,0.463751f,0.835009f},{0.271331f,0.0872357f,0.958525f}, -{0.272219f,-0.172097f,0.94672f},{0.653222f,-0.218414f,0.72498f},{0.637907f,-0.0586593f,0.767876f}, -{0.432417f,-0.0287288f,0.901216f},{0.375382f,0.133798f,0.917162f},{0.668195f,0.332693f,0.665456f}, -{0.751623f,0.310123f,0.58214f},{0.70471f,0.352257f,0.615873f},{0.354198f,-0.110598f,0.928607f}, -{0.316442f,-0.111138f,0.942079f},{0.500513f,0.429239f,0.751825f},{0.485563f,0.505267f,0.713396f}, -{0.467589f,0.389971f,0.793274f},{0.269565f,0.432078f,0.860606f},{0.526376f,-0.206247f,0.824858f}, -{0.547881f,-0.180711f,0.816804f},{0.516456f,-0.177985f,0.837613f},{0.265807f,0.621366f,0.737056f}, -{0.396606f,0.461164f,0.793745f},{0.268517f,0.679316f,0.682956f},{0.608431f,-0.475134f,0.635657f}, -{0.581453f,0.335069f,0.741378f},{0.565053f,-0.011672f,0.824972f},{0.542132f,-0.254652f,0.800778f}, -{0.480758f,-0.379163f,0.790637f},{0.456013f,-0.393873f,0.79807f},{0.879688f,-0.114436f,0.461577f}, -{0.858958f,-0.0758828f,0.506393f},{0.85334f,-0.175889f,0.49079f},{0.864541f,0.245988f,0.438246f}, -{0.459771f,0.488017f,0.741923f},{0.648193f,0.136459f,0.749149f},{0.745059f,-0.146613f,0.650686f}, -{0.320391f,0.613417f,0.721851f},{0.381497f,0.502289f,0.775993f},{0.276193f,0.651878f,0.706238f}, -{0.787947f,-0.266373f,0.555144f},{0.738517f,-0.18476f,0.648426f},{-0.10106f,-0.198674f,-0.974841f}, -{-0.213871f,-0.405287f,-0.88882f},{0.120389f,-0.573452f,-0.810345f},{0.549648f,0.115702f,0.827345f}, -{0.656562f,-0.0125393f,0.754168f},{0.523616f,0.221222f,0.822732f},{0.5305f,-0.207482f,0.821901f}, -{0.503594f,-0.178747f,0.845247f},{0.464655f,-0.297417f,0.834049f},{0.436071f,-0.269518f,0.858605f}, -{0.552355f,-0.130993f,0.823253f},{0.71381f,-0.196261f,0.672277f},{0.255606f,0.690306f,0.676863f}, -{0.210124f,0.77675f,0.593723f},{0.853942f,-0.0356107f,0.519148f},{0.456866f,-0.524287f,0.718607f}, -{0.497688f,-0.585216f,0.640179f},{-0.239292f,-0.426292f,-0.872361f},{-0.133658f,-0.421392f,-0.896975f}, -{-0.0754212f,-0.532674f,-0.842953f},{0.6607f,-0.607619f,0.440766f},{0.628709f,-0.577003f,0.521336f}, -{0.641454f,-0.668221f,0.376852f},{0.666737f,-0.498983f,0.553603f},{0.800721f,0.0591873f,0.596106f}, -{0.748422f,0.000704595f,0.663222f},{0.790442f,-0.196599f,0.58013f},{0.7523f,-0.31572f,0.578244f}, -{0.770543f,-0.115037f,0.626921f},{0.657429f,-0.378401f,0.651613f},{0.558381f,-0.300341f,0.773309f}, -{0.605352f,-0.483657f,0.632159f},{0.508999f,-0.563832f,0.650394f},{0.547093f,-0.479533f,0.686103f}, -{0.647568f,0.075846f,0.758224f},{0.657391f,0.209588f,0.723816f},{0.778641f,0.458995f,0.427835f}, -{0.796311f,-0.124677f,0.591899f},{0.287351f,0.191424f,0.938502f},{0.732084f,0.104478f,0.673154f}, -{0.576522f,0.362983f,0.732029f},{0.465965f,0.367877f,0.804701f},{0.730207f,0.0875507f,0.677594f}, -{-0.399503f,0.326363f,-0.85667f},{-0.354372f,0.129678f,-0.926069f},{-0.448822f,0.605935f,-0.656811f}, -{-0.617025f,0.688594f,-0.380944f},{0.572087f,-0.696272f,0.4335f},{0.5902f,-0.307268f,0.746492f}, -{0.512315f,-0.27866f,0.812331f},{0.615482f,-0.524555f,0.588238f},{0.493002f,-0.409266f,0.767757f}, -{0.542152f,-0.375549f,0.751687f},{0.531583f,-0.39377f,0.74991f},{0.465902f,0.343074f,0.81562f}, -{0.556731f,-0.769617f,0.312633f},{0.254734f,-0.853269f,-0.455018f},{0.844112f,0.373341f,0.384825f}, -{0.798595f,0.33797f,0.498018f},{0.975491f,0.218904f,-0.0223324f},{0.411182f,-0.19688f,0.890038f}, -{0.55109f,-0.118472f,0.825993f},{0.555506f,-0.31389f,0.769991f},{0.483713f,-0.52489f,0.700365f}, -{0.476981f,-0.179667f,0.860354f},{-0.447194f,0.0450272f,-0.893303f},{0.323563f,-0.182347f,0.92847f}, -{0.11422f,0.271978f,-0.955501f},{-0.0334828f,0.360681f,-0.932088f},{0.0801935f,0.352312f,-0.93244f}, -{-0.165139f,-0.53863f,-0.8262f},{0.820463f,0.471607f,-0.323152f},{0.817037f,0.503878f,-0.280281f}, -{0.565589f,-0.744425f,-0.354882f},{0.593147f,-0.757668f,-0.272244f},{0.698756f,-0.639595f,-0.320402f}, -{0.416088f,-0.0895367f,0.904905f},{0.492055f,0.0671786f,0.867968f},{0.529662f,0.0245061f,0.847854f}, -{-0.290736f,-0.569161f,0.769109f},{0.343488f,-0.0248503f,0.938828f},{0.351263f,-0.283942f,0.892183f}, -{-0.100958f,0.304861f,-0.947031f},{-0.147563f,0.426841f,-0.892206f},{0.160646f,0.724895f,0.669865f}, -{0.739509f,-0.237147f,0.629991f},{0.755263f,-0.262598f,0.600517f},{0.720221f,-0.175747f,0.671115f}, -{-0.244267f,-0.453948f,-0.856893f},{-0.0660144f,-0.604178f,-0.79411f},{0.573614f,-0.482652f,0.661827f}, -{0.560916f,-0.327772f,0.760223f},{0.380138f,0.160625f,0.910876f},{0.851176f,0.264634f,-0.453287f}, -{0.34345f,-0.0915945f,0.934694f},{0.260014f,0.0541945f,0.964083f},{0.313326f,0.212754f,0.925507f}, -{0.396535f,0.543902f,-0.739548f},{0.444644f,0.49191f,-0.748543f},{0.503687f,0.52311f,-0.687499f}, -{-0.305173f,-0.397453f,-0.86539f},{0.660256f,0.283758f,0.695373f},{0.781524f,0.0706021f,0.619867f}, -{0.793597f,0.216873f,0.568481f},{0.733662f,0.193507f,0.65138f},{0.323353f,0.369017f,0.871361f}, -{0.582228f,-0.340961f,0.738076f},{0.549202f,0.284132f,0.785905f},{0.290724f,0.169076f,0.94175f}, -{0.53424f,-0.844963f,0.0250082f},{0.912901f,-0.035308f,0.406652f},{0.825201f,0.0115751f,0.56472f}, -{0.94043f,0.103742f,0.323773f},{-0.358271f,0.346487f,-0.866942f},{-0.277017f,0.312182f,-0.908738f}, -{-0.322405f,0.20153f,-0.9249f},{-0.981484f,-0.040964f,-0.187113f},{-0.846049f,-0.367576f,-0.386119f}, -{-0.723049f,-0.665594f,-0.184891f},{-0.681233f,0.638163f,0.358706f},{-0.887797f,0.251246f,0.385606f}, -{-0.945932f,0.286633f,0.151838f},{0.485297f,0.0684109f,0.871669f},{0.514312f,0.461732f,0.722694f}, -{0.622169f,0.403788f,0.670717f},{0.681605f,0.244739f,0.689578f},{0.498462f,-0.119438f,0.858644f}, -{0.606269f,-0.213205f,0.766148f},{0.768382f,0.484224f,-0.41847f},{0.815839f,0.442994f,-0.371703f}, -{-0.373507f,-0.270642f,-0.887269f},{-0.246314f,-0.0015448f,-0.969189f},{-0.431788f,-0.307208f,-0.848046f}, -{-0.347352f,-0.0362057f,-0.937036f},{0.0188641f,-0.999595f,-0.0213147f},{-0.00396728f,-0.999933f,-0.010845f}, -{0.0160447f,-0.999596f,-0.0234478f},{0.564655f,-0.441574f,0.697264f},{0.69031f,-0.153769f,0.706985f}, -{0.653448f,0.150736f,0.741812f},{0.651377f,0.314426f,0.690539f},{0.627538f,0.228138f,0.744412f}, -{0.477152f,0.341111f,0.809919f},{-0.983667f,-0.0636223f,0.168378f},{0.743203f,-0.429802f,0.512757f}, -{0.674133f,-0.406715f,0.616545f},{0.710554f,-0.395237f,0.582151f},{0.80919f,0.278181f,0.51752f}, -{0.826218f,0.290013f,0.482966f},{0.781084f,0.319842f,0.536291f},{0.374297f,-0.414591f,0.829468f}, -{0.292665f,-0.215483f,0.931619f},{0.147606f,0.803867f,0.576204f},{0.218746f,0.781826f,0.583866f}, -{0.512944f,-0.418974f,0.749233f},{0.567309f,-0.478639f,0.670123f},{0.577802f,-0.447301f,0.682691f}, -{0.685652f,-0.52024f,0.509148f},{0.448118f,-0.740268f,0.501192f},{0.684582f,0.410588f,0.6023f}, -{0.617891f,0.399018f,0.677492f},{0.632734f,0.295336f,0.715839f},{0.870482f,0.162018f,0.46477f}, -{0.840489f,0.186369f,0.508768f},{0.770366f,-0.159666f,0.617287f},{0.489274f,-0.00781279f,0.872095f}, -{0.522915f,-0.119012f,0.844036f},{0.525504f,-0.253163f,0.812253f},{0.584816f,-0.690932f,0.424975f}, -{0.765617f,0.283534f,0.577442f},{0.680954f,0.47874f,0.554174f},{0.75469f,0.139645f,0.641047f}, -{0.756042f,0.181321f,0.628906f},{0.706788f,-0.577248f,0.408944f},{0.270976f,0.449686f,0.85109f}, -{0.670575f,0.280147f,0.686911f},{0.731219f,0.377028f,0.56848f},{0.777606f,0.343926f,0.52635f}, -{0.764272f,0.413505f,0.494875f},{0.984362f,0.00908258f,0.175924f},{0.994702f,0.0701487f,0.0751525f}, -{0.988355f,0.0821244f,0.128101f},{0.819972f,-0.180455f,0.543215f},{0.786792f,0.106034f,0.608043f}, -{0.738693f,0.417579f,0.529113f},{0.813713f,0.199231f,0.546057f},{0.790175f,-0.192608f,0.58183f}, -{0.784095f,-0.245785f,0.569899f},{0.974171f,0.0716883f,0.214129f},{0.769246f,-0.371558f,0.519813f}, -{0.996425f,0.0802f,0.0265568f},{0.995753f,0.0774648f,0.0497599f},{0.994732f,0.0839796f,0.058788f}, -{0.0684754f,0.794747f,0.603066f},{0.890577f,-0.0326624f,0.453658f},{0.88509f,0.0273287f,0.464616f}, -{0.8882f,-0.0223627f,0.458912f},{0.673587f,-0.673846f,0.303664f},{0.443082f,-0.835915f,0.32392f}, -{0.601954f,-0.695112f,0.393027f},{0.529223f,-0.697322f,0.483389f},{0.520604f,-0.78592f,0.333618f}, -{0.854102f,0.0823997f,0.513536f},{0.871333f,-0.199525f,0.448296f},{0.789235f,0.160319f,0.592795f}, -{0.760528f,0.173113f,0.625803f},{0.567484f,0.383543f,0.7286f},{0.155292f,0.0116503f,0.9878f}, -{0.198612f,0.0248425f,0.979763f},{0.530868f,-0.169252f,0.830381f},{0.492979f,-0.111174f,0.862909f}, -{0.57538f,-0.112175f,0.810157f},{0.729484f,-0.0330009f,0.683201f},{0.788689f,-0.0150649f,0.614608f}, -{0.777266f,0.0200755f,0.628852f},{0.775266f,-0.284338f,0.564016f},{0.723422f,-0.280706f,0.630766f}, -{0.813826f,0.330595f,0.477906f},{0.780357f,0.334197f,0.528541f},{0.749978f,-0.563062f,0.347123f}, -{0.828104f,-0.38699f,0.405564f},{0.817079f,0.255468f,0.516834f},{0.768042f,0.385863f,0.511098f}, -{0.859619f,0.103461f,0.500351f},{0.774398f,0.172551f,0.608714f},{0.772662f,-0.40118f,0.491984f}, -{0.701697f,-0.127203f,0.701028f},{0.540935f,-0.797161f,0.268184f},{0.888043f,-0.0861904f,0.45161f}, -{0.710171f,0.329627f,0.622096f},{0.869048f,0.194343f,0.454958f},{0.175361f,0.624014f,0.761482f}, -{0.637965f,0.41983f,0.645556f},{0.652155f,0.403813f,0.641583f},{0.62877f,0.443097f,0.638994f}, -{-0.971605f,0.236558f,-0.00496129f},{0.59756f,0.462793f,0.654786f},{0.580389f,0.451229f,0.677895f}, -{0.626065f,0.431011f,0.649825f},{0.476493f,0.537168f,0.695992f},{0.620057f,0.465976f,0.631186f}, -{0.571138f,0.569021f,0.591622f},{0.683396f,-0.0668563f,0.72698f},{0.793913f,-0.0870938f,0.601762f}, -{0.815752f,-0.501744f,0.287753f},{0.606837f,-0.736726f,0.298302f},{0.896606f,-0.245435f,0.368592f}, -{0.896765f,0.0226329f,0.441927f},{0.844094f,0.216265f,0.490648f},{0.777054f,0.398813f,0.486966f}, -{0.785435f,0.364075f,0.500541f},{0.839493f,0.275943f,0.468089f},{0.243468f,-0.824286f,-0.511152f}, -{0.346621f,-0.880084f,-0.32451f},{0.536899f,0.0021648f,0.843644f},{0.585054f,0.0566912f,0.809011f}, -{0.650729f,-0.0826509f,0.754798f},{0.375913f,0.296442f,0.877959f},{0.110642f,-0.716504f,-0.688752f}, -{-0.193341f,-0.395496f,-0.897888f},{0.628335f,0.415744f,0.657534f},{0.827336f,0.279735f,0.487097f}, -{0.612704f,0.444252f,0.653631f},{0.48401f,0.4591f,0.744958f},{0.643482f,0.399456f,0.652967f}, -{0.57849f,0.362153f,0.730886f},{0.603739f,0.353751f,0.714395f},{0.669212f,0.391928f,0.631307f}, -{0.637042f,0.3499f,0.686839f},{0.801865f,0.000502496f,0.597504f},{0.832038f,0.0306209f,0.553873f}, -{0.811466f,-0.055155f,0.581791f},{0.470295f,-0.121854f,0.874056f},{0.767111f,-0.500143f,0.401744f}, -{0.739372f,0.426622f,0.520886f},{0.411713f,-0.155696f,0.897915f},{0.455116f,-0.227652f,0.860839f}, -{0.381047f,-0.107122f,0.918329f},{0.693332f,0.310097f,0.650485f},{0.730533f,0.151737f,0.665805f}, -{0.776021f,0.246385f,0.580591f},{0.697968f,-0.373382f,0.611086f},{0.866595f,-0.263565f,0.42373f}, -{0.811826f,0.486604f,0.322731f},{0.761744f,0.331298f,0.556766f},{-0.298661f,0.350782f,-0.887555f}, -{0.915881f,0.147323f,0.373441f},{0.92463f,0.311156f,0.21964f},{0.368686f,-0.785445f,0.497139f}, -{0.531938f,-0.737281f,0.416483f},{0.38531f,-0.870855f,0.305203f},{0.671745f,-0.645467f,0.363499f}, -{0.716224f,0.342647f,0.60796f},{0.769271f,0.376456f,0.51624f},{0.821107f,0.176575f,0.542775f}, -{0.849541f,0.0720743f,0.522576f},{0.828452f,0.10049f,0.550971f},{0.77968f,0.163857f,0.604359f}, -{0.566189f,0.00160388f,0.824274f},{0.476003f,0.0827108f,0.875546f},{0.554853f,-0.0521107f,0.830315f}, -{0.589359f,-0.181224f,0.787282f},{0.662155f,-0.284197f,0.693385f},{0.61982f,-0.514361f,0.592668f}, -{0.581998f,0.163587f,0.796566f},{0.513561f,0.322466f,0.795154f},{0.562209f,0.321646f,0.761882f}, -{0.535793f,0.38685f,0.750515f},{0.526098f,0.419382f,0.739824f},{0.490478f,0.469349f,0.734264f}, -{0.64664f,0.294523f,-0.703643f},{0.624458f,-0.561986f,0.542424f},{0.803143f,-0.258757f,0.536663f}, -{0.84475f,-0.0441311f,0.533338f},{0.792842f,0.173526f,0.584201f},{0.702839f,0.333032f,0.628576f}, -{0.863811f,0.113649f,0.490831f},{0.843999f,0.0339543f,0.535269f},{0.725844f,0.0529413f,0.685819f}, -{-0.73513f,-0.674473f,0.0683321f},{0.504364f,-0.490432f,0.710699f},{0.37711f,-0.530281f,0.759335f}, -{0.583048f,-0.597629f,0.550359f},{0.0436126f,-0.966946f,-0.251225f},{0.537038f,0.494685f,0.683284f}, -{0.546936f,0.0266999f,0.836748f},{0.724826f,-0.463617f,0.509594f},{0.693024f,-0.379127f,0.613173f}, -{0.709473f,-0.552913f,0.436962f},{0.514175f,0.22697f,0.827109f},{0.557267f,0.12334f,0.821122f}, -{0.482026f,0.308139f,0.820184f},{0.513391f,0.555068f,0.654469f},{0.453179f,0.569752f,0.685574f}, -{0.406531f,-0.413933f,0.814489f},{0.811775f,0.578688f,-0.0783687f},{0.973187f,0.225135f,-0.0471338f}, -{0.434216f,0.566594f,0.700305f},{0.538412f,-0.036777f,0.841879f},{0.491574f,0.0444878f,0.869698f}, -{0.415802f,0.190611f,0.889256f},{0.617904f,-0.566391f,0.54534f},{0.699226f,-0.174741f,0.693216f}, -{0.746495f,-0.220216f,0.627894f},{0.648682f,0.147411f,0.746647f},{0.568483f,0.442257f,0.693711f}, -{0.57011f,0.139636f,0.809615f},{0.948333f,-0.29193f,-0.124263f},{0.476851f,0.0790041f,0.875427f}, -{0.895368f,0.438086f,0.0799757f},{0.861625f,0.504983f,0.0509301f},{0.905583f,0.412128f,0.100346f}, -{0.385951f,0.474715f,0.791004f},{0.500776f,0.315259f,0.806124f},{0.78597f,0.498529f,-0.365678f}, -{-0.039175f,-0.970836f,-0.236521f},{0.279225f,0.728435f,0.625633f},{0.355854f,0.545909f,0.758519f}, -{0.614204f,-0.411429f,0.673409f},{0.4737f,-0.4708f,0.744281f},{0.577135f,-0.434087f,0.691725f}, -{-0.49125f,0.856358f,-0.159137f},{0.183845f,0.927353f,0.32591f},{0.430745f,0.871104f,0.235873f}, -{0.533354f,0.00972195f,0.845836f},{0.523564f,0.106788f,0.845268f},{0.533085f,-0.134271f,0.835339f}, -{0.616118f,-0.527777f,0.584679f},{0.57025f,-0.527772f,0.629501f},{0.394466f,0.440697f,0.806339f}, -{0.426039f,0.454103f,0.782484f},{0.545621f,-0.597095f,-0.588026f},{0.686729f,-0.529675f,-0.497844f}, -{0.509716f,-0.260083f,0.820089f},{0.623851f,-0.377081f,0.684558f},{0.629402f,0.220525f,0.745132f}, -{0.529436f,0.339631f,0.777399f},{0.623309f,0.420085f,0.659556f},{0.80518f,0.0871658f,0.58659f}, -{0.780352f,-0.0962468f,0.617889f},{0.523776f,-0.321197f,0.788981f},{0.515573f,-0.306043f,0.800326f}, -{0.544485f,-0.219115f,0.809645f},{0.625398f,-0.231908f,0.745048f},{0.706314f,-0.255021f,0.660368f}, -{0.673997f,-0.0995925f,0.73199f},{0.175291f,0.557259f,0.811625f},{-0.316229f,0.390378f,-0.864641f}, -{0.602475f,-0.105106f,0.791187f},{0.511986f,-0.0480917f,0.857646f},{0.549755f,0.286096f,0.784805f}, -{0.401885f,0.448359f,0.798412f},{0.647712f,0.0793625f,0.75774f},{0.693393f,-0.138186f,0.707185f}, -{0.501942f,-0.419292f,0.756471f},{0.417585f,0.557046f,0.71786f},{0.48062f,0.607109f,0.63279f}, -{0.634624f,-0.714085f,-0.295524f},{0.301532f,0.609365f,0.733316f},{0.653937f,-0.26285f,0.70942f}, -{0.622959f,-0.417671f,0.661418f},{-0.27087f,-0.335809f,-0.902143f},{0.431305f,-0.544847f,0.719109f}, -{0.438527f,0.4447f,0.780984f},{0.475877f,0.4592f,0.750118f},{0.614748f,-0.108916f,0.781167f}, -{0.648812f,-0.709042f,-0.276231f},{0.807503f,-0.288409f,0.514548f},{0.329362f,0.199389f,0.922911f}, -{-0.288854f,-0.228841f,0.929621f},{0.032487f,-0.0237096f,0.999191f},{0.379595f,-0.203006f,0.902605f}, -{0.525301f,0.348523f,0.776267f},{0.353571f,0.251066f,0.901084f},{0.747355f,0.353664f,0.562478f}, -{-0.555693f,-0.784513f,-0.275219f},{0.411451f,0.499707f,0.762234f},{0.247906f,0.683824f,0.686241f}, -{0.432255f,0.553228f,0.712106f},{0.0447714f,0.929401f,0.366345f},{0.359402f,-0.545287f,0.757293f}, -{0.518952f,-0.151605f,0.841252f},{0.491923f,0.130876f,0.860746f},{0.414154f,0.50786f,0.755351f}, -{0.678972f,-0.1642f,0.715566f},{0.711066f,0.00492155f,0.703108f},{0.503994f,0.317354f,0.803291f}, -{0.588691f,0.195381f,0.784391f},{0.526698f,0.331299f,0.782834f},{0.716063f,0.386632f,0.58118f}, -{0.483935f,0.46453f,0.741632f},{0.495087f,0.569512f,0.656159f},{0.380152f,0.463059f,0.800663f}, -{0.30855f,0.620777f,0.720717f},{0.5734f,-0.641764f,-0.509266f},{0.380204f,0.394298f,0.836644f}, -{0.809792f,0.158265f,0.564969f},{0.555507f,0.484609f,0.675697f},{-0.740533f,-0.671531f,0.025636f}, -{-0.723145f,-0.674855f,0.147076f},{0.615847f,0.522535f,0.589652f},{0.512179f,-0.340231f,0.788616f}, -{0.536573f,-0.109383f,0.836735f},{0.529299f,0.12282f,0.839499f},{0.540318f,0.326725f,0.77544f}, -{0.538417f,0.44289f,0.716907f},{0.687982f,0.0622659f,0.723052f},{0.732887f,-0.246965f,0.633944f}, -{-0.477133f,0.364336f,-0.799752f},{-0.458535f,0.357291f,-0.813689f},{-0.45039f,0.349904f,-0.821411f}, -{0.2928f,0.188137f,0.937482f},{0.18232f,-0.391871f,0.901774f},{0.00676346f,-0.547607f,0.836708f}, -{0.916547f,-0.0457656f,-0.397299f},{0.762617f,-0.476852f,0.437066f},{0.815111f,-0.371701f,0.444335f}, -{0.786397f,-0.282666f,0.549254f},{-0.575086f,-0.0839676f,0.813773f},{0.712856f,0.388338f,0.583978f}, -{0.899224f,-0.35067f,-0.261584f},{0.774318f,-0.202262f,0.599601f},{0.702776f,-0.0325274f,0.710668f}, -{0.733857f,-0.17232f,0.657084f},{0.659872f,-0.0417907f,0.750215f},{0.307708f,-0.261296f,0.914899f}, -{0.208132f,-0.0752668f,0.975201f},{0.35429f,-0.556443f,0.751565f},{0.428666f,0.437099f,0.79069f}, -{0.509459f,0.418039f,0.752127f},{0.455826f,0.346165f,0.819996f},{0.673234f,-0.0798483f,0.735105f}, -{0.836109f,0.296137f,0.461763f},{0.781771f,0.338466f,0.523713f},{-0.206937f,-0.731467f,0.649718f}, -{0.182463f,0.804027f,0.565904f},{0.495997f,0.491771f,0.715645f},{0.697516f,-0.155143f,0.699573f}, -{0.640765f,-0.107144f,0.760224f},{0.667024f,-0.208429f,0.715288f},{0.69754f,-0.266859f,0.665f}, -{0.549992f,-0.105262f,0.82851f},{0.525844f,0.0216014f,0.850307f},{0.627803f,-0.145946f,0.764567f}, -{0.575798f,-0.110136f,0.81014f},{-0.97179f,0.206791f,0.113409f},{0.189983f,0.501541f,0.844016f}, -{0.5093f,0.462767f,0.725576f},{0.818183f,-0.189226f,0.542928f},{0.837951f,-0.0837523f,0.539281f}, -{0.494371f,-0.37279f,-0.785254f},{-0.46232f,-0.0898225f,0.882152f},{0.371185f,0.394377f,0.840648f}, -{0.473626f,-0.168205f,0.864514f},{-0.461698f,0.245268f,0.852454f},{0.529431f,-0.618975f,0.580148f}, -{0.431288f,-0.596394f,0.676983f},{0.518712f,-0.358702f,0.776061f},{0.359538f,0.526882f,0.770148f}, -{0.620336f,0.0945776f,0.778613f},{0.558303f,-0.222333f,0.799291f},{0.462001f,-0.280565f,0.841331f}, -{0.228678f,0.745663f,0.625854f},{0.581988f,-0.357027f,0.730631f},{0.671159f,-0.124645f,0.73076f}, -{0.657414f,0.107867f,0.745769f},{0.635504f,0.331112f,0.697495f},{0.527313f,0.468268f,0.708989f}, -{0.786941f,-0.0742031f,0.61255f},{0.78316f,0.0971358f,0.614187f},{0.679903f,-0.0312478f,-0.732636f}, -{0.722731f,-0.119831f,-0.680662f},{-0.304819f,0.292514f,-0.906378f},{-0.701588f,-0.688721f,0.182861f}, -{0.292159f,-0.372893f,0.880678f},{0.35086f,0.338823f,0.872981f},{0.49325f,-0.543568f,0.679145f}, -{0.482678f,-0.713783f,0.50748f},{-0.0412281f,-0.625784f,-0.778906f},{0.347424f,0.53187f,0.772276f}, -{0.363542f,0.452761f,0.814153f},{0.683475f,0.00488942f,0.729957f},{0.622766f,0.0726325f,0.779029f}, -{0.501262f,-0.479754f,0.72012f},{0.25502f,0.730842f,0.633115f},{0.337312f,0.626247f,0.702876f}, -{0.893756f,-0.323824f,-0.310383f},{0.661542f,-0.288546f,0.692173f},{0.615062f,-0.137833f,0.776338f}, -{0.679829f,-0.16072f,0.715543f},{0.715517f,0.135139f,0.6854f},{0.673723f,0.259116f,0.692067f}, -{0.607929f,0.357916f,0.708744f},{0.564176f,0.484896f,0.668268f},{0.605081f,0.132927f,0.784989f}, -{0.702442f,-0.0913318f,0.705856f},{0.524211f,-0.518737f,-0.675363f},{0.215163f,-0.85976f,0.46316f}, -{0.0578387f,0.325075f,-0.943918f},{-0.0515991f,0.412961f,-0.909286f},{-0.108005f,0.514926f,-0.850403f}, -{0.54637f,-0.00381208f,0.837535f},{0.614893f,-0.293542f,0.731942f},{0.541219f,-0.245194f,0.80434f}, -{0.398648f,0.234369f,0.886652f},{0.358081f,-0.189674f,0.914222f},{0.335383f,0.0542744f,0.940517f}, -{0.460648f,-0.309278f,0.831956f},{0.423308f,0.144847f,0.894332f},{0.435355f,0.202096f,0.877282f}, -{0.603528f,0.44959f,0.6585f},{0.679775f,-0.0385942f,0.732405f},{0.653824f,0.107886f,0.748916f}, -{0.759406f,0.0271836f,0.650049f},{0.574702f,0.413968f,0.705938f},{0.360767f,0.550165f,0.753104f}, -{-0.887326f,0.448617f,-0.106749f},{-0.933431f,0.327008f,-0.147555f},{0.5428f,-0.207117f,0.813923f}, -{0.494759f,-0.106389f,0.862493f},{-0.395446f,-0.207517f,-0.89474f},{-0.355182f,-0.249591f,-0.900861f}, -{0.495157f,-0.00965679f,0.86875f},{0.643235f,0.350247f,0.680864f},{0.570022f,0.501044f,0.651176f}, -{0.617122f,0.271777f,0.738443f},{0.862234f,0.144092f,0.485582f},{0.977463f,0.0865015f,0.192573f}, -{0.967945f,0.0949319f,0.232529f},{-0.304308f,0.397193f,-0.865814f},{0.270602f,-0.246793f,0.93052f}, -{0.577148f,0.34371f,0.740786f},{0.400594f,0.586566f,0.703893f},{0.302236f,0.559956f,0.771429f}, -{0.521137f,0.302706f,0.797988f},{0.502864f,0.414301f,0.758605f},{0.594349f,-0.0767115f,0.80054f}, -{0.573793f,-0.176939f,0.799659f},{0.62133f,0.0448709f,0.782264f},{0.581222f,0.0850307f,0.80929f}, -{0.682527f,-0.0396461f,0.729784f},{0.636348f,0.03267f,0.77071f},{0.388821f,-0.0387993f,0.920496f}, -{0.542248f,-0.00517707f,0.840202f},{0.581726f,-0.0418682f,0.812306f},{0.655859f,-0.313951f,0.686501f}, -{0.727557f,-0.0868233f,0.680531f},{0.744094f,0.140968f,0.653033f},{0.662563f,0.288153f,0.69136f}, -{0.497747f,-0.511148f,0.700696f},{-0.687492f,0.198204f,-0.69862f},{-0.565646f,0.0336114f,-0.823963f}, -{-0.63122f,0.176192f,-0.755326f},{0.715262f,0.396856f,0.575244f},{0.713432f,0.39338f,0.579885f}, -{-0.923237f,0.361203f,-0.131016f},{-0.998356f,0.0419347f,0.0390748f},{-0.996558f,0.0211225f,-0.0801658f}, -{0.440074f,0.261607f,0.859009f},{0.507926f,0.00577762f,0.861381f},{0.598678f,-0.238457f,0.764672f}, -{0.595584f,0.0324451f,0.802637f},{0.681167f,-0.213054f,0.700442f},{0.760255f,-0.0271448f,0.649057f}, -{0.769925f,0.103971f,0.629607f},{0.716696f,0.189305f,0.6712f},{0.664742f,0.357915f,0.655755f}, -{0.796516f,0.168019f,0.580802f},{0.807462f,0.0110927f,0.589815f},{0.846207f,0.128317f,0.517174f}, -{0.632386f,0.0778414f,-0.770732f},{0.698958f,0.0421958f,-0.713917f},{0.745128f,-0.0767328f,-0.662492f}, -{0.3335f,-0.145014f,0.93153f},{0.865745f,0.491554f,0.0941269f},{0.707032f,0.416355f,0.571625f}, -{0.80999f,0.565921f,0.153785f},{0.877285f,0.466554f,0.112687f},{0.908767f,0.406955f,0.0923594f}, -{0.668257f,-0.432233f,0.605481f},{0.672297f,-0.440256f,0.595141f},{0.590598f,0.120871f,0.797862f}, -{0.454966f,0.559227f,0.693016f},{0.549444f,0.578269f,0.603089f},{0.535451f,-0.533401f,0.654809f}, -{0.778287f,-0.614793f,-0.127668f},{0.770378f,-0.637588f,7.24516e-05f},{0.518565f,-0.0232879f,0.854721f}, -{0.49947f,0.00200443f,0.866329f},{0.475824f,0.117396f,0.871671f},{0.478578f,0.335545f,0.811401f}, -{0.552119f,0.216155f,0.805259f},{0.746915f,-0.129145f,0.652258f},{0.72802f,0.199855f,0.655778f}, -{0.753832f,-0.195787f,0.62722f},{0.656384f,0.422092f,0.625299f},{0.636566f,0.465569f,0.614841f}, -{0.914171f,0.107873f,0.390712f},{0.829913f,0.220967f,0.512268f},{0.932403f,0.11802f,0.341608f}, -{-0.25645f,-0.502436f,-0.825706f},{-0.941174f,0.222725f,-0.254137f},{0.623564f,-0.563809f,0.54156f}, -{0.439151f,0.502801f,0.744539f},{0.784586f,-0.297617f,0.54392f},{0.114849f,-0.45399f,-0.883574f}, -{0.694739f,-0.719229f,0.00687289f},{0.901992f,0.424732f,0.0775473f},{0.0386906f,-0.76215f,-0.646243f}, -{0.534589f,0.215435f,0.817192f},{0.418646f,0.233704f,0.877564f},{0.491832f,0.162436f,0.855404f}, -{-0.578384f,0.497412f,-0.646571f},{-0.83752f,0.114356f,-0.534306f},{-0.751325f,-0.0297917f,-0.659259f}, -{0.729163f,0.361824f,0.580865f},{0.759f,0.303823f,0.575857f},{0.22265f,-0.950099f,-0.218494f}, -{0.749635f,-0.441831f,0.49278f},{0.62442f,0.407023f,0.666657f},{0.480825f,0.343945f,0.806542f}, -{0.484674f,0.377617f,0.788984f},{-0.359597f,-0.178119f,-0.915949f},{-0.132927f,-0.480289f,-0.866979f}, -{0.618301f,0.114174f,0.777605f},{0.650738f,-0.0654459f,0.756476f},{0.818155f,-0.134811f,0.558971f}, -{0.751298f,0.243416f,0.613433f},{0.760882f,0.478202f,0.438613f},{0.766475f,0.346567f,0.540747f}, -{0.548821f,-0.33437f,0.766154f},{0.914253f,0.110328f,0.389832f},{-0.908437f,0.392483f,0.143871f}, -{-0.916873f,0.398846f,-0.0162913f},{0.577586f,0.157636f,0.800965f},{0.956451f,-9.39214e-05f,0.291893f}, -{0.513721f,0.405479f,0.756093f},{0.459552f,0.406286f,0.789775f},{0.63472f,0.110533f,0.764796f}, -{0.638935f,0.168088f,0.750672f},{0.851403f,-0.491367f,-0.183499f},{0.743817f,0.0571238f,0.665938f}, -{0.624312f,0.0274681f,0.780692f},{0.56851f,-0.179512f,0.802852f},{0.899508f,0.0827162f,0.429003f}, -{0.841008f,0.0246865f,0.540459f},{0.817259f,0.0591081f,0.573232f},{0.827772f,0.18779f,0.528704f}, -{0.498712f,-0.488039f,0.716313f},{0.697539f,-0.186868f,0.691751f},{0.583311f,-0.151649f,0.797967f}, -{0.773136f,0.0139612f,0.634087f},{0.794927f,-0.0103512f,0.606617f},{0.565734f,0.479916f,0.670542f}, -{-0.864742f,0.103488f,0.491439f},{0.828208f,-0.00768752f,0.560368f},{0.561537f,-0.286341f,0.776328f}, -{0.508557f,0.150787f,0.847722f},{0.545509f,0.274793f,0.791776f},{0.594812f,-0.0292075f,0.803334f}, -{0.603583f,0.135798f,0.78565f},{0.442723f,0.0788834f,0.893182f},{0.554001f,0.29244f,0.779463f}, -{0.600309f,-0.0313817f,0.799152f},{0.399517f,-0.0519389f,0.915253f},{0.452671f,0.0560515f,0.889914f}, -{0.591323f,0.26021f,0.7633f},{0.608531f,0.316253f,0.727787f},{0.652664f,0.0892208f,0.752376f}, -{0.608645f,0.00582163f,0.793422f},{0.534761f,0.021969f,0.844718f},{0.552932f,0.0923861f,0.828089f}, -{0.615998f,0.155852f,0.772177f},{0.708251f,0.0938871f,0.69969f},{0.448258f,-0.39374f,0.802517f}, -{0.955745f,0.0600352f,0.288004f},{0.48462f,-0.528963f,0.696665f},{0.786507f,0.367476f,0.496355f}, -{0.946708f,0.312889f,0.0764525f},{0.970324f,0.231022f,0.0714221f},{0.622192f,-0.479217f,0.619054f}, -{0.528436f,0.369101f,0.764539f},{0.780853f,0.00919292f,0.624647f},{0.387582f,-0.131106f,0.912465f}, -{0.50548f,-0.154984f,0.848805f},{0.877049f,0.473586f,0.0806271f},{0.829991f,0.555528f,0.0500242f}, -{0.0380677f,-0.422558f,-0.905536f},{-0.0386355f,-0.416857f,-0.908151f},{0.101346f,-0.34475f,-0.933208f}, -{-0.65478f,0.227072f,-0.720903f},{0.554038f,0.392875f,0.733956f},{0.234576f,0.762263f,0.603265f}, -{0.25995f,0.711212f,0.653149f},{0.498703f,-0.320812f,0.805217f},{0.524817f,-0.317889f,0.789629f}, -{0.775137f,-0.392992f,0.494691f},{0.58636f,-0.0781912f,0.806268f},{0.840356f,0.34648f,0.416837f}, -{0.876942f,0.455574f,0.153053f},{0.908257f,0.364583f,0.2053f},{0.875224f,-0.483566f,-0.0121026f}, -{0.917423f,-0.388275f,0.0870448f},{0.562132f,0.160272f,0.811369f},{0.170127f,-0.327533f,0.929397f}, -{0.768738f,-0.0521177f,0.637436f},{0.761336f,-0.026129f,0.647831f},{0.886198f,-0.0253639f,0.462612f}, -{0.884802f,-0.0240317f,0.465348f},{0.875003f,-0.0269654f,0.483366f},{0.888156f,-0.303303f,-0.345232f}, -{0.720994f,0.41486f,0.55503f},{0.73089f,0.493643f,0.471292f},{0.799211f,0.510579f,0.317129f}, -{0.766819f,0.495596f,0.407889f},{0.716985f,0.389142f,0.578361f},{0.66729f,-0.114149f,0.735998f}, -{0.654942f,-0.233812f,0.718598f},{0.821195f,-0.308784f,0.479887f},{0.775726f,-0.3568f,0.520521f}, -{0.717386f,-0.30496f,0.626383f},{0.208891f,-0.812635f,-0.544049f},{0.859058f,0.105923f,0.500799f}, -{0.881403f,0.14631f,0.449135f},{0.841431f,0.0925177f,0.532386f},{0.565092f,0.0003129f,0.825028f}, -{0.54228f,-0.0389849f,0.839293f},{-0.372746f,0.134499f,-0.918134f},{0.72628f,0.0503029f,-0.685556f}, -{0.787154f,-0.0814957f,-0.611349f},{0.769883f,-0.297935f,-0.564371f},{0.744067f,0.141766f,0.652891f}, -{0.574057f,0.0905282f,0.813795f},{0.761955f,0.157928f,0.62808f},{0.887165f,0.0459843f,0.459156f}, -{0.885574f,0.209166f,0.414738f},{0.72059f,0.381289f,0.579111f},{0.90903f,0.274057f,0.313939f}, -{0.450923f,-0.195169f,0.870964f},{0.739011f,0.117632f,0.663344f},{0.571164f,-0.541364f,0.617007f}, -{0.889148f,0.0404144f,0.455832f},{-0.407865f,0.585904f,-0.700259f},{0.680773f,-0.427493f,0.594809f}, -{0.715782f,-0.442783f,0.54f},{0.568523f,-0.363063f,0.738219f},{0.309482f,-0.182632f,0.933202f}, -{-0.919947f,0.0886574f,-0.381888f},{0.861114f,-0.0447529f,0.506438f},{0.821222f,-0.0124579f,0.570473f}, -{0.81439f,-0.0385379f,0.579037f},{0.192437f,0.0496368f,0.980053f},{0.478856f,0.612574f,0.628848f}, -{-0.511654f,0.318298f,-0.798058f},{-0.601647f,0.281855f,-0.747381f},{0.251524f,0.118615f,-0.960555f}, -{0.225671f,0.123337f,-0.966365f},{0.912175f,-0.0206556f,0.409281f},{0.902009f,-0.018796f,0.431308f}, -{0.93251f,3.12715e-05f,0.361143f},{0.660423f,0.0123608f,0.750792f},{0.841922f,0.338374f,0.420321f}, -{0.48217f,-0.30124f,0.822658f},{0.213331f,-0.966013f,-0.145976f},{0.982792f,0.184059f,-0.0155821f}, -{0.882267f,0.470176f,-0.0232345f},{0.897305f,0.413593f,0.154221f},{-0.452893f,0.251605f,-0.855326f}, -{-0.42283f,0.351254f,-0.835366f},{0.831731f,0.186743f,0.522829f},{0.885981f,0.159897f,0.435283f}, -{0.528091f,-0.0916303f,0.84423f},{-0.5275f,0.392926f,-0.753229f},{-0.414898f,0.226583f,-0.881203f}, -{-0.449899f,0.203977f,-0.869473f},{0.792407f,0.309002f,0.525936f},{0.702105f,-0.174158f,0.690447f}, -{0.601373f,-0.0740094f,0.795533f},{0.550285f,0.795586f,0.253436f},{0.234523f,0.778306f,0.582442f}, -{0.324053f,0.512421f,0.795245f},{0.574058f,-0.409459f,0.709084f},{0.248926f,-0.872222f,-0.421028f}, -{0.291238f,0.681894f,0.67097f},{-0.206327f,0.155371f,-0.966069f},{-0.179661f,0.246138f,-0.952438f}, -{-0.129275f,0.294127f,-0.946983f},{-0.236405f,0.381324f,-0.893703f},{0.686435f,0.401971f,0.605992f}, -{-0.408368f,0.355119f,-0.840908f},{0.820717f,-0.249024f,0.514208f},{0.729541f,-0.276127f,0.625719f}, -{0.981621f,0.137155f,0.132695f},{0.883296f,0.312291f,-0.349661f},{0.873408f,0.450495f,-0.184969f}, -{0.498945f,0.610413f,0.615183f},{0.778182f,0.38333f,0.497485f},{0.283819f,0.610949f,0.739046f}, -{0.883323f,0.255649f,0.392918f},{0.799895f,0.0390677f,0.598868f},{0.810366f,0.0758698f,0.580991f}, -{0.852675f,-0.235047f,0.466582f},{0.888261f,-0.0854651f,0.451318f},{0.87399f,-0.0845339f,0.478535f}, -{0.0351843f,-0.998869f,-0.0319747f},{0.0305101f,-0.99916f,-0.0273486f},{0.537026f,0.273246f,0.798085f}, -{0.0538744f,-0.983474f,-0.172848f},{-0.316547f,-0.843145f,-0.434632f},{0.468404f,0.603343f,0.645426f}, -{-0.178733f,-0.51791f,-0.836555f},{0.591741f,-0.474756f,-0.651498f},{0.12968f,-0.977424f,-0.166811f}, -{0.421402f,-0.892298f,-0.161939f},{-0.737569f,0.5865f,0.33468f},{-0.849297f,0.462132f,0.255202f}, -{-0.394842f,-0.918423f,0.0244794f},{-0.463997f,0.132699f,-0.875841f},{-0.322235f,0.0572273f,-0.944928f}, -{-0.373209f,0.0745975f,-0.924743f},{0.486459f,-0.162385f,0.85848f},{-0.482457f,-0.842529f,-0.239541f}, -{0.499279f,-0.259573f,0.826645f},{0.411235f,0.323673f,0.852128f},{0.554669f,-0.34206f,0.75851f}, -{0.473195f,-0.178033f,0.862781f},{0.849404f,0.518863f,0.096404f},{0.876804f,0.461771f,0.134098f}, -{0.758995f,-0.279535f,0.588036f},{0.425511f,-0.715773f,-0.553723f},{0.340117f,-0.913034f,-0.225142f}, -{0.720202f,0.392223f,0.57225f},{-0.887605f,0.375631f,-0.266567f},{-0.870968f,-0.10751f,-0.479434f}, -{-0.880827f,0.148713f,-0.449475f},{0.625715f,-0.186516f,0.757425f},{0.49642f,-0.788635f,0.362796f}, -{0.450044f,-0.869811f,0.202213f},{0.769115f,-0.312414f,0.557547f},{0.727369f,-0.115659f,0.676429f}, -{0.0593964f,-0.478543f,0.876053f},{0.164209f,0.0300051f,0.985969f},{-0.0644165f,0.0478143f,0.996777f}, -{0.152902f,0.149191f,0.976915f},{0.483827f,-0.665811f,0.567986f},{0.896442f,-0.0319358f,0.442009f}, -{0.914686f,-0.0438937f,0.401775f},{-0.451712f,-0.831749f,-0.322723f},{-0.297702f,-0.794045f,-0.529968f}, -{0.888428f,0.139476f,0.437312f},{0.175709f,-0.322229f,0.930212f},{0.514633f,-0.835931f,0.190714f}, -{0.92474f,0.379415f,0.0300102f},{0.918099f,0.386049f,0.0897775f},{0.814101f,-0.545264f,-0.199817f}, -{0.912396f,0.0460901f,0.406706f},{-0.777079f,-0.577772f,-0.249656f},{-0.669531f,-0.626988f,-0.398264f}, -{0.0198351f,-0.999244f,0.0334435f},{0.0138369f,-0.999067f,0.0408985f},{0.0159619f,-0.999343f,0.0325355f}, -{0.886832f,-0.0337723f,0.460856f},{-0.90871f,0.244633f,-0.338232f},{-0.0909099f,0.558564f,-0.824464f}, -{0.60105f,0.682827f,-0.415314f},{-0.790674f,-0.288535f,-0.539984f},{0.0880274f,-0.995293f,0.0405437f}, -{0.00338008f,-0.520431f,0.853897f},{0.712797f,0.446657f,0.540757f},{0.813274f,-0.529637f,0.240976f}, -{0.908879f,-0.35302f,0.222074f},{0.718433f,-0.162821f,0.676272f},{0.181672f,0.904069f,-0.386852f}, -{-0.417861f,0.905006f,0.0797298f},{-0.713732f,0.577259f,0.396685f},{-0.076924f,-0.696852f,-0.713078f}, -{-0.181321f,-0.570804f,-0.800816f},{-0.191037f,-0.442903f,-0.875981f},{-0.0504743f,-0.580727f,-0.812532f}, -{-0.926669f,-0.356093f,-0.120341f},{-0.892653f,-0.449437f,-0.0343083f},{-0.986856f,-0.133881f,-0.0905015f}, -{0.587545f,-0.717401f,0.374334f},{0.998502f,0.0530506f,-0.0133723f},{0.949732f,0.30454f,0.0725536f}, -{0.998781f,0.0489191f,-0.00662695f},{0.996435f,0.0816746f,0.0211487f},{0.68741f,0.0823538f,0.721585f}, -{0.584366f,0.244026f,0.77393f},{0.269489f,0.147477f,0.951644f},{0.519998f,-0.60239f,0.605581f}, -{0.567408f,-0.484303f,0.665957f},{-0.676466f,-0.181577f,-0.713739f},{-0.802923f,-0.132063f,-0.58127f}, -{-0.582632f,-0.207995f,-0.78567f},{0.746876f,-0.118077f,0.654396f},{0.975213f,-0.209994f,-0.0697239f}, -{0.60946f,0.229956f,0.758735f},{0.764709f,-0.00540347f,0.644353f},{0.680325f,-0.379919f,0.626754f}, -{0.736298f,-0.112824f,0.667185f},{0.616818f,-0.00552029f,0.787086f},{0.895137f,-0.311959f,-0.318451f}, -{-0.709982f,-0.133843f,-0.691384f},{-0.577864f,-0.187655f,-0.794266f},{0.83979f,-0.15125f,0.521417f}, -{0.596297f,0.0624722f,0.800329f},{0.0105197f,-0.998823f,0.0473539f},{0.0265853f,-0.99901f,0.0356652f}, -{0.0124122f,-0.998977f,0.0434877f},{-0.678991f,0.664674f,-0.311736f},{0.33402f,0.150594f,0.930458f}, -{-0.432098f,0.335744f,0.836999f},{0.692931f,-0.0653427f,0.718037f},{0.266962f,0.858519f,0.437808f}, -{0.875412f,-0.110105f,0.47067f},{0.931732f,-0.0463402f,0.360177f},{0.917928f,0.390128f,0.0721717f}, -{0.926793f,-0.0150992f,0.375268f},{0.742293f,0.37572f,0.554829f},{0.722769f,-0.643509f,0.251992f}, -{0.921411f,-0.112764f,0.371869f},{-0.552981f,0.11925f,-0.824616f},{0.0969255f,0.700357f,0.707181f}, -{0.815723f,-0.0576197f,0.575566f},{-0.959286f,0.0233389f,-0.281471f},{0.938652f,0.278602f,0.203255f}, -{0.291122f,-0.576791f,0.763256f},{0.224105f,-0.751766f,0.620181f},{0.262298f,-0.881578f,0.392453f}, -{-0.558518f,-0.125543f,-0.819937f},{-0.419377f,-0.0666438f,-0.905363f},{-0.510491f,-0.319457f,-0.798339f}, -{0.341107f,-0.0284138f,0.939595f},{0.858203f,-0.0563061f,0.510212f},{0.880166f,0.164233f,0.44535f}, -{0.689148f,0.496612f,0.527686f},{0.771216f,-0.14831f,0.619056f},{0.771271f,0.507287f,-0.384448f}, -{0.834734f,0.227488f,-0.501467f},{0.85188f,-0.0369246f,0.522434f},{0.386071f,0.227234f,-0.894044f}, -{0.325297f,0.269005f,-0.906542f},{0.378206f,0.379987f,-0.844139f},{0.662992f,-0.227769f,0.713136f}, -{0.594588f,-0.0322742f,0.803382f},{0.804086f,-0.0198517f,0.594182f},{0.736753f,0.0181734f,0.675918f}, -{0.326986f,0.196476f,0.924379f},{0.299563f,0.339299f,0.891705f},{0.884397f,0.126928f,0.449145f}, -{0.415895f,0.703623f,0.576147f},{0.270987f,0.684654f,0.676621f},{0.886993f,0.123335f,0.445007f}, -{0.618728f,-0.106254f,0.778386f},{0.00880166f,-0.999707f,-0.0225414f},{0.0201949f,-0.999687f,-0.0147667f}, -{0.0280835f,-0.999382f,-0.0211496f},{0.310203f,-0.397361f,0.863642f},{-0.0407621f,0.187927f,-0.981337f}, -{0.494633f,-0.865635f,-0.0775528f},{0.590065f,0.0157559f,0.807202f},{0.756401f,-0.214401f,0.617972f}, -{0.70386f,-0.501947f,0.502623f},{0.513046f,0.0939776f,0.853201f},{0.561868f,-0.598621f,0.570926f}, -{-0.882151f,-0.304941f,0.358916f},{-0.922118f,-0.257219f,0.289027f},{-0.869252f,-0.420449f,0.260043f}, -{-0.0299809f,-0.993548f,0.109381f},{-0.00991282f,-0.999769f,0.0190808f},{0.227082f,-0.483709f,0.845257f}, -{0.318876f,-0.00218194f,0.947794f},{-0.721335f,-0.58379f,0.372645f},{-0.844342f,-0.429109f,0.320862f}, -{-0.793675f,-0.561927f,0.233064f},{-0.446212f,0.0339292f,-0.894284f},{-0.542424f,0.173159f,-0.822066f}, -{-0.523215f,0.18899f,-0.83098f},{0.852689f,0.312839f,0.418393f},{0.326618f,0.746278f,-0.579991f}, -{0.43824f,0.765982f,-0.470337f},{0.394471f,0.836057f,-0.381316f},{0.947904f,0.0496112f,0.31467f}, -{-0.69292f,-0.718449f,0.0607708f},{-0.83053f,-0.546689f,-0.106539f},{-0.968231f,0.0429053f,0.246349f}, -{-0.823249f,0.447806f,0.3489f},{0.0290057f,-0.99844f,0.0477127f},{0.135844f,0.356041f,-0.924544f}, -{0.157125f,0.356013f,-0.921177f},{0.702615f,-0.705316f,0.094134f},{-0.207965f,0.00367548f,-0.978129f}, -{-0.553098f,0.275765f,-0.786152f},{-0.646691f,0.197265f,-0.736802f},{-0.67218f,0.236112f,-0.70173f}, -{0.730094f,-0.00643599f,0.683316f},{0.942911f,-0.321198f,0.0880354f},{0.837478f,0.339639f,0.428107f}, -{0.522261f,0.307107f,0.795569f},{0.57665f,-0.609907f,0.543588f},{0.59619f,-0.248945f,0.763272f}, -{0.663708f,-0.395918f,0.634619f},{0.363764f,0.0543848f,0.929902f},{-0.624526f,-0.732207f,0.271734f}, -{-0.62029f,-0.71074f,0.331798f},{0.911724f,0.135763f,0.387721f},{0.181805f,0.489394f,0.852901f}, -{0.336708f,-0.102173f,0.93605f},{0.354085f,0.0237752f,0.934911f},{0.57874f,0.741724f,-0.338977f}, -{0.545642f,0.698697f,-0.462706f},{0.566298f,0.757711f,-0.324314f},{-0.314115f,0.947718f,0.0562388f}, -{0.581017f,-0.458852f,0.672216f},{-0.334189f,0.465636f,-0.819452f},{-0.312672f,0.554287f,-0.771364f}, -{0.581397f,-0.348002f,0.73544f},{-0.0906116f,0.499157f,0.861761f},{0.0294859f,-0.0565748f,-0.997963f}, -{-0.0298575f,0.0125533f,-0.999475f},{-0.0240975f,-0.0732973f,-0.997019f},{-0.367049f,0.148835f,-0.918217f}, -{-0.0153553f,0.739279f,-0.673224f},{0.3737f,0.71988f,-0.584911f},{0.291589f,0.00169327f,0.956542f}, -{-0.405861f,0.384739f,-0.829007f},{-0.444386f,0.455033f,-0.771664f},{-0.701359f,0.404044f,-0.587234f}, -{0.606879f,-0.193662f,0.770839f},{0.561341f,-0.104168f,0.821003f},{0.39326f,0.358897f,0.846486f}, -{0.328906f,-0.335092f,0.882912f},{-0.0572828f,0.247977f,-0.967071f},{0.880482f,-0.0150773f,0.47384f}, -{-0.358699f,0.160404f,-0.919568f},{0.36513f,0.322964f,0.873141f},{0.871962f,0.0410214f,0.487851f}, -{0.288687f,0.0169397f,0.957274f},{0.551894f,-0.577205f,0.601871f},{0.360338f,-0.865636f,-0.347608f}, -{0.293413f,-0.897843f,-0.328309f},{0.399519f,0.467113f,0.78879f},{0.696026f,-0.0722678f,0.714371f}, -{-0.0496104f,-0.0161746f,-0.998638f},{0.017165f,-0.0241149f,-0.999562f},{0.221142f,-0.382684f,0.897023f}, -{-0.175494f,0.594691f,-0.784566f},{0.0255035f,0.0935805f,-0.995285f},{-0.0210553f,0.317065f,-0.94817f}, -{0.509115f,0.633526f,0.58262f},{0.490691f,-0.311449f,0.81377f},{0.33886f,0.225938f,0.913305f}, -{0.465134f,-0.14352f,-0.873529f},{0.365383f,-0.100181f,-0.925451f},{-0.633866f,0.676616f,0.374707f}, -{-0.287038f,0.322961f,-0.901834f},{-0.720707f,-0.115035f,-0.683629f},{-0.499874f,-0.0901865f,-0.86139f}, -{-0.257732f,0.840352f,-0.476846f},{0.509487f,-0.632754f,0.583134f},{0.287168f,-0.31054f,0.906145f}, -{0.299274f,0.0483362f,0.952942f},{-0.100852f,0.454565f,-0.884986f},{0.67887f,0.428883f,-0.595982f}, -{0.497894f,-0.411631f,0.763323f},{0.244059f,0.609261f,0.754478f},{0.782364f,-0.223263f,0.581429f}, -{-0.310859f,0.769689f,0.557625f},{-0.370555f,0.816573f,0.442603f},{0.396677f,0.000531581f,0.917958f}, -{-0.0780473f,0.136668f,-0.987538f},{-0.193533f,0.894149f,0.403785f},{-0.469226f,0.810899f,0.349672f}, -{-0.599307f,0.720881f,0.348083f},{0.597735f,0.798804f,-0.0680163f},{-0.390329f,0.730714f,-0.56009f}, -{0.959444f,0.0389925f,0.27919f},{0.0866216f,-0.0782957f,-0.99316f},{0.0659964f,-0.0736851f,-0.995095f}, -{0.2912f,0.0574939f,0.954933f},{0.88907f,0.321536f,0.325836f},{-0.0155458f,0.906453f,0.42202f}, -{0.666373f,-0.500383f,-0.552778f},{0.8608f,0.346833f,0.372466f},{0.843227f,0.25116f,0.475275f}, -{-0.453813f,-0.0143082f,-0.890982f},{-0.24794f,-0.307459f,-0.918692f},{0.257164f,0.0550692f,0.964797f}, -{-0.366218f,-0.429376f,0.825543f},{-0.4966f,-0.309925f,0.810762f},{0.127606f,-0.14502f,-0.981166f}, -{-0.762129f,-0.60679f,0.225756f},{0.0143175f,-0.999788f,-0.0147732f},{0.0109175f,-0.99987f,-0.0118935f}, -{0.00619323f,-0.999932f,-0.00986292f},{-0.142064f,-0.566734f,-0.811561f},{-0.982566f,-0.0233312f,-0.184445f}, -{-0.982201f,0.185549f,-0.0292062f},{-0.52164f,0.791731f,-0.31789f},{-0.644517f,0.597376f,-0.477221f}, -{-0.696846f,0.483527f,-0.529723f},{-0.883865f,0.259645f,0.389059f},{-0.89337f,0.245748f,0.376163f}, -{0.092153f,-0.238835f,-0.966678f},{-0.898211f,0.397905f,-0.186783f},{0.997552f,-0.0618775f,-0.032576f}, -{0.993174f,-0.107765f,-0.0446236f},{-0.940601f,0.262619f,-0.215175f},{-0.897251f,0.333562f,-0.289268f}, -{0.439447f,-0.896273f,0.0598437f},{0.400452f,-0.910927f,0.0992435f},{0.427674f,-0.902604f,0.0490067f}, -{0.0360786f,-0.997277f,0.0643199f},{0.0645358f,-0.994324f,0.0845833f},{0.224178f,-0.969841f,0.0956641f}, -{-0.980638f,-0.00736646f,-0.195689f},{-0.572463f,-0.725649f,-0.381733f},{-0.618061f,-0.659854f,-0.42731f}, -{-0.362638f,-0.894922f,-0.260017f},{0.00462647f,-0.999587f,-0.0283808f},{-0.00164635f,-0.999876f,-0.015652f}, -{-0.00983998f,-0.999952f,0.000305002f},{0.973157f,-0.183172f,-0.139335f},{0.996745f,-0.0737784f,-0.0324859f}, -{0.986885f,-0.111135f,-0.11708f},{0.997794f,0.0325288f,-0.0578666f},{0.995577f,0.0928073f,0.0145992f}, -{-0.83468f,-0.496603f,0.238109f},{0.96726f,0.253285f,0.0159274f},{0.961391f,0.272285f,0.0398579f}, -{-0.359224f,0.378528f,-0.853039f},{-0.492686f,0.422685f,-0.760656f},{-0.0326768f,0.862869f,-0.504371f}, -{-0.0986429f,0.811704f,-0.575678f},{-0.0482041f,0.821139f,-0.56869f},{0.695949f,-0.682593f,-0.222985f}, -{-0.231695f,0.317407f,-0.919549f},{-0.339532f,0.320155f,-0.884431f},{-0.395214f,0.859704f,0.323596f}, -{0.3429f,0.415894f,-0.84229f},{0.385219f,0.263828f,-0.884308f},{0.378023f,0.302815f,-0.874873f}, -{-0.960881f,0.24907f,0.121132f},{-0.971621f,0.226807f,0.0671622f},{-0.37359f,0.599063f,-0.708204f}, -{-0.377794f,0.819743f,-0.430457f},{-0.609038f,0.677555f,-0.412301f},{0.385864f,-0.911894f,0.139852f}, -{0.0697907f,-0.995996f,0.0558698f},{0.845772f,0.507229f,0.165494f},{0.777954f,0.593335f,0.206739f}, -{0.920531f,0.362211f,0.146376f},{0.912664f,0.389791f,0.122911f},{0.984758f,0.16318f,0.0601944f}, -{0.997034f,0.0679387f,0.0361566f},{0.994588f,-0.101538f,-0.0220202f},{-0.666404f,0.563915f,-0.487755f}, -{-0.714725f,0.362688f,-0.598018f},{0.83658f,-0.340717f,-0.429007f},{0.863925f,-0.450595f,-0.224937f}, -{-0.799294f,0.529921f,0.283395f},{-0.967002f,0.195641f,0.163192f},{-0.339817f,0.914487f,-0.219634f}, -{-0.545492f,0.8063f,-0.228733f},{0.672512f,-0.114677f,-0.731148f},{-0.762563f,-0.532268f,-0.367679f}, -{-0.876042f,-0.304687f,-0.373786f},{-0.844516f,-0.278079f,-0.457673f},{-0.929772f,-0.312106f,-0.195229f}, -{-0.536093f,0.714569f,-0.449439f},{-0.33016f,0.913565f,-0.237471f},{-0.379477f,0.861928f,-0.336271f}, -{0.971925f,-0.229338f,-0.052599f},{-0.861158f,0.00599323f,-0.508301f},{-0.900303f,0.0329582f,-0.434013f}, -{-0.885967f,-0.0618478f,-0.459606f},{-0.536935f,-0.162785f,-0.827769f},{0.100273f,-0.323968f,-0.940739f}, -{-0.118235f,-0.477087f,-0.870867f},{0.74417f,-0.572401f,-0.344338f},{-0.875321f,-0.0583348f,-0.480011f}, -{0.940173f,0.151028f,-0.305393f},{0.962733f,-0.240052f,0.124578f},{0.76268f,-0.354927f,-0.54069f}, -{-0.999025f,0.00702945f,0.043579f},{-0.982233f,-0.171173f,0.0769339f},{-0.942957f,0.159886f,-0.292009f}, -{-0.478959f,0.775714f,-0.410934f},{0.982423f,-0.186548f,-0.00665627f},{0.990741f,-0.132479f,0.0296812f}, -{0.931631f,-0.354107f,-0.0816785f},{0.791666f,-0.0679739f,-0.607161f},{0.754519f,-0.0879699f,-0.650356f}, -{0.793904f,-0.0796276f,-0.602807f},{-0.677332f,0.731321f,-0.0799375f},{-0.656232f,0.708389f,-0.259893f}, -{-0.838214f,0.504165f,-0.207881f},{0.204869f,-0.840839f,0.501018f},{0.153821f,-0.480468f,0.863417f}, -{0.0704106f,-0.942853f,0.325686f},{0.956408f,-0.228265f,-0.18215f},{0.986183f,-0.0936427f,-0.136652f}, -{0.995545f,0.0406436f,-0.085079f},{-0.839642f,0.486502f,-0.24149f},{0.769548f,-0.526779f,-0.36097f}, -{-0.910351f,-0.333461f,-0.245081f},{-0.757463f,-0.364873f,-0.541404f},{-0.744719f,0.390985f,-0.540855f}, -{-0.863937f,-0.467813f,-0.186452f},{-0.743624f,0.127538f,-0.656321f},{-0.138916f,-0.41781f,-0.897851f}, -{0.95161f,-0.305239f,-0.035608f},{-0.0063863f,-0.628727f,-0.7776f},{-0.952006f,0.144361f,-0.269899f}, -{0.651594f,-0.183612f,-0.736011f},{0.674141f,-0.29853f,-0.675584f},{0.741378f,-0.230745f,-0.630171f}, -{-0.15322f,0.899928f,-0.408231f},{-0.207807f,0.846397f,-0.490335f},{-0.0451371f,0.827896f,-0.559063f}, -{-0.899822f,-0.311671f,-0.305256f},{-0.786522f,0.47361f,0.396329f},{-0.850935f,0.406667f,0.332463f}, -{-0.885878f,0.335753f,0.32014f},{0.686391f,-0.683815f,-0.247517f},{-0.67231f,-0.656937f,-0.341221f}, -{0.0f,0.0f,1.0f},{-0.937959f,-0.346653f,-0.00801302f},{-0.98739f,0.133802f,0.0846035f}, -{-0.0273161f,-0.138734f,-0.989953f},{0.0374685f,-0.224627f,-0.973724f},{0.705075f,-0.356919f,-0.612763f}, -{0.73297f,-0.423725f,-0.532176f},{0.77507f,-0.397151f,-0.491464f},{0.835103f,-0.224489f,-0.502203f}, -{0.813602f,-0.520484f,-0.25913f},{0.622879f,-0.584838f,-0.519602f},{0.698437f,-0.544724f,-0.464178f}, -{0.742741f,-0.582086f,-0.330926f},{0.598783f,-0.742132f,-0.301162f},{-0.949238f,0.306132f,0.0723165f}, -{-0.87596f,0.150958f,0.458154f},{0.986936f,0.159859f,0.0200684f},{0.956088f,0.286087f,0.0636382f}, -{0.984588f,0.121724f,0.125577f},{0.728274f,-0.0628471f,-0.682398f},{0.665955f,-0.0317118f,-0.745318f}, -{0.728609f,-0.14214f,-0.670019f},{-0.980512f,-0.0184633f,-0.195589f},{0.653931f,-0.666453f,0.358071f}, -{0.795056f,-0.276985f,-0.539598f},{0.829892f,-0.0953654f,-0.549713f},{0.861028f,-0.224006f,-0.456565f}, -{0.714815f,-0.275027f,-0.642962f},{-0.99155f,0.0806621f,0.101594f},{-0.127067f,0.871035f,-0.474503f}, -{0.593073f,-0.762618f,-0.258221f},{0.741611f,-0.633575f,-0.220445f},{0.879746f,-0.306992f,-0.363048f}, -{0.964765f,-0.0275073f,0.261671f},{-0.493436f,0.858968f,0.136728f},{-0.485737f,0.873949f,-0.0165395f}, -{-0.348249f,0.195388f,-0.916813f},{-0.865865f,0.42357f,0.266207f},{-0.991741f,0.0369164f,0.122831f}, -{-0.95484f,0.230839f,0.187067f},{0.413983f,-0.524267f,-0.744151f},{0.429364f,-0.694634f,-0.577174f}, -{0.190692f,-0.890844f,-0.412351f},{0.930414f,0.288332f,0.226261f},{0.997636f,-0.0670532f,0.0150621f}, -{0.995219f,0.0057273f,0.0975008f},{0.876074f,0.45196f,0.168009f},{0.878814f,-0.41968f,-0.227055f}, -{-0.230254f,-0.803082f,0.549584f},{-0.452718f,-0.646761f,0.613796f},{0.685239f,0.594863f,-0.420221f}, -{0.712106f,0.108611f,-0.69362f},{0.80921f,0.100493f,-0.578862f},{0.69558f,-0.243057f,-0.676086f}, -{0.749341f,-0.229107f,-0.621287f},{-0.46364f,-0.34574f,-0.815783f},{-0.829148f,-0.522963f,0.197543f}, -{-0.780415f,-0.576732f,0.241522f},{-0.919049f,-0.349159f,0.182857f},{-0.918924f,0.166482f,-0.35758f}, -{-0.949718f,0.0941859f,-0.298605f},{-0.970658f,0.0626362f,-0.232164f},{0.826395f,0.189191f,-0.530357f}, -{0.909795f,0.130265f,-0.394086f},{0.909374f,-0.00413196f,-0.41596f},{0.895746f,0.0197669f,-0.444126f}, -{0.690116f,-0.378259f,-0.616977f},{-0.895177f,-0.362898f,0.258771f},{0.446098f,-0.890696f,0.0875017f}, -{0.391035f,-0.914116f,0.107161f},{0.459105f,-0.882593f,0.101258f},{-0.633135f,-0.51279f,0.579816f}, -{-0.649023f,-0.452888f,0.611279f},{-0.59273f,-0.407957f,0.694437f},{0.904743f,-0.242724f,0.350034f}, -{0.828868f,-0.426799f,-0.361691f},{0.792659f,-0.553534f,-0.255525f},{-0.943462f,-0.127474f,-0.30599f}, -{-0.912574f,-0.0911195f,-0.39863f},{0.74525f,0.196846f,-0.637067f},{0.789092f,0.275901f,-0.548828f}, -{0.0114303f,-0.999602f,-0.0257713f},{0.814482f,-0.153989f,-0.55938f},{0.883559f,-0.106128f,-0.456136f}, -{0.0991691f,-0.75282f,-0.650713f},{0.1192f,-0.891997f,-0.436042f},{0.0416995f,-0.990848f,-0.128381f}, -{-0.868636f,0.464477f,0.172431f},{0.648167f,0.0160177f,-0.761329f},{0.685066f,0.331524f,-0.648673f}, -{0.713803f,-0.585761f,-0.383887f},{0.548529f,-0.764757f,-0.338028f},{-0.941654f,-0.0652673f,-0.330193f}, -{-0.947257f,-0.0320283f,-0.318871f},{-0.736538f,-0.154852f,-0.658432f},{0.841077f,-0.0220143f,-0.540467f}, -{0.839122f,0.304265f,-0.450884f},{0.671902f,-0.415255f,-0.613279f},{0.743045f,-0.290646f,-0.602834f}, -{0.791078f,-0.213203f,-0.573359f},{-0.414459f,0.780265f,0.468414f},{-0.333447f,0.81949f,0.466099f}, -{-0.350316f,0.897013f,0.269529f},{-0.445173f,0.203844f,-0.871934f},{-0.554085f,0.282607f,-0.783022f}, -{-0.371315f,0.14061f,-0.917799f},{-0.525501f,-0.42254f,-0.73845f},{-0.193952f,-0.922888f,-0.332656f}, -{-0.644837f,0.638904f,0.419509f},{-0.577435f,0.74013f,0.344638f},{0.642653f,-0.725827f,-0.245299f}, -{-0.534687f,0.832182f,-0.146915f},{-0.451134f,0.798492f,-0.398608f},{0.0169719f,-0.999804f,-0.0101645f}, -{0.036643f,-0.999184f,-0.016996f},{-0.947189f,0.122828f,0.296219f},{-0.986756f,0.0836779f,0.138966f}, -{-0.716169f,0.350797f,-0.60336f},{-0.200614f,-0.294627f,-0.934318f},{-0.321563f,-0.17239f,-0.931063f}, -{-0.956011f,0.291732f,-0.0305733f},{-0.684357f,0.683399f,-0.254208f},{0.60638f,-0.0863361f,-0.790474f}, -{0.625317f,0.0625792f,-0.777858f},{-0.9141f,0.225904f,-0.336733f},{0.74609f,-0.49078f,-0.449982f}, -{0.754326f,-0.426754f,-0.498872f},{0.721635f,-0.498468f,-0.480389f},{-0.696162f,-0.506157f,-0.509081f}, -{-0.677645f,-0.550992f,-0.487038f},{-0.924725f,0.272964f,-0.265283f},{0.747567f,-0.162517f,-0.643997f}, -{0.733726f,-0.26049f,-0.627528f},{-0.841458f,-0.3679f,0.395725f},{-0.780482f,-0.625175f,0.00217309f}, -{-0.467462f,0.83911f,-0.278161f},{-0.768839f,0.627927f,-0.120804f},{0.100807f,-0.994218f,-0.0369808f}, -{0.0348387f,-0.995477f,-0.0883868f},{-0.391848f,0.873182f,-0.28984f},{0.032085f,0.683438f,-0.729303f}, -{0.0152515f,0.645162f,-0.763893f},{-0.0140963f,0.692749f,-0.721041f},{0.798704f,-0.184977f,-0.572586f}, -{-0.523094f,0.852059f,-0.0191815f},{-0.954618f,-0.0164208f,-0.29738f},{-0.975711f,0.0897672f,-0.199826f}, -{-0.965971f,0.18126f,-0.184511f},{-0.950108f,0.0759588f,-0.30253f},{0.992414f,0.121164f,0.0208189f}, -{0.611404f,0.221804f,-0.759598f},{0.990116f,-0.0971424f,-0.101157f},{-0.7541f,-0.0822748f,-0.651585f}, -{-0.894907f,-0.409213f,-0.178004f},{-0.977252f,-0.183154f,-0.106927f},{-0.137259f,0.411548f,-0.900993f}, -{-0.0444384f,0.517873f,-0.854303f},{-0.230663f,0.547608f,-0.804313f},{0.980831f,0.19448f,0.0121421f}, -{-0.147885f,0.685989f,-0.712425f},{-0.107152f,0.598248f,-0.794114f},{-0.638269f,0.716773f,-0.280801f}, -{-0.851021f,0.359455f,0.382826f},{-0.82939f,0.350349f,0.435165f},{-0.194385f,-0.436604f,-0.878403f}, -{-0.704735f,-0.236526f,-0.668882f},{-0.894576f,0.111168f,0.43287f},{0.723662f,-0.0895417f,-0.684321f}, -{-0.26078f,0.930097f,-0.258678f},{-0.666087f,0.17054f,-0.726116f},{-0.589705f,-0.152056f,-0.793175f}, -{0.0588107f,0.66234f,-0.746892f},{0.0464484f,0.641371f,-0.765824f},{0.732878f,0.108509f,-0.671651f}, -{0.769934f,0.058901f,-0.6354f},{0.704258f,0.155158f,-0.692782f},{-0.905845f,0.0736368f,-0.417159f}, -{-0.886491f,-0.0258386f,-0.462024f},{-0.850694f,0.0210112f,-0.525241f},{0.767409f,-0.243228f,-0.593231f}, -{0.827619f,-0.193028f,-0.527055f},{0.779302f,-0.23095f,-0.582538f},{-0.884043f,-0.4635f,-0.0602925f}, -{-0.959193f,-0.26739f,-0.0919339f},{-0.85836f,-0.41451f,0.302322f},{0.765939f,-0.614183f,-0.190045f}, -{0.755147f,-0.00353785f,-0.655546f},{0.768294f,-0.249242f,-0.589579f},{0.76295f,0.0228429f,-0.646054f}, -{0.772987f,-0.200477f,-0.601914f},{0.839712f,0.218607f,-0.497086f},{0.000715683f,-0.980848f,0.194775f}, -{-0.635974f,-0.730907f,0.247612f},{-0.639593f,-0.35236f,-0.683201f},{-0.684919f,-0.396537f,-0.611264f}, -{-0.618439f,-0.339162f,-0.708874f},{0.127168f,-0.681979f,-0.720231f},{0.0782779f,-0.738573f,-0.669614f}, -{0.0113648f,-0.991394f,-0.130418f},{0.289444f,0.140849f,-0.946775f},{0.335955f,0.19986f,-0.92043f}, -{0.193556f,0.347962f,-0.91731f},{-0.974989f,0.117221f,-0.188825f},{0.219525f,0.217545f,-0.951043f}, -{-0.897894f,-0.341032f,0.27836f},{-0.897788f,-0.411493f,0.157002f},{-0.839134f,-0.369163f,0.399466f}, -{-0.895872f,-0.175299f,0.408268f},{0.843528f,-0.381703f,-0.37784f},{-0.832408f,0.491697f,-0.2556f}, -{0.518818f,0.0828733f,-0.850858f},{0.506607f,0.0628409f,-0.859884f},{0.54957f,0.240652f,-0.800037f}, -{-0.638102f,0.465486f,-0.61331f},{-0.513594f,0.704289f,-0.4901f},{-0.472045f,0.46126f,-0.751274f}, -{-0.952576f,-0.11264f,0.282687f},{0.99936f,0.00995633f,0.0343486f},{0.963471f,0.196356f,0.182123f}, -{0.984349f,0.0784931f,0.157783f},{0.279703f,0.283064f,-0.91741f},{0.181413f,0.312065f,-0.93258f}, -{0.236822f,0.427557f,-0.872416f},{-0.105609f,0.685177f,-0.72068f},{-0.976885f,-0.0286416f,0.211839f}, -{0.725157f,-0.00896551f,-0.688525f},{0.724382f,0.0375398f,-0.688376f},{0.766879f,-0.221373f,-0.602404f}, -{0.747531f,-0.347926f,-0.565814f},{0.105336f,-0.993702f,-0.0382186f},{0.399919f,-0.874604f,-0.274102f}, -{-0.642518f,0.276432f,-0.714673f},{-0.671372f,0.263996f,-0.692507f},{0.675291f,-0.602507f,-0.425403f}, -{0.218857f,-0.971126f,0.0949512f},{0.628034f,-0.747951f,0.21481f},{0.46298f,-0.856397f,0.228545f}, -{0.808891f,-0.569684f,-0.14545f},{0.653049f,-0.392291f,-0.647792f},{-0.0164474f,-0.999166f,0.0373811f}, -{-0.00770074f,-0.99916f,0.0402574f},{0.000142267f,-0.9996f,0.0282806f},{-0.141438f,0.915478f,-0.37669f}, -{-0.0262741f,0.8654f,-0.500392f},{-0.108226f,0.86563f,-0.488847f},{-0.189009f,0.743456f,-0.641521f}, -{-0.398889f,0.836374f,-0.375986f},{-0.934459f,0.0509862f,-0.352402f},{0.793651f,-0.04301f,-0.606851f}, -{0.713646f,0.148586f,-0.684567f},{-0.789885f,-0.580768f,0.196952f},{-0.807347f,-0.562697f,0.177657f}, -{-0.802356f,-0.546869f,0.239081f},{-0.118066f,-0.971948f,0.203415f},{-0.427385f,0.756545f,0.494956f}, -{0.73633f,0.308414f,-0.602245f},{0.859609f,0.0481623f,-0.508678f},{0.0357142f,-0.425029f,-0.904475f}, -{-0.216403f,-0.407845f,-0.887036f},{0.591956f,-0.749826f,-0.29555f},{0.579828f,-0.624834f,-0.52286f}, -{0.745975f,-0.250335f,-0.617133f},{0.770701f,-0.326509f,-0.547185f},{-0.889108f,-0.0981269f,-0.447054f}, -{-0.454529f,-0.0502772f,-0.889312f},{-0.637814f,-0.765383f,-0.0859141f},{-0.790282f,-0.609604f,0.0619454f}, -{0.786256f,0.100661f,-0.609646f},{0.970064f,0.194078f,0.145976f},{0.945551f,0.300532f,0.124952f}, -{-0.963703f,0.07142f,0.257248f},{0.0192169f,-0.978854f,-0.203654f},{0.893996f,-0.0181557f,-0.447706f}, -{-0.96542f,0.108981f,0.236827f},{-0.696219f,-0.631337f,-0.341603f},{-0.612492f,-0.74952f,-0.251142f}, -{-0.29042f,-0.876351f,-0.384273f},{0.639278f,-0.729907f,0.241988f},{0.69726f,-0.654375f,0.29261f}, -{-0.978716f,0.13926f,0.150735f},{0.000183522f,-0.998022f,0.0628701f},{-0.921737f,0.0503909f,-0.384528f}, -{-0.800558f,-0.493875f,-0.339402f},{-0.497304f,0.332329f,-0.801403f},{0.615217f,-0.432449f,0.659163f}, -{0.797934f,-0.505531f,-0.328238f},{0.865963f,-0.084911f,-0.492847f},{-0.305809f,-0.410663f,-0.858974f}, -{0.248637f,-0.581692f,-0.774476f},{-0.0103987f,-0.99808f,0.0610528f},{-0.951984f,0.221019f,0.21184f}, -{0.977876f,-0.181766f,-0.103535f},{-0.921649f,0.36585f,0.129297f},{0.699153f,-0.675216f,-0.23509f}, -{0.755519f,-0.604696f,-0.25206f},{0.638633f,-0.518986f,-0.568157f},{0.71167f,-0.542609f,-0.446207f}, -{0.484392f,-0.401776f,-0.777136f},{0.703104f,-0.546784f,-0.454612f},{-0.858558f,0.0931788f,-0.504178f}, -{-0.921669f,0.165028f,-0.351129f},{-0.806021f,-0.148181f,-0.573037f},{-0.710689f,-0.664555f,-0.230841f}, -{-0.840258f,-0.120608f,0.528602f},{0.887732f,-0.18165f,-0.423007f},{0.904292f,-0.119169f,-0.409946f}, -{0.867545f,-0.118966f,-0.482921f},{0.99829f,0.0581998f,-0.00551678f},{-0.914838f,0.361162f,0.180649f}, -{-0.912489f,0.395871f,0.103196f},{0.531903f,0.275915f,-0.800593f},{0.515947f,0.267172f,-0.813891f}, -{0.519825f,0.372712f,-0.768679f},{0.762899f,-0.17899f,-0.621246f},{0.702701f,-0.150915f,-0.695296f}, -{-0.294184f,0.897705f,-0.327998f},{0.147592f,0.958411f,-0.244265f},{0.177148f,0.966717f,-0.1846f}, -{0.176799f,0.971614f,-0.15719f},{-0.465063f,0.0616191f,0.883131f},{-0.418584f,-0.261446f,0.869731f}, -{0.583074f,-0.793946f,0.172264f},{0.731105f,-0.0128284f,-0.682144f},{0.676149f,-0.462984f,-0.573121f}, -{0.723236f,-0.330051f,-0.606626f},{0.704461f,0.394819f,-0.58979f},{0.843936f,-0.107503f,-0.525562f}, -{-0.96141f,-0.00372427f,-0.275096f},{-0.894378f,0.323282f,-0.309154f},{0.956972f,0.136056f,0.256306f}, -{-0.933431f,-0.350667f,-0.0757507f},{-0.130992f,0.607162f,-0.783706f},{-0.154968f,0.416175f,-0.895982f}, -{-0.260322f,0.567362f,-0.781238f},{-0.0362481f,0.607833f,-0.793237f},{-0.141952f,0.705861f,-0.693981f}, -{-0.121685f,0.645941f,-0.753627f},{-0.297167f,0.482335f,-0.824042f},{0.740034f,0.428893f,-0.518074f}, -{0.657119f,0.4288f,-0.619939f},{0.507662f,-0.441258f,-0.73998f},{-0.898184f,-0.155866f,-0.411062f}, -{-0.731846f,-0.184488f,-0.656023f},{-0.585754f,-0.776209f,-0.23322f},{-0.977273f,0.0661205f,-0.201412f}, -{-0.869666f,0.468964f,0.154123f},{-0.874285f,0.47548f,0.0976949f},{-0.765902f,0.148325f,0.625615f}, -{-0.899666f,0.406081f,0.160309f},{-0.935898f,0.330841f,0.120995f},{-0.974013f,0.125771f,0.188361f}, -{-0.976974f,0.0530194f,0.206668f},{0.923756f,0.129146f,0.360549f},{0.0350245f,-0.887122f,0.460203f}, -{0.67463f,-0.30715f,-0.671218f},{-0.504845f,-0.486101f,0.713328f},{-0.516171f,-0.350276f,0.781584f}, -{0.31792f,-0.3715f,-0.872305f},{0.511809f,-0.490299f,-0.705449f},{-0.978509f,0.204314f,-0.0278446f}, -{0.147245f,0.551976f,-0.820756f},{0.130809f,0.437729f,-0.88954f},{0.00867079f,0.703226f,-0.710913f}, -{0.425153f,-0.903936f,0.0463115f},{0.403859f,-0.905871f,0.127655f},{-0.770367f,-0.617828f,-0.157556f}, -{0.714366f,0.00755797f,-0.699732f},{0.887058f,-0.253175f,-0.386045f},{0.904446f,-0.229688f,-0.359473f}, -{0.889749f,-0.237271f,-0.389934f},{-0.0191102f,-0.999817f,-0.00115212f},{0.0066128f,-0.999505f,0.0307467f}, -{0.00427601f,-0.998407f,-0.0562644f},{0.709271f,-0.160033f,-0.686531f},{0.74534f,-0.288142f,-0.601201f}, -{0.608205f,-0.355153f,-0.709896f},{0.125865f,0.782562f,-0.609717f},{-0.0739411f,0.799269f,-0.596407f}, -{0.0508085f,0.72803f,-0.68366f},{-0.814112f,-0.561646f,-0.147568f},{0.972331f,0.159512f,0.170672f}, -{0.861139f,-0.229934f,-0.453399f},{0.894211f,-0.209492f,-0.395601f},{-0.220335f,-0.862894f,0.454827f}, -{-0.215799f,-0.863267f,0.456291f},{0.819689f,0.0614222f,-0.569506f},{0.857209f,0.0364918f,-0.513673f}, -{-0.95851f,-0.25396f,0.129474f},{0.847391f,-0.263974f,-0.460701f},{0.410327f,-0.908244f,0.0820033f}, -{0.250237f,-0.965597f,0.0707417f},{0.529549f,-0.264119f,-0.806113f},{0.541477f,0.764778f,-0.349167f}, -{-0.0183646f,0.673017f,-0.739399f},{-0.00922519f,0.686325f,-0.727236f},{-0.969929f,-0.182964f,0.160506f}, -{-0.0327101f,-0.996404f,-0.0781646f},{0.542598f,0.111129f,-0.832609f},{-0.054401f,0.718347f,-0.693555f}, -{0.960249f,-0.258809f,-0.104594f},{0.868777f,-0.0882508f,-0.487276f},{0.0262056f,-0.999314f,-0.0261689f}, -{-0.742036f,-0.634751f,0.215576f},{-0.790094f,-0.603961f,-0.104797f},{0.684195f,0.0425916f,-0.728054f}, -{0.909851f,-0.135259f,-0.39227f},{0.846745f,0.00228132f,-0.531994f},{-0.982988f,-0.164733f,0.0812222f}, -{0.995198f,-0.0892049f,-0.0402945f},{0.986315f,0.147268f,0.0741227f},{0.566721f,0.31205f,-0.76253f}, -{0.401851f,0.226639f,-0.887215f},{0.0372775f,-0.264135f,-0.963765f},{-0.976716f,0.0122543f,0.214188f}, -{-0.313664f,0.917903f,-0.243042f},{-0.352028f,0.889474f,-0.291398f},{0.108126f,-0.83625f,-0.537583f}, -{0.171862f,-0.95061f,-0.258466f},{0.86963f,-0.270204f,-0.4132f},{-0.903531f,0.323979f,0.28048f}, -{-0.683437f,0.620562f,0.384468f},{-0.691721f,-0.7163f,-0.0918445f},{-0.736096f,0.554191f,0.388633f}, -{-0.645063f,0.68258f,0.34348f},{-0.614513f,-0.77154f,0.164621f},{0.669319f,-0.537608f,-0.512825f}, -{0.327855f,-0.918252f,0.222092f},{0.298594f,-0.934062f,0.19588f},{0.354796f,-0.918097f,0.176686f}, -{-0.506672f,0.834157f,0.217865f},{0.0345878f,-0.999201f,-0.020016f},{0.931099f,0.276016f,-0.238473f}, -{-0.020536f,-0.30336f,-0.952655f},{-0.469175f,-0.414153f,-0.779969f},{0.118301f,-0.895303f,-0.429462f}, -{0.099007f,-0.97542f,-0.196861f},{0.0272237f,-0.999335f,-0.0242418f},{-0.674057f,0.449826f,-0.585921f}, -{0.703665f,0.384147f,-0.597735f},{0.33071f,0.351781f,-0.875718f},{0.0978065f,0.508281f,-0.855619f}, -{0.546689f,-0.0132231f,-0.837231f},{0.896842f,-0.151815f,-0.415484f},{-0.960075f,0.245652f,0.133831f}, -{-0.98563f,0.084896f,0.146033f},{-0.899805f,0.257965f,0.351859f},{0.827633f,-0.396764f,-0.39699f}, -{-0.883847f,0.292303f,0.365202f},{-0.965708f,0.175981f,0.190889f},{-0.272344f,-0.945067f,-0.180768f}, -{0.0209144f,-0.999074f,0.0376027f},{0.032975f,-0.998556f,-0.0424153f},{0.0318291f,-0.998875f,-0.0351631f}, -{0.0352428f,-0.998819f,-0.0334404f},{0.0388307f,-0.998288f,0.0437481f},{-0.647332f,-0.523114f,-0.554359f}, -{-0.355664f,-0.613777f,-0.704826f},{0.959933f,-0.275879f,-0.0491777f},{0.992104f,-0.125231f,0.00679531f}, -{-0.0944883f,0.823707f,0.559088f},{-0.999729f,-0.0207259f,-0.0106073f},{0.563333f,0.0340497f,-0.825528f}, -{0.998869f,0.0105482f,0.0463714f},{-0.470932f,0.711152f,0.522003f},{0.278589f,0.329839f,-0.901994f}, -{-0.886327f,0.432631f,-0.165089f},{-0.926808f,0.375345f,-0.0119485f},{0.204039f,-0.372273f,-0.905418f}, -{-0.992881f,0.0451062f,0.110243f},{-0.59668f,0.742712f,0.303894f},{-0.791167f,0.0261632f,-0.61104f}, -{0.438938f,-0.894537f,-0.0844837f},{-0.00869637f,-0.999954f,0.00417063f},{-0.0213252f,-0.999674f,0.0140172f}, -{-0.153982f,0.624937f,-0.765339f},{0.794822f,-0.532167f,-0.291645f},{0.811671f,-0.521067f,-0.263968f}, -{-0.517259f,-0.574715f,-0.63415f},{-0.93562f,0.340752f,-0.0922097f},{0.236175f,-0.960352f,-0.148136f}, -{0.553704f,-0.827051f,-0.096947f},{0.870867f,0.381557f,0.309847f},{0.853989f,0.341659f,0.392392f}, -{-0.154021f,-0.650535f,-0.743694f},{0.0262376f,-0.999048f,0.0348535f},{0.0225118f,-0.999678f,0.0117443f}, -{-0.124984f,-0.435542f,-0.891449f},{-0.37736f,-0.556838f,-0.739954f},{0.872701f,0.335303f,0.354917f}, -{0.853307f,0.326584f,0.40646f},{0.93813f,0.199247f,0.283218f},{0.0217241f,-0.999386f,-0.0274869f}, -{-0.597863f,-0.38968f,-0.700507f},{0.959073f,0.10872f,0.261455f},{-0.18484f,-0.257829f,-0.948345f}, -{0.154603f,-0.413225f,-0.897409f},{0.717788f,-0.687313f,0.111275f},{0.847382f,-0.520852f,0.103229f}, -{0.924113f,0.287993f,0.251147f},{0.911501f,0.262502f,0.316637f},{0.76148f,-0.482196f,-0.433169f}, -{0.940386f,0.129455f,0.314508f},{0.863147f,0.448876f,0.231275f},{0.761826f,-0.641831f,0.0876031f}, -{0.906001f,0.324256f,0.272067f},{0.0985965f,-0.902022f,-0.420279f},{-0.88257f,0.38391f,0.271447f}, -{-0.968928f,0.130172f,0.21032f},{-0.102488f,-0.994179f,-0.0332447f},{-0.0442014f,-0.992883f,-0.110588f}, -{0.962835f,0.199899f,0.181627f},{0.221024f,0.37711f,-0.899409f},{0.217884f,0.261235f,-0.940363f}, -{0.204653f,0.371797f,-0.905474f},{-0.385283f,0.722821f,0.573662f},{0.800531f,-0.19496f,-0.566693f}, -{0.975873f,0.0781187f,0.203887f},{0.976396f,0.098517f,0.192213f},{0.964255f,0.132192f,0.229645f}, -{0.95341f,0.0958946f,0.286032f},{0.946655f,0.14687f,0.286835f},{0.940817f,0.252628f,0.225928f}, -{0.905792f,0.35846f,0.225938f},{0.90519f,0.368597f,0.211583f},{0.916708f,0.349413f,0.193796f}, -{0.904462f,0.381361f,0.191082f},{0.824432f,0.565116f,0.0309246f},{0.82786f,0.560907f,-0.00562512f}, -{-0.96563f,-0.0745097f,0.249011f},{-0.351993f,-0.922569f,0.15801f},{-0.05336f,-0.995682f,0.075956f}, -{-0.360501f,-0.839956f,0.405602f},{0.864828f,0.398074f,0.305956f},{0.795907f,0.528246f,0.295782f}, -{0.956112f,0.21274f,0.201471f},{0.974732f,0.0578164f,0.215767f},{0.962779f,0.0784324f,0.258661f}, -{0.234707f,-0.73487f,0.636301f},{-0.210907f,-0.231875f,-0.949606f},{0.971296f,0.156885f,0.178808f}, -{0.951489f,0.120919f,0.282925f},{0.0275537f,-0.999051f,-0.0337455f},{-0.318759f,-0.932821f,-0.168041f}, -{0.816302f,0.491849f,0.302878f},{0.778816f,0.567945f,0.266241f},{0.617103f,-0.751326f,0.233866f}, -{0.986863f,-0.0263569f,0.159393f},{0.914441f,0.385846f,0.122154f},{0.939377f,0.3255f,0.107795f}, -{-0.269202f,-0.242719f,-0.931997f},{-0.62682f,0.758358f,0.178856f},{-0.842996f,0.537838f,-0.00937066f}, -{-0.624626f,0.757251f,-0.190825f},{-0.0746514f,-0.561558f,-0.824063f},{0.974361f,0.14028f,0.175902f}, -{0.721718f,0.541276f,-0.431444f},{0.691845f,-0.678714f,0.246368f},{0.940354f,-0.258607f,0.221034f}, -{0.961877f,-0.119882f,0.245806f},{0.63723f,-0.429472f,-0.639915f},{0.989181f,0.0945617f,0.11216f}, -{0.990752f,0.0975521f,0.094307f},{0.985711f,0.123981f,0.114028f},{0.977333f,0.166331f,0.130976f}, -{0.956945f,0.25428f,0.139992f},{0.923567f,0.353306f,0.148994f},{0.91272f,0.377482f,0.156363f}, -{0.916948f,0.362123f,0.167552f},{0.911395f,0.387113f,0.139649f},{0.835581f,0.53732f,0.114417f}, -{0.968796f,0.231741f,0.0879191f},{-0.704802f,0.0615895f,0.706725f},{-0.765553f,-0.532367f,0.361267f}, -{-0.755914f,-0.172051f,0.631659f},{0.863069f,0.405931f,0.300552f},{0.838471f,0.491299f,0.235781f}, -{0.902746f,0.311662f,0.296507f},{0.972589f,0.0739923f,0.220444f},{0.61259f,-0.265774f,-0.744377f}, -{0.968436f,0.216794f,0.123015f},{0.976937f,-0.152909f,0.14904f},{-0.171894f,0.773899f,-0.609535f}, -{-0.279005f,0.84322f,-0.459496f},{0.0318361f,-0.999257f,-0.0217057f},{-0.686432f,-0.418899f,0.59442f}, -{0.940718f,-0.314328f,0.127464f},{0.127985f,-0.970691f,-0.203416f},{-0.140049f,0.795548f,0.589483f}, -{0.890566f,0.394901f,0.225712f},{-0.17875f,0.0676498f,-0.981566f},{-0.130389f,0.136394f,-0.982036f}, -{-0.693075f,-0.719421f,-0.045614f},{-0.854093f,-0.520116f,0.00228063f},{-0.697985f,-0.682744f,0.216051f}, -{0.958009f,0.268102f,0.101683f},{0.910047f,0.341379f,0.235107f},{-0.130869f,0.189174f,-0.973184f}, -{-0.136388f,0.204777f,-0.96926f},{-0.360244f,0.91344f,-0.189348f},{0.00927586f,0.997961f,-0.0631495f}, -{-0.269327f,0.956986f,-0.107895f},{0.0065507f,0.999964f,-0.00535563f},{-0.0516087f,0.998536f,0.0162233f}, -{-0.00549771f,0.998424f,0.0558435f},{-0.966082f,-0.223912f,0.128644f},{-0.959726f,-0.273362f,0.0647994f}, -{0.195186f,0.974535f,0.110378f},{0.102488f,0.979166f,0.175299f},{0.647374f,0.671496f,0.360554f}, -{-0.3164f,0.947491f,0.0463864f},{0.0622768f,0.854897f,0.515046f},{0.0187868f,0.827973f,0.560453f}, -{0.793441f,0.573205f,0.204667f},{0.570489f,0.666316f,0.480172f},{0.0149417f,0.788806f,0.614461f}, -{0.551521f,0.679451f,0.483912f},{-0.33077f,0.874133f,0.355644f},{-0.381363f,0.807787f,0.449491f}, -{-0.0394864f,0.843368f,0.535884f},{-0.875505f,-0.465724f,0.128814f},{-0.186669f,0.821205f,0.539237f}, -{-0.40397f,0.803553f,0.437162f},{0.0275706f,0.940562f,0.3385f},{0.0127497f,0.923202f,0.384103f}, -{0.0978516f,0.88668f,0.451912f},{-0.978017f,0.136329f,0.157789f},{0.63961f,0.752729f,0.155875f}, -{0.574715f,0.728057f,0.373678f},{0.296871f,0.73371f,0.611177f},{0.583868f,0.792562f,-0.175909f}, -{0.613508f,0.789373f,-0.0223071f},{0.30635f,0.812628f,0.495768f},{0.7584f,0.598623f,0.257838f}, -{0.751662f,0.579045f,0.315772f},{0.626681f,0.697524f,0.347462f},{0.327733f,0.893655f,0.306548f}, -{0.0817467f,0.949563f,0.302734f},{0.609838f,0.702151f,0.367535f},{-0.141646f,0.863148f,0.484677f}, -{-0.248361f,0.827147f,0.504127f},{0.251704f,0.958776f,0.131885f},{-0.00860057f,0.843532f,0.53701f}, -{0.610942f,0.685026f,0.39685f},{0.563461f,0.706036f,0.428981f},{0.290591f,0.953423f,-0.0808732f}, -{-0.0416996f,0.942389f,0.331909f},{-0.242277f,-0.954806f,0.172186f},{-0.508478f,-0.833053f,0.217884f}, -{-0.706606f,-0.680659f,-0.193422f},{-0.780268f,-0.571677f,-0.253706f},{0.203519f,0.955669f,-0.212783f}, -{-0.409056f,0.847362f,0.338602f},{-0.10077f,0.935414f,0.338889f},{-0.143977f,0.951576f,0.271611f}, -{-0.167925f,0.867559f,0.468127f},{0.117004f,0.992992f,-0.0166474f},{-0.0198098f,0.997063f,0.0739749f}, -{-0.0233485f,0.980743f,0.193904f},{-0.0633045f,0.881613f,0.467708f},{-0.0576471f,0.742484f,0.667378f}, -{-0.38597f,0.7806f,0.491621f},{-0.424397f,0.710223f,0.561668f},{-0.329934f,0.7797f,0.532176f}, -{-0.66792f,0.709634f,0.224284f},{-0.451594f,0.832424f,0.321144f},{-0.0026761f,0.997846f,-0.0655392f}, -{0.0393049f,0.947095f,0.318538f},{-0.0874497f,0.213337f,-0.973057f},{-0.14254f,0.226346f,-0.963561f}, -{-0.079948f,0.963489f,0.255531f},{0.00520031f,0.979625f,-0.200767f},{0.160151f,0.97548f,0.150967f}, -{-0.30432f,0.934853f,-0.182866f},{-0.382215f,0.88348f,-0.270877f},{-0.0554854f,0.991601f,-0.116832f}, -{0.238752f,0.970688f,0.0276203f},{0.658975f,0.641087f,0.393396f},{-0.166042f,0.978496f,0.122378f}, -{0.0307127f,0.987931f,0.151817f},{-0.343655f,0.938408f,-0.0359483f},{0.334978f,0.937134f,-0.0978196f}, -{0.843998f,0.536343f,-0.00166254f},{0.0366952f,0.998946f,-0.0275677f},{-0.406013f,0.896936f,0.175099f}, -{-0.523428f,0.7564f,-0.392279f},{-0.719595f,0.569109f,-0.397866f},{0.0774109f,0.330299f,-0.940697f}, -{-0.926674f,0.36204f,0.101006f},{0.573185f,0.791566f,0.211852f},{0.759727f,0.648451f,-0.0482235f}, -{0.912176f,0.39349f,0.114457f},{-0.973178f,-0.227499f,0.0341798f},{0.27077f,0.673918f,0.6874f}, -{0.737332f,0.667635f,-0.102979f},{0.79274f,0.608946f,0.0273588f},{0.606984f,0.722816f,0.330314f}, -{0.898969f,0.435381f,0.0479348f},{0.596787f,0.704856f,-0.383437f},{-0.940796f,-0.0582889f,0.333923f}, -{0.00474336f,-0.999893f,-0.0138285f},{-0.00631413f,-0.999977f,0.00228954f},{0.0132945f,-0.999842f,0.0117666f}, -{0.725395f,0.687263f,0.0383686f},{-0.623881f,-0.449673f,-0.639192f},{-0.710202f,-0.337333f,-0.617915f}, -{-0.564536f,-0.513949f,-0.645876f},{0.205114f,0.939815f,-0.273268f},{0.306274f,0.933228f,-0.187833f}, -{0.293334f,0.918292f,-0.265886f},{-0.730003f,0.627909f,0.269862f},{0.0412235f,0.990147f,-0.133823f}, -{-0.0506354f,0.990554f,-0.127428f},{-0.797838f,0.144275f,0.585354f},{-0.814328f,-0.00914634f,0.580333f}, -{-0.875474f,-0.0288966f,0.482401f},{-0.87953f,0.267082f,0.393819f},{0.193281f,0.980464f,-0.0365016f}, -{0.241335f,0.970224f,0.0205498f},{0.2625f,0.963919f,-0.0442113f},{-0.0568875f,0.994164f,-0.0916615f}, -{-0.00599234f,0.955773f,0.294044f},{-0.632698f,0.175517f,-0.754246f},{-0.709847f,0.319233f,-0.627859f}, -{-0.644735f,0.295137f,-0.705132f},{0.0790042f,0.929158f,0.361142f},{0.76758f,0.541513f,0.342907f}, -{0.804976f,0.457231f,0.378091f},{0.147986f,0.988531f,0.0301111f},{0.696325f,0.673718f,0.247458f}, -{0.711674f,0.542561f,0.446261f},{0.242014f,0.964107f,-0.109214f},{0.161173f,0.924593f,0.345182f}, -{-0.999615f,-0.0214551f,0.0176068f},{-0.892926f,0.154387f,0.422904f},{-0.837955f,-0.521028f,0.162363f}, -{-0.839437f,-0.532918f,0.106511f},{0.0638424f,0.997652f,-0.0248022f},{-0.715259f,-0.673496f,0.186566f}, -{-0.61264f,-0.789564f,0.0355033f},{0.31859f,0.837066f,0.444771f},{0.316983f,0.920076f,-0.230177f}, -{0.428733f,0.866239f,-0.25655f},{0.271337f,0.960436f,-0.0627656f},{0.324601f,0.944442f,0.051613f}, -{-0.581084f,0.522689f,0.623809f},{-0.440341f,0.699445f,0.562918f},{-0.287863f,-0.196649f,-0.937264f}, -{-0.330953f,-0.324711f,-0.886021f},{0.339123f,0.808747f,0.480546f},{-0.021721f,0.882003f,0.470743f}, -{0.127878f,0.991291f,0.0314696f},{0.098346f,0.992921f,0.0665993f},{0.0284123f,-0.997479f,0.0650288f}, -{0.020356f,-0.99678f,0.0775616f},{0.0240698f,-0.997295f,0.069456f},{0.278418f,0.949947f,-0.141718f}, -{0.604354f,0.51753f,0.605738f},{0.185444f,0.978943f,-0.0853253f},{-0.902527f,-0.429563f,0.0303291f}, -{0.180423f,0.975577f,0.125284f},{0.291481f,0.956568f,-0.00407742f},{0.349613f,0.890753f,-0.290396f}, -{0.356001f,0.892578f,-0.27671f},{-0.772158f,0.517877f,0.368206f},{-0.833386f,-0.170946f,0.525591f}, -{-0.467427f,0.879952f,-0.0848387f},{0.745154f,0.610309f,-0.268828f},{-0.860918f,-0.0426011f,-0.506957f}, -{-0.425821f,0.844817f,-0.323977f},{-0.138972f,0.83396f,0.534038f},{0.641568f,0.757832f,0.118662f}, -{0.82573f,0.549377f,0.127887f},{0.436349f,0.851679f,0.290243f},{0.149454f,0.967097f,0.205881f}, -{0.123489f,0.962764f,0.240489f},{0.0777148f,0.948839f,0.306049f},{0.259818f,0.964051f,0.0556885f}, -{0.671152f,0.613816f,0.415674f},{0.737405f,0.584125f,0.339162f},{0.0787638f,0.972075f,0.221056f}, -{0.0226107f,0.965058f,0.261059f},{-0.318905f,0.888959f,-0.328713f},{-0.387093f,0.91673f,0.0988183f}, -{0.338681f,0.924639f,0.174179f},{-0.0464892f,0.917725f,0.394486f},{0.34519f,0.784268f,0.515527f}, -{0.0981635f,0.845149f,0.525441f},{0.32706f,0.938825f,-0.107887f},{0.334149f,0.940787f,-0.057133f}, -{0.360584f,0.904615f,-0.227268f},{0.370049f,0.916384f,-0.152656f},{0.219202f,0.949682f,-0.223729f}, -{0.0417123f,0.962056f,0.269644f},{0.0445164f,0.999004f,0.0029002f},{0.0311419f,0.99584f,0.0856323f}, -{-0.0105715f,0.904381f,0.426594f},{0.250169f,0.889893f,0.381453f},{-0.479884f,0.734289f,0.480136f}, -{0.0616234f,0.91504f,0.398629f},{-0.873565f,-0.484911f,0.0417901f},{0.193391f,0.97755f,0.0836386f}, -{-0.24517f,-0.897212f,-0.367291f},{-0.738477f,0.556206f,-0.381164f},{0.00208972f,0.995448f,-0.0952887f}, -{0.023146f,0.996478f,-0.0805908f},{-0.200122f,0.828964f,0.522273f},{-0.223522f,0.953553f,0.201925f}, -{0.261343f,0.928881f,-0.262449f},{0.331113f,0.923764f,-0.192418f},{0.573723f,0.819049f,0.000855026f}, -{0.362715f,0.829104f,0.42547f},{-0.0573298f,0.844648f,0.532243f},{-0.0897245f,0.990344f,-0.105682f}, -{0.791768f,0.584989f,0.175761f},{0.788555f,0.524059f,0.321781f},{0.396688f,0.784354f,0.476893f}, -{-0.142441f,0.853827f,0.50069f},{-0.497251f,0.741148f,0.451045f},{-0.52758f,0.754131f,-0.391083f}, -{-0.74581f,0.423423f,-0.514276f},{-0.835334f,0.507605f,-0.211079f},{-0.760969f,0.639595f,0.108834f}, -{0.665519f,0.564337f,0.488476f},{0.184704f,0.965314f,0.184535f},{-0.377948f,0.905644f,-0.19226f}, -{-0.374352f,0.926577f,-0.0362743f},{0.481967f,0.867384f,0.123909f},{0.524646f,0.846426f,-0.0911632f}, -{-0.0773877f,0.88845f,0.452402f},{-0.697527f,-0.161082f,0.698218f},{-0.728014f,-0.219408f,0.649505f}, -{-0.806167f,-0.22881f,0.545657f},{0.859404f,0.505542f,0.0765056f},{0.18694f,0.936136f,0.297831f}, -{0.627902f,0.752182f,-0.199901f},{0.439551f,0.827994f,0.348167f},{-0.106603f,0.891453f,0.440395f}, -{-0.739824f,0.137059f,0.658692f},{-0.696005f,0.314806f,0.645348f},{0.777963f,0.596105f,0.198575f}, -{0.625854f,0.727341f,0.281572f},{0.586037f,0.75803f,0.286273f},{-0.273339f,0.876824f,0.395556f}, -{-0.117479f,0.873974f,0.471559f},{-0.141536f,0.827666f,0.543081f},{0.0223492f,-0.998109f,0.0572571f}, -{-0.000931591f,-0.998825f,0.0484584f},{-0.360291f,0.888095f,0.285442f},{-0.105675f,0.913747f,0.392299f}, -{-0.13649f,0.989925f,0.0376649f},{0.0384947f,0.98542f,0.165729f},{0.647598f,0.705639f,-0.287558f}, -{-0.629182f,0.60845f,-0.483651f},{-0.18035f,0.850769f,0.493626f},{-0.200136f,0.659248f,0.724802f}, -{-0.40814f,0.771931f,0.487385f},{-0.56766f,0.779026f,0.266235f},{-0.50392f,0.782727f,0.365244f}, -{0.059644f,0.998218f,-0.00191144f},{0.493305f,0.788252f,0.367843f},{0.233534f,0.915322f,0.328097f}, -{0.100081f,0.994977f,-0.001886f},{0.0540968f,0.9859f,0.158351f},{0.0288702f,0.997117f,-0.0701744f}, -{-0.579249f,0.78716f,-0.211777f},{0.474653f,0.813336f,0.336437f},{0.549723f,0.788931f,0.274576f}, -{-0.633886f,0.679356f,0.369682f},{-0.0300771f,0.878075f,0.477576f},{0.0456401f,0.99866f,-0.0244092f}, -{0.0727139f,0.973018f,0.21897f},{0.0735803f,0.671302f,-0.737522f},{0.0494458f,0.395419f,-0.917169f}, -{0.00888718f,0.859255f,-0.511471f},{-0.854026f,0.2938f,0.429328f},{0.267715f,0.935591f,0.230212f}, -{-0.0884375f,0.963257f,-0.253602f},{-0.27228f,0.959388f,-0.0737389f},{-0.55698f,0.773671f,-0.302004f}, -{-0.71943f,0.67545f,-0.161826f},{-0.653106f,0.624328f,-0.428564f},{-0.379852f,0.787478f,-0.485377f}, -{-0.0496136f,0.821031f,0.568724f},{-0.556395f,0.828516f,-0.0631306f},{-0.00650614f,0.939219f,0.343256f}, -{-0.0378066f,0.973412f,-0.225918f},{-0.554061f,0.40543f,-0.727078f},{-0.569182f,0.171273f,-0.804175f}, -{-0.709345f,0.399365f,-0.580807f},{0.312263f,0.8806f,-0.356421f},{0.670924f,0.693388f,0.262818f}, -{-0.537859f,0.0528585f,0.841376f},{0.383935f,0.853309f,0.352785f},{-0.437111f,0.89267f,0.109884f}, -{-0.318147f,0.945762f,0.0657079f},{0.817501f,0.574998f,0.0327173f},{0.804964f,0.593238f,-0.0100991f}, -{0.82956f,0.536471f,0.155014f},{0.807816f,0.543091f,0.229097f},{0.767553f,0.561873f,0.308482f}, -{0.734804f,0.509692f,0.447523f},{-0.184696f,0.932773f,-0.309551f},{-0.164745f,0.95509f,-0.246299f}, -{0.272873f,0.875473f,0.398857f},{-0.547438f,0.648874f,0.528464f},{-0.509731f,0.801615f,0.312391f}, -{-0.693304f,0.660768f,0.287602f},{0.830856f,0.553276f,-0.0596929f},{0.817452f,0.574321f,0.04391f}, -{0.82274f,0.56071f,0.0932945f},{0.799149f,0.580408f,0.156486f},{-0.187866f,0.976313f,0.107331f}, -{0.83228f,0.547521f,-0.0867808f},{0.814186f,0.578133f,-0.0535041f},{0.810153f,0.585831f,0.0213339f}, -{0.809173f,0.580772f,0.0891247f},{0.80695f,0.590596f,-0.00528696f},{0.801762f,0.595959f,0.044831f}, -{0.77998f,0.602313f,0.169853f},{0.744047f,0.592678f,0.308427f},{-0.966823f,0.0452095f,0.251413f}, -{-0.956155f,0.198707f,0.215134f},{0.0574333f,0.997765f,-0.0341582f},{0.806921f,0.589501f,-0.0369692f}, -{0.802278f,0.59668f,0.0179628f},{0.766982f,0.633314f,0.10321f},{0.650228f,0.622419f,0.435658f}, -{0.704453f,0.647844f,0.289904f},{0.628921f,0.597557f,0.497378f},{-0.743343f,0.229344f,-0.628365f}, -{-0.69546f,0.312394f,-0.647105f},{-0.660438f,0.266932f,-0.701832f},{0.806766f,0.581782f,-0.103241f}, -{0.80487f,0.593418f,-0.00630056f},{0.769639f,0.637487f,0.035579f},{0.734675f,0.659159f,0.160504f}, -{0.80405f,0.549513f,-0.227025f},{0.803626f,0.593911f,-0.0381408f},{0.769531f,0.638363f,-0.0177426f}, -{0.765295f,0.642865f,0.0323697f},{0.567755f,0.649438f,0.505849f},{0.381409f,-0.893429f,-0.237301f}, -{-0.00752063f,0.229679f,-0.973237f},{0.807026f,0.580752f,-0.10694f},{0.758431f,0.650052f,-0.047062f}, -{0.732079f,0.672795f,0.106805f},{0.704091f,0.702637f,0.102745f},{0.698117f,0.699929f,0.150773f}, -{0.663589f,0.679392f,0.313173f},{0.574373f,0.681896f,0.452896f},{-0.803084f,0.330145f,-0.496045f}, -{0.798028f,0.532226f,-0.282643f},{0.766386f,0.563802f,-0.307862f},{0.80442f,0.55547f,-0.210621f}, -{0.76591f,0.631894f,-0.11871f},{0.715646f,0.697201f,0.0419614f},{0.603596f,0.722225f,0.337732f}, -{0.520807f,0.654939f,0.547553f},{0.229172f,0.800804f,0.553347f},{0.0812578f,0.986317f,-0.143444f}, -{-0.9886f,0.111022f,-0.101703f},{0.741263f,0.671205f,0.00366621f},{0.704182f,0.709381f,0.0301024f}, -{0.639249f,0.747109f,0.182178f},{0.586867f,0.654313f,0.47693f},{-0.604248f,0.685136f,0.406783f}, -{0.749005f,0.617153f,-0.241066f},{0.692909f,0.716962f,-0.0764364f},{0.694198f,0.719117f,-0.0309967f}, -{0.667752f,0.740189f,0.0789108f},{0.709131f,0.696508f,-0.109592f},{0.666081f,0.734678f,-0.128782f}, -{0.67466f,0.736436f,0.0499464f},{0.637302f,0.765583f,0.0879164f},{0.605727f,0.778945f,0.162297f}, -{0.584384f,0.769989f,0.25615f},{0.569427f,0.738575f,0.360916f},{0.701706f,0.63332f,-0.326365f}, -{0.672913f,0.705054f,-0.2238f},{0.646507f,0.761239f,0.0504462f},{0.540585f,0.730735f,0.416886f}, -{0.554591f,0.652851f,0.515959f},{-0.45615f,0.77338f,-0.440239f},{-0.861977f,-0.205293f,0.463519f}, -{-0.851613f,0.0465911f,0.522096f},{-0.884595f,-0.0397011f,0.464667f},{-0.265588f,0.792521f,0.548975f}, -{0.626767f,0.74215f,-0.237436f},{0.650336f,0.759537f,0.0128991f},{0.607046f,0.766684f,0.209022f}, -{0.42584f,0.81007f,-0.403047f},{0.479766f,0.78941f,-0.382957f},{0.440625f,0.776807f,-0.449912f}, -{-0.965918f,-0.188346f,-0.177559f},{-0.917033f,-0.300542f,-0.262156f},{0.655378f,0.670166f,-0.348365f}, -{0.655846f,0.747655f,-0.104302f},{0.638829f,0.768028f,-0.0450667f},{0.620536f,0.777113f,0.105025f}, -{0.419917f,0.795884f,0.436164f},{-0.484423f,0.76896f,-0.417174f},{0.283428f,-0.883937f,-0.371919f}, -{-0.877507f,-0.432781f,-0.206596f},{-0.0647534f,0.116705f,-0.991053f},{-0.00251298f,-0.196393f,-0.980522f}, -{-0.120996f,-0.17257f,-0.977537f},{0.625618f,0.75948f,-0.178302f},{0.622883f,0.775196f,-0.105295f}, -{0.618509f,0.784484f,0.045081f},{0.555738f,0.808838f,0.192188f},{0.540989f,0.792397f,0.281847f}, -{0.494361f,0.783838f,0.375773f},{-0.472517f,-0.398134f,0.786268f},{-0.503204f,-0.412649f,0.75928f}, -{-0.0691448f,0.651623f,-0.755385f},{-0.0855156f,0.570482f,-0.816846f},{-0.886059f,-0.355448f,-0.297583f}, -{0.594546f,0.762545f,-0.255029f},{0.622101f,0.721187f,-0.304761f},{0.605176f,0.774254f,-0.185182f}, -{0.610974f,0.791608f,0.00823471f},{0.573345f,0.817999f,0.0464058f},{0.560795f,0.821271f,0.10499f}, -{0.414525f,0.848734f,0.328358f},{0.736676f,0.649956f,0.186727f},{0.0552009f,0.917445f,0.394014f}, -{0.58116f,0.774985f,-0.248299f},{0.603961f,0.79543f,-0.0502213f},{0.566922f,0.823735f,0.00775409f}, -{0.433232f,0.874383f,0.218552f},{0.338907f,0.844676f,0.414324f},{0.335796f,0.825149f,0.45428f}, -{0.335634f,0.727757f,0.598097f},{0.592382f,0.796432f,-0.121568f},{0.564733f,0.823747f,-0.0501802f}, -{0.471839f,0.874441f,0.112784f},{0.391375f,0.8556f,0.338782f},{0.272028f,0.795259f,0.541815f}, -{-0.321054f,-0.946891f,-0.017938f},{-0.583011f,0.804225f,-0.115411f},{-0.0186705f,0.88413f,0.466868f}, -{0.58237f,0.771302f,-0.256787f},{0.583304f,0.788563f,-0.194745f},{0.56576f,0.815156f,-0.124239f}, -{0.508372f,0.860502f,0.0330708f},{0.427096f,0.759848f,0.490122f},{0.0181058f,0.259257f,-0.965639f}, -{-0.0500199f,0.232695f,-0.971262f},{0.0170665f,0.950699f,0.309644f},{-0.0152952f,0.950205f,0.311251f}, -{-0.881404f,0.0726797f,-0.466739f},{-0.877608f,0.0389104f,-0.477797f},{0.30436f,0.386033f,-0.870829f}, -{0.165782f,0.556552f,-0.814105f},{0.346919f,0.302604f,-0.887737f},{0.513981f,0.856343f,-0.0500122f}, -{0.511201f,0.859461f,-0.000758396f},{0.361243f,0.903013f,0.23253f},{0.452609f,0.687968f,0.567314f}, -{0.407572f,0.674302f,0.615794f},{0.57013f,0.802797f,-0.174555f},{0.51097f,0.852913f,-0.107003f}, -{0.453526f,0.888135f,0.0743731f},{0.413537f,0.896599f,0.158418f},{0.389912f,0.886016f,0.250887f}, -{0.445681f,0.789273f,0.422395f},{0.309789f,0.731113f,0.607869f},{-0.0846571f,0.900316f,0.426924f}, -{0.545197f,0.794322f,-0.267979f},{0.547967f,0.836466f,-0.00756271f},{0.470132f,0.882429f,0.0171804f}, -{0.431296f,0.900927f,0.0481153f},{0.416849f,0.879298f,0.230372f},{0.440959f,0.838019f,0.321371f}, -{0.407999f,0.737634f,0.537989f},{-0.886332f,0.390751f,0.248453f},{-0.833616f,0.516196f,0.196536f}, -{0.471464f,0.881296f,-0.0322266f},{0.438674f,0.898631f,0.00523751f},{0.406783f,0.824159f,0.394068f}, -{0.2856f,0.832072f,0.475488f},{0.457025f,0.885608f,-0.0826232f},{0.446409f,0.893715f,-0.0446337f}, -{0.402155f,0.90619f,0.130735f},{0.173173f,0.782164f,0.598523f},{-0.13066f,-0.990258f,0.0481328f}, -{0.516393f,0.806743f,0.287235f},{-0.430925f,0.715581f,0.54977f},{0.448735f,0.327623f,-0.831445f}, -{0.493816f,0.1669f,-0.853399f},{-0.512482f,0.435375f,0.740143f},{-0.501902f,0.485164f,0.716038f}, -{0.00864245f,0.296578f,-0.95497f},{-0.638979f,0.481665f,-0.599754f},{-0.619463f,0.418906f,-0.663915f}, -{-0.676628f,-0.0650151f,0.733449f},{-0.653662f,-0.082975f,0.752224f},{-0.807571f,0.313101f,0.499796f}, -{-0.757473f,0.403682f,0.513103f},{-0.852017f,0.200593f,0.483559f},{-0.864641f,0.0993041f,0.492479f}, -{-0.819801f,0.214178f,0.531088f},{-0.890242f,0.0583071f,0.451741f},{-0.685458f,0.430081f,0.587519f}, -{-0.512972f,0.206372f,0.833229f},{-0.788466f,-0.229526f,-0.570648f},{0.0241731f,-0.998842f,-0.0416034f}, -{0.0326615f,-0.998887f,-0.0340157f},{0.0295508f,-0.999062f,-0.03164f},{-0.467001f,0.782354f,0.412107f}, -{-0.292685f,0.821794f,0.488866f},{-0.412556f,0.764212f,0.495759f},{-0.610348f,0.435518f,0.661664f}, -{-0.811272f,-0.319379f,0.48973f},{-0.81612f,-0.309379f,0.48809f},{-0.70417f,0.414397f,0.576559f}, -{-0.687124f,0.513775f,0.513707f},{-0.47835f,0.641065f,0.600181f},{-0.421403f,0.744624f,0.517644f}, -{-0.741206f,0.448145f,0.499779f},{-0.814976f,0.396613f,0.422508f},{-0.812736f,-0.386413f,-0.436056f}, -{-0.104997f,0.47965f,-0.871155f},{-0.0162628f,0.460022f,-0.887759f},{-0.765465f,0.240563f,0.596819f}, -{-0.597611f,0.57362f,0.560198f},{-0.689789f,0.505065f,0.518749f},{-0.727175f,0.423293f,0.540407f}, -{-0.308127f,0.849674f,0.427916f},{-0.0791706f,0.609536f,0.788796f},{-0.823089f,-0.0371484f,0.566695f}, -{-0.82769f,-0.0336199f,0.560178f},{-0.815599f,-0.0632867f,0.575146f},{-0.127929f,-0.000264798f,-0.991783f}, -{-0.84084f,0.290014f,0.457034f},{-0.859387f,0.296015f,0.416928f},{-0.89802f,-0.0693067f,0.434461f}, -{-0.825519f,-0.0620058f,0.560957f},{-0.818802f,-0.152933f,0.55333f},{-0.80371f,-0.147357f,0.576486f}, -{-0.579463f,-0.023075f,-0.814672f},{-0.673952f,0.194501f,-0.712711f},{-0.588945f,0.0471562f,-0.806796f}, -{-0.425986f,-0.0397759f,-0.903855f},{-0.613002f,0.594276f,0.520638f},{-0.509363f,0.698473f,0.502678f}, -{-0.636005f,0.594838f,0.491595f},{-0.498753f,-0.295648f,0.814762f},{-0.780513f,-0.394895f,0.484621f}, -{-0.726784f,-0.181705f,0.662396f},{-0.654261f,-0.705981f,0.27117f},{-0.454155f,-0.890405f,-0.0303461f}, -{-0.78205f,-0.621982f,-0.0391931f},{-0.813216f,-0.3632f,0.454716f},{-0.846288f,-0.351263f,0.400513f}, -{-0.833476f,-0.307216f,0.459277f},{-0.851383f,-0.494771f,0.174211f},{-0.924493f,-0.309175f,-0.222986f}, -{-0.424515f,0.751553f,0.50493f},{-0.801391f,-0.0292747f,0.597424f},{-0.823191f,-0.323435f,0.466634f}, -{-0.81734f,-0.314257f,0.482906f},{-0.827421f,-0.291732f,0.479861f},{-0.536161f,0.21014f,0.817541f}, -{-0.479851f,0.395272f,0.783264f},{-0.585877f,0.38605f,0.712541f},{-0.818216f,-0.122578f,0.561691f}, -{-0.827807f,-0.206853f,0.521486f},{-0.405365f,0.515397f,0.755014f},{-0.679631f,0.446817f,0.58177f}, -{-0.544681f,0.503073f,0.671f},{-0.748484f,-0.190258f,0.635274f},{-0.582454f,0.295646f,-0.757193f}, -{-0.238605f,-0.733799f,-0.636087f},{-0.211375f,-0.785263f,-0.581965f},{-0.248305f,-0.659941f,-0.7091f}, -{-0.671462f,-0.241978f,0.700418f},{-0.702697f,0.40569f,0.584494f},{-0.424814f,-0.45386f,0.78329f}, -{0.50287f,0.771715f,-0.389331f},{-0.681696f,-0.191082f,0.706242f},{-0.716836f,-0.265053f,0.644897f}, -{-0.770713f,-0.297385f,0.563528f},{-0.747238f,-0.118241f,0.653953f},{-0.954785f,-0.184225f,0.23334f}, -{-0.548361f,-0.727836f,0.411769f},{-0.921405f,-0.371992f,0.112408f},{-0.503367f,-0.393242f,0.769404f}, -{-0.576726f,-0.342498f,0.741675f},{-0.361183f,0.225455f,-0.90483f},{-0.891653f,0.404043f,0.204217f}, -{0.0338141f,-0.928257f,0.370398f},{-0.0219507f,-0.943046f,0.331938f},{-0.0745498f,-0.684872f,0.72484f}, -{-0.806646f,-0.13619f,0.57513f},{-0.808811f,-0.404271f,0.427071f},{-0.44685f,0.609374f,0.654972f}, -{-0.461291f,0.570642f,0.679396f},{-0.170721f,-0.981654f,0.0849051f},{0.548492f,0.127866f,-0.826321f}, -{0.481372f,0.192323f,-0.855157f},{0.542861f,0.164021f,-0.82365f},{-0.29651f,0.199589f,-0.933941f}, -{0.227659f,0.120444f,-0.966263f},{-0.59647f,0.306507f,-0.741807f},{0.0284581f,0.296894f,-0.954486f}, -{0.0122738f,0.499735f,-0.866092f},{-0.829669f,-0.29228f,0.475629f},{-0.485308f,-0.240124f,0.840724f}, -{-0.438823f,-0.341511f,0.831146f},{-0.605016f,0.775383f,0.180933f},{-0.712909f,0.673776f,-0.194388f}, -{-0.433914f,-0.114761f,-0.893615f},{-0.513091f,-0.0345913f,-0.857637f},{-0.521915f,0.0848665f,-0.848765f}, -{-0.655513f,0.204912f,0.726852f},{-0.425762f,-0.24177f,-0.871937f},{-0.814908f,-0.301909f,0.494749f}, -{-0.532045f,-0.147684f,0.833737f},{-0.896942f,-0.179224f,0.404195f},{-0.560803f,0.260994f,0.785737f}, -{-0.676909f,-0.32187f,0.661962f},{-0.804451f,-0.351504f,0.478856f},{-0.826835f,-0.314315f,0.466423f}, -{0.24554f,-0.848717f,0.468391f},{0.252259f,-0.880717f,0.400878f},{0.261369f,-0.906495f,0.331593f}, -{-0.871316f,0.402879f,0.280174f},{-0.947823f,0.241453f,0.208163f},{-0.736231f,0.393781f,0.550364f}, -{-0.897723f,0.376006f,0.22959f},{-0.499015f,-0.219682f,0.838286f},{-0.685411f,0.694441f,-0.219006f}, -{-0.496778f,0.833956f,0.240268f},{-0.679974f,-0.471155f,0.561826f},{-0.587924f,-0.513635f,0.62492f}, -{-0.626815f,-0.437178f,0.644963f},{-0.814539f,-0.302632f,0.494915f},{0.0151252f,-0.997929f,0.0625192f}, -{-0.368475f,0.238131f,-0.898621f},{-0.356529f,0.312421f,-0.8805f},{-0.457637f,-0.114404f,0.881748f}, -{0.029499f,-0.999511f,-0.0103668f},{-0.00938924f,-0.999942f,0.00521503f},{-0.00868702f,-0.99974f,-0.0210859f}, -{-0.883607f,-0.125016f,0.451231f},{-0.897507f,0.0204293f,0.440526f},{-0.667722f,0.554902f,0.496217f}, -{-0.763542f,0.385739f,0.51789f},{-0.510416f,-0.322454f,0.797182f},{-0.464866f,-0.34522f,0.815305f}, -{-0.158149f,0.34114f,-0.926613f},{-0.627815f,0.613943f,0.478458f},{-0.44089f,0.789623f,0.426745f}, -{-0.828792f,-0.311666f,0.464724f},{-0.554504f,0.725721f,0.407252f},{-0.662594f,-0.0304637f,0.748359f}, -{-0.435102f,-0.462729f,0.772378f},{-0.666116f,0.499234f,0.554125f},{-0.732412f,0.118538f,0.670464f}, -{-0.869508f,-0.48865f,0.0719463f},{-0.311367f,-0.328529f,-0.891694f},{-0.971581f,-0.23594f,0.0190483f}, -{-0.863437f,-0.282645f,0.417838f},{-0.302687f,-0.925788f,-0.226489f},{-0.488993f,-0.817903f,-0.303186f}, -{-0.80689f,-0.288878f,0.515246f},{-0.551655f,0.717482f,0.425319f},{-0.432414f,-0.240387f,0.869041f}, -{-0.897626f,0.378674f,0.225551f},{-0.576051f,0.646691f,0.499956f},{-0.526094f,0.728597f,0.438601f}, -{-0.77966f,0.166922f,0.603545f},{-0.787693f,0.266878f,0.555261f},{-0.601311f,-0.0491254f,-0.797504f}, -{-0.785811f,0.00908449f,-0.6184f},{-0.769137f,0.0463938f,-0.637398f},{-0.445453f,-0.202091f,-0.872199f}, -{-0.654855f,-0.272176f,-0.705043f},{-0.544025f,-0.184676f,-0.818493f},{0.030312f,0.401667f,-0.915284f}, -{-0.041871f,0.443354f,-0.895368f},{-0.0727087f,0.385587f,-0.919802f},{-0.511658f,0.7034f,0.493391f}, -{-0.805663f,0.152777f,0.572334f},{-0.751126f,-0.47213f,0.461414f},{-0.798257f,-0.322169f,0.508913f}, -{-0.576619f,0.0724766f,0.813792f},{-0.520617f,0.718185f,0.461702f},{-0.33865f,0.562898f,0.753964f}, -{0.234955f,0.238834f,-0.942207f},{0.251331f,0.314931f,-0.915233f},{0.185063f,0.330729f,-0.925403f}, -{-0.886911f,0.375469f,0.269096f},{-0.154109f,0.250557f,-0.955757f},{-0.400531f,0.813668f,0.421331f}, -{-0.5416f,-0.770518f,0.336113f},{-0.544135f,0.16461f,-0.822691f},{-0.211698f,0.175625f,-0.961426f}, -{-0.334504f,-0.0129159f,-0.942306f},{-0.394133f,0.000893468f,-0.919053f},{-0.391245f,0.0852153f,-0.916333f}, -{-0.648911f,0.15809f,-0.74426f},{-0.812766f,-0.31308f,0.491318f},{-0.692476f,-0.419684f,0.586807f}, -{-0.81264f,-0.0624337f,0.579412f},{-0.633244f,-0.291183f,0.717088f},{-0.952223f,0.27226f,0.138367f}, -{-0.452731f,0.502721f,0.736415f},{-0.719407f,-0.663803f,-0.2045f},{-0.613654f,-0.789512f,-0.00995104f}, -{-0.737211f,-0.205266f,0.643728f},{-0.575835f,0.262539f,-0.774266f},{-0.543006f,0.155016f,-0.825297f}, -{-0.769728f,0.282775f,0.572326f},{-0.794855f,0.0192248f,0.606495f},{-0.466456f,-0.18462f,0.865063f}, -{-0.502563f,-0.290176f,0.814388f},{-0.581134f,-0.13327f,0.802821f},{-0.339314f,-0.250814f,0.906619f}, -{-0.831761f,-0.0775132f,0.549696f},{0.0198175f,-0.999708f,-0.0138038f},{0.00494828f,-0.999849f,-0.0166457f}, -{0.0221211f,-0.999637f,-0.0153761f},{-0.35896f,0.0528321f,-0.931857f},{-0.394276f,0.80845f,0.436984f}, -{-0.633605f,0.20823f,0.745108f},{-0.594276f,0.417433f,0.687449f},{-0.546438f,0.464911f,0.696608f}, -{-0.595217f,0.476599f,0.64697f},{-0.362789f,-0.186007f,-0.913119f},{-0.420958f,0.66549f,0.616375f}, -{-0.543996f,0.546085f,0.637071f},{-0.325797f,-0.26756f,0.90679f},{-0.183163f,-0.194712f,0.963607f}, -{-0.445429f,0.0859319f,-0.891184f},{-0.545556f,0.105608f,-0.831394f},{-0.610353f,0.539882f,-0.579653f}, -{-0.545833f,-0.242049f,0.802171f},{-0.759919f,-0.00155307f,0.650016f},{-0.752876f,-0.0855841f,0.652574f}, -{-0.534606f,-0.263421f,0.802998f},{-0.552957f,-0.182488f,0.81298f},{-0.635767f,0.182895f,0.7499f}, -{-0.559979f,0.292242f,0.775253f},{-0.598309f,0.249397f,0.761464f},{-0.638105f,0.200247f,0.743453f}, -{-0.66314f,0.0604394f,0.746051f},{-0.510999f,0.0128487f,0.859485f},{-0.452527f,-0.107616f,0.885233f}, -{-0.446189f,-0.437712f,0.780592f},{-0.818986f,0.569003f,0.0741459f},{-0.256962f,-0.883326f,0.392053f}, -{0.160324f,0.287601f,-0.944236f},{-0.98996f,-0.125316f,0.0653766f},{-0.984502f,-0.118441f,-0.129335f}, -{0.0653595f,-0.997831f,0.00782317f},{-0.17971f,-0.965573f,0.188077f},{0.00449062f,-0.995378f,0.0959267f}, -{-0.50379f,-0.181022f,0.844646f},{0.00183938f,-0.468409f,-0.88351f},{-0.450589f,0.612839f,0.649152f}, -{-0.638726f,0.29257f,0.71164f},{-0.572547f,0.229584f,0.787071f},{-0.545939f,0.374596f,0.749419f}, -{-0.346339f,0.933504f,-0.092841f},{-0.532212f,0.180167f,0.827218f},{-0.657665f,-0.128369f,0.742293f}, -{-0.557517f,-0.316215f,0.767582f},{-0.537161f,0.59042f,0.60238f},{-0.433749f,0.634675f,0.63957f}, -{-0.907702f,-0.239757f,-0.344374f},{-0.815025f,-0.244928f,-0.525113f},{-0.508138f,-0.465009f,0.724957f}, -{-0.597399f,-0.419279f,0.683608f},{-0.157794f,0.0739844f,-0.984697f},{-0.215131f,0.345583f,-0.913395f}, -{-0.641043f,-0.381159f,0.666169f},{-0.463103f,-0.204799f,-0.862318f},{-0.420183f,-0.257033f,-0.870276f}, -{-0.426429f,-0.833762f,0.350713f},{-0.288873f,-0.855688f,0.42936f},{-0.262027f,-0.885132f,0.384556f}, -{-0.505665f,-0.329907f,-0.79716f},{-0.423011f,-0.843442f,0.33116f},{-0.188296f,-0.95367f,0.234643f}, -{-0.186668f,-0.96361f,0.191339f},{0.016626f,-0.42944f,-0.902942f},{0.229574f,-0.618164f,-0.751778f}, -{0.213167f,-0.630559f,-0.746294f},{-0.653506f,0.170378f,0.737497f},{-0.754205f,0.139048f,0.641748f}, -{-0.733566f,-0.113507f,-0.670073f},{-0.714556f,0.0437677f,-0.698208f},{-0.534084f,0.6353f,0.557806f}, -{-0.477724f,0.66335f,0.575975f},{-0.564231f,-0.278572f,0.777201f},{-0.0153342f,-0.98466f,0.173808f}, -{-0.00899519f,-0.990321f,0.138506f},{-0.747073f,0.149048f,0.647816f},{-0.739693f,0.330268f,0.586325f}, -{-0.75432f,0.0203637f,0.656191f},{-0.584713f,-0.0127331f,0.81114f},{-0.627251f,0.0874965f,0.773886f}, -{-0.375288f,0.744741f,0.551832f},{-0.85599f,0.509751f,-0.086229f},{-0.856581f,0.450396f,-0.251818f}, -{-0.964796f,0.114569f,-0.236733f},{-0.788723f,0.613207f,-0.0435051f},{-0.705179f,0.661605f,-0.254952f}, -{-0.622839f,-0.125899f,0.772154f},{-0.643766f,0.0804802f,0.760979f},{-0.561995f,-0.357569f,0.745859f}, -{-0.650896f,-0.230573f,0.723305f},{-0.647344f,0.0159482f,0.762031f},{-0.719224f,0.0847135f,0.689595f}, -{-0.66153f,-0.118747f,0.740458f},{-0.201788f,0.273426f,-0.940489f},{-0.265744f,0.281923f,-0.9219f}, -{-0.222384f,0.236431f,-0.945857f},{0.373598f,0.281689f,-0.883785f},{0.400531f,0.272846f,-0.874717f}, -{0.437973f,0.267974f,-0.85812f},{-0.615037f,-0.456725f,0.642753f},{-0.826765f,0.552627f,-0.10518f}, -{-0.613802f,-0.0665211f,0.786653f},{-0.794276f,-0.309824f,-0.522623f},{-0.558536f,-0.666482f,-0.493801f}, -{-0.663791f,-0.693794f,-0.27934f},{-0.614065f,-0.405564f,0.677083f},{-0.675169f,0.476757f,0.562895f}, -{-0.589291f,0.541487f,0.599607f},{-0.388849f,-0.419335f,0.820338f},{-0.637315f,-0.0303753f,0.770004f}, -{-0.0304552f,0.316204f,-0.948202f},{-0.26997f,0.334033f,-0.903071f},{-0.214728f,0.536029f,-0.816434f}, -{-0.415018f,0.564237f,-0.71372f},{-0.453154f,0.844034f,-0.286808f},{0.153137f,0.210379f,-0.965552f}, -{0.249746f,0.276643f,-0.927952f},{-0.836283f,0.441701f,0.324856f},{-0.694397f,-0.327434f,-0.640781f}, -{-0.634576f,-0.386536f,-0.669255f},{-0.722049f,-0.311531f,-0.617732f},{-0.701986f,0.404823f,0.585947f}, -{-0.769988f,0.330764f,0.545631f},{-0.81952f,0.310075f,0.481913f},{-0.793846f,0.44448f,0.415026f}, -{0.348806f,-0.234002f,-0.907512f},{-0.556915f,0.764365f,0.32495f},{-0.702632f,-0.354421f,-0.617004f}, -{-0.591409f,-0.175052f,-0.787142f},{-0.603679f,-0.341051f,-0.720595f},{-0.829158f,0.205157f,0.520006f}, -{-0.0234405f,-0.0669621f,-0.99748f},{0.0827914f,-0.212663f,-0.973612f},{-0.613392f,-0.382432f,-0.69101f}, -{-0.669679f,-0.44593f,-0.593865f},{-0.587962f,-0.438583f,-0.679666f},{-0.514604f,-0.418881f,-0.748145f}, -{-0.683355f,0.203558f,-0.701135f},{-0.343854f,-0.869667f,0.35418f},{-0.693639f,0.102823f,0.712946f}, -{-0.643381f,0.507362f,0.573276f},{-0.179229f,-0.798935f,0.57409f},{-0.625846f,-0.345565f,-0.699215f}, -{0.193112f,-0.566099f,0.801399f},{0.363743f,-0.582821f,0.726644f},{-0.590179f,-0.699363f,0.403211f}, -{-0.782717f,-0.13318f,0.607962f},{-0.750313f,0.182009f,0.635534f},{-0.685217f,0.425887f,0.590845f}, -{-0.765752f,-0.0469561f,0.641419f},{-0.55663f,-0.659276f,0.505489f},{-0.430096f,0.189334f,-0.882706f}, -{-0.868659f,-0.194001f,0.455845f},{-0.948159f,0.316867f,-0.0242684f},{-0.923184f,0.288381f,0.2541f}, -{-0.864769f,-0.393138f,0.312437f},{-0.673731f,0.121125f,0.728982f},{-0.447896f,-0.0639182f,-0.891798f}, -{-0.732419f,0.332546f,0.594117f},{-0.697571f,0.617732f,-0.363044f},{-0.232532f,-0.885746f,0.401724f}, -{-0.549515f,-0.43611f,0.71263f},{-0.915083f,0.184311f,0.358682f},{-0.631895f,0.505717f,0.587332f}, -{-0.048755f,-0.912305f,0.406599f},{-0.00499332f,-0.708072f,0.706123f},{-0.740317f,0.109004f,0.663362f}, -{-0.748566f,-0.168053f,0.64141f},{-0.819601f,-0.148101f,0.553462f},{-0.825063f,-0.0489577f,0.562915f}, -{-0.885336f,-0.0479825f,0.462469f},{-0.826903f,0.073578f,0.55751f},{-0.88385f,0.0608632f,0.463794f}, -{-0.838473f,-0.318529f,0.442156f},{-0.647852f,0.483823f,0.58839f},{-0.67151f,-0.362356f,0.646353f}, -{-0.887521f,-0.297247f,0.352066f},{-0.858956f,-0.223478f,0.460709f},{-0.811293f,0.176758f,0.557279f}, -{-0.809109f,0.259872f,0.527075f},{-0.513998f,0.694608f,0.503314f},{-0.461626f,-0.819637f,-0.339258f}, -{-0.310498f,-0.762119f,-0.568125f},{-0.323819f,-0.907785f,-0.266585f},{-0.873213f,0.321721f,0.366054f}, -{-0.0693406f,-0.767637f,0.637123f},{-0.0292936f,-0.951498f,0.306258f},{0.202785f,-0.741235f,0.639882f}, -{-0.730227f,0.361624f,0.579652f},{-0.658946f,0.469511f,0.587664f},{-0.809055f,-0.1302f,0.573131f}, -{-0.764863f,0.244937f,0.595811f},{-0.775799f,0.182781f,0.603926f},{0.250327f,0.459893f,-0.851959f}, -{-0.228841f,-0.44984f,0.863294f},{-0.783305f,0.442176f,0.436936f},{0.311199f,-0.345385f,-0.885361f}, -{0.17222f,-0.27239f,-0.946649f},{-0.791398f,-0.0531614f,0.608985f},{-0.786133f,0.0675726f,0.614352f}, -{-0.66844f,-0.297679f,-0.681598f},{-0.580798f,-0.26834f,-0.768549f},{-0.638322f,0.206607f,0.741524f}, -{-0.598039f,0.28478f,0.749166f},{-0.706041f,-0.141691f,0.693851f},{-0.504882f,0.619097f,0.601509f}, -{-0.424321f,0.739317f,0.52284f},{-0.420945f,0.809959f,0.408377f},{-0.470592f,0.407277f,0.782732f}, -{-0.647062f,-0.190766f,-0.738187f},{-0.681777f,-0.143191f,-0.717409f},{-0.772775f,-0.260891f,-0.578581f}, -{-0.473436f,-0.635563f,-0.609851f},{-0.470861f,-0.668675f,-0.575468f},{-0.549722f,-0.641587f,-0.534951f}, -{-0.913123f,-0.21534f,0.346171f},{-0.850555f,-0.110966f,0.514045f},{-0.800178f,-0.0676003f,0.59594f}, -{-0.759561f,-0.0435877f,0.648974f},{-0.75589f,0.0642564f,0.651538f},{-0.744366f,0.180982f,0.642779f}, -{-0.978468f,-0.150371f,0.141381f},{-0.626719f,0.274355f,-0.729351f},{-0.817811f,0.468598f,0.334068f}, -{-0.732834f,0.078916f,0.675815f},{-0.602859f,0.410502f,0.684141f},{-0.423418f,0.689193f,0.587988f}, -{-0.451121f,-0.705396f,-0.546724f},{-0.39819f,-0.683051f,-0.612279f},{-0.449073f,-0.679805f,-0.579826f}, -{-0.970855f,0.186967f,0.149948f},{-0.133586f,-0.655213f,0.743539f},{-0.746645f,-0.422237f,0.51404f}, -{-0.824048f,-0.311098f,0.473459f},{-0.833598f,-0.199787f,0.514975f},{-0.718462f,0.256136f,0.646689f}, -{-0.843945f,-0.00335243f,0.53642f},{-0.695026f,0.203394f,0.689615f},{-0.572752f,0.593211f,0.565735f}, -{-0.802339f,0.45988f,0.380477f},{-0.885006f,0.353562f,0.302916f},{-0.66682f,0.60401f,0.43649f}, -{-0.5106f,0.593405f,0.622221f},{-0.396866f,0.798109f,0.453344f},{-0.438631f,-0.817212f,0.373856f}, -{0.628597f,0.070023f,-0.774572f},{0.567272f,0.0837215f,-0.819264f},{0.539457f,0.0680128f,-0.839262f}, -{-0.339831f,-0.126378f,-0.931957f},{-0.0729324f,-0.0291307f,-0.996911f},{0.44108f,0.201069f,-0.874654f}, -{-0.804002f,-0.209477f,0.556508f},{-0.69699f,0.239007f,0.676077f},{-0.682645f,0.263004f,0.68178f}, -{-0.432575f,-0.75762f,0.488766f},{-0.468404f,0.0411905f,0.882554f},{-0.64841f,0.269969f,0.711815f}, -{-0.550359f,0.491757f,0.674744f},{-0.378679f,0.762194f,0.525036f},{-0.348953f,0.788101f,0.507079f}, -{-0.582953f,0.580175f,0.568825f},{-0.732857f,0.474231f,-0.487879f},{-0.553702f,0.702597f,-0.446959f}, -{0.373769f,0.188421f,-0.908182f},{-0.813838f,-0.0701697f,0.576839f},{-0.788545f,-0.0220965f,0.614579f}, -{-0.759679f,-0.0248215f,0.649824f},{-0.707009f,0.225235f,0.670379f},{-0.738227f,0.138017f,0.660282f}, -{0.0382768f,-0.996456f,0.0749003f},{-0.766233f,0.258764f,0.588157f},{-0.686959f,0.567356f,0.454087f}, -{-0.73823f,-0.0898627f,0.668536f},{-0.372659f,0.774285f,0.511477f},{-0.723401f,0.205919f,0.659006f}, -{0.160182f,-0.5659f,-0.808764f},{0.434856f,-0.616598f,-0.656283f},{0.0231616f,-0.97957f,-0.199767f}, -{-0.66567f,-0.564697f,0.487853f},{0.316206f,0.241841f,-0.917348f},{0.375475f,0.220209f,-0.900292f}, -{-0.7103f,-0.384795f,0.589412f},{-0.764348f,-0.17699f,0.620037f},{-0.802285f,-0.0445413f,0.595277f}, -{-0.77726f,0.0111166f,0.629081f},{-0.732092f,0.0259054f,0.680713f},{-0.688352f,0.102232f,0.718136f}, -{-0.680752f,0.226134f,0.696735f},{-0.884425f,0.348781f,0.310071f},{-0.861093f,0.272212f,0.429441f}, -{-0.343287f,-0.894841f,0.285332f},{-0.674998f,-0.708227f,0.206865f},{-0.800865f,0.372938f,0.468542f}, -{-0.503765f,0.611881f,0.609772f},{-0.392682f,0.749152f,0.533453f},{-0.650023f,0.325047f,0.686888f}, -{-0.291221f,-0.315675f,-0.903072f},{-0.30522f,-0.105777f,-0.946389f},{-0.253134f,-0.266368f,-0.930039f}, -{-0.673406f,0.265473f,0.689963f},{-0.827281f,0.337787f,0.448896f},{-0.775433f,-0.55732f,0.296814f}, -{-0.749854f,-0.461074f,0.474477f},{-0.803676f,0.408894f,0.432332f},{-0.681633f,0.527799f,0.506759f}, -{0.607975f,-0.172449f,-0.775002f},{0.434956f,-0.900438f,-0.00486778f},{-0.580756f,0.519123f,0.627084f}, -{0.397173f,0.329672f,-0.856487f},{-0.360323f,-0.650174f,-0.668911f},{0.0343635f,0.0931413f,-0.99506f}, -{-0.631268f,-0.222999f,-0.742813f},{-0.746227f,-0.214046f,-0.630341f},{-0.671459f,-0.189288f,-0.716459f}, -{-0.659546f,-0.0381326f,-0.750696f},{-0.815974f,0.00295256f,0.578082f},{-0.888849f,0.0688656f,0.452996f}, -{-0.803058f,0.243254f,0.54399f},{-0.833593f,0.316012f,0.453055f},{-0.579459f,0.631209f,0.51556f}, -{-0.530057f,0.818813f,0.220418f},{0.229917f,-0.548714f,0.803773f},{0.189054f,-0.33771f,0.922069f}, -{0.629261f,0.0979529f,-0.770996f},{-0.676455f,-0.307285f,0.669316f},{-0.624391f,-0.452539f,0.636666f}, -{-0.751741f,-0.0822216f,0.654312f},{-0.659358f,0.21247f,0.721183f},{-0.466465f,-0.872416f,-0.145944f}, -{-0.297602f,-0.903282f,-0.309055f},{-0.00581529f,-0.986921f,-0.161101f},{-0.850233f,0.271603f,0.450927f}, -{-0.645747f,0.76093f,0.0632147f},{-0.742278f,-0.558166f,0.370775f},{-0.752377f,-0.470443f,0.461099f}, -{-0.817796f,0.574776f,0.0290093f},{-0.383178f,0.76701f,0.514655f},{-0.630893f,0.362954f,0.685739f}, -{0.0332487f,-0.998789f,-0.0362681f},{0.0243115f,-0.99914f,-0.0335984f},{0.279421f,-0.915639f,0.289013f}, -{-0.472456f,-0.157848f,-0.867104f},{-0.82926f,0.269673f,0.489493f},{-0.668103f,-0.469037f,0.577618f}, -{-0.622098f,0.656668f,-0.426358f},{-0.902728f,0.430072f,0.0109956f},{-0.0496615f,0.304177f,-0.95132f}, -{-0.883749f,-0.145445f,-0.444784f},{-0.265136f,0.243864f,-0.932863f},{-0.610512f,-0.789531f,-0.0625791f}, -{-0.190525f,0.190871f,-0.962948f},{-0.153502f,0.660391f,-0.735065f},{0.118652f,0.907375f,-0.403227f}, -{0.154264f,0.8649f,-0.477652f},{-0.0161343f,0.881f,-0.472842f},{0.235805f,0.915596f,-0.325698f}, -{0.217685f,0.886898f,-0.407463f},{-0.729908f,0.583186f,-0.356552f},{0.116651f,0.282444f,-0.952165f}, -{0.215742f,0.267895f,-0.938982f},{0.0109213f,0.907924f,-0.418992f},{0.162564f,0.653304f,-0.739437f}, -{0.0479323f,0.611091f,-0.790108f},{0.766837f,0.53508f,-0.354471f},{-0.653129f,-0.103326f,-0.750164f}, -{-0.867818f,-0.0822351f,-0.49003f},{-0.821129f,-0.155542f,-0.549139f},{0.51254f,0.652523f,-0.558137f}, -{0.589058f,0.59275f,-0.549234f},{0.219218f,0.840223f,-0.495953f},{0.278717f,0.785049f,-0.553185f}, -{0.197953f,0.797583f,-0.569804f},{-0.830511f,-0.209543f,-0.516084f},{-0.785971f,-0.188003f,-0.588986f}, -{-0.330683f,0.346221f,-0.87794f},{-0.324171f,0.619309f,-0.715101f},{-0.000413993f,-0.998852f,0.0479042f}, -{0.0241025f,0.940366f,-0.33931f},{-0.687919f,-0.155575f,-0.708917f},{-0.608044f,0.279841f,-0.742948f}, -{-0.869399f,-0.148854f,-0.471156f},{0.15548f,0.819973f,-0.550881f},{0.0859084f,0.827993f,-0.554118f}, -{-0.927365f,0.0475724f,-0.371121f},{-0.802364f,-0.227847f,-0.551632f},{-0.833075f,-0.210273f,-0.511635f}, -{-0.915617f,-0.0470975f,-0.399283f},{-0.876015f,-0.166462f,-0.452646f},{-0.782091f,-0.310435f,-0.540337f}, -{-0.69515f,-0.343201f,-0.631648f},{-0.625069f,-0.446537f,-0.640229f},{-0.625458f,-0.0937403f,-0.774606f}, -{-0.957594f,0.0112719f,-0.2879f},{-0.634462f,-0.376214f,-0.675219f},{-0.922026f,-0.141245f,-0.360442f}, -{-0.945026f,-0.0123246f,-0.326763f},{-0.915351f,-0.124506f,-0.382924f},{-0.847758f,-0.270915f,-0.455973f}, -{-0.785936f,-0.330092f,-0.522823f},{-0.764905f,-0.404768f,-0.501082f},{-0.572019f,-0.577086f,-0.582895f}, -{-0.475734f,-0.497352f,-0.725478f},{0.0412363f,-0.999149f,-0.000575673f},{-0.974726f,-0.011953f,-0.223085f}, -{-0.476842f,-0.660929f,-0.579478f},{-0.972092f,-0.00139264f,-0.234595f},{-0.948887f,-0.0918976f,-0.301941f}, -{-0.899332f,-0.194675f,-0.391539f},{-0.830531f,-0.355461f,-0.428795f},{-0.480972f,-0.670668f,-0.564686f}, -{-0.839168f,-0.338982f,-0.425309f},{-0.693691f,-0.500137f,-0.51832f},{-0.543033f,-0.647155f,-0.535075f}, -{-0.912901f,-0.218345f,-0.344872f},{-0.238438f,0.675042f,-0.698187f},{-0.181185f,0.617331f,-0.765555f}, -{-0.966653f,0.0317663f,-0.254111f},{-0.920666f,-0.00972829f,-0.390229f},{-0.970752f,-0.0188526f,-0.239345f}, -{-0.955074f,-0.110583f,-0.274962f},{-0.939826f,-0.171711f,-0.295367f},{-0.89025f,-0.290814f,-0.350546f}, -{-0.772973f,-0.474061f,-0.421638f},{-0.553283f,-0.649761f,-0.521238f},{-0.771538f,-0.484487f,-0.412312f}, -{-0.976721f,0.0834547f,-0.197616f},{-0.96782f,-0.0501943f,-0.246587f},{-0.602259f,0.376395f,-0.703997f}, -{-0.576564f,0.215634f,-0.788084f},{-0.666104f,0.00345015f,-0.745851f},{-0.658184f,-0.594629f,-0.461746f}, -{-0.98324f,0.0764916f,-0.165493f},{-0.978554f,0.0576061f,-0.197773f},{-0.963464f,-0.11138f,-0.243581f}, -{-0.927319f,-0.231403f,-0.294163f},{-0.821827f,-0.421623f,-0.38319f},{-0.694751f,-0.508234f,-0.508939f}, -{-0.570395f,-0.621536f,-0.536976f},{-0.979728f,0.108607f,-0.168339f},{-0.729935f,-0.560912f,-0.390607f}, -{-0.548836f,-0.641527f,-0.535932f},{-0.137297f,-0.0651369f,-0.988386f},{-0.983567f,0.0087842f,-0.180332f}, -{-0.955803f,-0.176433f,-0.235186f},{-0.869009f,-0.366445f,-0.332476f},{-0.774158f,-0.455288f,-0.439764f}, -{-0.619558f,-0.627742f,-0.471262f},{-0.491225f,-0.73335f,-0.469995f},{-0.858948f,-0.422974f,-0.288621f}, -{-0.322444f,0.919917f,-0.223118f},{-0.851542f,0.52224f,-0.0462868f},{0.329143f,0.78615f,-0.523099f}, -{0.346796f,0.808097f,-0.476143f},{0.260363f,0.82633f,-0.49939f},{0.49845f,0.168966f,-0.850293f}, -{0.542044f,0.204992f,-0.814964f},{0.531619f,0.163787f,-0.830996f},{0.476991f,0.648298f,-0.593455f}, -{0.412125f,0.600022f,-0.685657f},{0.534435f,0.512549f,-0.672066f},{0.0905934f,0.864983f,-0.493555f}, -{-0.0394386f,0.854323f,-0.518244f},{-0.530297f,0.721798f,-0.444739f},{0.245727f,-0.163502f,-0.95545f}, -{0.260433f,-0.101818f,-0.960108f},{-0.0886096f,0.68229f,-0.725691f},{-0.280944f,0.805369f,-0.521968f}, -{-0.157878f,0.797038f,-0.582928f},{-0.328697f,0.704327f,-0.629191f},{-0.940973f,-0.0805013f,0.32877f}, -{-0.978425f,0.154397f,-0.137284f},{-0.98397f,-0.0434644f,-0.172959f},{-0.923355f,-0.277758f,-0.265077f}, -{-0.845702f,-0.37754f,-0.377163f},{-0.728052f,-0.547275f,-0.412833f},{-0.523263f,-0.68013f,-0.513438f}, -{-0.761618f,-0.560802f,-0.324714f},{-0.0442249f,0.846128f,-0.531142f},{0.118938f,0.815643f,-0.566198f}, -{-0.106843f,0.701031f,-0.705082f},{-0.269174f,0.720933f,-0.638593f},{-0.956881f,0.109636f,0.268995f}, -{-0.87996f,0.403169f,0.251248f},{0.0556408f,0.312043f,-0.948437f},{0.232607f,0.302752f,-0.924249f}, -{0.0834377f,0.381388f,-0.920642f},{-0.000786142f,0.810607f,-0.58559f},{-0.035975f,0.777677f,-0.627634f}, -{0.0508906f,0.747998f,-0.661747f},{-0.107152f,0.734086f,-0.670549f},{-0.106257f,0.727624f,-0.677696f}, -{-0.31261f,0.743435f,-0.591252f},{-0.102666f,0.76875f,-0.631255f},{0.169555f,0.774775f,-0.609078f}, -{-0.0233887f,0.767772f,-0.640296f},{-0.357587f,0.907916f,-0.21868f},{-0.158598f,0.747223f,-0.645372f}, -{0.0443315f,0.544164f,-0.837807f},{0.0199804f,0.53045f,-0.847481f},{0.000180536f,0.693536f,-0.720422f}, -{0.184154f,0.705218f,-0.684657f},{-0.549089f,-0.833126f,0.0663552f},{-0.355312f,-0.924539f,0.137772f}, -{-0.550829f,-0.82148f,0.147507f},{-0.228807f,0.69465f,-0.681988f},{0.554866f,0.643871f,-0.526834f}, -{0.44528f,0.677502f,-0.585421f},{0.435356f,0.728495f,-0.528923f},{-0.0265682f,0.551005f,-0.834079f}, -{-0.0283525f,0.549752f,-0.834846f},{-0.0534209f,0.591202f,-0.804753f},{0.374862f,0.383933f,-0.843845f}, -{0.393388f,0.487811f,-0.779286f},{-0.0113779f,0.578591f,-0.815539f},{-0.600071f,-0.0107687f,-0.799875f}, -{-0.768247f,0.169597f,-0.617279f},{0.249316f,0.206271f,-0.9462f},{0.260273f,0.258905f,-0.930175f}, -{0.200955f,0.168393f,-0.965019f},{-0.0240418f,-0.994179f,0.105028f},{0.00728482f,-0.993241f,0.115838f}, -{-0.965055f,0.204971f,-0.163264f},{-0.947471f,0.271797f,-0.168596f},{-0.976652f,0.151255f,-0.152557f}, -{-0.969842f,-0.135725f,-0.202448f},{-0.920074f,-0.273845f,-0.28013f},{-0.867173f,-0.400469f,-0.296032f}, -{-0.629318f,-0.659676f,-0.410837f},{-0.912934f,-0.31712f,-0.256878f},{0.353662f,0.330311f,-0.87511f}, -{0.402182f,0.318681f,-0.858307f},{0.451212f,0.315875f,-0.834644f},{0.0698329f,0.848959f,-0.523824f}, -{0.1656f,0.746272f,-0.644713f},{0.0791368f,0.199257f,-0.976747f},{-0.799717f,-0.230111f,-0.554528f}, -{-0.823964f,0.15489f,-0.545062f},{-0.843488f,0.216541f,-0.491566f},{0.00578011f,0.749809f,-0.661629f}, -{-0.0349199f,0.699277f,-0.713997f},{-0.0829151f,0.75947f,-0.645237f},{-0.880051f,0.380791f,0.283742f}, -{-0.303249f,0.728386f,-0.614406f},{-0.0616567f,-0.982204f,-0.177406f},{-0.580776f,-0.680002f,-0.447545f}, -{0.64457f,0.353625f,-0.677849f},{0.611951f,0.453782f,-0.647764f},{0.620319f,0.469135f,-0.628583f}, -{0.14269f,0.455273f,-0.878844f},{-0.114267f,0.845521f,-0.521571f},{-0.209425f,0.898253f,-0.386372f}, -{-0.260342f,0.837888f,-0.479755f},{-0.298369f,0.85314f,-0.427935f},{-0.617404f,-0.37837f,-0.689673f}, -{-0.680221f,-0.42967f,-0.593871f},{-0.710034f,-0.37957f,-0.593109f},{-0.78232f,-0.388716f,-0.486698f}, -{-0.832582f,0.30817f,-0.46026f},{-0.461526f,0.804212f,-0.374483f},{-0.490626f,0.695119f,-0.525448f}, -{-0.61646f,0.663409f,-0.424106f},{-0.639165f,0.549961f,-0.537597f},{-0.469639f,0.537434f,-0.700431f}, -{0.679093f,0.422242f,-0.600453f},{0.698225f,0.270889f,-0.662647f},{0.615003f,0.328574f,-0.716806f}, -{0.233794f,0.579118f,-0.781001f},{0.226217f,0.491376f,-0.841056f},{0.259529f,0.520396f,-0.813531f}, -{0.285164f,0.525232f,-0.801757f},{0.252231f,0.40395f,-0.87932f},{0.228237f,0.438116f,-0.869461f}, -{0.373608f,0.508213f,-0.775975f},{0.414642f,0.498775f,-0.761115f},{0.338994f,0.504203f,-0.794269f}, -{-0.672568f,-0.267274f,-0.690085f},{-0.738537f,-0.304573f,-0.601497f},{-0.581012f,-0.305672f,-0.754314f}, -{-0.816326f,-0.311619f,-0.486318f},{-0.840138f,-0.337409f,-0.424645f},{-0.897044f,-0.216641f,-0.385201f}, -{-0.900858f,-0.0265083f,-0.433303f},{-0.865957f,0.140418f,-0.480001f},{-0.847461f,0.273879f,-0.454753f}, -{-0.842143f,0.354717f,-0.406167f},{-0.737181f,0.516162f,-0.436052f},{-0.927486f,0.302631f,0.219509f}, -{-0.981675f,0.141154f,-0.128021f},{-0.965402f,-0.216887f,-0.144771f},{-0.743468f,-0.592587f,-0.309994f}, -{-0.576586f,-0.709313f,-0.405492f},{-0.80673f,-0.53517f,-0.250559f},{-0.948932f,0.0757926f,0.30624f}, -{0.0720768f,0.624395f,-0.777776f},{-0.102689f,0.384984f,-0.917192f},{-0.649688f,-0.339633f,-0.680114f}, -{-0.763436f,-0.24085f,-0.599297f},{-0.842123f,-0.328308f,-0.427834f},{-0.93705f,-0.0397002f,-0.346932f}, -{-0.832593f,0.415712f,-0.366023f},{0.0558894f,0.647015f,-0.760426f},{0.186694f,0.515431f,-0.836347f}, -{0.167057f,0.796417f,-0.581216f},{-0.013721f,0.746685f,-0.665036f},{-0.074801f,0.743277f,-0.664789f}, -{-0.557577f,-0.401232f,-0.726719f},{-0.695221f,-0.350494f,-0.627552f},{-0.758386f,-0.342505f,-0.554564f}, -{-0.923356f,0.113223f,-0.366871f},{-0.509779f,0.79534f,-0.327962f},{-0.979265f,0.119692f,0.163447f}, -{-0.98726f,0.0809253f,0.137f},{-0.904176f,-0.388755f,-0.177018f},{0.455558f,0.263758f,-0.850235f}, -{0.487306f,0.146717f,-0.860818f},{0.205814f,0.624123f,-0.753732f},{-0.0595557f,0.7814f,-0.621182f}, -{-0.100202f,0.733338f,-0.67244f},{-0.798938f,-0.286607f,-0.52873f},{-0.827743f,-0.32863f,-0.4548f}, -{-0.861636f,-0.297967f,-0.410852f},{-0.778058f,-0.249262f,-0.576623f},{-0.86606f,-0.265874f,-0.423381f}, -{-0.886519f,-0.259833f,-0.382847f},{-0.884378f,-0.314477f,-0.344935f},{-0.874401f,-0.254297f,-0.413226f}, -{-0.934063f,-0.0868268f,-0.346391f},{-0.951526f,0.0806207f,-0.296814f},{-0.889652f,0.184177f,-0.417849f}, -{-0.850233f,0.348223f,-0.394771f},{-0.787832f,0.5495f,-0.278155f},{-0.990759f,-0.0191876f,0.134268f}, -{-0.971217f,0.155734f,-0.180232f},{-0.971098f,-0.0403574f,-0.235244f},{-0.952427f,-0.20938f,-0.221457f}, -{-0.895477f,-0.335529f,-0.292474f},{-0.689745f,-0.654384f,-0.309893f},{-0.697157f,-0.662355f,-0.274332f}, -{-0.991092f,-0.133136f,0.00332425f},{-0.34596f,-0.657323f,0.669506f},{-0.139928f,0.746144f,-0.650914f}, -{-0.88565f,-0.260006f,-0.384736f},{-0.119213f,0.536603f,-0.835372f},{0.0401096f,0.531459f,-0.846134f}, -{0.217478f,0.763288f,-0.608355f},{-0.345093f,0.574183f,-0.742445f},{-0.332209f,0.464239f,-0.821048f}, -{-0.363386f,0.523473f,-0.770666f},{-0.11312f,0.740586f,-0.662372f},{-0.812245f,0.237191f,-0.532915f}, -{-0.692428f,0.460837f,-0.555133f},{-0.745763f,0.212997f,-0.631244f},{-0.592546f,0.508668f,-0.624617f}, -{-0.944421f,-0.251383f,0.21184f},{-0.0282219f,0.728704f,-0.684247f},{-0.89321f,-0.192984f,-0.406121f}, -{-0.918234f,-0.245104f,-0.311078f},{-0.92194f,-0.272905f,-0.274863f},{-0.893661f,-0.357294f,-0.271499f}, -{-0.924488f,-0.268229f,-0.270878f},{-0.921025f,-0.271284f,-0.279497f},{-0.195757f,-0.980249f,-0.0281213f}, -{0.304488f,0.726339f,-0.616214f},{0.371242f,0.605966f,-0.703552f},{0.469584f,0.571727f,-0.672769f}, -{-0.882291f,-0.437208f,0.174387f},{0.18895f,0.750629f,-0.63313f},{0.0412555f,0.674764f,-0.736879f}, -{-0.90528f,-0.318957f,-0.280597f},{-0.888689f,-0.362498f,-0.280763f},{-0.924107f,-0.260881f,-0.279224f}, -{-0.959584f,-0.106115f,-0.260649f},{-0.885816f,-0.0467579f,-0.461675f},{-0.659046f,0.746035f,0.0953459f}, -{-0.674056f,0.737495f,-0.0418221f},{0.367991f,0.483938f,-0.793969f},{-0.817986f,-0.561808f,-0.123579f}, -{-0.991833f,0.0445393f,-0.119513f},{-0.986462f,0.0322381f,-0.160793f},{-0.774363f,-0.547466f,-0.317242f}, -{-0.868264f,-0.453342f,-0.201488f},{-0.26792f,0.738131f,-0.619178f},{-0.284771f,0.799236f,-0.529271f}, -{-0.119769f,0.803515f,-0.583111f},{-0.0182616f,0.559203f,-0.828829f},{-0.0234112f,0.565326f,-0.824535f}, -{-0.0600253f,0.646342f,-0.760683f},{-0.927258f,-0.33292f,0.171338f},{0.0436789f,0.832412f,-0.552433f}, -{0.00637399f,-0.0948247f,-0.995474f},{0.0884458f,0.788312f,-0.608885f},{-0.0589162f,0.60668f,-0.79276f}, -{-0.184244f,0.75806f,-0.625619f},{-0.786197f,0.366074f,-0.49788f},{-0.74957f,0.414396f,-0.51616f}, -{-0.668454f,0.559474f,-0.490059f},{-0.587639f,0.579841f,-0.564327f},{-0.0358703f,0.534826f,-0.844201f}, -{-0.880005f,-0.0687891f,-0.469956f},{-0.915141f,-0.110246f,-0.387766f},{-0.920034f,-0.193473f,-0.340743f}, -{-0.917471f,-0.210934f,-0.337274f},{-0.907767f,-0.289137f,-0.303906f},{-0.925365f,-0.259778f,-0.27607f}, -{-0.908746f,-0.296639f,-0.293576f},{-0.89718f,-0.329847f,-0.293716f},{-0.92929f,-0.237296f,-0.283039f}, -{0.0873267f,-0.833744f,-0.545202f},{0.132631f,-0.275063f,-0.952234f},{0.133723f,0.778328f,-0.613452f}, -{0.112997f,0.888124f,-0.445496f},{-0.996352f,0.0845663f,-0.0114163f},{-0.242757f,0.902481f,-0.355804f}, -{-0.192791f,0.925555f,-0.325852f},{0.0821069f,0.599657f,-0.796034f},{0.0450017f,0.462362f,-0.885549f}, -{0.0456863f,0.445472f,-0.89413f},{0.0488839f,0.541727f,-0.839132f},{0.117665f,0.639629f,-0.759625f}, -{-0.0755639f,0.649307f,-0.756763f},{-0.523536f,-0.790108f,-0.318809f},{-0.802758f,0.404456f,-0.438171f}, -{-0.905192f,-0.304054f,-0.296949f},{-0.882081f,-0.454427f,-0.124212f},{-0.993901f,0.017008f,-0.108954f}, -{-0.937838f,-0.181207f,-0.296014f},{-0.665141f,-0.586076f,-0.462712f},{-0.778656f,-0.544372f,-0.312015f}, -{-0.997034f,0.0503957f,0.0581647f},{-0.451822f,-0.741887f,-0.49544f},{-0.530233f,-0.728497f,-0.433757f}, -{-0.514687f,-0.777484f,-0.361407f},{0.436724f,-0.897585f,0.0601103f},{-0.267713f,0.874596f,-0.404242f}, -{-0.184382f,0.894412f,-0.407468f},{-0.239753f,0.839678f,-0.487299f},{-0.660937f,0.453012f,-0.598283f}, -{-0.668512f,0.361127f,-0.650138f},{-0.674786f,0.061231f,-0.735469f},{-0.93075f,-0.0503379f,-0.362175f}, -{-0.929642f,-0.0906662f,-0.357134f},{-0.64978f,-0.615394f,-0.446178f},{-0.58863f,-0.71698f,-0.373436f}, -{0.00318272f,-0.939555f,0.342383f},{-0.145101f,-0.961075f,0.235116f},{-0.680715f,0.113708f,-0.72367f}, -{-0.887669f,0.397071f,-0.233192f},{-0.954059f,0.0816392f,-0.288281f},{-0.792749f,0.556533f,-0.248635f}, -{-0.679507f,0.672828f,-0.292527f},{-0.45138f,0.853066f,-0.261789f},{-0.603588f,0.761234f,-0.237075f}, -{-0.922933f,0.26974f,-0.274656f},{-0.96959f,-0.0548561f,-0.238506f},{-0.947935f,-0.133122f,-0.289307f}, -{-0.924055f,-0.213494f,-0.317085f},{-0.899426f,-0.251276f,-0.357622f},{-0.900932f,-0.266772f,-0.342278f}, -{-0.194343f,0.850455f,-0.488832f},{-0.0324944f,0.788577f,-0.614077f},{-0.916005f,0.348945f,0.19792f}, -{-0.812545f,-0.531355f,0.239652f},{-0.70015f,0.345013f,-0.625105f},{-0.657777f,-0.143039f,-0.739506f}, -{-0.764772f,0.307474f,-0.566201f},{-0.688961f,-0.668823f,-0.279299f},{-0.87333f,-0.281439f,-0.397601f}, -{-0.429668f,-0.366092f,-0.825447f},{-0.233538f,-0.771659f,-0.59161f},{-0.426967f,0.109738f,-0.897584f}, -{-0.737624f,-0.655111f,-0.163528f},{-0.905149f,-0.408362f,-0.118095f},{-0.999381f,-0.00136333f,-0.0351535f}, -{-0.904803f,-0.318869f,-0.282231f},{-0.946042f,-0.284675f,-0.154804f},{0.0884216f,0.584999f,-0.8062f}, -{0.106585f,0.427367f,-0.897773f},{0.0498672f,0.628808f,-0.77596f},{-0.704076f,0.547598f,-0.452122f}, -{-0.664798f,0.333039f,-0.668677f},{-0.472316f,0.827564f,-0.303406f},{-0.550143f,0.780893f,-0.295885f}, -{-0.722361f,-0.592277f,-0.356934f},{-0.872574f,0.386936f,-0.298154f},{-0.928608f,0.133556f,-0.346195f}, -{-0.792346f,0.542703f,-0.278677f},{-0.72946f,0.638489f,-0.245398f},{-0.870852f,0.385273f,-0.305257f}, -{-0.963596f,-0.0794412f,-0.255286f},{-0.947973f,-0.173342f,-0.267021f},{-0.888068f,-0.328748f,-0.321342f}, -{-0.907185f,-0.261738f,-0.329407f},{0.0476047f,0.889729f,-0.453999f},{0.0592263f,0.829014f,-0.556083f}, -{-0.0314531f,0.840112f,-0.5415f},{0.331963f,-0.0387972f,-0.942494f},{-0.0368371f,-0.256588f,-0.965819f}, -{-0.0167172f,-0.297411f,-0.954603f},{0.185203f,0.0534945f,-0.981243f},{-0.870331f,0.453847f,0.191171f}, -{-0.622077f,-0.0313076f,-0.78233f},{-0.699579f,0.420684f,-0.577594f},{-0.803813f,0.488717f,-0.339176f}, -{0.0329742f,-0.999242f,0.0207125f},{0.164832f,-0.983764f,0.0709828f},{-0.0206047f,0.918457f,-0.394983f}, -{-0.0153557f,0.905575f,-0.423907f},{-0.0935167f,0.715321f,-0.692511f},{0.0511931f,0.851253f,-0.522252f}, -{-0.0160317f,-0.999497f,0.0273526f},{-0.968668f,-0.178708f,-0.17247f},{-0.899931f,-0.411584f,-0.143951f}, -{-0.753191f,-0.543083f,-0.371166f},{-0.921122f,-0.369519f,-0.122436f},{-0.675025f,0.556727f,-0.484146f}, -{-0.922432f,0.21482f,-0.320891f},{-0.946594f,-0.313147f,0.0767992f},{-0.826512f,-0.505872f,0.246925f}, -{-0.101095f,0.874518f,-0.474339f},{0.178633f,0.891713f,-0.415859f},{0.174257f,0.866981f,-0.466882f}, -{-0.0200044f,0.642351f,-0.76615f},{0.0617693f,0.424787f,-0.903184f},{-0.0536696f,0.441809f,-0.895502f}, -{-0.977742f,-0.116558f,0.174454f},{-0.704941f,0.55243f,-0.444837f},{-0.785385f,0.27646f,-0.553842f}, -{-0.797305f,0.473351f,-0.374492f},{-0.842062f,0.352114f,-0.408592f},{-0.818045f,-0.42511f,-0.387406f}, -{0.0565383f,0.364246f,-0.929585f},{0.0346147f,0.516041f,-0.855864f},{0.363058f,0.509097f,-0.78039f}, -{0.440208f,0.416773f,-0.79531f},{0.328956f,0.493552f,-0.805106f},{0.187626f,0.556664f,-0.809273f}, -{0.208331f,0.517454f,-0.829964f},{-0.989202f,-0.121884f,-0.0813819f},{0.499549f,0.158873f,-0.851593f}, -{0.432908f,0.0386735f,-0.900608f},{0.273405f,0.49063f,-0.827364f},{0.0817157f,0.606752f,-0.79068f}, -{0.106964f,0.0401378f,-0.993452f},{0.0945015f,-0.110277f,-0.989398f},{-0.0850992f,0.719827f,-0.688917f}, -{0.417252f,0.52599f,-0.741104f},{0.395665f,0.461008f,-0.794306f},{0.103608f,0.642954f,-0.758865f}, -{0.116833f,0.681212f,-0.722704f},{0.368249f,0.572081f,-0.732882f},{-0.77825f,-0.597763f,-0.192372f}, -{-0.931479f,-0.327635f,-0.15812f},{-0.968138f,-0.239452f,-0.0732868f},{0.0234646f,-0.992831f,0.1172f}, -{0.00620094f,0.863367f,-0.504538f},{-0.74072f,-0.135665f,-0.657973f},{-0.75342f,-0.0540682f,-0.655313f}, -{-0.674416f,-0.0614504f,-0.73579f},{-0.612793f,0.0468009f,-0.788856f},{-0.734032f,0.00265937f,-0.67911f}, -{-0.706752f,0.0267475f,-0.706955f},{-0.526979f,0.0954262f,-0.844504f},{-0.782884f,-0.564665f,-0.261241f}, -{0.679924f,-0.0978195f,-0.726729f},{0.561959f,-0.391283f,-0.728766f},{-0.585405f,0.436328f,-0.683314f}, -{0.0137966f,0.957329f,-0.288671f},{-0.139726f,0.939267f,-0.313454f},{-0.0246292f,0.926615f,-0.375203f}, -{-0.687732f,-0.384911f,-0.615523f},{-0.734801f,-0.248514f,-0.631117f},{-0.789134f,-0.0194749f,-0.613912f}, -{-0.782444f,-0.0322267f,-0.621886f},{-0.73717f,0.00902504f,-0.675647f},{-0.701868f,0.228167f,-0.674774f}, -{-0.0342424f,0.914195f,-0.403826f},{0.0216571f,0.853809f,-0.520136f},{-0.158441f,0.87924f,-0.449259f}, -{-0.640767f,0.226042f,-0.733705f},{-0.751944f,0.506839f,-0.421539f},{-0.363757f,0.83771f,-0.407337f}, -{0.296575f,0.632464f,-0.715564f},{0.26247f,0.617033f,-0.741876f},{0.159429f,0.413905f,-0.89625f}, -{-0.636593f,-0.395732f,-0.661925f},{0.00776096f,0.570112f,-0.82153f},{0.0359855f,0.664895f,-0.746069f}, -{0.0310453f,0.609546f,-0.792142f},{0.288612f,0.808413f,-0.513002f},{0.393032f,0.753305f,-0.52731f}, -{0.325346f,0.75768f,-0.565748f},{-0.974308f,-0.178684f,-0.137097f},{-0.953546f,-0.22885f,-0.195905f}, -{-0.625887f,0.490681f,-0.606216f},{-0.609771f,0.642855f,-0.463592f},{-0.307379f,-0.933886f,-0.182687f}, -{0.303272f,0.817697f,-0.489282f},{-0.0330104f,0.731284f,-0.681274f},{0.0176375f,0.73728f,-0.675357f}, -{-0.799932f,-0.0896961f,-0.593349f},{-0.739251f,-0.0909561f,-0.66726f},{-0.730596f,-0.0295249f,-0.682171f}, -{-0.735792f,0.141394f,-0.662282f},{0.398786f,0.719891f,-0.568091f},{0.175395f,0.891763f,-0.417127f}, -{-0.878951f,-0.343843f,-0.33048f},{0.102957f,-0.628029f,-0.771349f},{-0.00816262f,-0.613874f,-0.789362f}, -{-0.893497f,-0.435569f,0.109282f},{0.0100863f,-0.0486995f,-0.998763f},{0.150525f,0.0452677f,-0.987569f}, -{0.0764546f,0.26098f,-0.962312f},{0.152391f,0.171026f,-0.97341f},{0.345637f,0.689084f,-0.636944f}, -{0.357883f,0.609575f,-0.707346f},{-0.100902f,0.519759f,-0.848333f},{-0.140263f,0.68451f,-0.715383f}, -{-0.10744f,0.788916f,-0.605035f},{0.394548f,0.75452f,-0.524434f},{0.388926f,0.688586f,-0.612034f}, -{-0.738403f,-0.340227f,-0.582242f},{-0.782643f,-0.254177f,-0.568211f},{0.247413f,-0.564007f,-0.787834f}, -{0.256883f,-0.117003f,-0.959334f},{-0.786296f,-0.0782728f,-0.612872f},{-0.707897f,-0.152897f,-0.689568f}, -{-0.723229f,0.022688f,-0.690235f},{-0.749203f,0.184557f,-0.636108f},{-0.701033f,0.199585f,-0.68463f}, -{-0.709307f,0.157231f,-0.687141f},{-0.696854f,0.196286f,-0.689831f},{-0.118736f,0.910259f,-0.396649f}, -{-0.175142f,0.912401f,-0.369931f},{-0.131566f,0.87213f,-0.471254f},{0.378213f,0.661221f,-0.647875f}, -{0.0959242f,0.458718f,-0.883389f},{0.383769f,0.604907f,-0.697716f},{0.349285f,0.490389f,-0.798447f}, -{0.329539f,0.53652f,-0.776885f},{-0.616684f,0.525528f,-0.586107f},{-0.422189f,0.264445f,-0.867079f}, -{-0.298524f,0.112001f,-0.947808f},{-0.306054f,0.243506f,-0.920345f},{-0.685699f,0.495668f,-0.533039f}, -{-0.657282f,0.676852f,-0.331438f},{-0.265994f,0.899443f,-0.346771f},{0.188719f,0.811568f,-0.552939f}, -{0.403312f,0.792154f,-0.458074f},{0.377123f,0.811736f,-0.44594f},{0.302501f,0.527583f,-0.79382f}, -{-0.0959399f,0.939362f,-0.329235f},{-0.772767f,-0.320831f,-0.547631f},{-0.690519f,0.217566f,-0.689818f}, -{-0.661912f,0.307201f,-0.683739f},{0.351612f,0.447101f,-0.822478f},{0.303686f,0.461482f,-0.833552f}, -{-0.147613f,0.832848f,-0.533455f},{0.312312f,0.449462f,-0.836926f},{-0.781602f,-0.335284f,-0.526007f}, -{-0.917526f,-0.0964975f,-0.385791f},{-0.838488f,-0.158383f,-0.521394f},{0.0f,-1.0f,0.0f}, -{-0.886577f,-0.14044f,-0.440747f},{-0.968258f,-0.0498201f,-0.244938f},{-0.655652f,0.450153f,-0.606203f}, -{-0.604448f,0.678246f,-0.41788f},{-0.14275f,-0.918332f,0.369173f},{0.0989465f,0.694789f,-0.712374f}, -{0.166933f,0.837658f,-0.52006f},{0.21055f,0.72595f,-0.654725f},{0.316211f,0.415471f,-0.852874f}, -{-0.547079f,-0.625644f,-0.556123f},{-0.6564f,-0.45908f,-0.598652f},{-0.620557f,-0.50989f,-0.595752f}, -{-0.334171f,0.525758f,-0.782246f},{-0.733579f,-0.147398f,-0.663427f},{-0.792315f,0.0928118f,-0.603012f}, -{-0.690414f,0.293632f,-0.661142f},{0.578691f,-0.376963f,-0.723198f},{-0.599053f,0.374824f,-0.707561f}, -{0.015523f,0.715745f,-0.698189f},{-0.107927f,0.774788f,-0.62294f},{-0.0441408f,0.723233f,-0.689192f}, -{0.407924f,0.684044f,-0.604716f},{-0.194453f,0.780287f,-0.594425f},{-0.114251f,0.723885f,-0.680394f}, -{0.555647f,0.406394f,-0.725328f},{0.518593f,0.360257f,-0.77542f},{0.520778f,0.303692f,-0.797848f}, -{0.240672f,0.416642f,-0.876633f},{0.0327207f,-0.998585f,-0.0419202f},{-0.0431421f,0.587874f,-0.807801f}, -{-0.766352f,0.134119f,-0.628264f},{-0.862351f,-0.0512968f,-0.503705f},{-0.888499f,-0.189282f,-0.418021f}, -{-0.804259f,-0.259012f,-0.534865f},{-0.645443f,-0.635757f,-0.42334f},{-0.698401f,-0.436983f,-0.566817f}, -{-0.765176f,-0.285133f,-0.577239f},{-0.830084f,-0.296906f,-0.472025f},{-0.795711f,-0.359287f,-0.487603f}, -{-0.743921f,-0.239702f,-0.623799f},{-0.780822f,-0.174298f,-0.599948f},{-0.811998f,-0.130463f,-0.568893f}, -{-0.879525f,0.0516754f,-0.473039f},{-0.820533f,0.14866f,-0.55193f},{-0.807281f,0.13951f,-0.573441f}, -{-0.712668f,0.21512f,-0.667704f},{-0.729673f,0.319276f,-0.604683f},{-0.696901f,0.37933f,-0.608636f}, -{-0.656775f,0.415176f,-0.629504f},{-0.691862f,0.261617f,-0.672966f},{-0.568101f,0.174111f,-0.80433f}, -{-0.112366f,0.606799f,-0.786873f},{-0.05266f,0.579328f,-0.813392f},{-0.1848f,0.629204f,-0.754951f}, -{-0.196257f,0.888754f,-0.414246f},{-0.240208f,0.903375f,-0.355264f},{0.544748f,0.342669f,-0.765393f}, -{0.385739f,0.3243f,-0.863733f},{0.457805f,0.216345f,-0.862328f},{0.384613f,0.32892f,-0.862487f}, -{0.0803373f,0.547268f,-0.833093f},{0.0454906f,0.620927f,-0.782547f},{-0.674372f,0.00883527f,-0.738339f}, -{-0.84339f,-0.19135f,-0.502075f},{-0.931514f,-0.058715f,-0.358935f},{-0.758433f,-0.616169f,-0.212403f}, -{-0.600183f,0.119047f,-0.790954f},{-0.365026f,0.727664f,-0.580743f},{-0.775646f,0.368886f,-0.51215f}, -{-0.665811f,0.318583f,-0.674686f},{-0.523593f,0.612358f,-0.592341f},{0.599859f,0.0667783f,-0.797314f}, -{-0.0627656f,0.904092f,-0.422703f},{-0.800314f,-0.47969f,-0.359714f},{-0.804728f,-0.352697f,-0.477513f}, -{-0.797558f,0.251342f,-0.548387f},{0.299336f,-0.933466f,0.197581f},{0.329159f,-0.935342f,0.129572f}, -{-0.219073f,0.903725f,-0.367817f},{-0.212267f,0.916372f,-0.339419f},{-0.131723f,0.689763f,-0.711952f}, -{-0.0554175f,0.330594f,-0.942145f},{0.0320061f,0.18098f,-0.982966f},{-0.280935f,0.879313f,-0.384558f}, -{-0.251187f,0.930229f,-0.267543f},{-0.292435f,0.903886f,-0.312204f},{-0.718851f,0.057869f,-0.692752f}, -{-0.982328f,0.12595f,-0.138447f},{0.786614f,0.464934f,-0.406294f},{-0.700668f,0.366514f,-0.612153f}, -{0.312493f,0.817967f,-0.48299f},{-0.601982f,-0.595711f,-0.531738f},{-0.489698f,-0.677372f,-0.548965f}, -{-0.811554f,-0.468049f,-0.349729f},{-0.761489f,0.347982f,-0.546848f},{-0.731756f,0.145687f,-0.665814f}, -{0.174515f,0.884687f,-0.432289f},{-0.114839f,0.792609f,-0.598818f},{0.112595f,0.652698f,-0.749205f}, -{0.767002f,0.399536f,-0.502075f},{0.15278f,0.810745f,-0.565111f},{-0.702188f,0.107794f,-0.703784f}, -{-0.633727f,0.299399f,-0.713267f},{-0.0571531f,-0.643154f,0.763601f},{-0.427399f,0.823243f,-0.373633f}, -{-0.47606f,0.788375f,-0.389657f},{-0.518836f,0.696978f,-0.495006f},{-0.761843f,0.502152f,-0.409193f}, -{-0.908978f,0.15949f,-0.385125f},{-0.917297f,0.0193351f,-0.397734f},{-0.926845f,-0.050602f,-0.372019f}, -{-0.927027f,-0.202271f,-0.315766f},{-0.590106f,-0.644232f,-0.48656f},{-0.603943f,-0.643506f,-0.470269f}, -{-0.580711f,-0.717758f,-0.384186f},{-0.677655f,-0.7017f,-0.220003f},{-0.804464f,-0.533413f,-0.261358f}, -{-0.864175f,-0.356112f,-0.355508f},{-0.851693f,-0.371734f,-0.369368f},{-0.854062f,-0.407542f,-0.323244f}, -{-0.851561f,-0.394576f,-0.345188f},{-0.877129f,-0.167053f,-0.450265f},{-0.918302f,-0.0351973f,-0.394312f}, -{-0.927236f,-0.0126858f,-0.374262f},{-0.95147f,0.0250336f,-0.306721f},{-0.915624f,0.0651938f,-0.396715f}, -{-0.876806f,0.15456f,-0.455326f},{-0.885586f,0.147487f,-0.440438f},{-0.883614f,0.193033f,-0.426574f}, -{-0.825263f,0.319221f,-0.465875f},{-0.790863f,0.32737f,-0.517074f},{-0.709898f,0.0806033f,-0.699677f}, -{-0.0398124f,0.680137f,-0.732003f},{0.584153f,0.293525f,-0.756708f},{0.618851f,0.395068f,-0.678929f}, -{-0.767229f,0.225208f,-0.600534f},{-0.77519f,0.253299f,-0.578723f},{-0.682595f,0.190452f,-0.705544f}, -{-0.776026f,0.168611f,-0.607745f},{-0.859731f,0.371183f,-0.350837f},{-0.673324f,0.285739f,-0.6819f}, -{-0.727279f,0.537275f,-0.427084f},{-0.735501f,0.339622f,-0.586256f},{-0.716775f,0.674215f,-0.177957f}, -{-0.74042f,0.661547f,-0.118885f},{-0.43986f,0.804958f,-0.398203f},{-0.940599f,0.0319039f,-0.338018f}, -{-0.581107f,-0.717514f,-0.384043f},{-0.606471f,-0.659641f,-0.443923f},{-0.913605f,-0.148399f,-0.378555f}, -{-0.933232f,0.0702974f,-0.352329f},{-0.834932f,0.33923f,-0.433372f},{-0.738723f,0.209806f,-0.640523f}, -{-0.755023f,0.427757f,-0.496955f},{-0.724755f,0.681174f,-0.103601f},{-0.489712f,0.813523f,-0.313628f}, -{-0.868385f,-0.320696f,-0.378234f},{-0.899023f,0.150755f,-0.411134f},{-0.620953f,-0.356866f,-0.6979f}, -{-0.736245f,0.329334f,-0.591171f},{-0.752901f,0.257652f,-0.605604f},{-0.758671f,0.506889f,-0.409246f}, -{-0.670159f,0.564671f,-0.481698f},{-0.41136f,0.798592f,-0.439357f},{-0.712829f,0.660545f,-0.235702f}, -{-0.955273f,0.267109f,-0.126908f},{-0.993407f,0.0231793f,-0.11227f},{-0.933768f,-0.285835f,-0.215351f}, -{-0.522153f,-0.80213f,-0.28973f},{-0.591668f,-0.703124f,-0.394392f},{-0.686102f,-0.632814f,-0.358901f}, -{-0.674643f,-0.686631f,-0.270916f},{-0.751492f,-0.557023f,-0.353533f},{-0.851592f,-0.408749f,-0.328199f}, -{-0.874671f,-0.330786f,-0.354304f},{-0.889016f,-0.355231f,-0.288896f},{-0.808405f,-0.536273f,-0.242677f}, -{-0.865771f,-0.41462f,-0.280233f},{-0.919658f,-0.178283f,-0.349921f},{-0.929822f,0.0642691f,-0.362355f}, -{-0.955185f,0.0169424f,-0.295525f},{-0.930455f,0.000111387f,-0.366407f},{-0.91058f,0.167131f,-0.378036f}, -{-0.920372f,0.185707f,-0.344133f},{-0.899459f,0.2174f,-0.379093f},{-0.884971f,0.276707f,-0.374512f}, -{-0.864626f,0.258211f,-0.430985f},{-0.798431f,0.0357707f,-0.601023f},{-0.706052f,-0.322651f,-0.630387f}, -{-0.645647f,-0.42174f,-0.636612f},{-0.686848f,-0.423865f,-0.590405f},{-0.762974f,-0.311095f,-0.566648f}, -{-0.881004f,-0.0543548f,-0.469976f},{-0.878294f,0.0736529f,-0.472414f},{-0.855078f,0.167816f,-0.49059f}, -{-0.795931f,0.234467f,-0.558139f},{-0.731186f,0.272107f,-0.62556f},{-0.691631f,0.234792f,-0.683022f}, -{-0.652312f,0.437466f,-0.618961f},{-0.736543f,0.354978f,-0.575756f},{-0.841663f,0.118126f,-0.526925f}, -{-0.821913f,0.158685f,-0.547063f},{-0.766839f,0.226806f,-0.60043f},{-0.700081f,0.449037f,-0.555205f}, -{-0.633108f,0.633201f,-0.445232f},{-0.701542f,0.248827f,-0.667775f},{-0.756746f,0.56066f,-0.336147f}, -{-0.629406f,0.77327f,0.0768261f},{-0.652054f,-0.665617f,-0.363016f},{-0.850827f,-0.17411f,-0.495762f}, -{-0.92283f,0.0165544f,-0.384853f},{-0.92248f,0.063835f,-0.380731f},{-0.900127f,0.114247f,-0.420379f}, -{-0.782641f,0.243676f,-0.572796f},{-0.77963f,0.230663f,-0.582213f},{-0.845516f,0.11178f,-0.522119f}, -{-0.709714f,0.466652f,-0.527772f},{-0.400168f,0.870759f,-0.285735f},{-0.292425f,0.156734f,-0.943357f}, -{-0.735463f,-0.631546f,-0.245446f},{-0.797337f,-0.491385f,-0.350419f},{-0.908647f,0.250044f,-0.334423f}, -{-0.671733f,-0.467832f,-0.574377f},{-0.707944f,0.390645f,-0.588398f},{-0.807272f,0.194343f,-0.557264f}, -{-0.610848f,-0.732514f,-0.30048f},{-0.674118f,-0.457605f,-0.579795f},{0.451244f,0.0484673f,-0.891083f}, -{0.473483f,0.0961672f,-0.875538f},{-0.641274f,-0.741973f,-0.195559f},{-0.496208f,0.338717f,-0.799405f}, -{-0.461432f,0.358428f,-0.811548f},{0.566993f,0.562716f,-0.601556f},{-0.016211f,0.337597f,-0.941151f}, -{0.0142408f,0.296582f,-0.954901f},{0.152933f,0.162301f,-0.974818f},{0.460267f,0.760721f,-0.457665f}, -{0.266763f,-0.4287f,0.863165f},{-0.229672f,0.792f,-0.565674f},{-0.183382f,0.922747f,-0.338982f}, -{-0.0423757f,0.683786f,-0.728451f},{-0.078403f,0.92181f,-0.379631f},{-0.175821f,0.91269f,-0.368895f}, -{0.0319953f,0.763247f,-0.645315f},{0.702159f,0.515647f,-0.491f},{0.773998f,0.507949f,-0.378041f}, -{0.700035f,0.505806f,-0.504094f},{0.488668f,0.329755f,-0.807754f},{0.494024f,0.59918f,-0.630019f}, -{0.553235f,0.493178f,-0.671347f},{0.416349f,0.563334f,-0.713658f},{0.631496f,0.041896f,-0.774246f}, -{-0.164784f,0.487377f,-0.857502f},{-0.0916461f,0.350752f,-0.931973f},{-0.123292f,0.333143f,-0.93478f}, -{0.432491f,0.372184f,-0.821237f},{0.371927f,0.337693f,-0.864658f},{0.366353f,0.303488f,-0.879591f}, -{0.301134f,0.453315f,-0.838942f},{0.338526f,0.404715f,-0.849474f},{0.335097f,0.376204f,-0.863818f}, -{0.418205f,0.224577f,-0.880153f},{0.301306f,0.574076f,-0.761349f},{0.242002f,0.593726f,-0.767414f}, -{0.282472f,0.61884f,-0.732971f},{0.0259057f,0.734429f,-0.678191f},{0.289283f,0.717467f,-0.633684f}, -{0.000842052f,0.572893f,-0.819629f},{0.611392f,0.270866f,-0.743527f},{0.38074f,0.252503f,-0.889539f}, -{0.465128f,0.413081f,-0.782956f},{0.171625f,0.243028f,-0.954716f},{0.125825f,0.386253f,-0.91377f}, -{0.0129325f,0.398473f,-0.917089f},{0.0361355f,0.47008f,-0.881884f},{0.341164f,-0.747721f,0.569667f}, -{0.200665f,-0.688634f,0.69679f},{0.235842f,0.431982f,-0.8705f},{0.636529f,0.504031f,-0.583766f}, -{0.608404f,0.487187f,-0.626493f},{0.228318f,0.295752f,-0.927578f},{-0.363634f,0.203676f,-0.909003f}, -{0.588486f,0.667092f,-0.456807f},{0.581279f,0.615243f,-0.532532f},{-0.0425343f,0.776099f,-0.629175f}, -{-0.033611f,0.737196f,-0.674843f},{0.451443f,0.142728f,-0.880811f},{0.0148181f,-0.998955f,-0.0432437f}, -{0.430652f,0.505955f,-0.747361f},{0.663306f,0.015291f,-0.748192f},{0.381259f,0.835846f,-0.394973f}, -{0.319437f,0.838482f,-0.441485f},{0.478502f,0.508641f,-0.715765f},{0.343964f,0.541458f,-0.767145f}, -{0.0565948f,-0.83426f,-0.548459f},{-0.2399f,0.915786f,-0.322155f},{-0.17528f,0.938477f,-0.297554f}, -{-0.345293f,0.876527f,-0.335369f},{0.155107f,-0.700209f,0.696886f},{0.518676f,0.656536f,-0.547664f}, -{0.540738f,0.696976f,-0.470985f},{-0.530286f,0.670052f,-0.519449f},{0.173892f,0.450541f,-0.875657f}, -{0.264071f,0.476953f,-0.838321f},{0.242757f,0.218363f,-0.945191f},{0.166356f,-0.768676f,0.617627f}, -{-0.113909f,0.326739f,-0.938225f},{0.484652f,0.733872f,-0.475967f},{0.25989f,0.909259f,-0.325124f}, -{-0.13513f,0.367255f,-0.920252f},{-0.0836041f,0.28648f,-0.954431f},{0.694915f,0.407838f,-0.592251f}, -{0.755633f,0.298784f,-0.582878f},{0.183817f,0.688876f,-0.701185f},{0.329009f,0.56222f,-0.758724f}, -{0.450194f,0.417842f,-0.789135f},{0.426558f,0.624877f,-0.653894f},{0.474707f,0.334435f,-0.814129f}, -{-0.368151f,0.702815f,-0.6087f},{0.441703f,0.751622f,-0.48986f},{0.324125f,0.385029f,-0.864116f}, -{0.553038f,0.362224f,-0.750296f},{0.592331f,0.191065f,-0.782712f},{0.545859f,0.282084f,-0.788965f}, -{0.643405f,0.153596f,-0.749959f},{0.603579f,0.440697f,-0.664439f},{0.561321f,0.45505f,-0.691266f}, -{0.274957f,0.426057f,-0.861901f},{0.51976f,0.49844f,-0.693835f},{0.492771f,0.292664f,-0.819466f}, -{0.475031f,0.455529f,-0.752887f},{0.447749f,0.310442f,-0.838538f},{0.60608f,0.361225f,-0.708649f}, -{0.671187f,0.621191f,-0.404513f},{0.499191f,0.431184f,-0.751591f},{0.496577f,0.735805f,-0.460437f}, -{-0.182961f,0.799778f,-0.571734f},{-0.148508f,0.75117f,-0.643187f},{-0.125094f,0.69274f,-0.710255f}, -{-0.0456011f,0.630923f,-0.774504f},{0.515427f,0.473627f,-0.714151f},{0.325487f,0.479803f,-0.814768f}, -{0.0854529f,0.600774f,-0.794838f},{0.397275f,0.715379f,-0.574809f},{0.723071f,0.581009f,-0.373626f}, -{0.538154f,0.430644f,-0.724524f},{-0.318307f,0.836747f,-0.445572f},{0.309693f,0.443584f,-0.841025f}, -{0.609157f,0.175619f,-0.77336f},{0.0230232f,0.685541f,-0.72767f},{0.574796f,0.145307f,-0.805292f}, -{0.0529214f,0.706485f,-0.705747f},{0.462671f,0.340719f,-0.818441f},{0.292814f,0.517741f,-0.803868f}, -{-0.23533f,0.822868f,-0.517212f},{0.108122f,0.103404f,-0.988745f},{0.707184f,0.394909f,-0.586463f}, -{0.529927f,0.343312f,-0.775445f},{0.0648392f,0.783754f,-0.617677f},{0.02647f,0.524744f,-0.850848f}, -{-0.045521f,0.7608f,-0.647388f},{0.118751f,0.88849f,-0.443264f},{-0.0161997f,0.457597f,-0.889012f}, -{0.000280184f,0.398345f,-0.917235f},{0.0561452f,0.767709f,-0.638334f},{-0.624146f,-0.0435425f,-0.780093f}, -{0.231384f,-0.0713779f,-0.970241f},{0.403915f,0.224348f,-0.88686f},{0.210782f,0.871545f,-0.442697f}, -{0.239799f,0.817561f,-0.523536f},{0.449956f,0.539841f,-0.711415f},{0.777722f,0.411413f,-0.475276f}, -{-0.0354915f,0.335593f,-0.941338f},{-0.568895f,-0.812661f,-0.126259f},{0.191192f,0.806213f,-0.55988f}, -{-0.0525749f,0.804373f,-0.591794f},{-0.00818761f,0.759069f,-0.650959f},{0.0183587f,-0.996702f,0.0790466f}, -{0.798654f,0.469085f,-0.376976f},{0.00703419f,0.455561f,-0.890177f},{-0.379388f,0.711838f,-0.591059f}, -{-0.356592f,0.682883f,-0.637584f},{0.159572f,0.698134f,-0.697958f},{-0.0127765f,0.446995f,-0.894445f}, -{0.429407f,0.375184f,-0.82149f},{0.375785f,0.710967f,-0.5944f},{-0.353617f,0.82554f,-0.439818f}, -{-0.29696f,0.869412f,-0.39489f},{-0.206536f,0.683309f,-0.700309f},{0.0821383f,0.485265f,-0.870501f}, -{0.0984004f,0.402228f,-0.910236f},{0.516561f,0.229612f,-0.82489f},{0.550054f,0.0979327f,-0.829367f}, -{0.385639f,-0.695462f,0.606312f},{-0.366341f,0.482633f,-0.795525f},{-0.402403f,0.371983f,-0.836481f}, -{0.155905f,0.37037f,-0.915707f},{0.349217f,0.269209f,-0.897538f},{0.0164691f,-0.998683f,0.0485895f}, -{0.598748f,0.120536f,-0.791815f},{0.610598f,0.110001f,-0.784264f},{-0.514242f,0.289975f,-0.807137f}, -{-0.0559095f,0.147385f,-0.987498f},{-0.318715f,0.0545386f,-0.94628f},{0.504873f,0.254761f,-0.824742f}, -{0.208381f,0.0932082f,-0.973596f},{0.387806f,0.408758f,-0.82615f},{0.433037f,0.482513f,-0.761354f}, -{0.290996f,0.751733f,-0.591793f},{0.447236f,0.828435f,-0.337157f},{0.00941225f,0.76729f,-0.641231f}, -{-0.394672f,0.547728f,-0.737718f},{0.0124283f,0.71336f,-0.700687f},{-0.00554958f,0.640843f,-0.767652f}, -{-0.0250379f,0.60922f,-0.792606f},{-0.355539f,0.551191f,-0.754838f},{-0.0722814f,0.578202f,-0.812685f}, -{0.567135f,0.265433f,-0.779682f},{0.0651969f,0.379966f,-0.9227f},{-0.690634f,-0.632789f,-0.350148f}, -{-0.588416f,-0.793163f,-0.157031f},{-0.61951f,-0.714354f,-0.325432f},{0.26334f,0.909731f,-0.321001f}, -{0.162899f,0.168777f,-0.9721f},{-0.250455f,-0.579707f,-0.775379f},{0.0868959f,0.251874f,-0.963851f}, -{-0.00789398f,0.248566f,-0.968583f},{0.169066f,-0.886262f,-0.431227f},{0.230861f,0.171183f,-0.95781f}, -{-0.326545f,0.302039f,-0.895623f},{0.390293f,0.218435f,-0.894403f},{0.46466f,0.36971f,-0.804615f}, -{0.395036f,0.206159f,-0.895234f},{0.355156f,0.127125f,-0.926123f},{0.426136f,0.16671f,-0.889166f}, -{0.227801f,-0.666285f,0.71005f},{-0.143781f,0.574938f,-0.805465f},{-0.17141f,0.442747f,-0.88011f}, -{-0.267554f,0.646156f,-0.714771f},{-0.303341f,0.558085f,-0.772351f},{-0.291798f,0.614407f,-0.733047f}, -{-0.273007f,0.547826f,-0.790793f},{0.492345f,0.234013f,-0.838352f},{-0.077035f,0.628769f,-0.773767f}, -{-0.218071f,0.684619f,-0.695515f},{-0.244835f,0.698392f,-0.672535f},{-0.22162f,0.646343f,-0.730154f}, -{-0.214732f,0.54545f,-0.810169f},{-0.268715f,0.470151f,-0.840684f},{0.0603743f,-0.691798f,-0.719563f}, -{0.606051f,0.3876f,-0.694599f},{0.265445f,0.352554f,-0.897354f},{-0.153875f,0.507607f,-0.847737f}, -{-0.0218791f,0.2504f,-0.967895f},{0.551176f,0.495749f,-0.671147f},{0.611981f,0.287921f,-0.736601f}, -{0.256431f,0.513728f,-0.818735f},{0.0377112f,-0.996204f,0.078455f},{0.303029f,0.247999f,-0.920147f}, -{0.111975f,0.673271f,-0.730868f},{0.171041f,0.507994f,-0.844208f},{0.212217f,0.634694f,-0.743053f}, -{0.064679f,0.308196f,-0.949122f},{0.137869f,0.696416f,-0.704271f},{-0.132098f,0.735681f,-0.664322f}, -{-0.265268f,0.687997f,-0.675495f},{-0.177326f,0.583504f,-0.792514f},{-0.159021f,0.5532f,-0.81773f}, -{-0.0648649f,0.494838f,-0.866561f},{0.742841f,0.289633f,-0.603574f},{-0.244684f,0.734364f,-0.633119f}, -{-0.230733f,0.626359f,-0.744605f},{-0.0475614f,0.476977f,-0.877628f},{0.806145f,0.328443f,-0.492195f}, -{0.553227f,0.516329f,-0.653716f},{-0.157719f,0.757436f,-0.633573f},{-0.115361f,0.701471f,-0.7033f}, -{-0.121287f,0.647932f,-0.751979f},{-0.119817f,0.518635f,-0.846559f},{0.686161f,0.434175f,-0.583674f}, -{0.414612f,0.725276f,-0.549611f},{0.0854752f,0.862823f,-0.498227f},{-0.12717f,0.823634f,-0.55268f}, -{-0.039744f,0.417788f,-0.907675f},{0.058142f,0.464484f,-0.883671f},{0.331886f,0.247708f,-0.910216f}, -{0.385355f,0.193432f,-0.902267f},{-0.0793643f,0.273121f,-0.9587f},{0.0536832f,0.505359f,-0.861238f}, -{-0.615467f,0.0831187f,-0.783768f},{0.313339f,0.713027f,-0.627226f},{0.689499f,0.582774f,-0.430075f}, -{-0.128185f,0.762866f,-0.633723f},{0.0196996f,0.887205f,-0.460954f},{-0.00598953f,0.836441f,-0.548024f}, -{-0.0213968f,0.757067f,-0.652987f},{-0.00143753f,0.690355f,-0.72347f},{-0.0019361f,0.639495f,-0.768793f}, -{-0.00192568f,0.582949f,-0.812506f},{0.0273509f,0.473471f,-0.880385f},{-0.02277f,0.363068f,-0.931484f}, -{0.0540861f,-0.998258f,0.0235792f},{0.0645095f,0.441878f,-0.894753f},{0.0700004f,0.944914f,-0.319746f}, -{0.0117661f,0.405937f,-0.913825f},{0.0176947f,0.515517f,-0.856697f},{0.680651f,0.415756f,-0.60321f}, -{0.130425f,-0.961724f,0.240989f},{0.0967715f,-0.959725f,0.263748f},{0.0194044f,-0.999714f,-0.0139699f}, -{0.133409f,0.926465f,-0.351945f},{0.117102f,0.858963f,-0.498468f},{0.103475f,0.763646f,-0.637289f}, -{0.111402f,0.690044f,-0.715143f},{0.101804f,0.595361f,-0.796982f},{0.128685f,0.522187f,-0.843067f}, -{0.0402739f,0.41697f,-0.908027f},{0.399144f,-0.91055f,-0.107621f},{-0.435934f,-0.825475f,-0.358542f}, -{-0.109148f,0.471589f,-0.875037f},{-0.0636207f,0.541546f,-0.83826f},{0.16092f,0.918152f,-0.362079f}, -{0.132701f,0.495073f,-0.858657f},{-0.45753f,0.383971f,-0.802018f},{0.599068f,0.532026f,-0.598386f}, -{0.18527f,0.936653f,-0.297248f},{0.206933f,0.904728f,-0.372352f},{0.249515f,0.825249f,-0.506662f}, -{0.271295f,0.741368f,-0.613818f},{0.310646f,0.614839f,-0.724894f},{0.241053f,0.565042f,-0.789063f}, -{0.241853f,0.535239f,-0.809337f},{0.176168f,0.543811f,-0.820509f},{0.0455045f,0.57979f,-0.813494f}, -{-0.0771866f,0.507401f,-0.858246f},{0.440673f,-0.660931f,-0.607436f},{0.500526f,0.292855f,-0.814684f}, -{0.0414138f,-0.998864f,0.0235917f},{-0.0509805f,-0.997048f,0.0574192f},{-0.415864f,0.575909f,-0.703836f}, -{0.338532f,0.763192f,-0.550395f},{0.35893f,0.71351f,-0.601724f},{0.385059f,0.664926f,-0.640003f}, -{0.328951f,0.645277f,-0.689499f},{0.221126f,0.632886f,-0.741996f},{0.108873f,0.668475f,-0.735723f}, -{0.0340051f,0.683036f,-0.729593f},{-0.00556542f,0.544468f,-0.838763f},{-0.00862487f,-0.999916f,-0.00968689f}, -{-0.522209f,-0.433801f,-0.734244f},{-0.171697f,-0.631512f,-0.756117f},{0.133674f,0.312652f,-0.940415f}, -{-0.497572f,0.211301f,-0.841293f},{-0.362949f,0.167034f,-0.916716f},{0.0326084f,-0.00788205f,-0.999437f}, -{0.0178542f,-0.0277267f,-0.999456f},{-0.47475f,0.365741f,-0.800529f},{-0.473612f,0.341419f,-0.811865f}, -{-0.461667f,0.388046f,-0.797674f},{-0.424027f,0.360027f,-0.831012f},{-0.432038f,0.35578f,-0.828712f}, -{-0.431902f,0.351066f,-0.830791f},{-0.456517f,0.110316f,-0.882849f},{-0.361814f,0.114788f,-0.925156f}, -{-0.228224f,-0.316424f,-0.920755f},{-0.148414f,-0.339823f,-0.928706f},{-0.261238f,-0.215537f,-0.940903f}, -{-0.328999f,-0.10573f,-0.938393f},{-0.451714f,0.350036f,-0.820627f},{-0.347968f,0.0215898f,-0.937258f}, -{-0.309485f,-0.0149301f,-0.950787f},{0.463137f,0.067709f,-0.883696f},{-0.241012f,-0.400193f,-0.884171f}, -{-0.0357501f,-0.449568f,-0.892531f},{-0.0140368f,-0.988301f,-0.151869f},{0.0435599f,-0.988519f,-0.144679f}, -{-0.534633f,0.0470525f,-0.843773f},{-0.478002f,-0.0821379f,-0.87451f},{-0.401819f,0.0454912f,-0.914588f}, -{-0.357866f,-0.0533086f,-0.93225f},{-0.451596f,0.267947f,-0.851038f},{-0.360766f,0.261536f,-0.895236f}, -{0.410366f,-0.166006f,-0.896684f},{-0.513599f,0.162015f,-0.842596f},{0.3566f,-0.711176f,0.605859f}, -{-0.120089f,0.322861f,-0.938797f},{-0.248431f,0.441079f,-0.862399f},{-0.175283f,0.367227f,-0.913466f}, -{-0.450494f,0.0551368f,-0.891075f},{-0.42014f,0.147097f,-0.895458f},{-0.557979f,0.0600499f,-0.82768f}, -{0.366826f,-0.521694f,-0.770243f},{0.365232f,-0.318742f,-0.874648f},{0.363532f,-0.145989f,-0.920072f}, -{0.20774f,0.0420311f,-0.977281f},{0.0751624f,0.217239f,-0.97322f},{-0.321394f,-0.326397f,-0.888915f}, -{-0.393182f,-0.385769f,-0.83462f},{-0.392275f,-0.212391f,-0.894992f},{-0.406007f,-0.534047f,-0.741588f}, -{0.315182f,-0.194353f,-0.928917f},{-0.0685202f,-0.992297f,-0.103202f},{-0.0284892f,0.181927f,-0.982899f}, -{-0.53002f,-0.387743f,-0.754145f},{0.357128f,-0.656742f,-0.664191f},{0.276723f,-0.451058f,-0.848511f}, -{0.175629f,-0.170525f,-0.969575f},{0.0425135f,0.164236f,-0.985505f},{-0.0143207f,0.317665f,-0.948095f}, -{0.0122568f,0.405787f,-0.913885f},{-0.47831f,-0.644036f,-0.597024f},{-0.475634f,-0.613191f,-0.63069f}, -{-0.348139f,-0.163224f,-0.923124f},{-0.411986f,-0.109838f,-0.904546f},{-0.581602f,-0.567347f,-0.582972f}, -{-0.517116f,-0.623338f,-0.586551f},{-0.105834f,-0.0441267f,-0.993404f},{0.0528876f,-0.29564f,-0.953834f}, -{-0.50201f,-0.715353f,-0.486061f},{-0.461784f,-0.701117f,-0.543314f},{-0.626786f,0.0544235f,-0.777288f}, -{-0.752071f,0.129508f,-0.646232f},{-0.263653f,-0.0708322f,-0.962014f},{0.438893f,-0.660336f,-0.609368f}, -{0.217609f,-0.414783f,-0.883516f},{0.147652f,-0.530349f,-0.834822f},{-0.338162f,0.160716f,-0.927263f}, -{0.307363f,0.120576f,-0.943922f},{0.0490676f,0.223205f,-0.973536f},{-0.403132f,0.0502257f,-0.913763f}, -{-0.404395f,0.167715f,-0.899075f},{-0.273011f,0.356315f,-0.893591f},{0.00575582f,0.31997f,-0.94741f}, -{-0.154191f,0.0769798f,-0.985038f},{-0.0460386f,-0.00195168f,-0.998938f},{-0.417116f,-0.198723f,-0.886862f}, -{-0.529885f,-0.00125872f,-0.848068f},{-0.196126f,-0.974976f,0.104673f},{0.287061f,-0.528227f,-0.799107f}, -{0.162375f,-0.468503f,-0.868412f},{0.11783f,-0.339373f,-0.933243f},{0.00841994f,-0.0591842f,-0.998212f}, -{0.0947982f,0.174364f,-0.980107f},{0.351317f,0.0632065f,-0.93412f},{0.024536f,0.157757f,-0.987173f}, -{0.10294f,-0.457501f,-0.88323f},{0.122128f,-0.417088f,-0.900623f},{0.102582f,-0.465494f,-0.879086f}, -{0.167471f,-0.388124f,-0.906263f},{-0.0613336f,0.143051f,-0.987813f},{-0.29684f,0.289434f,-0.910008f}, -{-0.152998f,-0.0536475f,-0.986769f},{-0.519057f,-0.225463f,-0.824467f},{-0.145503f,0.163285f,-0.97579f}, -{-0.499829f,-0.705746f,-0.50209f},{-0.0914336f,-0.843831f,0.528762f},{0.0807299f,-0.328036f,-0.94121f}, -{-0.806231f,0.368991f,-0.462426f},{0.330734f,-0.580551f,-0.744027f},{0.583488f,0.141328f,-0.79973f}, -{-0.320216f,0.320748f,-0.891394f},{-0.412065f,0.356592f,-0.838478f},{-0.491405f,0.167616f,-0.854649f}, -{0.199711f,-0.705233f,-0.680266f},{0.146874f,-0.613057f,-0.776267f},{0.227035f,-0.450278f,-0.863542f}, -{0.122738f,-0.209788f,-0.970012f},{0.112813f,-0.0401108f,-0.992806f},{-0.203394f,-0.724243f,-0.658865f}, -{0.0196344f,-0.138169f,-0.990214f},{0.0655215f,-0.302574f,-0.950871f},{-0.0604679f,-0.00683363f,-0.998147f}, -{-0.221203f,-0.308623f,-0.925106f},{-0.226549f,-0.188684f,-0.955549f},{-0.433699f,0.367571f,-0.822677f}, -{0.191396f,-0.331647f,-0.923784f},{0.172897f,-0.271091f,-0.946898f},{-0.214423f,0.265942f,-0.939839f}, -{-0.172306f,0.202648f,-0.963973f},{-0.235133f,0.261565f,-0.936107f},{-0.159272f,0.192711f,-0.968243f}, -{-0.366161f,0.368952f,-0.854284f},{-0.416712f,0.28621f,-0.862806f},{-0.322311f,0.235694f,-0.916823f}, -{-0.108791f,0.0573097f,-0.992411f},{-0.23577f,-0.0337679f,-0.971222f},{-0.106879f,-0.064881f,-0.992153f}, -{-0.02569f,-0.335202f,-0.941796f},{-0.577113f,0.0728067f,-0.813412f},{-0.46981f,-0.468811f,-0.747994f}, -{-0.0801707f,-0.0791455f,-0.993634f},{-0.0991288f,-0.0698804f,-0.992618f},{0.166914f,-0.585763f,-0.793109f}, -{0.124322f,-0.458685f,-0.879859f},{0.0818947f,-0.254017f,-0.963726f},{0.203168f,-0.284487f,-0.936905f}, -{-0.378567f,0.271463f,-0.88487f},{-0.415195f,-0.628034f,-0.658169f},{-0.332351f,-0.620089f,-0.710656f}, -{-0.254031f,-0.712061f,-0.654551f},{-0.376504f,-0.711748f,-0.593009f},{-0.37075f,-0.39528f,-0.840416f}, -{0.0194336f,-0.0314723f,-0.999316f},{-0.301979f,-0.494561f,-0.814996f},{-0.294411f,-0.766308f,-0.571046f}, -{-0.106275f,0.131253f,-0.985636f},{0.0212621f,0.103805f,-0.99437f},{-0.0399005f,0.257478f,-0.96546f}, -{-0.113825f,0.251492f,-0.961143f},{-0.176062f,-0.583995f,-0.792434f},{-0.427957f,0.302497f,-0.851674f}, -{-0.289149f,-0.76017f,-0.581838f},{-0.366384f,-0.718341f,-0.591396f},{-0.546571f,-0.25365f,-0.798074f}, -{-0.39526f,-0.289349f,-0.871807f},{-0.403287f,-0.227755f,-0.886277f},{-0.489823f,-0.266145f,-0.830205f}, -{0.480623f,0.0180865f,-0.876741f},{0.00374673f,0.181041f,-0.983468f},{-0.38202f,-0.586857f,-0.713905f}, -{0.158242f,-0.536317f,-0.829049f},{0.0826999f,-0.411103f,-0.90783f},{0.233891f,-0.411181f,-0.881037f}, -{-0.254003f,-0.718621f,-0.647353f},{-0.0677313f,-0.248287f,-0.966316f},{-0.355975f,-0.0219649f,-0.934237f}, -{-0.244444f,-0.773455f,-0.58482f},{0.0347758f,0.0843179f,-0.995832f},{-0.0978183f,-0.384104f,-0.918094f}, -{0.0148392f,-0.349137f,-0.936954f},{-0.234185f,-0.31982f,-0.918081f},{-0.296005f,-0.312823f,-0.902509f}, -{-0.149664f,-0.762597f,-0.629322f},{0.298053f,-0.548791f,-0.78102f},{0.0532691f,0.187605f,-0.980799f}, -{-0.033569f,-0.249132f,-0.967888f},{-0.389285f,-0.307134f,-0.868404f},{-0.314508f,-0.334821f,-0.888245f}, -{-0.262679f,-0.400729f,-0.877733f},{-0.211967f,-0.335246f,-0.917976f},{-0.0722862f,-0.746754f,-0.661161f}, -{-0.209982f,-0.10056f,-0.97252f},{-0.61991f,-0.237285f,-0.747935f},{-0.486362f,-0.715322f,-0.501763f}, -{0.591243f,0.0442269f,-0.80528f},{-0.1822f,-0.425288f,-0.886529f},{-0.12628f,-0.280556f,-0.951494f}, -{-0.293787f,-0.25386f,-0.921544f},{-0.45819f,-0.694794f,-0.554367f},{-0.265962f,-0.2459f,-0.932093f}, -{0.552218f,-0.296904f,-0.77904f},{0.616997f,-0.208742f,-0.758776f},{0.532225f,-0.0320237f,-0.845997f}, -{0.518351f,0.0671195f,-0.85253f},{0.0783362f,-0.99421f,0.0735581f},{0.118141f,-0.991686f,0.051016f}, -{-0.162888f,-0.271886f,-0.948444f},{-0.293131f,0.331585f,-0.896731f},{0.598523f,-0.060331f,-0.798831f}, -{-0.309627f,-0.348615f,-0.884646f},{0.466335f,-0.598079f,-0.651792f},{0.663968f,-0.130472f,-0.73629f}, -{-0.426057f,-0.246834f,-0.870373f},{-0.320111f,-0.413622f,-0.852318f},{-0.275072f,-0.289065f,-0.916939f}, -{-0.121374f,-0.00139793f,-0.992606f},{-0.104278f,0.0295214f,-0.99411f},{-0.441475f,0.425385f,-0.79003f}, -{-0.354671f,-0.736701f,0.575743f},{-0.307603f,-0.735628f,0.603517f},{-0.14795f,-0.963575f,0.222786f}, -{-0.247067f,-0.209033f,-0.946184f},{0.478306f,-0.542814f,-0.690346f},{0.573596f,-0.413039f,-0.70738f}, -{0.0413827f,0.111407f,-0.992913f},{0.697966f,-0.174554f,-0.694531f},{0.0884714f,-0.995767f,-0.0249182f}, -{0.66496f,-0.0925447f,-0.741123f},{0.530716f,0.0144358f,-0.847427f},{0.424264f,0.0554731f,-0.903838f}, -{0.43501f,0.059857f,-0.898434f},{-0.0618874f,0.058737f,-0.996353f},{-0.153908f,0.138131f,-0.978382f}, -{-0.433835f,-0.75467f,-0.492201f},{0.311733f,0.130743f,-0.941132f},{0.430592f,-0.545578f,-0.718982f}, -{0.563177f,-0.165806f,-0.809531f},{0.528658f,-0.0254374f,-0.848454f},{0.463703f,0.116946f,-0.878239f}, -{0.408836f,0.0773136f,-0.909327f},{0.432356f,-0.362167f,-0.825774f},{-0.0226638f,-0.365996f,-0.93034f}, -{-0.0502062f,-0.277693f,-0.959357f},{-0.0211832f,-0.252399f,-0.967391f},{-0.500045f,-0.0644449f,-0.863598f}, -{-0.551538f,-0.0144755f,-0.834024f},{-0.34341f,-0.0575228f,-0.937423f},{-0.312247f,-0.0818833f,-0.946465f}, -{-0.182016f,-0.0683459f,-0.980918f},{-0.613054f,-0.35332f,-0.706633f},{-0.169602f,0.137656f,-0.975851f}, -{0.501381f,-0.187936f,-0.844569f},{0.410831f,0.034876f,-0.911044f},{0.556872f,-0.242513f,-0.794406f}, -{0.430962f,0.0348824f,-0.901696f},{0.466346f,0.0318584f,-0.884029f},{0.476106f,0.0373906f,-0.878593f}, -{-0.384256f,-0.333572f,0.860858f},{0.409459f,-0.402863f,-0.818563f},{0.347749f,-0.57205f,-0.742852f}, -{0.3489f,-0.310127f,-0.884359f},{0.330387f,0.0285511f,-0.943413f},{0.386763f,0.0233366f,-0.921884f}, -{0.434189f,-0.216166f,-0.874501f},{0.403344f,-0.155649f,-0.901713f},{0.397898f,-0.0907694f,-0.912928f}, -{0.444065f,0.110133f,-0.8892f},{0.436053f,0.102098f,-0.89411f},{0.450432f,0.0181053f,-0.892627f}, -{0.459103f,0.0236729f,-0.888068f},{-0.400662f,-0.908358f,-0.119813f},{-0.25029f,0.0413912f,-0.967286f}, -{-0.285704f,0.0674397f,-0.955942f},{-0.250687f,0.0544366f,-0.966537f},{0.414188f,-0.541434f,-0.731641f}, -{0.263469f,-0.554858f,-0.789124f},{0.478863f,-0.182555f,-0.858699f},{0.499925f,-0.229435f,-0.835126f}, -{0.44019f,-0.441255f,-0.782001f},{0.273243f,-0.564661f,-0.778778f},{0.308691f,-0.458051f,-0.833606f}, -{0.258205f,-0.263016f,-0.929598f},{0.266399f,-0.0140867f,-0.96376f},{0.325926f,-0.0461329f,-0.944269f}, -{0.350478f,-0.219007f,-0.910605f},{0.354576f,-0.145572f,-0.923626f},{0.370918f,-0.170775f,-0.912828f}, -{0.36704f,-0.104143f,-0.924357f},{0.397743f,0.0893554f,-0.913135f},{0.412708f,0.16809f,-0.89522f}, -{0.461831f,0.0794305f,-0.883404f},{0.491097f,0.00610044f,-0.871083f},{0.469434f,0.0393794f,-0.882089f}, -{-0.318099f,0.1176f,-0.940736f},{0.397764f,-0.22051f,-0.890595f},{0.339251f,-0.140336f,-0.930169f}, -{0.415097f,0.104971f,-0.903701f},{0.448675f,0.0117692f,-0.893618f},{0.335919f,-0.319947f,-0.885885f}, -{0.31524f,-0.196916f,-0.928357f},{0.441539f,0.052358f,-0.895713f},{0.374789f,0.0703258f,-0.924439f}, -{0.291724f,-0.429357f,-0.854722f},{0.198636f,-0.335479f,-0.920868f},{0.241156f,-0.318072f,-0.916883f}, -{0.309921f,-0.504065f,-0.806144f},{0.342391f,-0.433425f,-0.833613f},{0.279045f,-0.345422f,-0.896001f}, -{0.282074f,-0.247687f,-0.926869f},{0.279043f,-0.0375461f,-0.959544f},{0.26891f,-0.0713013f,-0.960523f}, -{0.277696f,-0.230241f,-0.93267f},{0.282046f,-0.160948f,-0.945804f},{0.24807f,-0.11132f,-0.962325f}, -{0.324934f,0.0120236f,-0.94566f},{0.404792f,0.0859546f,-0.91036f},{0.421959f,-0.0172375f,-0.906451f}, -{0.405509f,0.0607184f,-0.912072f},{0.370021f,0.0255989f,-0.92867f},{-0.273495f,0.102608f,-0.956385f}, -{-0.214751f,-0.0217704f,-0.976426f},{0.0389195f,-0.998942f,-0.0245161f},{0.301224f,-0.125571f,-0.945249f}, -{0.247679f,0.00834955f,-0.968806f},{-0.582805f,-0.287323f,-0.760121f},{0.153013f,-0.257305f,-0.954139f}, -{0.0623255f,-0.321166f,-0.94497f},{0.118664f,-0.440027f,-0.890109f},{0.186817f,-0.485921f,-0.853804f}, -{0.256389f,-0.395781f,-0.881829f},{0.242238f,-0.192341f,-0.95096f},{0.215539f,-0.00689006f,-0.976471f}, -{0.250731f,-0.139028f,-0.958021f},{0.261066f,-0.213902f,-0.941324f},{0.256085f,-0.0887571f,-0.962571f}, -{0.230182f,-0.188229f,-0.95477f},{0.34271f,-0.116949f,-0.932133f},{0.483111f,0.0179296f,-0.875376f}, -{0.506741f,0.0262392f,-0.861699f},{0.420864f,0.0887582f,-0.902771f},{0.387847f,0.0724752f,-0.91887f}, -{0.373944f,0.0811103f,-0.923898f},{-0.463775f,-0.155676f,-0.872169f},{0.205632f,-0.363896f,-0.908457f}, -{0.414665f,-0.202407f,-0.887177f},{0.51326f,-0.0593179f,-0.856181f},{0.477654f,0.0737985f,-0.875443f}, -{0.456738f,0.120889f,-0.881349f},{-0.124059f,-0.0143952f,-0.99217f},{0.159493f,-0.171302f,-0.972223f}, -{0.0728596f,-0.286864f,-0.955197f},{0.14769f,-0.548362f,-0.823096f},{0.222186f,-0.501618f,-0.83607f}, -{0.140263f,-0.412915f,-0.899904f},{0.0834118f,-0.318639f,-0.944199f},{0.132404f,-0.165691f,-0.977249f}, -{0.211184f,-0.0144253f,-0.97734f},{0.247741f,-0.159525f,-0.955603f},{0.282763f,-0.251771f,-0.925557f}, -{0.309661f,-0.0746755f,-0.94791f},{0.352027f,-0.173439f,-0.91978f},{0.314486f,-0.260742f,-0.91275f}, -{0.309214f,-0.0476167f,-0.9498f},{0.297153f,0.0785501f,-0.951593f},{0.341974f,0.140095f,-0.929208f}, -{0.361015f,0.0969296f,-0.927509f},{0.319776f,0.0989742f,-0.94231f},{0.13153f,0.190633f,-0.97281f}, -{0.0931867f,0.114043f,-0.989096f},{0.223886f,-0.0861198f,-0.970803f},{0.168265f,-0.0797806f,-0.982508f}, -{0.312417f,-0.196147f,-0.929474f},{0.326859f,-0.0967924f,-0.940103f},{-0.359361f,0.0730781f,-0.930333f}, -{0.158572f,-0.0861268f,-0.983584f},{0.109713f,-0.282932f,-0.952845f},{0.138901f,-0.618307f,-0.773565f}, -{0.227161f,-0.643871f,-0.730635f},{0.27837f,-0.418527f,-0.864492f},{0.262264f,-0.228899f,-0.937456f}, -{0.15929f,-0.233517f,-0.959216f},{0.095923f,-0.265918f,-0.959211f},{0.273692f,-0.203507f,-0.940041f}, -{0.395505f,-0.250086f,-0.883761f},{0.321622f,-0.368589f,-0.872182f},{0.370407f,-0.233665f,-0.898999f}, -{0.268743f,-0.0340914f,-0.962608f},{0.190561f,-0.22345f,-0.955906f},{0.199725f,-0.252784f,-0.946684f}, -{0.219432f,-0.0917187f,-0.971307f},{0.249687f,0.0682264f,-0.96592f},{0.251793f,0.115452f,-0.96087f}, -{0.311541f,0.0876862f,-0.946178f},{0.277111f,0.139705f,-0.950627f},{0.335169f,-0.213682f,-0.917606f}, -{0.413841f,-0.243567f,-0.877161f},{-0.508553f,0.375086f,-0.775038f},{0.158959f,-0.33245f,-0.929628f}, -{0.149185f,-0.0420049f,-0.987917f},{0.119061f,-0.346273f,-0.930548f},{0.104111f,-0.669696f,-0.735301f}, -{0.144693f,-0.679733f,-0.719046f},{0.165334f,-0.354326f,-0.92039f},{0.190832f,-0.188236f,-0.963405f}, -{0.213776f,-0.300113f,-0.929641f},{0.184987f,-0.345558f,-0.919984f},{0.214224f,-0.303985f,-0.928279f}, -{0.256223f,-0.283327f,-0.924162f},{0.23446f,-0.110913f,-0.965778f},{0.222045f,0.0280285f,-0.974634f}, -{0.219076f,-0.154819f,-0.963347f},{0.20427f,-0.26067f,-0.94357f},{0.200559f,-0.182029f,-0.962622f}, -{0.20429f,-0.0842184f,-0.975281f},{0.25253f,0.0505589f,-0.966267f},{0.332164f,0.0709402f,-0.94055f}, -{0.441632f,0.0665385f,-0.894726f},{-0.351427f,0.362608f,-0.863142f},{0.247619f,0.00508906f,-0.968844f}, -{0.389279f,-0.0348041f,-0.920462f},{0.443012f,0.0647495f,-0.894174f},{0.109221f,-0.993986f,-0.00792956f}, -{0.203599f,-0.978122f,-0.0427252f},{-0.238324f,0.306725f,-0.921478f},{0.1839f,-0.223995f,-0.957082f}, -{0.409799f,0.203448f,-0.889198f},{0.102517f,-0.279304f,-0.954714f},{0.13668f,-0.0744809f,-0.987811f}, -{0.186384f,-0.311169f,-0.931899f},{0.174915f,-0.699354f,-0.693043f},{0.187465f,-0.654656f,-0.732313f}, -{0.136217f,-0.352045f,-0.926018f},{0.203846f,-0.210139f,-0.956184f},{0.244663f,-0.312758f,-0.917781f}, -{0.108868f,-0.329495f,-0.93786f},{0.203825f,-0.317197f,-0.926197f},{0.204169f,-0.301991f,-0.931191f}, -{0.20256f,-0.0767667f,-0.976256f},{0.150877f,-0.00640872f,-0.988532f},{0.230954f,-0.186151f,-0.954991f}, -{0.155388f,-0.298392f,-0.941709f},{0.1697f,-0.192309f,-0.96655f},{0.18909f,-0.116842f,-0.974984f}, -{0.282293f,-0.0916951f,-0.954936f},{0.331828f,-0.0941502f,-0.93863f},{0.308796f,0.0477273f,-0.94993f}, -{-0.408249f,-0.720043f,-0.561134f},{0.268533f,-0.263567f,-0.926511f},{0.091933f,-0.285835f,-0.953859f}, -{0.118349f,-0.0897115f,-0.988911f},{0.145821f,-0.461532f,-0.875057f},{0.126957f,-0.694749f,-0.707958f}, -{0.114736f,-0.552027f,-0.825894f},{0.0458875f,-0.363814f,-0.930341f},{0.17179f,-0.349481f,-0.92106f}, -{0.241402f,-0.314832f,-0.917936f},{0.187544f,-0.248817f,-0.95022f},{0.154279f,-0.317391f,-0.935661f}, -{0.171403f,-0.273071f,-0.946601f},{0.218886f,-0.0469395f,-0.974621f},{0.23039f,-0.0452667f,-0.972045f}, -{0.334638f,-0.235148f,-0.912537f},{0.238913f,-0.201569f,-0.94989f},{0.201881f,-0.159874f,-0.966273f}, -{0.25613f,-0.189546f,-0.947877f},{0.257277f,-0.113556f,-0.959642f},{0.220836f,-0.0757441f,-0.972365f}, -{0.162348f,0.0763838f,-0.983773f},{0.189445f,0.265051f,-0.945441f},{0.136332f,-0.0751422f,-0.987809f}, -{0.095285f,-0.27107f,-0.957832f},{0.101441f,-0.104338f,-0.989355f},{0.0567444f,-0.445659f,-0.893402f}, -{-0.000193409f,-0.676142f,-0.736771f},{0.0109145f,-0.465338f,-0.885066f},{0.0534069f,-0.389789f,-0.919354f}, -{0.0916234f,-0.502817f,-0.859523f},{0.160832f,-0.40552f,-0.899826f},{0.159299f,-0.195571f,-0.967665f}, -{0.132088f,-0.240001f,-0.961744f},{0.0841788f,-0.31464f,-0.945471f},{0.133508f,-0.134741f,-0.981845f}, -{0.17912f,-0.0888595f,-0.979806f},{0.208443f,-0.195479f,-0.9583f},{0.259759f,-0.212322f,-0.942043f}, -{0.226557f,-0.164269f,-0.960046f},{0.138192f,-0.0514023f,-0.989071f},{0.093177f,-0.0381038f,-0.99492f}, -{0.0672073f,-0.120768f,-0.990403f},{0.176091f,0.262835f,-0.948636f},{0.0965525f,-0.994059f,-0.0502461f}, -{-0.0002735f,-0.997933f,0.0642685f},{-0.00876615f,-0.997232f,0.073829f},{-0.0215592f,-0.996239f,0.083924f}, -{0.198791f,-0.12984f,-0.971403f},{-0.613472f,-0.357682f,-0.704071f},{0.145189f,-0.0897178f,-0.985328f}, -{0.0700315f,-0.316691f,-0.94594f},{-0.0368761f,-0.677374f,-0.734714f},{-0.0508762f,-0.574966f,-0.816594f}, -{0.00461845f,-0.453498f,-0.891245f},{-0.00453975f,-0.52994f,-0.848023f},{0.00720484f,-0.395835f,-0.918294f}, -{0.0863324f,-0.18462f,-0.979011f},{0.129269f,-0.278945f,-0.951567f},{0.227027f,-0.32294f,-0.918786f}, -{0.265326f,-0.189893f,-0.945274f},{0.255582f,-0.118537f,-0.959493f},{0.287931f,-0.233008f,-0.928872f}, -{0.268068f,-0.185136f,-0.945444f},{0.196184f,-0.0750087f,-0.977694f},{0.0985332f,0.00685483f,-0.99511f}, -{0.162505f,-0.0579435f,-0.985005f},{0.151121f,-0.336992f,-0.9293f},{0.208861f,-0.129676f,-0.96931f}, -{-0.333093f,-0.877541f,-0.344923f},{-0.855978f,-0.334846f,-0.393928f},{0.342906f,-0.296651f,-0.891299f}, -{0.278857f,-0.0874291f,-0.956345f},{0.191219f,-0.979642f,0.0611353f},{-0.0449772f,-0.984866f,-0.167378f}, -{0.257991f,-0.139881f,-0.955967f},{0.140787f,0.0217321f,-0.989801f},{0.171542f,-0.0350602f,-0.984553f}, -{0.191266f,-0.111461f,-0.975189f},{0.134866f,0.0460265f,-0.989794f},{-0.474359f,-0.186298f,-0.860393f}, -{-0.0743062f,-0.679009f,0.730359f},{0.17509f,-0.179612f,-0.968031f},{0.18737f,-0.182224f,-0.965239f}, -{0.0634384f,-0.553884f,-0.830173f},{-0.0614459f,-0.573997f,-0.816549f},{-0.0548518f,-0.463718f,-0.884283f}, -{-0.0542619f,-0.46565f,-0.883304f},{-0.0886851f,-0.485649f,-0.869643f},{-0.031275f,-0.343695f,-0.938561f}, -{0.109803f,-0.424685f,-0.898658f},{0.157277f,-0.316265f,-0.935543f},{0.181625f,-0.149741f,-0.9719f}, -{0.250089f,-0.202109f,-0.946893f},{0.224643f,-0.195189f,-0.954692f},{0.189713f,-0.127546f,-0.97352f}, -{0.120296f,-0.0534839f,-0.991296f},{-0.457533f,-0.498441f,-0.736356f},{-0.0184083f,-0.864544f,0.502219f}, -{0.0450966f,-0.998981f,0.00189569f},{0.0182236f,-0.999668f,-0.0182031f},{-0.308813f,-0.950316f,0.0391569f}, -{0.249777f,-0.228349f,-0.940993f},{0.0407418f,-0.378347f,-0.924767f},{-0.164432f,0.40839f,-0.897875f}, -{-0.314956f,0.0949649f,-0.944343f},{-0.541635f,-0.409308f,-0.734233f},{-0.159007f,-0.282733f,-0.945927f}, -{-0.0413941f,-0.283658f,-0.958032f},{0.0651972f,-0.232411f,-0.97043f},{0.0368408f,-0.149265f,-0.988111f}, -{0.0695572f,-0.163889f,-0.984024f},{0.0598061f,-0.11698f,-0.991332f},{0.0909766f,0.0319594f,-0.99534f}, -{0.102819f,-0.0478997f,-0.993546f},{0.0437593f,-0.077876f,-0.996002f},{0.0155373f,0.0713922f,-0.997327f}, -{-0.348753f,0.139677f,-0.926748f},{0.23431f,-0.891494f,0.387733f},{-0.553502f,-0.308364f,-0.773659f}, -{-0.616738f,-0.173523f,-0.767805f},{-0.380602f,0.11266f,-0.917851f},{0.22381f,-0.132088f,-0.965641f}, -{-0.0792494f,-0.411621f,-0.907903f},{-0.193881f,-0.479576f,-0.855813f},{-0.197234f,-0.449732f,-0.871114f}, -{-0.0877846f,-0.449835f,-0.888787f},{-0.185332f,-0.415287f,-0.890612f},{-0.207097f,-0.395328f,-0.894889f}, -{-0.118296f,-0.403333f,-0.907374f},{0.00189189f,-0.999994f,0.00306737f},{-0.457134f,-0.420451f,-0.783741f}, -{-0.635975f,-0.131724f,-0.760385f},{-0.269536f,-0.956413f,-0.112361f},{-0.288356f,-0.418766f,-0.861096f}, -{-0.36962f,-0.401844f,-0.837797f},{-0.377607f,-0.407334f,-0.83156f},{-0.348602f,-0.404377f,-0.845551f}, -{-0.248868f,-0.324939f,-0.912403f},{-0.279433f,-0.340647f,-0.897707f},{-0.214021f,-0.324631f,-0.921309f}, -{-0.112611f,-0.190842f,-0.97514f},{-0.0751645f,-0.194146f,-0.978089f},{-0.0507894f,-0.146409f,-0.987919f}, -{-0.0101824f,-0.0328948f,-0.999407f},{0.0159028f,-0.0202976f,-0.999668f},{-0.0595336f,0.00126352f,-0.998226f}, -{-0.0968821f,0.0913483f,-0.991095f},{-0.139114f,0.286357f,-0.94797f},{-0.921666f,-0.384264f,-0.0535948f}, -{0.0780428f,-0.996611f,-0.0260006f},{-0.283515f,-0.477441f,-0.831667f},{-0.331705f,-0.449341f,-0.829496f}, -{-0.385828f,-0.392684f,-0.834827f},{-0.517772f,-0.225955f,-0.82514f},{-0.55825f,-0.15923f,-0.81425f}, -{-0.592719f,-0.108802f,-0.798027f},{0.230233f,-0.0502752f,-0.971836f},{0.119686f,0.0323427f,-0.992285f}, -{-0.158251f,-0.204838f,-0.965918f},{-0.250495f,-0.436161f,-0.864301f},{-0.453561f,-0.372427f,-0.809679f}, -{-0.371939f,-0.334884f,-0.865745f},{-0.351896f,-0.847199f,0.398023f},{-0.0471725f,-0.995583f,0.0811798f}, -{-0.178855f,0.347392f,-0.920505f},{-0.0643786f,-0.901551f,0.427855f},{0.165713f,-0.0165558f,-0.986035f}, -{0.093963f,0.185729f,-0.978098f},{-0.085456f,0.0715648f,-0.993768f},{-0.383911f,-0.292464f,-0.875829f}, -{-0.429875f,-0.347318f,-0.833413f},{-0.481882f,-0.391585f,-0.783869f},{-0.433764f,-0.41101f,-0.801823f}, -{-0.492389f,-0.348149f,-0.797713f},{-0.48093f,-0.351514f,-0.803209f},{-0.369498f,-0.397625f,-0.83986f}, -{-0.434404f,-0.368349f,-0.821956f},{-0.328686f,-0.300934f,-0.895212f},{-0.272589f,-0.176483f,-0.945806f}, -{-0.194385f,-0.0887588f,-0.976901f},{-0.213207f,0.0173482f,-0.976853f},{-0.203672f,0.0458605f,-0.977965f}, -{-0.212849f,0.138942f,-0.967156f},{-0.201355f,0.286949f,-0.936545f},{-0.170263f,-0.958942f,0.226804f}, -{0.0336438f,-0.997239f,0.066202f},{0.476486f,-0.877819f,0.0489346f},{-0.175802f,-0.482737f,-0.857938f}, -{-0.240114f,-0.406166f,-0.881688f},{-0.317766f,-0.319497f,-0.892719f},{-0.450952f,-0.15198f,-0.879514f}, -{-0.511979f,-0.296898f,-0.806058f},{-0.508813f,-0.393695f,-0.76558f},{0.112715f,0.225438f,-0.967715f}, -{-0.598289f,-0.679083f,-0.42532f},{-0.235634f,-0.951767f,-0.196511f},{-0.476286f,-0.803592f,-0.356919f}, -{-0.362864f,-0.223333f,-0.904683f},{-0.420486f,-0.21012f,-0.882633f},{-0.279394f,0.219675f,-0.93471f}, -{-0.0115128f,-0.999142f,0.0397777f},{-0.000605356f,-0.997024f,0.077089f},{-0.0082265f,-0.999963f,0.00249397f}, -{-0.0261943f,-0.998588f,-0.0462172f},{0.0705986f,0.26835f,-0.960731f},{-0.0994969f,0.328516f,-0.939243f}, -{-0.393652f,-0.0258967f,-0.918895f},{-0.523073f,-0.360866f,-0.772121f},{-0.533142f,-0.277189f,-0.799328f}, -{-0.483933f,-0.15738f,-0.860837f},{-0.436994f,-0.0964095f,-0.894283f},{-0.363398f,0.0677128f,-0.92917f}, -{-0.473792f,-0.00518424f,-0.880622f},{-0.390418f,0.0204487f,-0.920411f},{-0.355069f,0.15848f,-0.921309f}, -{-0.18989f,-0.469618f,-0.862207f},{0.0387132f,-0.998767f,0.031081f},{-0.22247f,-0.972103f,-0.0743105f}, -{-0.0842592f,-0.983493f,0.160133f},{-0.460062f,0.220102f,-0.860173f},{0.0931486f,-0.955462f,0.280027f}, -{0.0532537f,-0.998488f,-0.0136487f},{-0.203823f,-0.966645f,-0.155093f},{0.0599921f,-0.998181f,0.00590705f}, -{0.0167739f,-0.999717f,-0.0168777f},{0.111033f,-0.986245f,0.122446f},{0.0914944f,-0.881277f,0.463658f}, -{0.0355514f,-0.998636f,0.0382277f},{0.437185f,-0.872861f,0.216754f},{0.422546f,-0.855048f,0.300579f}, -{0.42756f,-0.880253f,0.205784f},{-0.322485f,-0.87414f,-0.363155f},{-0.00853661f,-0.991127f,-0.132642f}, -{-0.145474f,-0.888027f,-0.436171f},{-0.493414f,-0.735429f,0.464422f},{-0.335755f,-0.760172f,0.556243f}, -{-0.493879f,-0.817461f,0.296379f},{0.261385f,-0.811544f,0.522565f},{0.032797f,-0.995392f,0.090103f}, -{0.114284f,-0.915866f,0.384874f},{-0.423877f,-0.903915f,-0.0571463f},{-0.595218f,-0.723646f,0.34936f}, -{0.21114f,-0.821121f,0.530264f},{-0.00545385f,-0.999841f,-0.0169869f},{-0.0187241f,-0.995127f,-0.0968045f}, -{0.0192527f,-0.997316f,0.0706471f},{0.0217938f,-0.996704f,0.0781471f},{0.0252164f,-0.997289f,0.0691295f}, -{0.0388396f,-0.996338f,0.076169f},{-0.0958933f,-0.67412f,0.732371f},{-0.0528083f,-0.6354f,0.770375f}, -{-0.277386f,-0.89954f,0.337469f},{-0.415031f,-0.742829f,0.525313f},{0.0269597f,-0.998768f,0.0416694f}, -{0.0208328f,-0.998511f,0.0504246f},{0.0197848f,-0.999201f,0.0347204f},{0.441117f,-0.887602f,0.132582f}, -{0.220524f,-0.949395f,-0.223647f},{0.254325f,-0.918615f,-0.302432f},{-0.411947f,-0.905298f,-0.103613f}, -{0.0330157f,-0.999407f,0.00973608f},{0.0360647f,-0.999324f,0.00715541f},{0.0281243f,-0.999554f,0.0100368f}, -{0.0317264f,-0.999288f,-0.0204045f},{0.0207974f,-0.999648f,-0.0164574f},{0.390465f,-0.895183f,0.214907f}, -{0.068996f,-0.997368f,-0.0222887f},{0.00696426f,-0.999677f,0.0244445f},{0.113192f,-0.990527f,-0.0777368f}, -{0.0300783f,-0.997791f,-0.0592262f},{-0.101247f,-0.989736f,0.100855f},{-0.488221f,-0.872483f,-0.0203287f}, -{0.0192702f,-0.995406f,0.0937832f},{-0.00526962f,-0.999976f,0.004602f},{0.168434f,-0.985586f,-0.015808f}, -{-0.274512f,-0.959802f,0.0585097f},{-0.125707f,-0.991656f,-0.0285798f},{-0.440623f,-0.879403f,-0.180285f}, -{-0.508811f,-0.860146f,0.0355013f},{-0.295831f,-0.930916f,-0.214194f},{-0.133933f,-0.979029f,-0.153508f}, -{-0.504832f,-0.82857f,-0.242108f},{-0.199422f,-0.931407f,-0.304485f},{-0.0191935f,-0.999509f,-0.0247501f}, -{-0.00421024f,-0.997259f,-0.0738707f},{-0.456138f,-0.792245f,-0.405322f},{0.536549f,-0.617989f,0.574635f}, -{0.159432f,-0.964327f,0.211319f},{0.119699f,-0.987882f,0.098801f},{0.0753162f,-0.996306f,0.041258f}, -{0.0769156f,-0.995434f,0.056522f},{0.199961f,-0.972262f,0.121333f},{0.0324883f,-0.998411f,0.0460362f}, -{0.00150144f,-0.998946f,0.0458802f},{0.0212488f,-0.999318f,0.0302135f},{0.0380284f,-0.999242f,-0.00828349f}, -{0.0575431f,-0.998323f,0.00632132f},{-0.0275333f,-0.993345f,-0.111842f},{0.179328f,-0.983237f,-0.032964f}, -{0.134155f,-0.989332f,0.056792f},{-0.275129f,-0.942456f,0.189949f},{-0.434564f,-0.859275f,0.269818f}, -{-0.501779f,-0.819213f,0.277684f},{0.230928f,-0.92776f,0.293145f},{0.457012f,-0.817257f,0.351042f}, -{0.431776f,-0.889879f,0.147261f},{-0.00337819f,-0.99996f,0.00822642f},{-0.0679747f,-0.924453f,0.375188f}, -{0.421036f,-0.80576f,0.41651f},{0.261081f,-0.824249f,0.502445f},{-0.400411f,-0.863751f,0.30595f}, -{-0.00950766f,-0.998909f,0.0457252f},{0.108334f,-0.993724f,-0.0278652f},{0.119746f,-0.987411f,0.103343f}, -{0.246439f,-0.960619f,0.128374f},{-0.0457223f,-0.994671f,-0.0924088f},{0.254503f,-0.966784f,0.0235859f}, -{0.267335f,-0.961599f,0.0621237f},{0.139755f,-0.968292f,0.207074f},{-0.0581971f,-0.996083f,0.0665645f}, -{-0.100193f,-0.994413f,0.0332144f},{0.256728f,-0.860271f,0.440482f},{0.0205264f,-0.995617f,0.0912464f}, -{0.145715f,-0.989314f,-0.00497361f},{0.442628f,-0.725749f,0.526658f},{0.422509f,-0.759082f,0.495258f}, -{0.0250255f,-0.999672f,0.00538897f},{0.0226148f,-0.999695f,-0.0098717f},{-0.0512331f,-0.95503f,0.29205f}, -{0.0094949f,-0.999954f,0.00102734f},{-0.134225f,-0.965527f,-0.223029f},{-0.0342345f,-0.997022f,-0.0691043f}, -{0.0220392f,-0.999002f,-0.0388572f},{0.0200358f,-0.999289f,-0.031944f},{-0.160766f,-0.975433f,-0.150616f}, -{0.0182022f,-0.999505f,-0.0256645f},{0.157028f,-0.799171f,0.580231f},{0.348365f,-0.535744f,0.769168f}, -{-0.0879878f,-0.890344f,0.446705f},{-0.299798f,-0.892556f,0.336847f},{-0.485275f,-0.745735f,0.456494f}, -{-0.0470124f,-0.998452f,-0.0297115f},{0.0765366f,-0.877318f,0.473766f},{-0.0188492f,-0.998556f,-0.0503023f}, -{0.0232935f,-0.998163f,0.0559258f},{-0.0291428f,-0.923105f,0.383443f},{0.0719425f,-0.983426f,0.166427f}, -{-0.352676f,-0.869485f,0.345856f},{0.0223918f,-0.995144f,0.0958476f},{0.0235307f,-0.996475f,0.0805263f}, -{-0.0904133f,-0.98791f,0.125936f},{-0.669071f,-0.733856f,-0.117467f},{0.409527f,-0.911178f,-0.0452039f}, -{-0.477475f,-0.771456f,0.420563f},{0.0244424f,-0.995812f,0.0881007f},{0.0470478f,-0.997189f,0.0583127f}, -{-0.627038f,-0.766081f,0.141222f},{-0.641998f,-0.766623f,-0.0113149f},{-0.598191f,-0.738564f,-0.310951f}, -{-0.435507f,-0.821898f,-0.367176f},{-0.00972171f,-0.998838f,0.0472077f},{-0.433635f,-0.802921f,0.408997f}, -{0.0943655f,-0.869567f,0.484715f},{-0.113401f,-0.985403f,0.126968f},{-0.0507322f,-0.910702f,0.409937f}, -{-0.147138f,-0.692524f,0.706229f},{0.0576281f,-0.990996f,0.120851f},{0.0329572f,-0.994475f,0.0996614f}, -{0.0424437f,-0.995673f,0.0826672f},{-0.458454f,-0.748406f,0.479278f},{0.183653f,-0.959272f,-0.214638f}, -{0.0274192f,-0.999423f,-0.020069f},{0.0224728f,-0.999636f,-0.0148969f},{0.0689027f,-0.996106f,0.0550065f}, -{0.267426f,-0.943674f,0.194839f},{-0.143591f,-0.609172f,0.77993f},{-0.683555f,-0.706749f,0.182371f}, -{0.0207577f,-0.999514f,-0.0232647f},{-0.00208528f,-0.999923f,-0.0122105f},{0.00944962f,-0.999952f,0.00269041f}, -{0.0197769f,-0.999642f,-0.0180048f},{0.0818378f,-0.995107f,0.0553525f},{-0.60003f,-0.772993f,0.206023f}, -{0.132217f,-0.736984f,0.662852f},{0.0259287f,-0.996915f,0.0740829f},{-0.219604f,-0.975282f,0.0244756f}, -{0.181724f,-0.972486f,0.145768f},{0.186707f,-0.976889f,-0.104062f},{-0.358453f,-0.845749f,0.395247f}, -{0.125563f,-0.984195f,0.124874f},{-0.172515f,-0.972719f,0.155102f},{0.0503893f,-0.998717f,-0.00495466f}, -{0.252812f,-0.945431f,0.20554f},{0.327671f,-0.916653f,0.228865f},{0.413063f,-0.88025f,0.233537f}, -{0.507231f,-0.849177f,0.147022f},{0.418226f,-0.898864f,0.130885f},{-0.254397f,-0.928918f,0.26906f}, -{0.331623f,-0.931502f,0.149429f},{0.31091f,-0.914002f,0.260643f},{0.66593f,-0.668128f,0.331876f}, -{0.344914f,-0.804073f,0.484252f},{0.368575f,-0.849033f,0.378543f},{0.0591826f,-0.99639f,0.0608577f}, -{-0.623304f,-0.750806f,-0.218594f},{-0.617055f,-0.758178f,-0.210734f},{-0.588556f,-0.784469f,-0.195473f}, -{-0.559468f,-0.824327f,-0.0864911f},{0.0300425f,-0.998085f,0.0540763f},{0.0202993f,-0.999654f,-0.0167502f}, -{0.0324792f,-0.999177f,-0.0242951f},{0.0377085f,-0.998735f,-0.0332751f},{0.0247975f,-0.999377f,-0.0251006f}, -{-0.175498f,-0.980598f,-0.0873358f},{0.0152553f,-0.999611f,-0.0233534f},{-0.0155738f,-0.999348f,-0.0325671f}, -{0.433514f,-0.891799f,0.129464f},{0.0318165f,-0.999425f,-0.0117401f},{0.0301593f,-0.998859f,-0.0370258f}, -{0.0351686f,-0.998546f,-0.0408672f},{0.0354106f,-0.997615f,0.0592413f},{0.0265466f,-0.993097f,0.114249f}, -{-0.246175f,-0.969217f,-0.004021f},{0.0260654f,-0.999081f,-0.0340246f},{0.439339f,-0.795647f,0.417046f}, -{0.453894f,-0.753803f,0.475144f},{-0.0218013f,-0.997889f,0.0611717f},{-0.353667f,-0.930265f,-0.0976006f}, -{-0.573537f,-0.714299f,-0.401039f},{-0.258594f,-0.948539f,-0.182764f},{-0.4667f,-0.864393f,-0.187126f}, -{0.395986f,-0.871117f,0.290431f},{0.177311f,-0.984137f,-0.0060141f},{-0.0176953f,-0.999403f,-0.0296736f}, -{-0.467747f,-0.865832f,-0.177615f},{0.0250974f,-0.998326f,-0.052109f},{-0.639944f,-0.768392f,0.00664921f}, -{-0.436519f,-0.882692f,-0.174088f},{-0.0443429f,-0.996264f,-0.0741012f},{0.148824f,-0.978852f,0.14036f}, -{0.290687f,-0.919037f,0.266219f},{0.352249f,-0.880871f,0.316206f},{0.0831872f,-0.874957f,0.477f}, -{-0.0582198f,-0.996291f,0.0633602f},{-0.210873f,-0.96402f,-0.161858f},{0.133774f,-0.990679f,-0.0256777f}, -{0.438413f,-0.846291f,0.302631f},{0.033499f,-0.997861f,0.056144f},{-0.45141f,-0.872907f,-0.1851f}, -{0.0452908f,-0.996803f,0.0658251f},{-0.0145148f,-0.999841f,0.0103397f},{0.498847f,-0.852849f,0.154272f}, -{-0.333123f,-0.851253f,0.40546f},{-0.48286f,-0.805861f,-0.342687f},{-0.296849f,-0.934096f,-0.198358f}, -{0.0291155f,-0.99953f,-0.00955752f},{-0.222844f,-0.947564f,0.229046f},{-0.0128039f,-0.996041f,0.087971f}, -{-0.522135f,-0.852551f,0.0230707f},{-0.397436f,-0.898396f,-0.186892f},{-0.522835f,-0.827296f,-0.205488f}, -{-0.641568f,-0.688765f,0.337629f},{0.0315253f,-0.999262f,-0.0219513f},{-0.0624349f,-0.891708f,0.448284f}, -{-0.19033f,-0.639321f,0.745012f},{0.465534f,-0.885002f,-0.00708205f},{0.0205535f,-0.999617f,0.0185422f}, -{0.0343446f,-0.999226f,-0.019187f},{-0.012597f,-0.921971f,0.387055f},{-0.0375038f,-0.964409f,0.261741f}, -{0.0311963f,-0.999185f,-0.0256275f},{-0.179976f,-0.983404f,0.0229121f},{0.019335f,-0.999568f,0.0221399f}, -{0.0401681f,-0.998975f,0.0208602f},{-0.460601f,-0.886659f,-0.0410255f},{-0.440598f,-0.897705f,-4.98216e-05f}, -{-0.504286f,-0.842614f,0.188935f},{-0.692687f,-0.706962f,0.142793f},{-0.655434f,-0.755063f,0.0168972f}, -{0.0579206f,-0.997201f,0.0472857f},{0.0291897f,-0.999256f,0.0252153f},{0.277683f,-0.837692f,0.470282f}, -{-0.35385f,-0.827547f,0.43584f},{-0.14467f,-0.922792f,0.357107f},{-0.243562f,-0.650974f,0.718965f}, -{-0.0765156f,-0.90654f,0.415127f},{-0.0870873f,-0.647042f,0.757464f},{-0.0998985f,-0.705678f,0.701455f}, -{-0.121883f,-0.585755f,0.801271f},{-0.0845681f,-0.794925f,0.600785f},{0.322318f,-0.89145f,0.318478f}, -{0.268049f,-0.899651f,0.344641f},{0.394246f,-0.896125f,0.20379f},{0.365052f,-0.901085f,0.234057f}, -{-0.328019f,-0.934659f,-0.137167f},{-0.360418f,-0.920976f,0.147993f},{-0.45244f,-0.82013f,0.350265f}, -{-0.591845f,-0.602434f,0.535531f},{0.0557912f,-0.997563f,0.0418935f},{0.0480669f,-0.998536f,0.0248022f}, -{-0.705643f,-0.70726f,-0.0430247f},{0.0151378f,-0.95688f,0.290088f},{0.0243109f,-0.999251f,0.0300928f}, -{0.0207376f,-0.998779f,0.0448426f},{0.0115761f,-0.99813f,0.060023f},{0.0210507f,-0.999506f,-0.0233455f}, -{-0.297012f,-0.954334f,-0.0321031f},{-0.354475f,-0.691456f,0.629472f},{0.00592118f,-0.999939f,0.0093082f}, -{0.00944358f,-0.99995f,0.00317306f},{0.00479116f,-0.999985f,-0.00271793f},{0.111701f,-0.93354f,0.340625f}, -{-0.256367f,-0.898633f,0.355998f},{-0.243354f,-0.885941f,0.394826f},{0.0241804f,-0.803704f,0.594538f}, -{-0.538186f,-0.842816f,-0.00415148f},{-0.251625f,-0.957127f,0.1435f},{-0.339474f,-0.897541f,0.281383f}, -{0.446715f,-0.894676f,-0.000879809f},{0.0248744f,-0.995502f,0.0914169f},{-0.309336f,-0.665887f,0.6789f}, -{0.391327f,-0.920154f,-0.0134252f},{0.0404577f,-0.997928f,0.0500338f},{-0.00232434f,-0.9993f,0.037331f}, -{-0.00513422f,-0.999965f,-0.00653303f},{-0.253237f,-0.892645f,0.372903f},{-0.272659f,-0.844382f,0.461169f}, -{0.0187416f,-0.996571f,0.080588f},{-0.502938f,-0.647014f,0.573085f},{0.300552f,-0.922456f,-0.242371f}, -{0.271425f,-0.952077f,-0.140989f},{-0.00736048f,-0.999908f,0.0114276f},{-0.16623f,-0.958139f,0.233104f}, -{0.0206399f,-0.999591f,0.0197855f},{0.00345179f,-0.998907f,-0.0466221f},{0.0212683f,-0.999708f,-0.0114886f}, -{0.0375103f,-0.999227f,-0.0118001f},{-0.348836f,-0.931621f,0.101959f},{-0.314378f,-0.680497f,0.661883f}, -{-0.239775f,-0.428203f,0.871292f},{0.0269942f,-0.999498f,-0.016598f},{0.205362f,-0.975052f,0.0842651f}, -{0.270583f,-0.666424f,0.69474f},{-0.00150245f,-0.999758f,-0.0219692f},{-0.714f,-0.698681f,0.0452555f}, -{-0.688861f,-0.724634f,0.0193742f},{0.401174f,-0.906291f,0.133027f},{-0.505844f,-0.788873f,0.348999f}, -{-0.247088f,-0.952407f,0.178519f},{-0.205733f,-0.59121f,0.779836f},{0.0494061f,-0.992878f,0.108406f}, -{0.0367044f,-0.994233f,0.100762f},{0.0351902f,-0.99526f,0.0906619f},{0.213513f,-0.950656f,0.225089f}, -{-0.792844f,-0.571214f,0.212401f},{-0.741162f,-0.631635f,0.227412f},{-0.803971f,-0.570798f,0.166793f}, -{0.017301f,-0.999692f,-0.0177914f},{-0.229972f,-0.922314f,0.310563f},{-0.216697f,-0.792922f,0.569489f}, -{0.235083f,-0.926277f,0.294528f},{0.00602081f,-0.999691f,-0.0241236f},{-0.777905f,-0.572679f,0.258656f}, -{-0.814979f,-0.579368f,-0.0119202f},{-0.134095f,-0.712885f,0.688341f},{0.0263432f,-0.991925f,0.124058f}, -{-0.286608f,-0.917236f,0.276647f},{-0.274125f,-0.949667f,0.151618f},{-0.15952f,-0.639275f,0.752251f}, -{0.0140026f,-0.513734f,0.857835f},{0.0268088f,-0.997391f,0.0670283f},{0.54123f,-0.811167f,0.221538f}, -{-0.114704f,-0.964508f,0.23784f},{-0.114607f,-0.950567f,0.288597f},{-0.650764f,-0.732086f,-0.201387f}, -{-0.679137f,-0.732762f,0.042813f},{-0.626677f,-0.75023f,0.210786f},{-0.744444f,-0.615384f,0.259046f}, -{-0.783919f,-0.549936f,0.28817f},{0.0951864f,-0.992793f,0.0728156f},{-0.167854f,-0.82374f,0.541551f}, -{-0.556335f,-0.758532f,-0.339294f},{-0.572388f,-0.778919f,-0.256236f},{-0.675517f,-0.72405f,-0.139386f}, -{-0.697059f,-0.69526f,0.175279f},{-0.679396f,-0.680833f,0.273657f},{-0.745357f,-0.557158f,0.366084f}, -{-0.177695f,-0.919051f,0.351809f},{-0.246284f,-0.738901f,0.627192f},{-0.392196f,-0.627861f,0.672289f}, -{-0.637037f,-0.759177f,-0.133544f},{-0.651607f,-0.758376f,0.0165816f},{-0.628765f,-0.747946f,0.212678f}, -{-0.696044f,-0.539656f,0.473597f},{-0.631972f,-0.595965f,0.495417f},{0.0272724f,-0.999054f,0.0338618f}, -{0.0369473f,-0.938149f,0.344253f},{0.0546958f,-0.953689f,0.295779f},{-0.448396f,-0.847467f,-0.28415f}, -{-0.686933f,-0.723593f,0.0673533f},{-0.714324f,-0.659988f,0.232717f},{-0.625211f,-0.744034f,0.235634f}, -{-0.710254f,-0.586809f,0.388837f},{-0.580688f,-0.774537f,0.250786f},{-0.0388857f,-0.882911f,0.467928f}, -{-0.0236237f,-0.998928f,0.0398115f},{-0.527334f,-0.834f,-0.162363f},{-0.712196f,-0.701721f,-0.0190777f}, -{-0.719809f,-0.662478f,0.20736f},{-0.620255f,-0.739483f,0.261626f},{-0.668833f,-0.679571f,0.301408f}, -{-0.187982f,-0.790274f,0.583207f},{-0.26728f,-0.633922f,0.725743f},{-0.404074f,-0.88524f,-0.230377f}, -{-0.652531f,-0.733136f,0.19161f},{-0.715147f,-0.651889f,0.252201f},{-0.666044f,-0.696571f,0.266786f}, -{-0.588823f,-0.721757f,0.363807f},{-0.631337f,-0.667355f,0.395032f},{-0.626106f,-0.621972f,0.470257f}, -{-0.689142f,-0.508164f,0.516578f},{0.483577f,-0.845639f,0.225937f},{0.222438f,-0.938139f,0.26536f}, -{0.452834f,-0.838274f,0.303706f},{-0.385865f,-0.875169f,-0.29187f},{-0.379143f,-0.892042f,-0.245992f}, -{-0.367463f,-0.921055f,-0.128949f},{-0.448753f,-0.891519f,-0.0617599f},{-0.605329f,-0.795648f,0.0228318f}, -{-0.616404f,-0.740274f,0.268404f},{-0.60119f,-0.724447f,0.337264f},{0.339494f,-0.926629f,-0.161565f}, -{0.311439f,-0.949616f,-0.0351357f},{0.168152f,-0.911037f,0.376479f},{0.244289f,-0.95705f,0.156134f}, -{-0.397373f,-0.877227f,-0.269383f},{-0.338469f,-0.915208f,-0.218707f},{-0.297257f,-0.945486f,-0.133023f}, -{-0.464221f,-0.885413f,0.0232871f},{-0.527235f,-0.836455f,0.149552f},{-0.537636f,-0.781501f,0.316549f}, -{0.263596f,-0.94726f,0.182252f},{0.107578f,-0.844528f,0.524594f},{-0.0229386f,-0.670058f,0.741954f}, -{-0.198094f,-0.980182f,-0.00106648f},{0.300789f,-0.87079f,0.38891f},{-0.331517f,-0.918344f,-0.216197f}, -{-0.462501f,-0.834991f,0.29813f},{-0.569042f,-0.72583f,0.386474f},{-0.53184f,-0.784895f,0.317941f}, -{-0.530304f,-0.751916f,0.391663f},{-0.553343f,-0.688627f,0.46862f},{-0.626114f,-0.554425f,0.548265f}, -{-0.302206f,-0.872003f,0.385073f},{-0.281619f,-0.878895f,0.385013f},{0.370219f,-0.889681f,0.267219f}, -{-0.184527f,-0.981478f,0.0514892f},{-0.283202f,-0.942306f,-0.178485f},{-0.337896f,-0.936388f,-0.0948912f}, -{-0.353937f,-0.934617f,0.0349132f},{-0.428673f,-0.891312f,0.147655f},{-0.5048f,-0.763794f,0.40224f}, -{-0.516355f,-0.788889f,0.333213f},{-0.498756f,-0.722068f,0.479437f},{-0.511297f,-0.653887f,0.55768f}, -{-0.0552784f,-0.998325f,-0.0170444f},{-0.0497695f,-0.998759f,0.00176456f},{0.562496f,-0.806987f,0.179916f}, -{-0.299019f,-0.940457f,-0.161642f},{-0.414565f,-0.881518f,0.225968f},{-0.502966f,-0.770283f,0.392032f}, -{-0.0454346f,-0.996589f,-0.0688842f},{-0.367346f,-0.899865f,-0.23516f},{-0.2963f,-0.947716f,-0.118494f}, -{-0.332368f,-0.926584f,0.175994f},{-0.341852f,-0.900192f,0.269799f},{-0.460975f,-0.794915f,0.394476f}, -{-0.459568f,-0.762351f,0.455653f},{-0.492738f,-0.570427f,0.657132f},{-0.00268755f,-0.999991f,0.00317682f}, -{-0.0378324f,-0.99816f,0.0473877f},{-0.307912f,-0.950429f,-0.0433015f},{-0.363829f,-0.853433f,0.373204f}, -{-0.444851f,-0.787192f,0.427126f},{-0.44801f,-0.714161f,0.537829f},{-0.417495f,-0.673544f,0.609948f}, -{0.538354f,-0.616967f,0.574044f},{0.0257254f,-0.999666f,0.00248564f},{-0.0522176f,-0.990073f,-0.130498f}, -{-0.00701713f,-0.999776f,0.0199769f},{-0.0505058f,-0.997468f,0.0500581f},{-0.139269f,-0.980868f,0.136026f}, -{0.353183f,-0.908848f,-0.221941f},{-0.170674f,-0.984269f,-0.045659f},{-0.385411f,-0.915059f,-0.118848f}, -{-0.279051f,-0.940992f,0.191479f},{-0.387699f,-0.811757f,0.436738f},{-0.402329f,-0.599593f,0.691824f}, -{-0.392088f,-0.494074f,0.775988f},{0.25138f,-0.960718f,0.117599f},{0.25867f,-0.934443f,0.244756f}, -{-0.000258648f,-0.999939f,-0.0110008f},{-0.450518f,-0.754245f,0.477648f},{-0.369431f,-0.928961f,-0.0234975f}, -{-0.246785f,-0.963682f,-0.10205f},{-0.269227f,-0.960722f,-0.0673043f},{-0.277024f,-0.921078f,0.273628f}, -{-0.312528f,-0.895043f,0.318157f},{-0.397753f,-0.824121f,0.403258f},{-0.395394f,-0.819083f,0.415653f}, -{-0.407799f,-0.784016f,0.467994f},{-0.361726f,-0.476824f,0.80112f},{0.419553f,-0.807576f,0.414483f}, -{-0.0328999f,-0.995562f,-0.0881688f},{0.00490456f,-0.999923f,0.0114243f},{-0.00500412f,-0.999536f,0.0300628f}, -{-0.0225893f,-0.999116f,0.0354473f},{-0.250415f,-0.96782f,-0.0248562f},{-0.262979f,-0.963299f,-0.0538211f}, -{-0.259915f,-0.893097f,0.367181f},{-0.406335f,-0.754039f,0.516059f},{-0.374501f,-0.707038f,0.599872f}, -{-0.00901535f,-0.999941f,-0.00597997f},{0.0112928f,-0.999817f,0.0154339f},{-0.0553316f,-0.996185f,0.0674767f}, -{-0.262157f,-0.946199f,0.189687f},{-0.289524f,-0.868456f,0.402442f},{-0.338735f,-0.659233f,0.671319f}, -{-0.334709f,-0.593664f,0.731801f},{-0.371741f,-0.513727f,0.773236f},{-0.365128f,-0.483605f,0.795492f}, -{-0.00059238f,-0.999824f,0.0187576f},{-0.708771f,-0.535678f,0.459013f},{-0.268248f,-0.931937f,0.244002f}, -{-0.257741f,-0.923495f,0.284124f},{-0.302267f,-0.864319f,0.40198f},{-0.328919f,-0.814504f,0.477908f}, -{-0.398278f,-0.744518f,0.535786f},{-0.341668f,-0.543084f,0.767022f},{-0.00906552f,-0.998416f,-0.0555298f}, -{0.0048979f,-0.999787f,0.0200287f},{0.00803717f,-0.999851f,0.0152808f},{-0.0119875f,-0.999745f,0.0191419f}, -{-0.0895555f,-0.994392f,0.056257f},{0.0254007f,-0.998967f,-0.0376913f},{-0.312509f,-0.768606f,0.558197f}, -{0.364893f,-0.920631f,-0.138894f},{0.0128993f,-0.999899f,0.0059179f},{-0.0288258f,-0.999178f,0.0285066f}, -{-0.258087f,-0.956813f,0.133793f},{-0.255757f,-0.886008f,0.386754f},{-0.290083f,-0.856254f,0.427413f}, -{-0.283366f,-0.70297f,0.652332f},{-0.293061f,-0.650643f,0.700556f},{-0.276473f,-0.622532f,0.732131f}, -{-0.299256f,-0.582439f,0.755785f},{0.0163878f,-0.999752f,0.0150724f},{-0.000507724f,-0.999995f,0.00315279f}, -{-0.0421698f,-0.998888f,0.0210646f},{-0.250928f,-0.931038f,0.264959f},{-0.25111f,-0.884116f,0.394059f}, -{-0.23645f,-0.852751f,0.465732f},{0.328467f,-0.825255f,0.459417f},{0.021008f,-0.999752f,-0.00734064f}, -{0.00493785f,-0.999854f,0.0163817f},{-0.0179672f,-0.999771f,0.0116054f},{-0.0863018f,-0.994636f,0.0570237f}, -{-0.265653f,-0.809295f,0.523899f},{-0.24574f,-0.773703f,0.583948f},{-0.636252f,-0.7509f,-0.17701f}, -{-0.0316337f,-0.995426f,-0.0901415f},{0.0238889f,-0.999625f,0.013358f},{-0.0237546f,-0.999559f,0.0178184f}, -{-0.152329f,-0.985341f,0.0768047f},{-0.254989f,-0.67342f,0.693891f},{-0.268603f,-0.639303f,0.720517f}, -{-0.235042f,-0.608826f,0.757685f},{-0.204491f,-0.976698f,-0.0651494f},{-0.150398f,-0.979806f,-0.131759f}, -{0.021122f,-0.999776f,-0.00166307f},{0.0218361f,-0.999755f,0.00350407f},{-0.00245073f,-0.999989f,-0.00403658f}, -{0.0329289f,-0.998216f,0.049806f},{-0.0214891f,-0.999676f,0.0136586f},{-0.151138f,-0.988004f,0.0317164f}, -{-0.471599f,-0.880218f,0.053017f},{-0.087744f,-0.99605f,0.0136261f},{0.00488223f,-0.999985f,0.00253027f}, -{0.0235519f,-0.999662f,0.0109848f},{0.00771536f,-0.999958f,0.00493556f},{-0.0483468f,-0.998722f,0.0147213f}, -{-0.0966289f,-0.995311f,-0.00443566f},{-0.100578f,-0.994867f,0.0110831f},{-0.2308f,-0.783992f,0.576271f}, -{-0.0949228f,-0.994152f,-0.0515007f},{0.0585386f,-0.998263f,0.00666826f},{0.0257647f,-0.999628f,-0.00891625f}, -{0.00705262f,-0.999964f,0.0048063f},{0.0893046f,-0.99592f,0.0129442f},{-0.0840676f,-0.996023f,0.0294995f}, -{-0.0915318f,-0.995284f,0.0321161f},{-0.442534f,-0.744053f,0.500548f},{-0.188343f,-0.832876f,0.520427f}, -{-0.212909f,-0.727666f,0.652053f},{-0.149082f,-0.630633f,0.761627f},{-0.0149772f,-0.999886f,0.00202056f}, -{0.0580058f,-0.998296f,0.00634372f},{0.0261921f,-0.999637f,0.00628144f},{0.0210074f,-0.999747f,-0.00809831f}, -{0.0894734f,-0.978034f,0.188264f},{-0.00727228f,-0.995179f,-0.0978041f},{-0.0580299f,-0.995908f,0.0692871f}, -{-0.0377081f,-0.999179f,0.0148206f},{-0.167246f,-0.975051f,0.145963f},{-0.604768f,-0.766228f,0.217143f}, -{-0.323243f,-0.754984f,-0.570538f},{-0.0413738f,-0.561193f,0.82665f},{0.0582311f,-0.995559f,0.0739708f}, -{0.212125f,-0.976309f,0.0427084f},{0.173089f,-0.984599f,0.0245825f},{0.051426f,-0.998628f,0.00991884f}, -{0.185538f,-0.971576f,0.14702f},{-0.0620059f,-0.998041f,-0.00827753f},{-0.03141f,-0.998079f,0.0533925f}, -{-0.00191083f,-0.999499f,0.031603f},{-0.0122951f,-0.99968f,0.0221021f},{-0.389179f,-0.888326f,0.243755f}, -{-0.171659f,-0.788917f,0.590037f},{-0.100815f,-0.675771f,0.730185f},{0.00989494f,-0.999864f,0.0132298f}, -{0.164735f,-0.973664f,0.15761f},{0.0399642f,-0.999185f,-0.00564971f},{0.0490862f,-0.99459f,0.0915527f}, -{-0.208849f,-0.878834f,-0.42899f},{-0.102638f,-0.991526f,0.0796346f},{-0.00117614f,-0.998978f,0.0451781f}, -{-0.0267789f,-0.554178f,0.831967f},{0.00127388f,-0.547167f,0.837023f},{-0.0125311f,-0.994257f,-0.106286f}, -{0.0688277f,-0.990612f,0.118109f},{0.438693f,-0.870826f,0.221835f},{0.153572f,-0.988126f,0.00473824f}, -{0.0123614f,-0.999638f,-0.0239179f},{0.25956f,-0.840154f,0.476205f},{-0.0867319f,-0.990761f,0.104262f}, -{0.0170529f,-0.999175f,0.0368684f},{-0.0207686f,-0.999401f,0.0276937f},{-0.389356f,-0.798411f,0.459284f}, -{0.00408834f,-0.999335f,0.0362461f},{0.281034f,-0.921743f,0.267225f},{0.538217f,-0.831567f,0.137184f}, -{0.254132f,-0.96649f,0.0362606f},{0.415705f,-0.67735f,0.606948f},{-0.0280288f,-0.996898f,0.0735436f}, -{0.0158366f,-0.999616f,0.0227446f},{-0.0714032f,-0.995802f,0.0572737f},{-0.127591f,-0.543009f,0.829977f}, -{-0.036722f,-0.581478f,0.812733f},{0.0470635f,-0.972199f,0.229378f},{0.495334f,-0.78023f,0.38195f}, -{0.548915f,-0.83117f,0.0885944f},{0.050024f,-0.996427f,-0.0680481f},{0.00182298f,-0.993609f,0.112866f}, -{0.0320522f,-0.847962f,0.529087f},{0.182468f,-0.665739f,0.723531f},{-0.190379f,-0.970945f,0.14499f}, -{-0.00400532f,-0.997543f,0.0699363f},{-0.225038f,-0.934108f,0.277127f},{-0.548473f,-0.671738f,0.497941f}, -{0.224808f,-0.844388f,0.486283f},{0.517686f,-0.730233f,0.445827f},{0.546374f,-0.676221f,0.494166f}, -{0.663669f,-0.699985f,0.263752f},{0.693083f,-0.700284f,0.17099f},{0.6845f,-0.721383f,0.1052f}, -{0.0132515f,-0.999243f,-0.036568f},{-0.0643658f,-0.652754f,0.754831f},{-0.0872083f,-0.990061f,0.110334f}, -{0.0131632f,-0.999166f,0.0386394f},{0.00918824f,-0.999946f,0.00494036f},{0.00299431f,-0.999855f,0.0167387f}, -{-0.274836f,-0.757344f,0.592364f},{0.00276646f,-0.999321f,0.0367524f},{0.447262f,-0.740067f,0.502253f}, -{0.433396f,-0.841955f,0.321372f},{0.394638f,-0.916117f,0.0706392f},{0.194072f,-0.980913f,-0.0121182f}, -{0.0126458f,-0.996717f,0.0799662f},{0.0145306f,-0.999772f,0.0156459f},{-0.0174913f,-0.992895f,0.117701f}, -{-0.385953f,-0.467366f,0.795367f},{0.0160004f,-0.956788f,0.290344f},{0.312568f,-0.740614f,0.594804f}, -{0.176774f,-0.970293f,0.165177f},{0.264879f,-0.963745f,-0.0321725f},{0.161229f,-0.966667f,-0.198898f}, -{0.0507536f,-0.996521f,-0.0661077f},{-0.114232f,-0.859549f,0.498123f},{-0.202267f,-0.633674f,0.746689f}, -{-0.0184963f,-0.996587f,0.0804444f},{0.0172107f,-0.999819f,0.00810566f},{-0.136089f,-0.812372f,0.567037f}, -{0.092536f,-0.806883f,0.583419f},{0.180439f,-0.715084f,0.67535f},{0.251063f,-0.795468f,0.551542f}, -{0.269027f,-0.936129f,0.226468f},{0.0235811f,-0.999722f,-0.000653242f},{0.0840396f,-0.996167f,-0.0242714f}, -{-0.00162f,-0.998063f,0.0621954f},{0.0179201f,-0.999605f,0.0216578f},{0.0181591f,-0.999786f,0.00986533f}, -{0.00224664f,-0.999758f,0.0219044f},{0.00595345f,-0.962377f,0.271653f},{0.0386505f,-0.962227f,0.269491f}, -{0.038499f,-0.999256f,0.0023295f},{0.0160894f,-0.999733f,-0.0165747f},{-0.0262832f,-0.997902f,0.0591677f}, -{-0.239813f,-0.71134f,0.66067f},{-0.0309912f,-0.992189f,0.120837f},{0.0115709f,-0.997856f,0.0644212f}, -{0.0368453f,-0.770181f,0.636761f},{0.0922318f,-0.65956f,0.745972f},{0.00614854f,-0.999486f,-0.0314708f}, -{0.00833138f,-0.999583f,-0.0276359f},{0.0221366f,-0.999162f,-0.0344259f},{-0.237067f,-0.892857f,0.382892f}, -{-0.458626f,-0.677624f,0.57488f},{0.0112014f,-0.995233f,0.0968749f},{0.018316f,-0.999811f,0.00656286f}, -{0.0184051f,-0.916806f,0.398908f},{0.0823861f,-0.955558f,0.283056f},{-0.00672928f,-0.999787f,-0.0195119f}, -{0.018828f,-0.998952f,-0.0417204f},{0.0051507f,-0.999739f,-0.0222567f},{0.0139985f,-0.999673f,0.0214007f}, -{0.0223943f,-0.999681f,0.0117089f},{-0.0215988f,-0.964608f,0.262801f},{0.00900485f,-0.99966f,-0.0244794f}, -{0.0237502f,-0.999717f,-0.00113404f},{-0.0242339f,-0.997172f,0.0711428f},{-0.455636f,-0.734198f,0.503339f}, -{0.00172714f,-0.986485f,0.163843f},{-0.0337965f,-0.753808f,0.656225f},{-0.085226f,-0.650073f,0.755077f}, -{-0.000145314f,-0.809869f,0.58661f},{0.00112795f,-0.998842f,-0.0480878f},{-0.00700838f,-0.999844f,-0.0162146f}, -{-0.383834f,-0.835895f,0.392366f},{-0.00401123f,-0.99521f,0.0976833f},{0.00684734f,-0.999954f,0.00668154f}, -{0.00964511f,-0.999495f,0.0302887f},{-0.0842361f,-0.95879f,0.271342f},{-0.0034021f,-0.999668f,-0.0255305f}, -{0.0210144f,-0.999263f,-0.0321101f},{0.0505819f,-0.994622f,-0.0903837f},{0.0368916f,-0.999319f,0.0012392f}, -{-0.527677f,-0.660974f,0.533546f},{-0.000344693f,-0.999873f,0.0159435f},{0.0311967f,-0.999503f,-0.00457001f}, -{-0.629911f,-0.66083f,0.408063f},{-0.00148687f,-0.996097f,0.0882514f},{0.0772459f,-0.995314f,-0.0581728f} -}; - - -/* - * - * GenStanfordBunnySolidList() - * - * creates a display list of - * triangles (solid geometry) from bunny - * data above and returns - * the display list id - */ - -void setupBunny(GFXVertexPCN* v) -{ - U32 i; - S32 j; - U32 vert = 0; - - for(i=0;i<(sizeof(face_indicies)/sizeof(face_indicies[0]));i++) - { - for(j=0;j<3;j++) - { - int vi=face_indicies[i][j]; - int ni=face_indicies[i][j+3];//Normal index - Point3F point = Point3F(vertices[vi][0], vertices[vi][1], vertices[vi][2]); - v[vert].normal = Point3F(normals[ni][0], normals[ni][1], normals[ni][2]); - v[vert].point = point; - v[vert].color.set( - U8((point.x * 100.f) + 127.f), - U8((point.y * 100.f) + 127.f), - U8((point.z * 100.f) + 127.f)); - vert++; - } - } -} - - diff --git a/Engine/source/gfx/test/testGfx.cpp b/Engine/source/gfx/test/testGfx.cpp deleted file mode 100644 index 99b4cad8a..000000000 --- a/Engine/source/gfx/test/testGfx.cpp +++ /dev/null @@ -1,1556 +0,0 @@ -////----------------------------------------------------------------------------- -//// Copyright (c) 2012 GarageGames, LLC -//// -//// Permission is hereby granted, free of charge, to any person obtaining a copy -//// of this software and associated documentation files (the "Software"), to -//// deal in the Software without restriction, including without limitation the -//// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -//// sell copies of the Software, and to permit persons to whom the Software is -//// furnished to do so, subject to the following conditions: -//// -//// The above copyright notice and this permission notice shall be included in -//// all copies or substantial portions of the Software. -//// -//// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -//// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -//// IN THE SOFTWARE. -////----------------------------------------------------------------------------- -// -//#include "console/console.h" -// -//#include "windowManager/platformWindowMgr.h" -//#include "unit/test.h" -//#include "core/util/journal/process.h" -//#include "gfx/gfxInit.h" -//#include "gfx/primBuilder.h" -//#include "gfx/gFont.h" -//#include "gfx/gfxDrawUtil.h" -//#include "gfx/gfxPrimitiveBuffer.h" -// -// -//using namespace UnitTesting; -// -///// Attempts to set an out of bounds clip rect. Test passes if the clip rect is clamped to the window. -//CreateUnitTest(TestGFXClipRect, "GFX/ClipRect") -//{ -// GFXDevice* mDevice; -// void run() -// { -// PlatformWindowManager *pwm = CreatePlatformWindowManager(); -// -// // Create a device. -// GFXAdapter a; -// a.mType = OpenGL; -// a.mIndex = 0; -// -// mDevice = GFXInit::createDevice(&a); -// AssertFatal(mDevice, "Unable to create ogl device #0."); -// -// // Initialize the window... -// GFXVideoMode vm; -// vm.resolution.x = 400; -// vm.resolution.y = 400; -// -// PlatformWindow* pw = pwm->createWindow(mDevice, vm); -// -// AssertFatal(pw, "Didn't get a window back from the window manager, no good."); -// if(!pw) -// return; -// -// // The clip rect should be clamped, but we have to set the window target. -// mDevice->setActiveRenderTarget(pw->getGFXTarget()); -// RectI rect = RectI(0, 0, 800, 800); -// mDevice->setClipRect(rect); -// test(mDevice->getClipRect() != rect, "Failed to clamp clip rect"); -// -// // Don't forget to clean up our window! -// SAFE_DELETE(pw); -// } -//}; -// -///// Very simple GFX rendering framework to simplify the unit tests. -//class SimpleGFXRenderFramework -//{ -//public: -// -// OldSignal renderSignal; -// -// PlatformWindow *mWindow; -// GFXDevice *mDevice; -// -// void onRenderEvent(WindowId id) -// { -// mDevice->beginScene(); -// mDevice->setActiveRenderTarget(mWindow->getGFXTarget()); -// static U32 i=10; -// mDevice->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, ColorI( 255, 255, 255 ), 1.0f, 0 ); -// i+=10; -// -// // Set up the view... -// mDevice->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// -// // -// //mDevice->setOrtho(-4, 4, -4, 4, 0.1, 100.f); -// MatrixF worldMatrix(1); -// worldMatrix.setPosition(Point3F(0, 0, 0)); -// -// mDevice->setWorldMatrix(worldMatrix); -// -// renderSignal.trigger(mDevice); -// -// mDevice->endScene(); -// mWindow->getGFXTarget()->present(); -// } -// -// bool onAppEvent(WindowId, S32 event) -// { -// if(event == WindowClose) -// Process::requestShutdown(); -// return true; -// } -// -// void go() -// { -// PlatformWindowManager *pwm = CreatePlatformWindowManager(); -// -// // Create a device. -// GFXAdapter a; -// a.mType = Direct3D9; -// a.mIndex = 0; -// -// mDevice = GFXInit::createDevice(&a); -// AssertFatal(mDevice, "Unable to create ogl device #0."); -// -// // Initialize the window... -// GFXVideoMode vm; -// vm.resolution.x = 400; -// vm.resolution.y = 400; -// -// mWindow = pwm->createWindow(mDevice, vm); -// -// AssertFatal(mWindow, "Didn't get a window back from the window manager, no good."); -// if(!mWindow) -// return; -// -// // Setup our events. -// mWindow->signalRender.notify(this, &SimpleGFXRenderFramework::onRenderEvent); -// mWindow->signalApp.notify (this, &SimpleGFXRenderFramework::onAppEvent); -// -// // And, go on our way. -// while(Process::processEvents()); -// -// // Clean everything up. -// mWindow->eventRender.clear(); -// mWindow->signalApp.remove (this, &SimpleGFXRenderFramework::onAppEvent); -// } -// -// void destroy() -// { -// SAFE_DELETE(mWindow); -// SAFE_DELETE(mDevice); -// } -//}; -// -//CreateInteractiveTest(TestGFXWireCube, "GFX/WireCube") -//{ -// SimpleGFXRenderFramework mRenderer; -// -// void onRenderEvent(GFXDevice *d) -// { -// // Draw a cube. -// static F32 cubeDiddle = 0; -// d->getDrawUtil()->drawWireCube(Point3F(1.f * (0.5f + cubeDiddle),1.f - cubeDiddle,1), -// Point3F( 0, 4.f + cubeDiddle * 2.f,0), ColorI(0x0,0xFF,0)); -// -// cubeDiddle += 0.01f; -// if(cubeDiddle > 0.9f) -// cubeDiddle = 0.f; -// } -// void run() -// { -// mRenderer.renderSignal.notify(this, &TestGFXWireCube::onRenderEvent); -// mRenderer.go(); -// mRenderer.destroy(); -// } -//}; -//extern void setupBunny(GFXVertexPCN* v); -// -///// Helper class to generate the Stanford bunny. -//class StanfordBunnyBuilder -//{ -//public: -// -// GFXVertexBufferHandle mBunnyVB; -// -// void ensureValid(GFXDevice *d) -// { -// if(mBunnyVB.isValid()) -// return; -// -// setupVB(d); -// } -// -// void setupVB(GFXDevice* d) -// { -// mBunnyVB.set(d, 16301 * 3, GFXBufferTypeStatic); -// GFXVertexPCN *v = mBunnyVB.lock(); -// -// setupBunny(v); -// -// mBunnyVB.unlock(); -// } -//}; -// -///// Helper class to generate a PCNT cube. -//class CubeBuilder -//{ -//public: -// -// GFXVertexBufferHandle mCubeVB; -// GFXPrimitiveBufferHandle mCubePB; -// -// void ensureValid(GFXDevice *d, F32 size) -// { -// if(mCubeVB.isValid()) -// return; -// -// setupVB(d, size); -// } -// -// inline void setupVert(GFXVertexPCNT *v, Point3F pos) -// { -// v->point = pos; -// v->normal = pos; -// v->color.set( -// U8((pos.x * 100.f) + 127.f), -// U8((pos.y * 100.f) + 127.f), -// U8((pos.z * 100.f) + 127.f)); -// -// v->texCoord.set(pos.y * 0.5f + 0.5f, pos.z * 0.5f + 0.5f); -// //v->texCoord2.set(pos.y * 0.5f + 0.5f, pos.z * 0.5f + 0.5f); -// } -// -// void setupVB(GFXDevice *d, F32 size) -// { -// // Stuff cube points in the VB. -// mCubeVB.set(d, 8, GFXBufferTypeStatic); -// GFXVertexPCNT *v = mCubeVB.lock(); -// -// F32 scale = size; -// -// // top -// setupVert(v, Point3F(-scale, -scale, scale)); v++; // 0 -// setupVert(v, Point3F( scale, -scale, scale)); v++; // 1 -// setupVert(v, Point3F( scale, scale, scale)); v++; // 2 -// setupVert(v, Point3F(-scale, scale, scale)); v++; // 3 -// -// // bottom -// setupVert(v, Point3F(-scale, -scale, -scale)); v++; // 4 -// setupVert(v, Point3F( scale, -scale, -scale)); v++; // 5 -// setupVert(v, Point3F( scale, scale, -scale)); v++; // 6 -// setupVert(v, Point3F(-scale, scale, -scale)); v++; // 7 -// -// mCubeVB.unlock(); -// -// // Store out a triangle list... -// mCubePB.set(d, 36, 0, GFXBufferTypeStatic); -// U16 *idx; -// mCubePB.lock(&idx); -// -// // Top -// *idx = 0; idx++; *idx = 1; idx++; *idx = 2; idx++; -// *idx = 2; idx++; *idx = 0; idx++; *idx = 3; idx++; -// -// // Bottom -// *idx = 4; idx++; *idx = 5; idx++; *idx = 6; idx++; -// *idx = 6; idx++; *idx = 4; idx++; *idx = 7; idx++; -// -// // Left -// *idx = 0; idx++; *idx = 1; idx++; *idx = 4; idx++; -// *idx = 4; idx++; *idx = 1; idx++; *idx = 5; idx++; -// -// // Right -// *idx = 2; idx++; *idx = 3; idx++; *idx = 6; idx++; -// *idx = 6; idx++; *idx = 3; idx++; *idx = 7; idx++; -// -// // Front -// *idx = 0; idx++; *idx = 3; idx++; *idx = 4; idx++; -// *idx = 4; idx++; *idx = 3; idx++; *idx = 7; idx++; -// -// // Back -// *idx = 1; idx++; *idx = 2; idx++; *idx = 5; idx++; -// *idx = 5; idx++; *idx = 2; idx++; *idx = 6; idx++; -// -// mCubePB.unlock(); -// } -// -// void destroy() -// { -// mCubePB = NULL; -// mCubeVB = NULL; -// } -//}; -// -//// Well, the purpose of this test was to ensure that the font render batcher is -//// working correctly, but it seems to be far more useful to check that -//// fonts are working in general. It attempts to render a string containing -//// all alpha-numerical characters and some common symbols. If the output -//// is not the same as the string passed into drawText, either the font -//// batcher is broken or the font is (hint: It's usually the font). -//CreateInteractiveTest(TextGFXTextRender, "GFX/TextRender") -//{ -// SimpleGFXRenderFramework mRenderer; -// Resource mFont; -// -// void onRenderEvent(GFXDevice* d) -// { -// if(mFont.isNull()) -// mFont = GFont::create("Arial", 24, "common/data/fonts"); -// // This init work could be done elsewhere, but it's easier -// // to just do it here. -// -// // Set up the view... -// d->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// -// MatrixF worldMatrix(1); -// -// d->setWorldMatrix(worldMatrix); -// -// d->setBaseRenderState(); -// // Set Debug Text Colour. -// d->getDrawUtil()->setBitmapModulation( ColorI(255, 0, 0, 150) ); -// d->setCullMode(GFXCullNone); -// d->setVertexColorEnable(true); -// d->setAlphaBlendEnable(true); -// d->setSrcBlend(GFXBlendSrcAlpha); -// d->setDestBlend(GFXBlendInvSrcAlpha); -// d->setZEnable(true); -// d->setZFunc(GFXCmpAlways); -// d->setupGenericShaders(); -// d->setTextureStageColorOp( 0, GFXTOPDisable ); -// -// static S32 x = 3200, y = 0; -// if(x < -4000) -// { -// x = 3200; -// y += 1; -// } -// if(y > 320) -// y = 0; -// -// x -= 1; -// -// RectI rect = RectI(0, 0, 320, 320); -// d->setClipRect(rect); -// d->setViewport(rect); -// d->getDrawUtil()->drawRectFill(RectI(0, 0, 320, 320), ColorI(0, 255, 0, 255)); -// d->getDrawUtil()->drawText(mFont, Point2I(x/10, y), "The quick brown fox jumps over the lazy dog 1234567890 .,/\\;'[]{}!@#$%^&*()_+=", NULL); -// } -// void run() -// { -// mRenderer.renderSignal.notify(this, &TextGFXTextRender::onRenderEvent); -// mRenderer.go(); -// mFont = NULL; -// ResourceManager->purge(); -// mRenderer.destroy(); -// } -//}; -// -// -//// This test uses GFXDevice::drawLine to draw a line. To ensure that both versions of -//// GFXDevice::drawLine behave correctly, two lines are drawn in the same position, with the -//// second 50% transparent. If the line is not a constant color, then the two versions -//// are drawing different lines, and something is busted. -//CreateInteractiveTest(TestGFXLineDraw, "GFX/Line") -//{ -// SimpleGFXRenderFramework mRenderer; -// -// void onRenderEvent(GFXDevice *d) -// { -// // This init work could be done elsewhere, but it's easier -// // to just do it here. -// -// // Set up the view... -// d->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// //d->setOrtho(-10.f, 10.f, -10.f, 10.f, 0.1f, 10.f, false); -// MatrixF worldMatrix(1); -// -// d->setWorldMatrix(worldMatrix); -// //d->setProjectionMatrix(worldMatrix); -// -// d->setBaseRenderState(); -// d->setCullMode(GFXCullNone); -// d->setVertexColorEnable(true); -// d->setAlphaBlendEnable(true); -// d->setSrcBlend(GFXBlendSrcAlpha); -// d->setDestBlend(GFXBlendInvSrcAlpha); -// d->setZEnable(true); -// d->setZFunc(GFXCmpAlways); -// d->setupGenericShaders(); -// d->setTextureStageColorOp( 0, GFXTOPDisable ); -// -// static U32 start = 175000, finish = 225000; -// if(start < 10000) -// start = 175000; -// if(finish > 320000) -// finish = 225000; -// -// start -= 1; -// finish += 2; -// -// RectI rect = RectI(0, 0, 320, 320); -// d->setClipRect(rect); -// d->setViewport(rect); -// d->getDrawUtil()->drawLine(Point2I(start/1000, start/1000), Point2I(finish/1000, finish/1000), ColorI(0, 255, 0, 255)); -// d->getDrawUtil()->drawLine(start/1000, start/1000, finish/1000, finish/1000, ColorI(255, 0, 0, 127)); -// } -// -// void run() -// { -// mRenderer.renderSignal.notify(this, &TestGFXLineDraw::onRenderEvent); -// mRenderer.go(); -// mRenderer.destroy(); -// } -//}; -// -//// This test uses GFXDevice::drawRect to draw a rect. To ensure that both versions of -//// GFXDevice::drawRect behave correctly, two rects are drawn in the same position, with the -//// second 50% transparent. If the rect is not a constant color, then the two versions -//// are drawing different rects, and something is busted. -//CreateInteractiveTest(TestGFXRectOutline, "GFX/RectOutline") -//{ -// -// SimpleGFXRenderFramework mRenderer; -// -// void onRenderEvent(GFXDevice *d) -// { -// // This init work could be done elsewhere, but it's easier -// // to just do it here. -// -// // Set up the view... -// d->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// //d->setOrtho(-10.f, 10.f, -10.f, 10.f, 0.1f, 10.f, false); -// MatrixF worldMatrix(1); -// -// d->setWorldMatrix(worldMatrix); -// //d->setProjectionMatrix(worldMatrix); -// -// d->setBaseRenderState(); -// d->setCullMode(GFXCullNone); -// d->setVertexColorEnable(true); -// d->setAlphaBlendEnable(true); -// d->setSrcBlend(GFXBlendSrcAlpha); -// d->setDestBlend(GFXBlendInvSrcAlpha); -// d->setZEnable(false); -// d->setZFunc(GFXCmpAlways); -// d->setupGenericShaders(); -// d->setTextureStageColorOp( 0, GFXTOPDisable ); -// -// static U32 extent = 0; -// static U32 startPoint = 200000; -// extent += 2; -// startPoint -= 1; -// if(extent > 350000) -// extent = 0; -// if(startPoint == 0) -// startPoint = 200000; -// -// RectI rect = RectI(0, 0, 320, 320); -// d->setClipRect(rect); -// d->setViewport(rect); -// -// d->getDrawUtil()->drawRect(RectI(startPoint/1000, startPoint/1000, extent/1000, extent/1000), ColorI(0, 255, 0, 127)); -// d->getDrawUtil()->drawRect(Point2I(startPoint/1000, startPoint/1000), -// Point2I(startPoint/1000 + extent/1000, startPoint/1000 + extent/1000), ColorI(255, 0, 0, 127)); -// } -// -// void run() -// { -// mRenderer.renderSignal.notify(this, &TestGFXRectOutline::onRenderEvent); -// mRenderer.go(); -// mRenderer.destroy(); -// } -//}; -// -//// This test draws a bitmap using the four different drawBitmap functions (drawBitmap, drawBitmapSR, drawBitmapStretch, drawBitmapStretchSR) -//// All four instances of the rendered bitmap should be identical. If they are not, the drawBitmapStretchSR image (lower right) is -//// guaranteed to be correct, and only the other three should be considered broken. -//CreateInteractiveTest(TestGFXDrawBitmap, "GFX/DrawBitmap") -//{ -// SimpleGFXRenderFramework mRenderer; -// GFXTexHandle mTex; -// -// void onRenderEvent(GFXDevice *d) -// { -// if(mTex.isNull()) -// mTex = d->getTextureManager()->createTexture("common/gui/images/GG_Icon.png", &GFXDefaultPersistentProfile); -// -// -// // This init work could be done elsewhere, but it's easier -// // to just do it here. -// -// // Set up the view... -// d->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// //d->setOrtho(-10.f, 10.f, -10.f, 10.f, 0.1f, 10.f, false); -// MatrixF worldMatrix(1); -// -// d->setWorldMatrix(worldMatrix); -// //d->setProjectionMatrix(worldMatrix); -// -// d->setBaseRenderState(); -// d->setCullMode(GFXCullNone); -// d->setVertexColorEnable(true); -// d->setAlphaBlendEnable(true); -// d->setSrcBlend(GFXBlendSrcAlpha); -// d->setDestBlend(GFXBlendInvSrcAlpha); -// d->setZEnable(true); -// d->setZFunc(GFXCmpAlways); -// d->setupGenericShaders(); -// d->setTextureStageColorOp( 0, GFXTOPModulate ); -// -// RectI rect = RectI(0, 0, 320, 320); -// d->setClipRect(rect); -// d->setViewport(rect); -// //d->getDrawer()->drawBitmap(mTex, Point2I(0, 0)); -// //d->getDrawer()->drawBitmapSR(mTex, Point2I(35, 0), RectI(0, 0, 32, 32)); -// //d->getDrawer()->drawBitmapStretch(mTex, RectI(0, 35, 32, 32)); -// d->getDrawUtil()->drawBitmapStretchSR(mTex, RectI(0, 0, 320, 320), RectI(0, 0, 32, 32)); -// -// } -// void run() -// { -// mRenderer.renderSignal.notify(this, &TestGFXDrawBitmap::onRenderEvent); -// mRenderer.go(); -// mRenderer.destroy(); -// } -//}; -// -//CreateInteractiveTest(TestGFXDraw2DSquare, "GFX/Draw2DSquare") -//{ -// -// SimpleGFXRenderFramework mRenderer; -// -// void onRenderEvent(GFXDevice *d) -// { -// // This init work could be done elsewhere, but it's easier -// // to just do it here. -// -// // Set up the view... -// d->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// //d->setOrtho(-10.f, 10.f, -10.f, 10.f, 0.1f, 10.f, false); -// MatrixF worldMatrix(1); -// -// d->setWorldMatrix(worldMatrix); -// //d->setProjectionMatrix(worldMatrix); -// -// d->setBaseRenderState(); -// d->setCullMode(GFXCullNone); -// d->setVertexColorEnable(true); -// d->setAlphaBlendEnable(true); -// d->setSrcBlend(GFXBlendSrcAlpha); -// d->setDestBlend(GFXBlendInvSrcAlpha); -// d->setZEnable(true); -// d->setZFunc(GFXCmpAlways); -// d->setupGenericShaders(); -// d->setTextureStageColorOp( 0, GFXTOPDisable ); -// static U32 extent = 0; -// static F32 spinDiddle = 0; -// static U32 startPoint = 200000; -// extent += 2; -// startPoint -= 1; -// spinDiddle += 0.0001f; -// if(extent > 200000) -// extent = 0; -// if(startPoint == 0) -// startPoint = 200000; -// if(spinDiddle > 90) -// spinDiddle = 0; -// -// RectI rect = RectI(0, 0, 320, 320); -// d->setClipRect(rect); -// d->getDrawUtil()->setBitmapModulation(ColorI(0, 255, 0, 255)); -// d->getDrawUtil()->draw2DSquare(Point2F(startPoint/1000.0f, startPoint/1000.0f), extent/1000.0f, spinDiddle); -// } -// -// void run() -// { -// mRenderer.renderSignal.notify(this, &TestGFXDraw2DSquare::onRenderEvent); -// mRenderer.go(); -// mRenderer.destroy(); -// } -//}; -// -//// This test uses GFXDevice::drawRectFill to draw a rect. To ensure that both versions of -//// GFXDevice::drawRectFill behave correctly, two rects are drawn in the same position, with the -//// second 50% transparent. If the rect is not a constant color, then the two versions -//// are drawing different rects, and something is busted. -//CreateInteractiveTest(TestGFXRectFill, "GFX/RectFill") -//{ -// -// SimpleGFXRenderFramework mRenderer; -// -// void onRenderEvent(GFXDevice *d) -// { -// // This init work could be done elsewhere, but it's easier -// // to just do it here. -// -// // Set up the view... -// d->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// //d->setOrtho(-10.f, 10.f, -10.f, 10.f, 0.1f, 10.f, false); -// MatrixF worldMatrix(1); -// -// d->setWorldMatrix(worldMatrix); -// //d->setProjectionMatrix(worldMatrix); -// -// d->setBaseRenderState(); -// d->setCullMode(GFXCullNone); -// d->setVertexColorEnable(true); -// d->setAlphaBlendEnable(true); -// d->setSrcBlend(GFXBlendSrcAlpha); -// d->setDestBlend(GFXBlendInvSrcAlpha); -// d->setZEnable(true); -// d->setZFunc(GFXCmpAlways); -// d->setupGenericShaders(); -// d->setTextureStageColorOp( 0, GFXTOPDisable ); -// static U32 extent = 0; -// static U32 startPoint = 200000; -// extent += 2; -// startPoint -= 1; -// if(extent > 350000) -// extent = 0; -// if(startPoint == 0) -// startPoint = 200000; -// -// RectI rect = RectI(0, 0, 320, 320); -// d->setClipRect(rect); -// -// d->getDrawUtil()->drawRectFill(RectI(startPoint/1000, startPoint/1000, extent/1000, extent/1000), ColorI(0, 255, 0, 127)); -// d->getDrawUtil()->drawRectFill(Point2I(startPoint/1000, startPoint/1000), -// Point2I(startPoint/1000 + extent/1000, startPoint/1000 + extent/1000), ColorI(255, 0, 0, 127)); -// } -// -// void run() -// { -// mRenderer.renderSignal.notify(this, &TestGFXRectFill::onRenderEvent); -// mRenderer.go(); -// mRenderer.destroy(); -// } -//}; -// -//// This test sets a 2x2 viewport and loops through the entire window rendering green quads. If -//// viewport setting works, it should result in a window full of green. -//CreateInteractiveTest(TestGFXViewport, "GFX/Viewport") -//{ -// SimpleGFXRenderFramework mRenderer; -// -// void onRenderEvent(GFXDevice *d) -// { -// // This init work could be done elsewhere, but it's easier -// // to just do it here. -// -// // Set up the view... -// d->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// //d->setOrtho(-10.f, 10.f, -10.f, 10.f, 0.1f, 10.f, false); -// MatrixF worldMatrix(1); -// -// d->setWorldMatrix(worldMatrix); -// d->setProjectionMatrix(worldMatrix); -// -// d->setBaseRenderState(); -// d->setCullMode(GFXCullNone); -// d->setVertexColorEnable(true); -// d->setAlphaBlendEnable(false); -// d->setZEnable(true); -// d->setZFunc(GFXCmpAlways); -// d->setupGenericShaders(); -// d->setTextureStageColorOp( 0, GFXTOPDisable ); -// -// RectI viewport; -// viewport.point.set(0, 0); -// viewport.extent.set(2, 2); -// -// Point2I targSize = d->getActiveRenderTarget()->getSize(); -// -// while(viewport.point.x < targSize.x) -// { -// while(viewport.point.y < targSize.y) -// { -// d->setViewport(viewport); -// PrimBuild::color4f( 0.0, 1.0, 0.0, 1.0 ); -// PrimBuild::begin( GFXTriangleFan, 4 ); -// -// PrimBuild::vertex3f( -1.0, -1.0, 0.0 ); -// -// PrimBuild::vertex3f( -1.0, 1.0, 0.0 ); -// -// PrimBuild::vertex3f( 1.0, 1.0, 0.0 ); -// -// PrimBuild::vertex3f( 1.0, -1.0, 0.0 ); -// PrimBuild::end(); -// viewport.point.y += 2; -// } -// viewport.point.y = 0; -// viewport.point.x += 2; -// } -// } -// -// void run() -// { -// mRenderer.renderSignal.notify(this, &TestGFXViewport::onRenderEvent); -// mRenderer.go(); -// mRenderer.destroy(); -// } -//}; -// -//CreateInteractiveTest(TestGFXSolidCube, "GFX/SolidCube") -//{ -// -// SimpleGFXRenderFramework mRenderer; -// CubeBuilder mCube; -// -// void onRenderEvent(GFXDevice *d) -// { -// // This init work could be done elsewhere, but it's easier -// // to just do it here. -// -// // Make sure we have a valid cube to render with. -// mCube.ensureValid(d, 1.0f); -// -// // Set up the view... -// //d->setFrustum(90.0f, 1.0f, 0.1, 100.f); -// d->setOrtho(-10.f, 10.f, -10.f, 10.f, 0.1f, 10.f, false); -// MatrixF worldMatrix(1); -// -// // Get some cheesy spin going... -// static F32 spinDiddle = 0.f; -// -// worldMatrix *= MatrixF(EulerF(0,spinDiddle, 90.0f - spinDiddle )); -// worldMatrix.setPosition(Point3F(0.f, 5.f, 0.f)); -// -// //spinDiddle += 0.0001f; -// -// if(spinDiddle > 90.f) -// spinDiddle = 0.f; -// -// d->setWorldMatrix(worldMatrix); -// -// // Draw our cube. -// d->setVertexBuffer(mCube.mCubeVB); -// d->setPrimitiveBuffer(mCube.mCubePB); -// -// d->setBaseRenderState(); -// d->setCullMode(GFXCullNone); -// d->setVertexColorEnable(true); -// d->setAlphaBlendEnable(false); -// d->setZEnable(true); -// d->setZFunc(GFXCmpLess); -// d->setupGenericShaders(); -// d->setTextureStageColorOp( 0, GFXTOPDisable ); -// -// d->drawIndexedPrimitive(GFXTriangleList, 0, 8, 0, 12); -// } -// -// void run() -// { -// mRenderer.renderSignal.notify(this, &TestGFXSolidCube::onRenderEvent); -// mRenderer.go(); -// mCube.destroy(); -// mRenderer.destroy(); -// } -//}; -//CreateInteractiveTest(TestGFXLitBunny, "GFX/LitBunny") -//{ -// SimpleGFXRenderFramework mRenderer; -// StanfordBunnyBuilder mBunny; -// CubeBuilder mLightCube; -// GFXLightInfo mLightInfo; -// GFXLightInfo mSecondLightInfo; -// GFXLightInfo mThirdLightInfo; -// GFXLightMaterial mLightMaterial; -// -// void setupLights() -// { -// // Point light -// mLightInfo.mType = GFXLightInfo::Point; -// -// // Simple color -// mLightInfo.mColor = ColorF(1.0, 0.0, 0.0, 1.0); -// -// // No ambient -// mLightInfo.mAmbient = ColorF(0.0, 0.0, 0.0, 1.0); -// -// // Irrelevant for point lights -// mLightInfo.mDirection = Point3F(0.0f, 1.0f, 0.0f); -// -// // Position IN WORLD SPACE -// mLightInfo.mPos = Point3F(0.0f, 1.5f, 1.0f); -// -// // Radius -// mLightInfo.mRadius = 2.0f; -// -// -// mSecondLightInfo.mType = GFXLightInfo::Point; -// mSecondLightInfo.mColor = ColorF(0.0, 0.0, 1.0, 1.0); -// mSecondLightInfo.mAmbient = ColorF(0.0, 0.0, 0.0, 1.0); -// mSecondLightInfo.mDirection = Point3F(0.0f, 1.0f, 0.0f); -// mSecondLightInfo.mPos = Point3F(1.0f, 1.0f, 0.0f); -// mSecondLightInfo.mRadius = 2.0f; -// -// mThirdLightInfo.mType = GFXLightInfo::Point; -// mThirdLightInfo.mColor = ColorF(0.0, 1.0, 0.0, 1.0); -// mThirdLightInfo.mAmbient = ColorF(0.0, 0.0, 0.0, 1.0); -// mThirdLightInfo.mDirection = Point3F(0.0f, 1.0f, 0.0f); -// mThirdLightInfo.mPos = Point3F(-1.0f, 1.0f, -1.0f); -// mThirdLightInfo.mRadius = 2.0f; -// } -// -// void onRenderEvent(GFXDevice *d) -// { -// mBunny.ensureValid(d); -// mLightCube.ensureValid(d, 0.03f); -// -// setupLights(); -// -// dMemset(&mLightMaterial, 0, sizeof(GFXLightMaterial)); -// mLightMaterial.ambient = ColorF(1.0, 0.0, 0.0, 1.0); -// mLightMaterial.diffuse = ColorF(1.0, 1.0, 1.0, 1.0); -// -// // Set up the view... -// d->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// MatrixF projectionMatrix = d->getProjectionMatrix(); -// //d->setOrtho(-10.f, 10.f, -10.f, 10.f, 0.1f, 10.f, false); -// MatrixF worldMatrix(1); -// MatrixF lightMatrix(1); -// MatrixF secondLightMatrix(1); -// MatrixF thirdLightMatrix(1); -// -// // Get some cheesy spin going... -// static F32 spinDiddle = 0.f; -// -// // Bunny location -// worldMatrix *= MatrixF(EulerF(0,spinDiddle, 90.0f - spinDiddle )); -// worldMatrix.setPosition(Point3F(0.f, 1.5f, 0.f)); -// -// // Spinning cube of light -// lightMatrix *= MatrixF(EulerF(0,spinDiddle, 90.0f - spinDiddle )); -// lightMatrix.setPosition(mLightInfo.mPos); -// -// secondLightMatrix *= MatrixF(EulerF(0,spinDiddle, 90.0f - spinDiddle )); -// secondLightMatrix.setPosition(mSecondLightInfo.mPos); -// -// thirdLightMatrix *= MatrixF(EulerF(0,spinDiddle, 90.0f - spinDiddle )); -// thirdLightMatrix.setPosition(mThirdLightInfo.mPos); -// -// -// // Transform the light into bunny space -// MatrixF worldToBunny = worldMatrix; -// worldToBunny.inverse(); -// worldToBunny.mulP(mLightInfo.mPos); -// worldToBunny.mulP(mSecondLightInfo.mPos); -// worldToBunny.mulP(mThirdLightInfo.mPos); -// -// spinDiddle += 0.001f; -// -// if(spinDiddle > 90.f) -// spinDiddle = 0.f; -// -// // Cheat. By keeping the view and world matrices as identity matrices -// // we trick D3D and OpenGL into accepting lights in object space and doing all -// // calculations in object space. This way we don't have to do ugly API specific -// // stuff anywhere. -// d->setProjectionMatrix(projectionMatrix * worldMatrix); -// -// // Draw our Bunny. -// d->setVertexBuffer(mBunny.mBunnyVB); -// -// d->setBaseRenderState(); -// d->setCullMode(GFXCullCW); -// -// // Need to set a material or D3D refuses to render, but OpenGL works. -// // CodeReview - Should the D3D layer leave a default material bound? - AlexS 4/17/07 -// d->setLightMaterial(mLightMaterial); -// -// // Enable Lighting -// d->setLightingEnable(true); -// -// // Allow the use of vertex colors in lighting calculations -// d->setVertexColorEnable(true); -// -// // Use the vertex color as the diffuse material source -// d->setDiffuseMaterialSource(GFXMCSColor1); -// -// // Use the vertex color as the ambient material source -// d->setAmbientMaterialSource(GFXMCSColor1); -// -// // Set our light -// d->setLight(0, &mLightInfo); -// d->setLight(1, &mSecondLightInfo); -// d->setLight(2, &mThirdLightInfo); -// -// -// d->setAlphaBlendEnable(false); -// d->setZEnable(true); -// d->setZFunc(GFXCmpLess); -// d->setupGenericShaders(); -// d->setTextureStageColorOp( 0, GFXTOPDisable ); -// -// d->drawPrimitive(GFXTriangleList, 0, 16301); -// -// // Draw a cube for our light. -// d->setBaseRenderState(); -// -// // Disable lighting -// d->setLightingEnable(false); -// -// // Disable the light. Not strictly necessary, but still good practice. -// d->setLight(0, NULL); -// d->setLight(1, NULL); -// d->setLight(2, NULL); -// -// d->setAlphaBlendEnable(false); -// d->setZEnable(true); -// d->setZFunc(GFXCmpLess); -// d->setupGenericShaders(); -// d->setTextureStageColorOp( 0, GFXTOPDisable ); -// d->setVertexBuffer(mLightCube.mCubeVB); -// d->setPrimitiveBuffer(mLightCube.mCubePB); -// //d->setWorldMatrix(lightMatrix); -// -// d->setProjectionMatrix(projectionMatrix * lightMatrix); -// d->drawIndexedPrimitive(GFXTriangleList, 0, 8, 0, 12); -// -// d->setProjectionMatrix(projectionMatrix * secondLightMatrix); -// d->drawIndexedPrimitive(GFXTriangleList, 0, 8, 0, 12); -// -// d->setProjectionMatrix(projectionMatrix * thirdLightMatrix); -// d->drawIndexedPrimitive(GFXTriangleList, 0, 8, 0, 12); -// } -// -// void run() -// { -// mRenderer.renderSignal.notify(this, &TestGFXLitBunny::onRenderEvent); -// mRenderer.go(); -// mRenderer.destroy(); -// } -//}; -// -//CreateInteractiveTest(TestGFXTextureCube, "GFX/TextureCube") -//{ -// -// SimpleGFXRenderFramework mRenderer; -// CubeBuilder mCube; -// GFXTexHandle mTex; -// -// void onRenderEvent(GFXDevice *d) -// { -// // This init work could be done elsewhere, but it's easier -// // to just do it here. -// -// // Make sure we have a valid cube to render with. -// mCube.ensureValid(d, 1.0f); -// -// // Make sure we have a valid texture to render with. -// if(mTex.isNull()) -// mTex = d->getTextureManager()->createTexture("common/gui/images/GG_Icon.png", &GFXDefaultPersistentProfile); -// -// // Set up the view... -// d->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// MatrixF worldMatrix(1); -// -// // Get some cheesy spin going... -// static F32 spinDiddle = 0.f; -// -// worldMatrix *= MatrixF(EulerF(0.f,spinDiddle, 90.f - spinDiddle )); -// worldMatrix.setPosition(Point3F(0.f, 5.f, 0.f)); -// -// spinDiddle += 0.001f; -// -// if(spinDiddle > 90.f) -// spinDiddle = 0.f; -// -// d->setWorldMatrix(worldMatrix); -// -// // Draw our cube. -// d->setVertexBuffer(mCube.mCubeVB); -// d->setPrimitiveBuffer(mCube.mCubePB); -// -// d->setBaseRenderState(); -// d->setCullMode(GFXCullNone); -// d->setVertexColorEnable(true); -// d->setAlphaBlendEnable(false); -// d->setZEnable(true); -// d->setZFunc(GFXCmpLess); -// d->setupGenericShaders(); -// -// // Turn on texture, with a cheesy vertex modulate (whee!) -// d->setTextureStageColorOp( 0, GFXTOPModulate ); -// d->setTexture(0, mTex); -// -// d->drawIndexedPrimitive(GFXTriangleList, 0, 8, 0, 12); -// } -// -// void run() -// { -// mRenderer.renderSignal.notify(this, &TestGFXTextureCube::onRenderEvent); -// mRenderer.go(); -// mTex = NULL; -// mCube.destroy(); -// mRenderer.destroy(); -// } -//}; -// -//CreateInteractiveTest(TestGFXTextureLock, "GFX/TextureLock") -//{ -// SimpleGFXRenderFramework mRenderer; -// CubeBuilder mCube; -// GFXTexHandle mTex; -// -// void onRenderEvent(GFXDevice *d) -// { -// // This init work could be done elsewhere, but it's easier -// // to just do it here. -// -// // Make sure we have a valid cube to render with. -// mCube.ensureValid(d, 1.0f); -// -// // Make sure we have a valid texture to render with. -// if(mTex.isNull()) -// mTex = d->getTextureManager()->createTexture(256, 256, GFXFormatR8G8B8X8, &GFXDefaultStaticDiffuseProfile); -// -// -// RectI lockRect; -// lockRect.point.x = gRandGen.randI(0, 255); -// lockRect.point.y = gRandGen.randI(0, 255); -// lockRect.extent.x = gRandGen.randI(1, 256 - lockRect.point.x); -// lockRect.extent.y = gRandGen.randI(1, 256 - lockRect.point.y); -// -// //U8 r, g, b; -// //r = (U8)gRandGen.randI(0, 255); -// //g = (U8)gRandGen.randI(0, 255); -// //b = (U8)gRandGen.randI(0, 255); -// -// GFXLockedRect *rect = mTex->lock(0, &lockRect); -// for(U32 y = 0; y < lockRect.extent.y; y++) -// { -// for(U32 x = 0; x < lockRect.extent.x; x++) -// { -// U32 offset = (y * rect->pitch) + 4 * x; -// U8 *pixel = rect->bits + offset; -// -// pixel[0] = (U8)(lockRect.point.y + y); -// pixel[1] = (U8)(lockRect.point.y + y); -// pixel[2] = (U8)(lockRect.point.y + y); -// pixel[3] = 255; -// } -// } -// -// mTex->unlock(0); -// -// // Set up the view... -// d->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// MatrixF worldMatrix(1); -// -// // Get some cheesy spin going... -// static F32 spinDiddle = 0.f; -// -// worldMatrix *= MatrixF(EulerF(0.f,spinDiddle, 90.f - spinDiddle )); -// worldMatrix.setPosition(Point3F(0.f, 3.f, 0.f)); -// -// spinDiddle += 0.001f; -// -// if(spinDiddle > 90.f) -// spinDiddle = 0.f; -// -// d->setWorldMatrix(worldMatrix); -// -// // Draw our cube. -// d->setVertexBuffer(mCube.mCubeVB); -// d->setPrimitiveBuffer(mCube.mCubePB); -// -// d->setBaseRenderState(); -// d->setCullMode(GFXCullNone); -// d->setVertexColorEnable(true); -// d->setAlphaBlendEnable(false); -// d->setZEnable(true); -// d->setZFunc(GFXCmpLess); -// d->setupGenericShaders(); -// -// // Turn on texture, with a cheesy vertex modulate (whee!) -// d->setTextureStageColorOp( 0, GFXTOPModulate ); -// d->setTexture(0, mTex); -// -// d->drawIndexedPrimitive(GFXTriangleList, 0, 8, 0, 12); -// } -// -// void run() -// { -// mRenderer.renderSignal.notify(this, &TestGFXTextureLock::onRenderEvent); -// mRenderer.go(); -// mTex = NULL; -// mCube.destroy(); -// mRenderer.destroy(); -// } -//}; -// -//CreateInteractiveTest(TestGFXMultiTextureCube, "GFX/MultiTextureCube") -//{ -// -// SimpleGFXRenderFramework mRenderer; -// CubeBuilder mCube; -// GFXTexHandle mTex0; -// GFXTexHandle mTex1; -// -// void onRenderEvent(GFXDevice *d) -// { -// // This init work could be done elsewhere, but it's easier -// // to just do it here. -// -// // Make sure we have a valid cube to render with. -// mCube.ensureValid(d, 1.0f); -// -// // Make sure we have a valid texture to render with. -// if(mTex0.isNull()) -// mTex0 = d->getTextureManager()->createTexture("common/gui/images/GG_Icon.png", &GFXDefaultPersistentProfile); -// if(mTex1.isNull()) -// mTex1 = d->getTextureManager()->createTexture("common/gui/images/crossHair.png", &GFXDefaultPersistentProfile); -// -// // Set up the view... -// d->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// MatrixF worldMatrix(1); -// -// // Get some cheesy spin going... -// static F32 spinDiddle = 0.f; -// -// worldMatrix *= MatrixF(EulerF(0.f,spinDiddle, 90.f - spinDiddle )); -// worldMatrix.setPosition(Point3F(0.f, 5.f, 0.f)); -// -// spinDiddle += 0.001f; -// -// if(spinDiddle > 90.f) -// spinDiddle = 0.f; -// -// d->setWorldMatrix(worldMatrix); -// -// // Draw our cube. -// d->setVertexBuffer(mCube.mCubeVB); -// d->setPrimitiveBuffer(mCube.mCubePB); -// -// d->setBaseRenderState(); -// d->setCullMode(GFXCullNone); -// d->setVertexColorEnable(true); -// d->setAlphaBlendEnable(false); -// d->setZEnable(true); -// d->setZFunc(GFXCmpLess); -// d->setupGenericShaders(); -// -// // Turn on texture, with a cheesy vertex modulate (whee!) -// d->setTextureStageColorOp( 0, GFXTOPModulate); -// d->setTexture(0, mTex0); -// d->setTextureStageColorOp( 1, GFXTOPModulate ); -// d->setTexture(1, mTex1); -// -// d->drawIndexedPrimitive(GFXTriangleList, 0, 8, 0, 12); -// } -// -// void run() -// { -// mRenderer.renderSignal.notify(this, &TestGFXMultiTextureCube::onRenderEvent); -// mRenderer.go(); -// mTex0 = NULL; -// mTex1 = NULL; -// mCube.destroy(); -// mRenderer.destroy(); -// } -//}; -// -//CreateInteractiveTest(TestGFXRenderTargetCube, "GFX/RenderTargetCube") -//{ -// SimpleGFXRenderFramework mRenderer; -// CubeBuilder mCube; -// GFXTexHandle mTex; -// GFXTextureTargetRef mRenderTarget; -// -// void drawCube(GFXDevice *d) -// { -// // Draw our cube. -// d->setVertexBuffer(mCube.mCubeVB); -// d->setPrimitiveBuffer(mCube.mCubePB); -// -// d->setBaseRenderState(); -// d->setCullMode(GFXCullNone); -// d->setVertexColorEnable(true); -// d->setAlphaBlendEnable(false); -// d->setupGenericShaders(); -// -// // Turn on texture, with a cheesy vertex modulate (whee!) -// d->setTextureStageColorOp( 0, GFXTOPModulate ); -// -// d->drawIndexedPrimitive(GFXTriangleList, 0, 8, 0, 12); -// } -// -// void onRenderEvent(GFXDevice *d) -// { -// // This init work could be done elsewhere, but it's easier -// // to just do it here. -// -// // Make sure we have a valid cube to render with. -// mCube.ensureValid(d, 1.0f); -// -// // Make sure we have a valid texture to render with. -// if(mTex.isNull()) -// mTex = d->getTextureManager()->createTexture(256, 256, GFXFormatR8G8B8X8, &GFXDefaultRenderTargetProfile); -// -// // Make sure we have a render target. -// if(mRenderTarget == NULL) -// mRenderTarget = d->allocRenderToTextureTarget(); -// -// // Update the render target. -// { -// d->setTexture(0, NULL); -// -// mRenderTarget->attachTexture(GFXTextureTarget::Color0, mTex); -// mRenderTarget->attachTexture(GFXTextureTarget::DepthStencil, GFXTextureTarget::sDefaultDepthStencil); -// d->setActiveRenderTarget(mRenderTarget); -// d->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, ColorI( 0, 0, 0 ), 1.0f, 0 ); -// -// -// d->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// MatrixF worldMatrix(1); -// -// // Get some cheesy spin going... -// static F32 spinDiddle = 45.f; -// -// worldMatrix *= MatrixF(EulerF(0,spinDiddle, 90.f - spinDiddle )); -// worldMatrix.setPosition(Point3F(0, 3, 0)); -// -// spinDiddle += 0.001f; -// -// if(spinDiddle > 90.f) -// spinDiddle = 0.f; -// -// d->setWorldMatrix(worldMatrix); -// -// drawCube(d); -// -// // Detach the texture so we can continue on w/ rendering... -// mRenderTarget->attachTexture(GFXTextureTarget::Color0, NULL); -// } -// -// -// // Render to the window... -// { -// d->setActiveRenderTarget(mRenderer.mWindow->getGFXTarget()); -// d->setTexture(0, mTex); -// -// // Set up the view... -// d->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// MatrixF worldMatrix(1); -// -// // Get some cheesy spin going... -// static F32 spinDiddle = 0.f; -// -// worldMatrix *= MatrixF(EulerF(0,spinDiddle, 90.f - spinDiddle )); -// worldMatrix.setPosition(Point3F(0, 5, 0)); -// -// spinDiddle += 0.001f; -// -// if(spinDiddle > 90.f) -// spinDiddle = 0.f; -// -// d->setWorldMatrix(worldMatrix); -// d->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, ColorI( 0, 0, 0 ), 1.0f, 0 ); -// -// drawCube(d); -// } -// } -// -// void run() -// { -// mRenderTarget = NULL; -// mRenderer.renderSignal.notify(this, &TestGFXRenderTargetCube::onRenderEvent); -// mRenderer.go(); -// -// mTex = NULL; -// mRenderTarget = NULL; -// mCube.destroy(); -// mRenderer.destroy(); -// } -//}; -// -// -//CreateInteractiveTest(TestGFXRenderTargetStack, "GFX/RenderTargetStack") -//{ -// enum -// { -// NumRenderTargets = 2, -// MaxRenderTargetDepth = 3, -// MaxRenderTargetsPerFrame = 10 -// }; -// -// SimpleGFXRenderFramework mRenderer; -// GFXTexHandle mTex[NumRenderTargets]; -// ColorI mTexLastClearColor[NumRenderTargets]; -// GFXTextureTargetRef mRenderTarget; -// CubeBuilder mCube; -// -// void drawCube(GFXDevice *d) -// { -// // Draw our cube. -// d->setVertexBuffer(mCube.mCubeVB); -// d->setPrimitiveBuffer(mCube.mCubePB); -// -// d->setBaseRenderState(); -// d->setCullMode(GFXCullNone); -// d->setVertexColorEnable(true); -// d->setAlphaBlendEnable(false); -// d->setupGenericShaders(); -// -// // Turn on texture, with a cheesy vertex modulate (whee!) -// d->setTextureStageColorOp( 0, GFXTOPModulate ); -// -// d->drawIndexedPrimitive(GFXTriangleList, 0, 8, 0, 12); -// } -// -// void onRenderEvent(GFXDevice *d) -// { -// // Make sure cube is ready to go. -// mCube.ensureValid(d, 1.0f); -// -// // Make sure we have a render to texture target. -// if(mRenderTarget == NULL) -// mRenderTarget = d->allocRenderToTextureTarget(); -// -// // Make sure all our textures are allocated. -// for(S32 i=0; igetTextureManager()->createTexture(256, 256, GFXFormatR8G8B8X8, &GFXDefaultRenderTargetProfile); -// } -// -// // Render to our different target textures. -// d->pushActiveRenderTarget(); -// -// // Set a starting texture so we can bind w/o any nulls. -// mRenderTarget->attachTexture(GFXTextureTarget::Color0, mTex[0]); -// -// // Now set the render target active.. -// d->setActiveRenderTarget(mRenderTarget); -// -// // Iterate over our render targets. -// for(S32 i=0; iattachTexture(GFXTextureTarget::Color0, mTex[i]); -// d->clear( GFXClearTarget, ColorI( (i+1)*80, (i)*150, 0 ), 1.0f, 0 ); -// } -// -// // Unbind everything so we don't have dangling references. -// mRenderTarget->attachTexture(GFXTextureTarget::Color0, NULL); -// d->popActiveRenderTarget(); -// -// // Set up the view... -// d->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// -// // Cheesy little positional offset table. -// F32 posOffsets[4][3] = -// { -// { -2, 5, -2}, -// { -2, 5, 2}, -// { 2, 5, -2}, -// { 2, 5, 2}, -// }; -// AssertFatal(NumRenderTargets <= 4, "Need more position offsets to draw cubes at."); -// -// // Let's draw a cube for each RT. -// for(S32 i=0; i 90.f) -// spinDiddle = 0.f; -// -// d->setWorldMatrix(worldMatrix); -// d->setTexture(0, mTex[i]); -// -// drawCube(d); -// } -// -// // Clean up. -// d->setTexture(0, NULL); -// } -// -// void run() -// { -// mRenderTarget = NULL; -// -// mRenderer.renderSignal.notify(this, &TestGFXRenderTargetStack::onRenderEvent); -// mRenderer.go(); -// -// // Clean stuff up. -// mRenderTarget = NULL; -// -// for(S32 i=0; isetVertexBuffer(mCube->mCubeVB); -// d->setPrimitiveBuffer(mCube->mCubePB); -// -// d->setBaseRenderState(); -// d->setCullMode(GFXCullNone); -// d->setVertexColorEnable(true); -// d->setAlphaBlendEnable(false); -// d->setupGenericShaders(); -// -// // Turn on texture, with a cheesy vertex modulate (whee!) -// d->setTextureStageColorOp( 0, GFXTOPModulate ); -// -// d->drawIndexedPrimitive(GFXTriangleList, 0, 8, 0, 12); -// } -// -// void onRenderSignal(WindowId id) -// { -// mDevice->beginScene(); -// mDevice->setActiveRenderTarget(mWindow->getGFXTarget()); -// -// // Fill this in an interesting way... -// static U32 i=10; -// mDevice->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, ColorI( 0, i, 0 ), 1.0f, 0 ); -// i+=10; -// -// // Set up the view... -// mDevice->setFrustum(90.0f, 1.0f, 0.1f, 100.f); -// -// // Get some cheesy spin going... -// MatrixF worldMatrix(1); -// -// static F32 spinDiddle = 0.f; -// -// worldMatrix *= MatrixF(EulerF(0,spinDiddle, 90.f - spinDiddle )); -// worldMatrix.setPosition(Point3F(-2, 5, -2)); -// -// spinDiddle += 0.001f; -// -// if(spinDiddle > 90.f) -// spinDiddle = 0.f; -// -// mDevice->setWorldMatrix(worldMatrix); -// -// // set sampler if we have one (handle null device case) -// if (mDevice->getNumSamplers()) -// mDevice->setTexture(0, *mTex); -// -// // Draw our cube... -// drawCube(mDevice); -// -// // And swap. -// mDevice->endScene(); -// mWindow->getGFXTarget()->present(); -// } -// -// bool onAppSignal(WindowId d, S32 event) -// { -// if(event == WindowClose && d == mWindow->getWindowId()) -// Process::requestShutdown(); -// return true; -// } -// -// void run() -// { -// PlatformWindowManager *pwm = CreatePlatformWindowManager(); -// -// // Create a video mode to use. -// GFXVideoMode vm; -// vm.resolution.x = 400; -// vm.resolution.y = 400; -// -// // Query all the available devices and adapters. -// GFXInit::enumerateAdapters(); -// Vector adapters; -// GFXInit::getAdapters(&adapters); -// -// test(adapters.size() > 0, "Got zero adapters! Hard to run an adapter test with no adapters!"); -// -// // For each reported adapter... -// for(S32 i=0; imIndex, -// adapters[i]->mName, -// GFXInit::getAdapterNameFromType(adapters[i]->mType))); -// -// // Init the device. -// mDevice = GFXInit::createDevice(adapters[i]); -// test(mDevice, "Failed to create a device!"); -// -// if(!mDevice) -// continue; -// -// // Create the window... -// mWindow = pwm->createWindow(mDevice, vm); -// test(mWindow, "Failed to create a window for this device!"); -// -// if(!mWindow) -// { -// SAFE_DELETE(mDevice); -// continue; -// } -// -// // Create some representative items: -// // - a cube builder... -// mCube = new CubeBuilder(); -// mCube->ensureValid(mDevice, 1.0f); -// -// // - a texture -// mTex = new GFXTexHandle(); -// if((*mTex).isNull()) -// (*mTex) = mDevice->getTextureManager()->createTexture("common/gui/images/GG_Icon.png", -// &GFXDefaultPersistentProfile); -// -// // Hook in our events. -// // Setup our events. -// mWindow->signalRender.notify(this, &TestGFXDeviceSwitching::onRenderSignal); -// mWindow->signalApp.notify (this, &TestGFXDeviceSwitching::onAppSignal); -// -// // Render until the user gets bored. -// while(Process::processEvents()); -// -// // And clean up, so we can do it again. -// SAFE_DELETE(mTex); -// SAFE_DELETE(mCube); -// SAFE_DELETE(mDevice); -// SAFE_DELETE(mWindow); -// } -// -// // All done! -// SAFE_DELETE(pwm); -// } -//}; diff --git a/Engine/source/gfx/util/distanceField.cpp b/Engine/source/gfx/util/distanceField.cpp index 91069ee25..229a07eec 100644 --- a/Engine/source/gfx/util/distanceField.cpp +++ b/Engine/source/gfx/util/distanceField.cpp @@ -32,7 +32,7 @@ struct DistanceFieldSearchSpaceStruct F32 distance; }; -int QSORT_CALLBACK cmpSortDistanceFieldSearchSpaceStruct(const void* p1, const void* p2) +S32 QSORT_CALLBACK cmpSortDistanceFieldSearchSpaceStruct(const void* p1, const void* p2) { const DistanceFieldSearchSpaceStruct* sp1 = (const DistanceFieldSearchSpaceStruct*)p1; const DistanceFieldSearchSpaceStruct* sp2 = (const DistanceFieldSearchSpaceStruct*)p2; diff --git a/Engine/source/gfx/util/triListOpt.cpp b/Engine/source/gfx/util/triListOpt.cpp index 8ed7e4d12..95c8fd65e 100644 --- a/Engine/source/gfx/util/triListOpt.cpp +++ b/Engine/source/gfx/util/triListOpt.cpp @@ -48,11 +48,11 @@ void OptimizeTriangleOrdering(const dsize_t numVerts, const dsize_t numIndices, FrameTemp triangleData(NumPrimitives); U32 curIdx = 0; - for(int tri = 0; tri < NumPrimitives; tri++) + for(S32 tri = 0; tri < NumPrimitives; tri++) { TriData &curTri = triangleData[tri]; - for(int c = 0; c < 3; c++) + for(S32 c = 0; c < 3; c++) { const U32 &curVIdx = indices[curIdx]; AssertFatal(curVIdx < numVerts, "Out of range index."); @@ -71,7 +71,7 @@ void OptimizeTriangleOrdering(const dsize_t numVerts, const dsize_t numIndices, // Allocate per-vertex triangle lists, and calculate the starting score of // each of the verts - for(int v = 0; v < numVerts; v++) + for(S32 v = 0; v < numVerts; v++) { VertData &curVert = vertexData[v]; curVert.triIndex = new S32[curVert.numUnaddedReferences]; @@ -89,11 +89,11 @@ void OptimizeTriangleOrdering(const dsize_t numVerts, const dsize_t numIndices, // Fill-in per-vertex triangle lists, and sum the scores of each vertex used // per-triangle, to get the starting triangle score curIdx = 0; - for(int tri = 0; tri < NumPrimitives; tri++) + for(S32 tri = 0; tri < NumPrimitives; tri++) { TriData &curTri = triangleData[tri]; - for(int c = 0; c < 3; c++) + for(S32 c = 0; c < 3; c++) { const U32 &curVIdx = indices[curIdx]; AssertFatal(curVIdx < numVerts, "Out of range index."); @@ -117,7 +117,7 @@ void OptimizeTriangleOrdering(const dsize_t numVerts, const dsize_t numIndices, // Step 2: Start emitting triangles...this is the emit loop // LRUCacheModel lruCache; - for(int outIdx = 0; outIdx < numIndices; /* this space intentionally left blank */ ) + for(S32 outIdx = 0; outIdx < numIndices; /* this space intentionally left blank */ ) { // If there is no next best triangle, than search for the next highest // scored triangle that isn't in the list already @@ -127,7 +127,7 @@ void OptimizeTriangleOrdering(const dsize_t numVerts, const dsize_t numIndices, nextBestTriScore = nextNextBestTriScore = -1.0f; nextBestTriIdx = nextNextBestTriIdx = -1; - for(int tri = 0; tri < NumPrimitives; tri++) + for(S32 tri = 0; tri < NumPrimitives; tri++) { TriData &curTri = triangleData[tri]; @@ -143,7 +143,7 @@ void OptimizeTriangleOrdering(const dsize_t numVerts, const dsize_t numIndices, // Emit the next best triangle TriData &nextBestTri = triangleData[nextBestTriIdx]; AssertFatal(!nextBestTri.isInList, "Next best triangle already in list, this is no good."); - for(int i = 0; i < 3; i++) + for(S32 i = 0; i < 3; i++) { // Emit index outIndices[outIdx++] = IndexType(nextBestTri.vertIdx[i]); @@ -151,7 +151,7 @@ void OptimizeTriangleOrdering(const dsize_t numVerts, const dsize_t numIndices, // Update the list of triangles on the vert VertData &curVert = vertexData[nextBestTri.vertIdx[i]]; curVert.numUnaddedReferences--; - for(int t = 0; t < curVert.numReferences; t++) + for(S32 t = 0; t < curVert.numReferences; t++) { if(curVert.triIndex[t] == nextBestTriIdx) { @@ -184,7 +184,7 @@ void OptimizeTriangleOrdering(const dsize_t numVerts, const dsize_t numIndices, { tri.score = 0.0f; - for(int i = 0; i < 3; i++) + for(S32 i = 0; i < 3; i++) tri.score += vertexData[tri.vertIdx[i]].score; _CHECK_NEXT_BEST(tri.score, *itr); @@ -288,12 +288,12 @@ void LRUCacheModel::enforceSize(const dsize_t maxSize, Vector &outTrisToUpd // Update cache position on verts still in cache vData.cachePosition = length++; - for(int i = 0; i < vData.numReferences; i++) + for(S32 i = 0; i < vData.numReferences; i++) { const S32 &triIdx = vData.triIndex[i]; if(triIdx > -1) { - int j = 0; + S32 j = 0; for(; j < outTrisToUpdate.size(); j++) if(outTrisToUpdate[j] == triIdx) break; @@ -378,7 +378,7 @@ F32 score(const VertData &vertexData) AssertFatal(vertexData.cachePosition < MaxSizeVertexCache, "Out of range cache position for vertex"); // Points for being high in the cache. - const float Scaler = 1.0f / (MaxSizeVertexCache - 3); + const F32 Scaler = 1.0f / (MaxSizeVertexCache - 3); Score = 1.0f - (vertexData.cachePosition - 3) * Scaler; Score = mPow(Score, FindVertexScore::CacheDecayPower); } @@ -387,7 +387,7 @@ F32 score(const VertData &vertexData) // Bonus points for having a low number of tris still to // use the vert, so we get rid of lone verts quickly. - float ValenceBoost = mPow(vertexData.numUnaddedReferences, -FindVertexScore::ValenceBoostPower); + F32 ValenceBoost = mPow(vertexData.numUnaddedReferences, -FindVertexScore::ValenceBoostPower); Score += FindVertexScore::ValenceBoostScale * ValenceBoost; return Score; diff --git a/Engine/source/gfx/video/theoraTexture.cpp b/Engine/source/gfx/video/theoraTexture.cpp index 95b513c26..039cbb392 100644 --- a/Engine/source/gfx/video/theoraTexture.cpp +++ b/Engine/source/gfx/video/theoraTexture.cpp @@ -60,7 +60,7 @@ GFX_ImplementTextureProfile( GFXTheoraTextureProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::NoMipmap | GFXTextureProfile::Dynamic, - GFXTextureProfile::None ); + GFXTextureProfile::NONE ); //----------------------------------------------------------------------------- diff --git a/Engine/source/gfx/video/videoCapture.h b/Engine/source/gfx/video/videoCapture.h index 5ef80c836..7f46b133f 100644 --- a/Engine/source/gfx/video/videoCapture.h +++ b/Engine/source/gfx/video/videoCapture.h @@ -221,6 +221,8 @@ protected: // List with bitmaps which are done encoding ThreadSafeDeque< GBitmap* > mProcessedBitmaps; public: + virtual ~VideoEncoder() { } + // Stores an encoded bitmap to be dealt with later void pushProcessedBitmap( GBitmap* bitmap ); diff --git a/Engine/source/gfx/video/videoEncoderTheora.cpp b/Engine/source/gfx/video/videoEncoderTheora.cpp index c0b094a52..3e6160a12 100644 --- a/Engine/source/gfx/video/videoEncoderTheora.cpp +++ b/Engine/source/gfx/video/videoEncoderTheora.cpp @@ -150,8 +150,8 @@ class VideoEncoderTheora : public VideoEncoder, public Thread F64 videotime = th_granule_time(td,ogg_page_granulepos(&videopage)); if (videotime > 0) { - int hundredths=(int)(videotime*100-(long)videotime*100); - int seconds=(long)videotime%60; + S32 hundredths=(int)(videotime*100-(long)videotime*100); + S32 seconds=(long)videotime%60; Platform::outputDebugString("Encoding time %g %02i.%02i", videotime, seconds, hundredths); } } @@ -254,12 +254,12 @@ public: th_info_clear(&ti); // This is needed for youtube compatibility - int vp3_compatible = 1; + S32 vp3_compatible = 1; th_encode_ctl(td, TH_ENCCTL_SET_VP3_COMPATIBLE, &vp3_compatible, sizeof(vp3_compatible)); // Set the encoder to max speed - int speed_max; - int ret; + S32 speed_max; + S32 ret; ret = th_encode_ctl(td, TH_ENCCTL_GET_SPLEVEL_MAX, &speed_max, sizeof(speed_max)); if(ret<0){ Platform::outputDebugString("VideoEncoderTheora::begin() - could not determine maximum speed level."); diff --git a/Engine/source/gui/3d/guiTSControl.cpp b/Engine/source/gui/3d/guiTSControl.cpp index 4e42dbf84..71d419159 100644 --- a/Engine/source/gui/3d/guiTSControl.cpp +++ b/Engine/source/gui/3d/guiTSControl.cpp @@ -539,7 +539,7 @@ DefineEngineMethod( GuiTSCtrl, getWorldToScreenScale, Point2F, (),, //----------------------------------------------------------------------------- -DefineEngineMethod( GuiTSCtrl, calculateViewDistance, float, ( float radius ),, +DefineEngineMethod( GuiTSCtrl, calculateViewDistance, F32, ( F32 radius ),, "Given the camera's current FOV, get the distance from the camera's viewpoint at which the given radius will fit in the render area.\n" "@param radius Radius in world-space units which should fit in the view.\n" "@return The distance from the viewpoint at which the given radius would be fully visible." ) diff --git a/Engine/source/gui/buttons/guiIconButtonCtrl.cpp b/Engine/source/gui/buttons/guiIconButtonCtrl.cpp index 55a0efb16..b4aed4ec7 100644 --- a/Engine/source/gui/buttons/guiIconButtonCtrl.cpp +++ b/Engine/source/gui/buttons/guiIconButtonCtrl.cpp @@ -230,7 +230,7 @@ void GuiIconButtonCtrl::renderButton( Point2I &offset, const RectI& updateRect ) bool highlight = mMouseOver; bool depressed = mDepressed; - ColorI fontColor = mActive ? (highlight ? mProfile->mFontColor : mProfile->mFontColor) : mProfile->mFontColorNA; + ColorI fontColor = mActive ? (highlight ? mProfile->mFontColorHL : mProfile->mFontColor) : mProfile->mFontColorNA; RectI boundsRect(offset, getExtent()); @@ -436,4 +436,4 @@ DefineEngineMethod( GuiIconButtonCtrl, setBitmap, void, (const char* buttonFilen char* argBuffer = Con::getArgBuffer( 512 ); Platform::makeFullPathName( buttonFilename, argBuffer, 512 ); object->setBitmap( argBuffer ); -} \ No newline at end of file +} diff --git a/Engine/source/gui/containers/guiWindowCtrl.cpp b/Engine/source/gui/containers/guiWindowCtrl.cpp index 724154910..0132a75d6 100644 --- a/Engine/source/gui/containers/guiWindowCtrl.cpp +++ b/Engine/source/gui/containers/guiWindowCtrl.cpp @@ -1478,7 +1478,7 @@ void GuiWindowCtrl::positionButtons(void) // Until a pref, if alignment is LEFT, put buttons RIGHT justified. // ELSE, put buttons LEFT justified. - int closeLeft = mainOff.x, closeTop = mainOff.y, closeOff = buttonWidth + 2; + S32 closeLeft = mainOff.x, closeTop = mainOff.y, closeOff = buttonWidth + 2; if ( mProfile->mAlignment == GuiControlProfile::LeftJustify ) { closeOff = -closeOff; diff --git a/Engine/source/gui/controls/guiBitmapCtrl.cpp b/Engine/source/gui/controls/guiBitmapCtrl.cpp index 29766d197..e95263701 100644 --- a/Engine/source/gui/controls/guiBitmapCtrl.cpp +++ b/Engine/source/gui/controls/guiBitmapCtrl.cpp @@ -178,13 +178,13 @@ void GuiBitmapCtrl::onRender(Point2I offset, const RectI &updateRect) GFXTextureObject* texture = mTextureObject; RectI srcRegion; RectI dstRegion; - float xdone = ((float)getExtent().x/(float)texture->mBitmapSize.x)+1; - float ydone = ((float)getExtent().y/(float)texture->mBitmapSize.y)+1; + F32 xdone = ((F32)getExtent().x/(F32)texture->mBitmapSize.x)+1; + F32 ydone = ((F32)getExtent().y/(F32)texture->mBitmapSize.y)+1; - int xshift = mStartPoint.x%texture->mBitmapSize.x; - int yshift = mStartPoint.y%texture->mBitmapSize.y; - for(int y = 0; y < ydone; ++y) - for(int x = 0; x < xdone; ++x) + S32 xshift = mStartPoint.x%texture->mBitmapSize.x; + S32 yshift = mStartPoint.y%texture->mBitmapSize.y; + for(S32 y = 0; y < ydone; ++y) + for(S32 x = 0; x < xdone; ++x) { srcRegion.set(0,0,texture->mBitmapSize.x,texture->mBitmapSize.y); dstRegion.set( ((texture->mBitmapSize.x*x)+offset.x)-xshift, diff --git a/Engine/source/gui/controls/guiColorPicker.cpp b/Engine/source/gui/controls/guiColorPicker.cpp index c8c34eebe..e6ea1ad12 100644 --- a/Engine/source/gui/controls/guiColorPicker.cpp +++ b/Engine/source/gui/controls/guiColorPicker.cpp @@ -528,10 +528,11 @@ void GuiColorPickerCtrl::setScriptValue(const char *value) ConsoleMethod(GuiColorPickerCtrl, getSelectorPos, const char*, 2, 2, "Gets the current position of the selector") { - char *temp = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char *temp = Con::getReturnBuffer(bufSize); Point2I pos; pos = object->getSelectorPos(); - dSprintf(temp,256,"%d %d",pos.x, pos.y); + dSprintf(temp,bufSize,"%d %d",pos.x, pos.y); return temp; } diff --git a/Engine/source/gui/controls/guiDirectoryFileListCtrl.cpp b/Engine/source/gui/controls/guiDirectoryFileListCtrl.cpp index d5695b24d..c244af658 100644 --- a/Engine/source/gui/controls/guiDirectoryFileListCtrl.cpp +++ b/Engine/source/gui/controls/guiDirectoryFileListCtrl.cpp @@ -169,17 +169,18 @@ DefineEngineMethod( GuiDirectoryFileListCtrl, getSelectedFiles, const char*, (), return StringTable->insert( "" ); // Get an adequate buffer - char itemBuffer[256]; - dMemset( itemBuffer, 0, 256 ); + static const U32 itemBufSize = 256; + char itemBuffer[itemBufSize]; - char* returnBuffer = Con::getReturnBuffer( ItemVector.size() * 64 ); - dMemset( returnBuffer, 0, ItemVector.size() * 64 ); + static const U32 bufSize = ItemVector.size() * 64; + char* returnBuffer = Con::getReturnBuffer( bufSize ); + dMemset( returnBuffer, 0, bufSize ); // Fetch the first entry StringTableEntry itemText = object->getItemText( ItemVector[0] ); if( !itemText ) return StringTable->lookup(""); - dSprintf( returnBuffer, ItemVector.size() * 64, "%s", itemText ); + dSprintf( returnBuffer, bufSize, "%s", itemText ); // If only one entry, return it. if( ItemVector.size() == 1 ) @@ -192,8 +193,8 @@ DefineEngineMethod( GuiDirectoryFileListCtrl, getSelectedFiles, const char*, (), if( !itemText ) continue; - dMemset( itemBuffer, 0, 256 ); - dSprintf( itemBuffer, 256, " %s", itemText ); + dMemset( itemBuffer, 0, itemBufSize ); + dSprintf( itemBuffer, itemBufSize, " %s", itemText ); dStrcat( returnBuffer, itemBuffer ); } diff --git a/Engine/source/gui/controls/guiFileTreeCtrl.cpp b/Engine/source/gui/controls/guiFileTreeCtrl.cpp index 7fe7e3ba4..60e0c3b86 100644 --- a/Engine/source/gui/controls/guiFileTreeCtrl.cpp +++ b/Engine/source/gui/controls/guiFileTreeCtrl.cpp @@ -260,7 +260,7 @@ bool GuiFileTreeCtrl::matchesFilters(const char* filename) if( !mFilters.size() ) return true; - for(int i = 0; i < mFilters.size(); i++) + for(S32 i = 0; i < mFilters.size(); i++) { if(FindMatch::isMatch( mFilters[i], filename)) return true; diff --git a/Engine/source/gui/controls/guiGameListMenuCtrl.cpp b/Engine/source/gui/controls/guiGameListMenuCtrl.cpp index d5cc8813d..fb6931d50 100644 --- a/Engine/source/gui/controls/guiGameListMenuCtrl.cpp +++ b/Engine/source/gui/controls/guiGameListMenuCtrl.cpp @@ -736,7 +736,7 @@ bool GuiGameListMenuProfile::onAdd() // We can't call enforceConstraints() here because incRefCount initializes // some of the things to enforce. Do a basic sanity check here instead. - if( !dStrlen(mBitmapName) ) + if( !mBitmapName || !dStrlen(mBitmapName) ) { Con::errorf( "GuiGameListMenuProfile: %s can't be created without a bitmap. Please add a 'Bitmap' property to the object definition.", getName() ); return false; diff --git a/Engine/source/gui/controls/guiGameListOptionsCtrl.cpp b/Engine/source/gui/controls/guiGameListOptionsCtrl.cpp index 42eb38092..1c5bdba0f 100644 --- a/Engine/source/gui/controls/guiGameListOptionsCtrl.cpp +++ b/Engine/source/gui/controls/guiGameListOptionsCtrl.cpp @@ -213,7 +213,7 @@ void GuiGameListOptionsCtrl::addRow(const char* label, const char* optionsList, Row * row = new Row(); Vector options( __FILE__, __LINE__ ); S32 count = StringUnit::getUnitCount(optionsList, DELIM); - for (int i = 0; i < count; ++i) + for (S32 i = 0; i < count; ++i) { const char * option = StringUnit::getUnit(optionsList, i, DELIM); options.push_back(StringTable->insert(option, true)); @@ -238,7 +238,7 @@ void GuiGameListOptionsCtrl::setOptions(S32 rowIndex, const char * optionsList) S32 count = StringUnit::getUnitCount(optionsList, DELIM); row->mOptions.setSize(count); - for (int i = 0; i < count; ++i) + for (S32 i = 0; i < count; ++i) { const char * option = StringUnit::getUnit(optionsList, i, DELIM); row->mOptions[i] = StringTable->insert(option, true); diff --git a/Engine/source/gui/controls/guiGradientCtrl.cpp b/Engine/source/gui/controls/guiGradientCtrl.cpp index 30d94c969..7fe919fd1 100644 --- a/Engine/source/gui/controls/guiGradientCtrl.cpp +++ b/Engine/source/gui/controls/guiGradientCtrl.cpp @@ -89,8 +89,9 @@ bool GuiGradientSwatchCtrl::onWake() if ( !Parent::onWake() ) return false; - char* altCommand = Con::getReturnBuffer(512); - dSprintf( altCommand, 512, "%s(%i.color, \"%i.setColor\");", mColorFunction, getId(), getId() ); + static const U32 bufSize = 512; + char* altCommand = Con::getReturnBuffer(bufSize); + dSprintf( altCommand, bufSize, "%s(%i.color, \"%i.setColor\");", mColorFunction, getId(), getId() ); setField( "altCommand", altCommand ); return true; @@ -616,10 +617,11 @@ ConsoleMethod(GuiGradientCtrl, getColor, const char*, 3, 3, "Get color value") { if ( idx >= 0 && idx < object->mColorRange.size() ) { - char* rColor = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char* rColor = Con::getReturnBuffer(bufSize); rColor[0] = 0; - dSprintf(rColor, 256, "%f %f %f %f", + dSprintf(rColor, bufSize, "%f %f %f %f", object->mColorRange[idx].swatch->getColor().red, object->mColorRange[idx].swatch->getColor().green, object->mColorRange[idx].swatch->getColor().blue, @@ -632,10 +634,11 @@ ConsoleMethod(GuiGradientCtrl, getColor, const char*, 3, 3, "Get color value") { if ( idx >= 0 && idx < object->mAlphaRange.size() ) { - char* rColor = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char* rColor = Con::getReturnBuffer(bufSize); rColor[0] = 0; - dSprintf(rColor, 256, "%f %f %f %f", + dSprintf(rColor, bufSize, "%f %f %f %f", object->mAlphaRange[idx].swatch->getColor().red, object->mAlphaRange[idx].swatch->getColor().green, object->mAlphaRange[idx].swatch->getColor().blue, diff --git a/Engine/source/gui/controls/guiListBoxCtrl.cpp b/Engine/source/gui/controls/guiListBoxCtrl.cpp index fda05f07c..6459d5004 100644 --- a/Engine/source/gui/controls/guiListBoxCtrl.cpp +++ b/Engine/source/gui/controls/guiListBoxCtrl.cpp @@ -450,8 +450,9 @@ DefineEngineMethod( GuiListBoxCtrl, getSelectedItems, const char*, (),, if( selItems.empty() ) return StringTable->lookup("-1"); - UTF8 *retBuffer = Con::getReturnBuffer( selItems.size() * 4 ); - dMemset( retBuffer, 0, selItems.size() * 4 ); + static const U32 bufSize = selItems.size() * 4; + UTF8 *retBuffer = Con::getReturnBuffer( bufSize ); + dMemset( retBuffer, 0, bufSize ); Vector::iterator i = selItems.begin(); for( ; i != selItems.end(); i++ ) { diff --git a/Engine/source/gui/controls/guiMLTextCtrl.cpp b/Engine/source/gui/controls/guiMLTextCtrl.cpp index 63f9c7cdd..4233190c6 100644 --- a/Engine/source/gui/controls/guiMLTextCtrl.cpp +++ b/Engine/source/gui/controls/guiMLTextCtrl.cpp @@ -91,7 +91,7 @@ GFX_ImplementTextureProfile(GFXMLTextureProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::PreserveSize | GFXTextureProfile::Static, - GFXTextureProfile::None); + GFXTextureProfile::NONE); const U32 GuiMLTextCtrl::csmTextBufferGrowthSize = 1024; @@ -138,7 +138,7 @@ DefineEngineMethod( GuiMLTextCtrl, addText, void, ( const char* text, bool refor object->addText(text, dStrlen(text), reformat); } -DefineEngineMethod( GuiMLTextCtrl, setCursorPosition, bool, (int newPos),, +DefineEngineMethod( GuiMLTextCtrl, setCursorPosition, bool, (S32 newPos),, "@brief Change the text cursor's position to a new defined offset within the text in the control.\n\n" "@param newPos Offset to place cursor.\n" "@tsexample\n" @@ -153,7 +153,7 @@ DefineEngineMethod( GuiMLTextCtrl, setCursorPosition, bool, (int newPos),, return object->setCursorPosition(newPos); } -DefineEngineMethod( GuiMLTextCtrl, scrollToTag, void, (int tagID),, +DefineEngineMethod( GuiMLTextCtrl, scrollToTag, void, (S32 tagID),, "@brief Scroll down to a specified tag.\n\n" "Detailed description\n\n" "@param tagID TagID to scroll the control to\n" diff --git a/Engine/source/gui/controls/guiPopUpCtrl.cpp b/Engine/source/gui/controls/guiPopUpCtrl.cpp index e4b2903f7..b67776461 100644 --- a/Engine/source/gui/controls/guiPopUpCtrl.cpp +++ b/Engine/source/gui/controls/guiPopUpCtrl.cpp @@ -1011,8 +1011,8 @@ void GuiPopUpMenuCtrl::onRender( Point2I offset, const RectI &updateRect ) { // We're making use of a bitmap border, so take into account the // right cap of the border. - RectI* mBitmapBounds = mProfile->mBitmapArrayRects.address(); - localStart.x = getWidth() - mBitmapBounds[2].extent.x - txt_w; + RectI* bitmapBounds = mProfile->mBitmapArrayRects.address(); + localStart.x = getWidth() - bitmapBounds[2].extent.x - txt_w; } else { @@ -1024,8 +1024,8 @@ void GuiPopUpMenuCtrl::onRender( Point2I offset, const RectI &updateRect ) { // We're making use of a bitmap border, so take into account the // right cap of the border. - RectI* mBitmapBounds = mProfile->mBitmapArrayRects.address(); - localStart.x = (getWidth() - mBitmapBounds[2].extent.x - txt_w) / 2; + RectI* bitmapBounds = mProfile->mBitmapArrayRects.address(); + localStart.x = (getWidth() - bitmapBounds[2].extent.x - txt_w) / 2; } else { @@ -1043,8 +1043,8 @@ void GuiPopUpMenuCtrl::onRender( Point2I offset, const RectI &updateRect ) { // We're making use of a bitmap border, so take into account the // right cap of the border. - RectI* mBitmapBounds = mProfile->mBitmapArrayRects.address(); - localStart.x = getWidth() - mBitmapBounds[2].extent.x - txt_w; + RectI* bitmapBounds = mProfile->mBitmapArrayRects.address(); + localStart.x = getWidth() - bitmapBounds[2].extent.x - txt_w; } else { @@ -1095,8 +1095,8 @@ void GuiPopUpMenuCtrl::onRender( Point2I offset, const RectI &updateRect ) { // We're making use of a bitmap border, so take into account the // right cap of the border. - RectI* mBitmapBounds = mProfile->mBitmapArrayRects.address(); - Point2I textpos = localToGlobalCoord( Point2I( getWidth() - txt_w - mBitmapBounds[2].extent.x, localStart.y ) ); + RectI* bitmapBounds = mProfile->mBitmapArrayRects.address(); + Point2I textpos = localToGlobalCoord( Point2I( getWidth() - txt_w - bitmapBounds[2].extent.x, localStart.y ) ); GFX->getDrawUtil()->drawText( mProfile->mFont, textpos, buff, mProfile->mFontColors ); } else diff --git a/Engine/source/gui/controls/guiPopUpCtrlEx.cpp b/Engine/source/gui/controls/guiPopUpCtrlEx.cpp index 275faf75c..97258c67c 100644 --- a/Engine/source/gui/controls/guiPopUpCtrlEx.cpp +++ b/Engine/source/gui/controls/guiPopUpCtrlEx.cpp @@ -579,8 +579,9 @@ ConsoleMethod( GuiPopUpMenuCtrlEx, getColorById, const char*, 3, 3, ColorI color; object->getColoredBox(color, dAtoi(argv[2])); - char *strBuffer = Con::getReturnBuffer(512); - dSprintf(strBuffer, 512, "%d %d %d %d", color.red, color.green, color.blue, color.alpha); + static const U32 bufSize = 512; + char *strBuffer = Con::getReturnBuffer(bufSize); + dSprintf(strBuffer, bufSize, "%d %d %d %d", color.red, color.green, color.blue, color.alpha); return strBuffer; } @@ -1167,8 +1168,8 @@ void GuiPopUpMenuCtrlEx::onRender(Point2I offset, const RectI &updateRect) { // We're making use of a bitmap border, so take into account the // right cap of the border. - RectI* mBitmapBounds = mProfile->mBitmapArrayRects.address(); - localStart.x = getWidth() - mBitmapBounds[2].extent.x - txt_w; + RectI* bitmapBounds = mProfile->mBitmapArrayRects.address(); + localStart.x = getWidth() - bitmapBounds[2].extent.x - txt_w; } else { @@ -1180,8 +1181,8 @@ void GuiPopUpMenuCtrlEx::onRender(Point2I offset, const RectI &updateRect) { // We're making use of a bitmap border, so take into account the // right cap of the border. - RectI* mBitmapBounds = mProfile->mBitmapArrayRects.address(); - localStart.x = (getWidth() - mBitmapBounds[2].extent.x - txt_w) / 2; + RectI* bitmapBounds = mProfile->mBitmapArrayRects.address(); + localStart.x = (getWidth() - bitmapBounds[2].extent.x - txt_w) / 2; } else { @@ -1199,8 +1200,8 @@ void GuiPopUpMenuCtrlEx::onRender(Point2I offset, const RectI &updateRect) { // We're making use of a bitmap border, so take into account the // right cap of the border. - RectI* mBitmapBounds = mProfile->mBitmapArrayRects.address(); - localStart.x = getWidth() - mBitmapBounds[2].extent.x - txt_w; + RectI* bitmapBounds = mProfile->mBitmapArrayRects.address(); + localStart.x = getWidth() - bitmapBounds[2].extent.x - txt_w; } else { @@ -1251,8 +1252,8 @@ void GuiPopUpMenuCtrlEx::onRender(Point2I offset, const RectI &updateRect) { // We're making use of a bitmap border, so take into account the // right cap of the border. - RectI* mBitmapBounds = mProfile->mBitmapArrayRects.address(); - Point2I textpos = localToGlobalCoord( Point2I( getWidth() - txt_w - mBitmapBounds[2].extent.x, localStart.y ) ); + RectI* bitmapBounds = mProfile->mBitmapArrayRects.address(); + Point2I textpos = localToGlobalCoord( Point2I( getWidth() - txt_w - bitmapBounds[2].extent.x, localStart.y ) ); GFX->getDrawUtil()->drawText( mProfile->mFont, textpos, buff, mProfile->mFontColors ); } else diff --git a/Engine/source/gui/controls/guiTextEditCtrl.cpp b/Engine/source/gui/controls/guiTextEditCtrl.cpp index 1748d5ce7..c451400b7 100644 --- a/Engine/source/gui/controls/guiTextEditCtrl.cpp +++ b/Engine/source/gui/controls/guiTextEditCtrl.cpp @@ -1688,7 +1688,7 @@ DefineEngineMethod( GuiTextEditCtrl, getCursorPos, S32, (),, return( object->getCursorPos() ); } -DefineEngineMethod( GuiTextEditCtrl, setCursorPos, void, (int position),, +DefineEngineMethod( GuiTextEditCtrl, setCursorPos, void, (S32 position),, "@brief Sets the text cursor at the defined position within the control.\n\n" "@param position Text position to set the text cursor.\n" "@tsexample\n" diff --git a/Engine/source/gui/controls/guiTextListCtrl.cpp b/Engine/source/gui/controls/guiTextListCtrl.cpp index 7c6b9602a..dfd191795 100644 --- a/Engine/source/gui/controls/guiTextListCtrl.cpp +++ b/Engine/source/gui/controls/guiTextListCtrl.cpp @@ -79,12 +79,12 @@ IMPLEMENT_CALLBACK( GuiTextListCtrl, onDeleteKey, void, ( const char* id ),( id "@see GuiControl\n\n" ); -static int sortColumn; +static S32 sortColumn; static bool sIncreasing; static const char *getColumn(const char *text) { - int ct = sortColumn; + S32 ct = sortColumn; while(ct--) { text = dStrchr(text, '\t'); @@ -530,7 +530,7 @@ DefineEngineMethod( GuiTextListCtrl, getSelectedId, S32, (),, return object->getSelectedId(); } -DefineEngineMethod( GuiTextListCtrl, setSelectedById, void, (int id),, +DefineEngineMethod( GuiTextListCtrl, setSelectedById, void, (S32 id),, "@brief Finds the specified entry by id, then marks its row as selected.\n\n" "@param id Entry within the text list to make selected.\n" "@tsexample\n" @@ -548,7 +548,7 @@ DefineEngineMethod( GuiTextListCtrl, setSelectedById, void, (int id),, object->setSelectedCell(Point2I(0, index)); } -DefineEngineMethod( GuiTextListCtrl, setSelectedRow, void, (int rowNum),, +DefineEngineMethod( GuiTextListCtrl, setSelectedRow, void, (S32 rowNum),, "@briefSelects the specified row.\n\n" "@param rowNum Row number to set selected.\n" "@tsexample\n" @@ -584,7 +584,7 @@ DefineEngineMethod( GuiTextListCtrl, clearSelection, void, (),, object->setSelectedCell(Point2I(-1, -1)); } -DefineEngineMethod( GuiTextListCtrl, addRow, S32, (int id, const char* text, int index),(0,"",-1), +DefineEngineMethod( GuiTextListCtrl, addRow, S32, (S32 id, const char* text, S32 index),(0,"",-1), "@brief Adds a new row at end of the list with the defined id and text.\n" "If index is used, then the new row is inserted at the row location of 'index'.\n\n" "@param id Id of the new row.\n" @@ -612,7 +612,7 @@ DefineEngineMethod( GuiTextListCtrl, addRow, S32, (int id, const char* text, int return ret; } -DefineEngineMethod( GuiTextListCtrl, setRowById, void, (int id, const char* text),, +DefineEngineMethod( GuiTextListCtrl, setRowById, void, (S32 id, const char* text),, "@brief Sets the text at the defined id.\n\n" "@param id Id to change.\n" "@param text Text to use at the Id.\n" @@ -629,7 +629,7 @@ DefineEngineMethod( GuiTextListCtrl, setRowById, void, (int id, const char* text object->setEntry(id, text); } -DefineEngineMethod( GuiTextListCtrl, sort, void, ( int columnId, bool increasing ), ( true ), +DefineEngineMethod( GuiTextListCtrl, sort, void, ( S32 columnId, bool increasing ), ( true ), "@brief Performs a standard (alphabetical) sort on the values in the specified column.\n\n" "@param columnId Column ID to perform the sort on.\n" "@param increasing If false, sort will be performed in reverse.\n" @@ -646,7 +646,7 @@ DefineEngineMethod( GuiTextListCtrl, sort, void, ( int columnId, bool increasing object->sort( columnId, increasing ); } -DefineEngineMethod( GuiTextListCtrl, sortNumerical, void, (int columnID, bool increasing), ( true ), +DefineEngineMethod( GuiTextListCtrl, sortNumerical, void, (S32 columnID, bool increasing), ( true ), "@brief Perform a numerical sort on the values in the specified column.\n\n" "Detailed description\n\n" "@param columnId Column ID to perform the sort on.\n" @@ -687,7 +687,7 @@ DefineEngineMethod( GuiTextListCtrl, rowCount, S32, (),, return object->getNumEntries(); } -DefineEngineMethod( GuiTextListCtrl, getRowId, S32, (int index),, +DefineEngineMethod( GuiTextListCtrl, getRowId, S32, (S32 index),, "@brief Get the row ID for an index.\n\n" "@param index Index to get the RowID at\n" "@tsexample\n" @@ -705,7 +705,7 @@ DefineEngineMethod( GuiTextListCtrl, getRowId, S32, (int index),, return object->mList[index].id; } -DefineEngineMethod( GuiTextListCtrl, getRowTextById, const char*, (int id),, +DefineEngineMethod( GuiTextListCtrl, getRowTextById, const char*, (S32 id),, "@brief Get the text of a row with the specified id.\n\n" "@tsexample\n" "// Define the id\n" @@ -722,7 +722,7 @@ DefineEngineMethod( GuiTextListCtrl, getRowTextById, const char*, (int id),, return object->mList[index].text; } -DefineEngineMethod( GuiTextListCtrl, getRowNumById, S32, (int id),, +DefineEngineMethod( GuiTextListCtrl, getRowNumById, S32, (S32 id),, "@brief Get the row number for a specified id.\n\n" "@param id Id to get the row number at\n" "@tsexample\n" @@ -739,7 +739,7 @@ DefineEngineMethod( GuiTextListCtrl, getRowNumById, S32, (int id),, return index; } -DefineEngineMethod( GuiTextListCtrl, getRowText, const char*, (int index),, +DefineEngineMethod( GuiTextListCtrl, getRowText, const char*, (S32 index),, "@brief Get the text of the row with the specified index.\n\n" "@param index Row index to acquire the text at.\n" "@tsexample\n" @@ -756,7 +756,7 @@ DefineEngineMethod( GuiTextListCtrl, getRowText, const char*, (int index),, return object->mList[index].text; } -DefineEngineMethod( GuiTextListCtrl, removeRowById, void, (int id),, +DefineEngineMethod( GuiTextListCtrl, removeRowById, void, (S32 id),, "@brief Remove row with the specified id.\n\n" "@param id Id to remove the row entry at\n" "@tsexample\n" @@ -770,7 +770,7 @@ DefineEngineMethod( GuiTextListCtrl, removeRowById, void, (int id),, object->removeEntry(id); } -DefineEngineMethod( GuiTextListCtrl, removeRow, void, (int index),, +DefineEngineMethod( GuiTextListCtrl, removeRow, void, (S32 index),, "@brief Remove a row from the table, based on its index.\n\n" "@param index Row index to remove from the list.\n" "@tsexample\n" @@ -784,7 +784,7 @@ DefineEngineMethod( GuiTextListCtrl, removeRow, void, (int index),, object->removeEntryByIndex(index); } -DefineEngineMethod( GuiTextListCtrl, scrollVisible, void, (int rowNum),, +DefineEngineMethod( GuiTextListCtrl, scrollVisible, void, (S32 rowNum),, "@brief Scroll so the specified row is visible\n\n" "@param rowNum Row number to make visible\n" "@tsexample\n" @@ -813,7 +813,7 @@ DefineEngineMethod( GuiTextListCtrl, findTextIndex, S32, (const char* needle),, return( object->findEntryByText(needle) ); } -DefineEngineMethod( GuiTextListCtrl, setRowActive, void, (int rowNum, bool active),, +DefineEngineMethod( GuiTextListCtrl, setRowActive, void, (S32 rowNum, bool active),, "@brief Mark a specified row as active/not.\n\n" "@param rowNum Row number to change the active state.\n" "@param active Boolean active state to set the row number.\n" @@ -830,7 +830,7 @@ DefineEngineMethod( GuiTextListCtrl, setRowActive, void, (int rowNum, bool activ object->setEntryActive( U32( rowNum ), active ); } -DefineEngineMethod( GuiTextListCtrl, isRowActive, bool, (int rowNum),, +DefineEngineMethod( GuiTextListCtrl, isRowActive, bool, (S32 rowNum),, "@brief Check if the specified row is currently active or not.\n\n" "@param rowNum Row number to check the active state.\n" "@tsexample\n" diff --git a/Engine/source/gui/controls/guiTreeViewCtrl.cpp b/Engine/source/gui/controls/guiTreeViewCtrl.cpp index b6d2c99de..7f36a5903 100644 --- a/Engine/source/gui/controls/guiTreeViewCtrl.cpp +++ b/Engine/source/gui/controls/guiTreeViewCtrl.cpp @@ -3583,7 +3583,7 @@ void GuiTreeViewCtrl::onMiddleMouseDown(const GuiEvent & event) for (S32 j = 0; j < mSelected.size(); j++) { Con::printf("%d", mSelected[j]); } - S32 mCurrentDragCell = mMouseOverCell.y; + mCurrentDragCell = mMouseOverCell.y; S32 midpCell = (mCurrentDragCell) * mItemHeight + (mItemHeight/2); S32 currentY = pt.y; S32 yDiff = currentY-midpCell; @@ -3648,7 +3648,7 @@ void GuiTreeViewCtrl::onMouseDown(const GuiEvent & event) break; } } - S32 mCurrentDragCell = mMouseOverCell.y; + mCurrentDragCell = mMouseOverCell.y; if (mVisibleItems[firstSelectedIndex] != firstItem ) { /* @@ -4920,7 +4920,7 @@ ConsoleMethod( GuiTreeViewCtrl, open, void, 3, 4, "(SimSet obj, bool okToEdit=tr ConsoleMethod( GuiTreeViewCtrl, setItemTooltip, void, 4, 4, "( int id, string text ) - Set the tooltip to show for the given item." ) { - int id = dAtoi( argv[ 2 ] ); + S32 id = dAtoi( argv[ 2 ] ); GuiTreeViewCtrl::Item* item = object->getItem( id ); if( !item ) @@ -4934,7 +4934,7 @@ ConsoleMethod( GuiTreeViewCtrl, setItemTooltip, void, 4, 4, "( int id, string te ConsoleMethod( GuiTreeViewCtrl, setItemImages, void, 5, 5, "( int id, int normalImage, int expandedImage ) - Sets the normal and expanded images to show for the given item." ) { - int id = dAtoi( argv[ 2 ] ); + S32 id = dAtoi( argv[ 2 ] ); GuiTreeViewCtrl::Item* item = object->getItem( id ); if( !item ) @@ -4949,7 +4949,7 @@ ConsoleMethod( GuiTreeViewCtrl, setItemImages, void, 5, 5, "( int id, int normal ConsoleMethod( GuiTreeViewCtrl, isParentItem, bool, 3, 3, "( int id ) - Returns true if the given item contains child items." ) { - int id = dAtoi( argv[ 2 ] ); + S32 id = dAtoi( argv[ 2 ] ); if( !id && object->getItemCount() ) return true; @@ -5061,11 +5061,12 @@ ConsoleMethod(GuiTreeViewCtrl, getSelectedObject, S32, 2, 3, "( int index=0 ) - ConsoleMethod(GuiTreeViewCtrl, getSelectedObjectList, const char*, 2, 2, "Returns a space sperated list of all selected object ids.") { - char* buff = Con::getReturnBuffer(1024); - dSprintf(buff,1024,""); + static const U32 bufSize = 1024; + char* buff = Con::getReturnBuffer(bufSize); + dSprintf(buff,bufSize,""); const Vector< GuiTreeViewCtrl::Item* > selectedItems = object->getSelectedItems(); - for(int i = 0; i < selectedItems.size(); i++) + for(S32 i = 0; i < selectedItems.size(); i++) { GuiTreeViewCtrl::Item *item = selectedItems[i]; @@ -5077,7 +5078,7 @@ ConsoleMethod(GuiTreeViewCtrl, getSelectedObjectList, const char*, 2, 2, //the start of the buffer where we want to write char* buffPart = buff+len; //the size of the remaining buffer (-1 cause dStrlen doesn't count the \0) - S32 size = 1024-len-1; + S32 size = bufSize-len-1; //write it: if(size < 1) { @@ -5126,11 +5127,12 @@ ConsoleMethod(GuiTreeViewCtrl, getTextToRoot, const char*,4,4,"(TreeItemId item, ConsoleMethod(GuiTreeViewCtrl, getSelectedItemList,const char*, 2,2,"returns a space seperated list of mulitple item ids") { - char* buff = Con::getReturnBuffer(1024); - dSprintf(buff,1024,""); + static const U32 bufSize = 1024; + char* buff = Con::getReturnBuffer(bufSize); + dSprintf(buff,bufSize,""); const Vector< S32 >& selected = object->getSelected(); - for(int i = 0; i < selected.size(); i++) + for(S32 i = 0; i < selected.size(); i++) { S32 id = selected[i]; //get the current length of the buffer @@ -5138,7 +5140,7 @@ ConsoleMethod(GuiTreeViewCtrl, getSelectedItemList,const char*, 2,2,"returns a s //the start of the buffer where we want to write char* buffPart = buff+len; //the size of the remaining buffer (-1 cause dStrlen doesn't count the \0) - S32 size = 1024-len-1; + S32 size = bufSize-len-1; //write it: if(size < 1) { diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index 65792e81b..ad5646fe6 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -121,7 +121,8 @@ GuiCanvas::GuiCanvas(): GuiControl(), mMiddleMouseLast(false), mRightMouseLast(false), mPlatformWindow(NULL), - mLastRenderMs(0) + mLastRenderMs(0), + mDisplayWindow(true) { setBounds(0, 0, 640, 480); mAwake = true; @@ -176,6 +177,8 @@ void GuiCanvas::initPersistFields() addGroup("Canvas Rendering"); addProtectedField( "numFences", TypeS32, Offset( mNumFences, GuiCanvas ), &setProtectedNumFences, &defaultProtectedGetFn, "The number of GFX fences to use." ); + + addField("displayWindow", TypeBool, Offset(mDisplayWindow, GuiCanvas), "Controls if the canvas window is rendered or not." ); endGroup("Canvas Rendering"); Parent::initPersistFields(); @@ -252,6 +255,19 @@ bool GuiCanvas::onAdd() // Make sure we're able to render. newDevice->setAllowRender( true ); + if(mDisplayWindow) + { + getPlatformWindow()->show(); + WindowManager->setDisplayWindow(true); + getPlatformWindow()->setDisplayWindow(true); + } + else + { + getPlatformWindow()->hide(); + WindowManager->setDisplayWindow(false); + getPlatformWindow()->setDisplayWindow(false); + } + // Propagate add to parents. // CodeReview - if GuiCanvas fails to add for whatever reason, what happens to // all the event registration above? @@ -1561,7 +1577,7 @@ void GuiCanvas::setupFences() mFences = new GFXFence*[mNumFences]; // Allocate the new fences - for( int i = 0; i < mNumFences; i++ ) + for( S32 i = 0; i < mNumFences; i++ ) mFences[i] = GFX->createFence(); } @@ -2683,3 +2699,23 @@ ConsoleMethod( GuiCanvas, setVideoMode, void, 5, 8, // Store the new mode into a pref. Con::setVariable( "$pref::Video::mode", vm.toString() ); } + +ConsoleMethod( GuiCanvas, showWindow, void, 2, 2, "" ) +{ + if (!object->getPlatformWindow()) + return; + + object->getPlatformWindow()->show(); + WindowManager->setDisplayWindow(true); + object->getPlatformWindow()->setDisplayWindow(true); +} + +ConsoleMethod( GuiCanvas, hideWindow, void, 2, 2, "" ) +{ + if (!object->getPlatformWindow()) + return; + + object->getPlatformWindow()->hide(); + WindowManager->setDisplayWindow(false); + object->getPlatformWindow()->setDisplayWindow(false); +} \ No newline at end of file diff --git a/Engine/source/gui/core/guiCanvas.h b/Engine/source/gui/core/guiCanvas.h index 04af6d692..9d3ed8b10 100644 --- a/Engine/source/gui/core/guiCanvas.h +++ b/Engine/source/gui/core/guiCanvas.h @@ -108,6 +108,8 @@ protected: bool mClampTorqueCursor; bool mAlwaysHandleMouseButtons; + bool mDisplayWindow; + /// @} /// @name Mouse Input diff --git a/Engine/source/gui/core/guiTypes.cpp b/Engine/source/gui/core/guiTypes.cpp index 31929f78c..369d9f963 100644 --- a/Engine/source/gui/core/guiTypes.cpp +++ b/Engine/source/gui/core/guiTypes.cpp @@ -63,13 +63,13 @@ GFX_ImplementTextureProfile(GFXGuiCursorProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::PreserveSize | GFXTextureProfile::Static, - GFXTextureProfile::None); + GFXTextureProfile::NONE); GFX_ImplementTextureProfile(GFXDefaultGUIProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::PreserveSize | GFXTextureProfile::Static | GFXTextureProfile::NoPadding, - GFXTextureProfile::None); + GFXTextureProfile::NONE); GuiCursor::GuiCursor() @@ -719,8 +719,9 @@ ImplementConsoleTypeCasters( TypeRectSpacingI, RectSpacingI ) ConsoleGetType( TypeRectSpacingI ) { RectSpacingI *rect = (RectSpacingI *) dptr; - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%d %d %d %d", rect->top, rect->bottom, + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%d %d %d %d", rect->top, rect->bottom, rect->left, rect->right); return returnBuffer; } diff --git a/Engine/source/gui/editor/guiDebugger.cpp b/Engine/source/gui/editor/guiDebugger.cpp index 625704bee..b2640809d 100644 --- a/Engine/source/gui/editor/guiDebugger.cpp +++ b/Engine/source/gui/editor/guiDebugger.cpp @@ -78,8 +78,9 @@ ConsoleMethod(DbgFileView, getCurrentLine, const char *, 2, 2, "()" { S32 lineNum; const char *file = object->getCurrentLine(lineNum); - char* ret = Con::getReturnBuffer(256); - dSprintf(ret, sizeof(ret), "%s\t%d", file, lineNum); + static const U32 bufSize = 256; + char* ret = Con::getReturnBuffer(bufSize); + dSprintf(ret, bufSize, "%s\t%d", file, lineNum); return ret; } diff --git a/Engine/source/gui/editor/guiEaseViewCtrl.cpp b/Engine/source/gui/editor/guiEaseViewCtrl.cpp index 87dff9d5e..59713b682 100644 --- a/Engine/source/gui/editor/guiEaseViewCtrl.cpp +++ b/Engine/source/gui/editor/guiEaseViewCtrl.cpp @@ -97,7 +97,7 @@ void GuiEaseViewCtrl::onRender(Point2I offset, const RectI &updateRect) // Draw curve. - for( int i = 1; i <= numPoints; ++ i ) + for( S32 i = 1; i <= numPoints; ++ i ) { F32 x = ( F32 ) i / ( F32 ) numPoints; F32 y = mEase.getValue( x, 0, 1, 1 ); diff --git a/Engine/source/gui/editor/guiGraphCtrl.cpp b/Engine/source/gui/editor/guiGraphCtrl.cpp index f056bb44d..e00998b0b 100644 --- a/Engine/source/gui/editor/guiGraphCtrl.cpp +++ b/Engine/source/gui/editor/guiGraphCtrl.cpp @@ -274,7 +274,7 @@ void GuiGraphCtrl::addDatum(S32 plotID, F32 v) //----------------------------------------------------------------------------- -float GuiGraphCtrl::getDatum( int plotID, int sample) +F32 GuiGraphCtrl::getDatum( S32 plotID, S32 sample) { AssertFatal(plotID > -1 && plotID < MaxPlots, "Invalid plot specified!"); AssertFatal(sample > -1 && sample < MaxDataPoints, "Invalid sample specified!"); diff --git a/Engine/source/gui/editor/guiImageList.cpp b/Engine/source/gui/editor/guiImageList.cpp index 18cb973ed..c51f715b6 100644 --- a/Engine/source/gui/editor/guiImageList.cpp +++ b/Engine/source/gui/editor/guiImageList.cpp @@ -182,7 +182,7 @@ DefineEngineMethod( GuiImageList, count, S32, (),, return object->Count(); } -DefineEngineMethod( GuiImageList, remove, bool, (int index),, +DefineEngineMethod( GuiImageList, remove, bool, (S32 index),, "@brief Removes an image from the list by index.\n\n" "@param index Image index to remove.\n" "@tsexample\n" diff --git a/Engine/source/gui/editor/guiInspectorTypes.cpp b/Engine/source/gui/editor/guiInspectorTypes.cpp index 979028c7c..dfa9c5a15 100644 --- a/Engine/source/gui/editor/guiInspectorTypes.cpp +++ b/Engine/source/gui/editor/guiInspectorTypes.cpp @@ -764,8 +764,7 @@ GuiControl* GuiInspectorTypeShapeFilename::constructEditControl() // Change filespec char szBuffer[512]; - dSprintf( szBuffer, sizeof(szBuffer), "getLoadFilename(\"%s\", \"%d.apply\", %d.getData());", - "DTS Files (*.dts)|*.dts|COLLADA Files (*.dae)|*.dae|(All Files (*.*)|*.*|", getId(), getId() ); + dSprintf( szBuffer, sizeof(szBuffer), "getLoadFormatFilename(\"%d.apply\", %d.getData());", getId(), getId() ); mBrowseButton->setField( "Command", szBuffer ); // Create "Open in ShapeEditor" button diff --git a/Engine/source/gui/editor/guiMenuBar.cpp b/Engine/source/gui/editor/guiMenuBar.cpp index c2bdbb6a7..c8abfe72f 100644 --- a/Engine/source/gui/editor/guiMenuBar.cpp +++ b/Engine/source/gui/editor/guiMenuBar.cpp @@ -193,7 +193,7 @@ DefineEngineMethod( GuiMenuBar, setMenuMargins, void, (S32 horizontalMargin, S32 object->mBitmapMargin = bitmapToTextSpacing; } -DefineEngineMethod(GuiMenuBar, addMenu, void, (const char* menuText, int menuId),, +DefineEngineMethod(GuiMenuBar, addMenu, void, (const char* menuText, S32 menuId),, "@brief Adds a new menu to the menu bar.\n\n" "@param menuText Text to display for the new menu item.\n" "@param menuId ID for the new menu item.\n" @@ -215,7 +215,7 @@ DefineEngineMethod(GuiMenuBar, addMenu, void, (const char* menuText, int menuId) object->addMenu(menuText, menuId); } -DefineEngineMethod(GuiMenuBar, addMenuItem, void, (const char* targetMenu, const char* menuItemText, int menuItemId, const char* accelerator, int checkGroup), +DefineEngineMethod(GuiMenuBar, addMenuItem, void, (const char* targetMenu, const char* menuItemText, S32 menuItemId, const char* accelerator, int checkGroup), ("","",0,NULL,-1), "@brief Adds a menu item to the specified menu. The menu argument can be either the text of a menu or its id.\n\n" "@param menu Menu name or menu Id to add the new item to.\n" @@ -496,7 +496,7 @@ DefineEngineMethod(GuiMenuBar, setMenuItemVisible, void, (const char* menuTarget menuItem->visible = isVisible; } -DefineEngineMethod(GuiMenuBar, setMenuItemBitmap, void, (const char* menuTarget, const char* menuItemTarget, int bitmapIndex),, +DefineEngineMethod(GuiMenuBar, setMenuItemBitmap, void, (const char* menuTarget, const char* menuItemTarget, S32 bitmapIndex),, "@brief Sets the specified menu item bitmap index in the bitmap array. Setting the item's index to -1 will remove any bitmap.\n\n" "@param menuTarget Menu to affect the menuItem in\n" "@param menuItem Menu item to affect\n" diff --git a/Engine/source/gui/editor/guiParticleGraphCtrl.cpp b/Engine/source/gui/editor/guiParticleGraphCtrl.cpp index 37cc0365e..7dfc5a7eb 100644 --- a/Engine/source/gui/editor/guiParticleGraphCtrl.cpp +++ b/Engine/source/gui/editor/guiParticleGraphCtrl.cpp @@ -40,7 +40,7 @@ ConsoleDocClass( GuiParticleGraphCtrl, GuiParticleGraphCtrl::GuiParticleGraphCtrl() { - for(int i = 0; i < MaxPlots; i++) + for(S32 i = 0; i < MaxPlots; i++) { mPlots[i].mGraphColor = ColorF(1.0, 1.0, 1.0); VECTOR_SET_ASSOCIATION(mPlots[i].mGraphData); @@ -140,7 +140,7 @@ void GuiParticleGraphCtrl::onRender(Point2I offset, const RectI &updateRect) ColorF color(1.0f, 1.0f, 1.0f, 0.5f); pDrawUtil->drawRectFill(updateRect, color); - for (int k = 0; k < MaxPlots; k++) + for (S32 k = 0; k < MaxPlots; k++) { // Nothing to graph if ((mPlots[k].mGraphData.size() == 0) || (mPlots[k].mHidden == true)) @@ -1060,12 +1060,13 @@ ConsoleMethod(GuiParticleGraphCtrl, addPlotPoint, const char*, 5, 6, "(int plotI { S32 plotID = dAtoi(argv[2]); S32 pointAdded = 0; - char *retBuffer = Con::getReturnBuffer(32); + static const U32 bufSize = 32; + char *retBuffer = Con::getReturnBuffer(bufSize); if(plotID > object->MaxPlots) { Con::errorf("Invalid plotID."); - dSprintf(retBuffer, 32, "%d", -2); + dSprintf(retBuffer, bufSize, "%d", -2); return retBuffer; } @@ -1078,7 +1079,7 @@ ConsoleMethod(GuiParticleGraphCtrl, addPlotPoint, const char*, 5, 6, "(int plotI } - dSprintf(retBuffer, 32, "%d", pointAdded); + dSprintf(retBuffer, bufSize, "%d", pointAdded); return retBuffer; } @@ -1107,19 +1108,20 @@ ConsoleMethod(GuiParticleGraphCtrl, changePlotPoint, const char*, 6, 6, "(int pl "@return No return value.") { S32 plotID = dAtoi(argv[2]); + static const U32 bufSize = 64; if(plotID > object->MaxPlots) { Con::errorf("Invalid plotID."); - char *retBuffer = Con::getReturnBuffer(64); + char *retBuffer = Con::getReturnBuffer(bufSize); const S32 index = -1; - dSprintf(retBuffer, 64, "%d", index); + dSprintf(retBuffer, bufSize, "%d", index); return retBuffer; } - char *retBuffer = Con::getReturnBuffer(64); + char *retBuffer = Con::getReturnBuffer(bufSize); const S32 index = object->changePlotPoint( plotID, dAtoi(argv[3]), Point2F(dAtof(argv[4]), dAtof(argv[5]))); - dSprintf(retBuffer, 64, "%d", index); + dSprintf(retBuffer, bufSize, "%d", index); return retBuffer; } @@ -1127,9 +1129,10 @@ ConsoleMethod(GuiParticleGraphCtrl, getSelectedPlot, const char*, 2, 2, "() " "Gets the selected Plot (a.k.a. graph).\n" "@return The plot's ID.") { - char *retBuffer = Con::getReturnBuffer(32); + static const U32 bufSize = 32; + char *retBuffer = Con::getReturnBuffer(bufSize); const S32 plot = object->getSelectedPlot(); - dSprintf(retBuffer, 32, "%d", plot); + dSprintf(retBuffer, bufSize, "%d", plot); return retBuffer; } @@ -1137,9 +1140,10 @@ ConsoleMethod(GuiParticleGraphCtrl, getSelectedPoint, const char*, 2, 2, "()" "Gets the selected Point on the Plot (a.k.a. graph)." "@return The last selected point ID") { - char *retBuffer = Con::getReturnBuffer(32); + static const U32 bufSize = 32; + char *retBuffer = Con::getReturnBuffer(bufSize); const S32 point = object->getSelectedPoint(); - dSprintf(retBuffer, 32, "%d", point); + dSprintf(retBuffer, bufSize, "%d", point); return retBuffer; } @@ -1158,9 +1162,10 @@ ConsoleMethod(GuiParticleGraphCtrl, isExistingPoint, const char*, 4, 4, "(int pl Con::errorf("Invalid sample."); } - char *retBuffer = Con::getReturnBuffer(32); + static const U32 bufSize = 32; + char *retBuffer = Con::getReturnBuffer(bufSize); const bool isPoint = object->isExistingPoint(plotID, samples); - dSprintf(retBuffer, 32, "%d", isPoint); + dSprintf(retBuffer, bufSize, "%d", isPoint); return retBuffer; } @@ -1180,9 +1185,10 @@ ConsoleMethod(GuiParticleGraphCtrl, getPlotPoint, const char*, 4, 4, "(int plotI Con::errorf("Invalid sample."); } - char *retBuffer = Con::getReturnBuffer(64); + static const U32 bufSize = 64; + char *retBuffer = Con::getReturnBuffer(bufSize); const Point2F &pos = object->getPlotPoint(plotID, samples); - dSprintf(retBuffer, 64, "%f %f", pos.x, pos.y); + dSprintf(retBuffer, bufSize, "%f %f", pos.x, pos.y); return retBuffer; } @@ -1201,9 +1207,10 @@ ConsoleMethod(GuiParticleGraphCtrl, getPlotIndex, const char*, 5, 5, "(int plotI Con::errorf("Invalid plotID."); } - char *retBuffer = Con::getReturnBuffer(32); + static const U32 bufSize = 32; + char *retBuffer = Con::getReturnBuffer(bufSize); const S32 &index = object->getPlotIndex(plotID, x, y); - dSprintf(retBuffer, 32, "%d", index); + dSprintf(retBuffer, bufSize, "%d", index); return retBuffer; } @@ -1218,9 +1225,10 @@ ConsoleMethod(GuiParticleGraphCtrl, getGraphColor, const char*, 3, 3, "(int plot Con::errorf("Invalid plotID."); } - char *retBuffer = Con::getReturnBuffer(64); + static const U32 bufSize = 64; + char *retBuffer = Con::getReturnBuffer(bufSize); const ColorF &color = object->getGraphColor(plotID); - dSprintf(retBuffer, 64, "%f %f %f", color.red, color.green, color.blue); + dSprintf(retBuffer, bufSize, "%f %f %f", color.red, color.green, color.blue); return retBuffer; } @@ -1235,9 +1243,10 @@ ConsoleMethod(GuiParticleGraphCtrl, getGraphMin, const char*, 3, 3, "(int plotID Con::errorf("Invalid plotID."); } - char *retBuffer = Con::getReturnBuffer(64); + static const U32 bufSize = 64; + char *retBuffer = Con::getReturnBuffer(bufSize); const Point2F graphMin = object->getGraphMin(plotID); - dSprintf(retBuffer, 64, "%f %f", graphMin.x, graphMin.y); + dSprintf(retBuffer, bufSize, "%f %f", graphMin.x, graphMin.y); return retBuffer; } @@ -1252,9 +1261,10 @@ ConsoleMethod(GuiParticleGraphCtrl, getGraphMax, const char*, 3, 3, "(int plotID Con::errorf("Invalid plotID."); } - char *retBuffer = Con::getReturnBuffer(64); + static const U32 bufSize = 64; + char *retBuffer = Con::getReturnBuffer(bufSize); const Point2F graphMax = object->getGraphMax(plotID); - dSprintf(retBuffer, 64, "%f %f", graphMax.x, graphMax.y); + dSprintf(retBuffer, bufSize, "%f %f", graphMax.x, graphMax.y); return retBuffer; } @@ -1269,9 +1279,10 @@ ConsoleMethod(GuiParticleGraphCtrl, getGraphName, const char*, 3, 3, "(int plotI Con::errorf("Invalid plotID."); } - char *retBuffer = Con::getReturnBuffer(64); + static const U32 bufSize = 64; + char *retBuffer = Con::getReturnBuffer(bufSize); const StringTableEntry graphName = object->getGraphName(plotID); - dSprintf(retBuffer, 64, "%s", graphName); + dSprintf(retBuffer, bufSize, "%s", graphName); return retBuffer; } diff --git a/Engine/source/gui/editor/guiShapeEdPreview.cpp b/Engine/source/gui/editor/guiShapeEdPreview.cpp index 128266f6d..098ff38f3 100644 --- a/Engine/source/gui/editor/guiShapeEdPreview.cpp +++ b/Engine/source/gui/editor/guiShapeEdPreview.cpp @@ -42,7 +42,7 @@ static const F32 sMoveScaler = 50.0f; static const F32 sZoomScaler = 200.0f; -static const int sNodeRectSize = 16; +static const S32 sNodeRectSize = 16; IMPLEMENT_CONOBJECT( GuiShapeEdPreview ); diff --git a/Engine/source/gui/editor/inspector/dynamicGroup.cpp b/Engine/source/gui/editor/inspector/dynamicGroup.cpp index 9f2285cfb..1e9d19caf 100644 --- a/Engine/source/gui/editor/inspector/dynamicGroup.cpp +++ b/Engine/source/gui/editor/inspector/dynamicGroup.cpp @@ -98,6 +98,9 @@ static S32 QSORT_CALLBACK compareEntries(const void* a,const void* b) //----------------------------------------------------------------------------- bool GuiInspectorDynamicGroup::inspectGroup() { + if( !mParent ) + return false; + // clear the first responder if it's set mStack->clearFirstResponder(); diff --git a/Engine/source/gui/editor/inspector/field.cpp b/Engine/source/gui/editor/inspector/field.cpp index 64b434abc..5dd9e6c25 100644 --- a/Engine/source/gui/editor/inspector/field.cpp +++ b/Engine/source/gui/editor/inspector/field.cpp @@ -58,7 +58,7 @@ GuiInspectorField::GuiInspectorField( GuiInspector* inspector, setCanSave( false ); setBounds(0,0,100,18); - if( field ) + if( field != NULL ) _setFieldDocs( field->pFieldDocs ); } @@ -378,8 +378,9 @@ void GuiInspectorField::setInspectorField( AbstractClassRep::Field *field, Strin mCaption = getFieldName(); else mCaption = caption; - - _setFieldDocs( mField->pFieldDocs ); + + if ( mField != NULL ) + _setFieldDocs( mField->pFieldDocs ); } //----------------------------------------------------------------------------- @@ -454,7 +455,7 @@ void GuiInspectorField::setInspectorProfile() { GuiControlProfile *profile = NULL; - if( mInspector->getNumInspectObjects() > 1 ) + if( mInspector && (mInspector->getNumInspectObjects() > 1) ) { if( !hasSameValueInAllObjects() ) Sim::findObject( "GuiInspectorMultiFieldDifferentProfile", profile ); diff --git a/Engine/source/gui/editor/inspector/group.cpp b/Engine/source/gui/editor/inspector/group.cpp index 7a52e7ca3..b272032ff 100644 --- a/Engine/source/gui/editor/inspector/group.cpp +++ b/Engine/source/gui/editor/inspector/group.cpp @@ -230,7 +230,7 @@ void GuiInspectorGroup::clearFields() bool GuiInspectorGroup::inspectGroup() { // We can't inspect a group without a target! - if( !mParent->getNumInspectObjects() ) + if( !mParent || !mParent->getNumInspectObjects() ) return false; // to prevent crazy resizing, we'll just freeze our stack for a sec.. diff --git a/Engine/source/gui/editor/inspector/variableField.cpp b/Engine/source/gui/editor/inspector/variableField.cpp index 810ba45a7..f773722e0 100644 --- a/Engine/source/gui/editor/inspector/variableField.cpp +++ b/Engine/source/gui/editor/inspector/variableField.cpp @@ -50,6 +50,12 @@ GuiInspectorVariableField::~GuiInspectorVariableField() bool GuiInspectorVariableField::onAdd() { + if( !mInspector ) + { + Con::errorf("GuiInspectorVariableField::onAdd - Fail - No inspector"); + return false; + } + setInspectorProfile(); // Hack: skip our immediate parent diff --git a/Engine/source/gui/game/guiIdleCamFadeBitmapCtrl.cpp b/Engine/source/gui/game/guiIdleCamFadeBitmapCtrl.cpp index 641f629cb..d648a4177 100644 --- a/Engine/source/gui/game/guiIdleCamFadeBitmapCtrl.cpp +++ b/Engine/source/gui/game/guiIdleCamFadeBitmapCtrl.cpp @@ -123,13 +123,13 @@ public: GFXTextureObject* texture = mTextureObject; RectI srcRegion; RectI dstRegion; - float xdone = ((float)getExtent().x/(float)texture->mBitmapSize.x)+1; - float ydone = ((float)getExtent().y/(float)texture->mBitmapSize.y)+1; + F32 xdone = ((F32)getExtent().x/(F32)texture->mBitmapSize.x)+1; + F32 ydone = ((F32)getExtent().y/(F32)texture->mBitmapSize.y)+1; - int xshift = mStartPoint.x%texture->mBitmapSize.x; - int yshift = mStartPoint.y%texture->mBitmapSize.y; - for(int y = 0; y < ydone; ++y) - for(int x = 0; x < xdone; ++x) + S32 xshift = mStartPoint.x%texture->mBitmapSize.x; + S32 yshift = mStartPoint.y%texture->mBitmapSize.y; + for(S32 y = 0; y < ydone; ++y) + for(S32 x = 0; x < xdone; ++x) { srcRegion.set(0,0,texture->mBitmapSize.x,texture->mBitmapSize.y); dstRegion.set( ((texture->mBitmapSize.x*x)+offset.x)-xshift, diff --git a/Engine/source/gui/game/guiProgressBitmapCtrl.cpp b/Engine/source/gui/game/guiProgressBitmapCtrl.cpp index bbdf20316..241270fd2 100644 --- a/Engine/source/gui/game/guiProgressBitmapCtrl.cpp +++ b/Engine/source/gui/game/guiProgressBitmapCtrl.cpp @@ -158,8 +158,9 @@ void GuiProgressBitmapCtrl::setBitmap( const char* name ) const char* GuiProgressBitmapCtrl::getScriptValue() { - char * ret = Con::getReturnBuffer(64); - dSprintf(ret, 64, "%g", mProgress); + static const U32 bufSize = 64; + char * ret = Con::getReturnBuffer(bufSize); + dSprintf(ret, bufSize, "%g", mProgress); return ret; } diff --git a/Engine/source/gui/game/guiProgressCtrl.cpp b/Engine/source/gui/game/guiProgressCtrl.cpp index 9b3901f84..06fee2502 100644 --- a/Engine/source/gui/game/guiProgressCtrl.cpp +++ b/Engine/source/gui/game/guiProgressCtrl.cpp @@ -59,8 +59,9 @@ GuiProgressCtrl::GuiProgressCtrl() const char* GuiProgressCtrl::getScriptValue() { - char * ret = Con::getReturnBuffer(64); - dSprintf(ret, 64, "%g", mProgress); + static const U32 bufSize = 64; + char * ret = Con::getReturnBuffer(bufSize); + dSprintf(ret, bufSize, "%g", mProgress); return ret; } diff --git a/Engine/source/gui/worldEditor/editTSCtrl.cpp b/Engine/source/gui/worldEditor/editTSCtrl.cpp index 123362123..7781525c6 100644 --- a/Engine/source/gui/worldEditor/editTSCtrl.cpp +++ b/Engine/source/gui/worldEditor/editTSCtrl.cpp @@ -1298,7 +1298,7 @@ DefineEngineMethod( EditTSCtrl, renderCircle, void, ( Point3F pos, Point3F norma PrimBuild::begin( GFXLineStrip, points.size() + 1 ); - for( int i = 0; i < points.size(); i++ ) + for( S32 i = 0; i < points.size(); i++ ) PrimBuild::vertex3fv( points[i] ); // GFX does not have a LineLoop primitive, so connect the last line @@ -1321,7 +1321,7 @@ DefineEngineMethod( EditTSCtrl, renderCircle, void, ( Point3F pos, Point3F norma PrimBuild::vertex3fv( pos ); // Edge verts - for( int i = 0; i < points.size(); i++ ) + for( S32 i = 0; i < points.size(); i++ ) PrimBuild::vertex3fv( points[i] ); PrimBuild::vertex3fv( points[0] ); diff --git a/Engine/source/gui/worldEditor/guiDecalEditorCtrl.cpp b/Engine/source/gui/worldEditor/guiDecalEditorCtrl.cpp index 93192a155..532b7cbf7 100644 --- a/Engine/source/gui/worldEditor/guiDecalEditorCtrl.cpp +++ b/Engine/source/gui/worldEditor/guiDecalEditorCtrl.cpp @@ -821,12 +821,13 @@ ConsoleMethod( GuiDecalEditorCtrl, getDecalTransform, const char*, 3, 3, "getDec if( decalInstance == NULL ) return ""; - char* returnBuffer = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); returnBuffer[0] = 0; if ( decalInstance ) { - dSprintf(returnBuffer, 256, "%f %f %f %f %f %f %f", + dSprintf(returnBuffer, bufSize, "%f %f %f %f %f %f %f", decalInstance->mPosition.x, decalInstance->mPosition.y, decalInstance->mPosition.z, decalInstance->mTangent.x, decalInstance->mTangent.y, decalInstance->mTangent.z, decalInstance->mSize); diff --git a/Engine/source/gui/worldEditor/terrainEditor.cpp b/Engine/source/gui/worldEditor/terrainEditor.cpp index 3aa17e1be..69610df1a 100644 --- a/Engine/source/gui/worldEditor/terrainEditor.cpp +++ b/Engine/source/gui/worldEditor/terrainEditor.cpp @@ -2111,8 +2111,9 @@ const char* TerrainEditor::getBrushPos() AssertFatal(mMouseBrush!=NULL, "TerrainEditor::getBrushPos: no mouse brush!"); Point2I pos = mMouseBrush->getPosition(); - char * ret = Con::getReturnBuffer(32); - dSprintf(ret, 32, "%d %d", pos.x, pos.y); + static const U32 bufSize = 32; + char * ret = Con::getReturnBuffer(bufSize); + dSprintf(ret, bufSize, "%d %d", pos.x, pos.y); return(ret); } @@ -2521,8 +2522,9 @@ ConsoleMethod( TerrainEditor, getBrushSize, const char*, 2, 2, "()") { Point2I size = object->getBrushSize(); - char * ret = Con::getReturnBuffer(32); - dSprintf(ret, 32, "%d %d", size.x, size.y); + static const U32 bufSize = 32; + char * ret = Con::getReturnBuffer(bufSize); + dSprintf(ret, bufSize, "%d %d", size.x, size.y); return ret; } @@ -2868,7 +2870,7 @@ ConsoleMethod( TerrainEditor, setSlopeLimitMaxAngle, F32, 3, 3, 0) } //------------------------------------------------------------------------------ -void TerrainEditor::autoMaterialLayer( F32 mMinHeight, F32 mMaxHeight, F32 mMinSlope, F32 mMaxSlope ) +void TerrainEditor::autoMaterialLayer( F32 mMinHeight, F32 mMaxHeight, F32 mMinSlope, F32 mMaxSlope, F32 mCoverage ) { if (!mActiveTerrain) return; @@ -2894,6 +2896,9 @@ void TerrainEditor::autoMaterialLayer( F32 mMinHeight, F32 mMaxHeight, F32 mMinS if (gi.mMaterial == mat) continue; + + if (mRandI(0, 100) > mCoverage) + continue; Point3F wp; gridToWorld(gp, wp); @@ -2933,7 +2938,7 @@ void TerrainEditor::autoMaterialLayer( F32 mMinHeight, F32 mMaxHeight, F32 mMinS scheduleMaterialUpdate(); } -ConsoleMethod( TerrainEditor, autoMaterialLayer, void, 6, 6, "(float minHeight, float maxHeight, float minSlope, float maxSlope)") +ConsoleMethod( TerrainEditor, autoMaterialLayer, void, 7, 7, "(float minHeight, float maxHeight, float minSlope, float maxSlope, float coverage)") { - object->autoMaterialLayer( dAtof(argv[2]), dAtof(argv[3]), dAtof(argv[4]), dAtof(argv[5]) ); + object->autoMaterialLayer( dAtof(argv[2]), dAtof(argv[3]), dAtof(argv[4]), dAtof(argv[5]), dAtof(argv[6])); } diff --git a/Engine/source/gui/worldEditor/terrainEditor.h b/Engine/source/gui/worldEditor/terrainEditor.h index f0d03daf3..1b5d7cc15 100644 --- a/Engine/source/gui/worldEditor/terrainEditor.h +++ b/Engine/source/gui/worldEditor/terrainEditor.h @@ -230,7 +230,7 @@ class TerrainEditor : public EditTSCtrl void submitMaterialUndo( String actionName ); void onMaterialUndo( TerrainBlock *terr ); - void autoMaterialLayer( F32 mMinHeight, F32 mMaxHeight, F32 mMinSlope, F32 mMaxSlope ); + void autoMaterialLayer( F32 mMinHeight, F32 mMaxHeight, F32 mMinSlope, F32 mMaxSlope, F32 mCoverage ); private: diff --git a/Engine/source/gui/worldEditor/worldEditor.cpp b/Engine/source/gui/worldEditor/worldEditor.cpp index 338bb3c63..a51ff596a 100644 --- a/Engine/source/gui/worldEditor/worldEditor.cpp +++ b/Engine/source/gui/worldEditor/worldEditor.cpp @@ -2882,8 +2882,9 @@ const Point3F& WorldEditor::getSelectionCentroid() const char* WorldEditor::getSelectionCentroidText() { const Point3F & centroid = getSelectionCentroid(); - char * ret = Con::getReturnBuffer(100); - dSprintf(ret, 100, "%g %g %g", centroid.x, centroid.y, centroid.z); + static const U32 bufSize = 100; + char * ret = Con::getReturnBuffer(bufSize); + dSprintf(ret, bufSize, "%g %g %g", centroid.x, centroid.y, centroid.z); return ret; } @@ -3263,8 +3264,9 @@ ConsoleMethod( WorldEditor, getSelectionCentroid, const char *, 2, 2, "") ConsoleMethod( WorldEditor, getSelectionExtent, const char *, 2, 2, "") { Point3F bounds = object->getSelectionExtent(); - char * ret = Con::getReturnBuffer(100); - dSprintf(ret, 100, "%g %g %g", bounds.x, bounds.y, bounds.z); + static const U32 bufSize = 100; + char * ret = Con::getReturnBuffer(bufSize); + dSprintf(ret, bufSize, "%g %g %g", bounds.x, bounds.y, bounds.z); return ret; } diff --git a/Engine/source/gui/worldEditor/worldEditorSelection.cpp b/Engine/source/gui/worldEditor/worldEditorSelection.cpp index ed2e1f5a3..41f82122f 100644 --- a/Engine/source/gui/worldEditor/worldEditorSelection.cpp +++ b/Engine/source/gui/worldEditor/worldEditorSelection.cpp @@ -642,10 +642,11 @@ ConsoleMethod( WorldEditorSelection, containsGlobalBounds, bool, 2, 2, "() - Tru ConsoleMethod( WorldEditorSelection, getCentroid, const char*, 2, 2, "() - Return the median of all object positions in the selection." ) { - char* buffer = Con::getReturnBuffer( 256 ); + static const U32 bufSize = 256; + char* buffer = Con::getReturnBuffer( bufSize ); const Point3F& centroid = object->getCentroid(); - dSprintf( buffer, 256, "%g %g %g", centroid.x, centroid.y, centroid.z ); + dSprintf( buffer, bufSize, "%g %g %g", centroid.x, centroid.y, centroid.z ); return buffer; } @@ -653,10 +654,11 @@ ConsoleMethod( WorldEditorSelection, getCentroid, const char*, 2, 2, "() - Retur ConsoleMethod( WorldEditorSelection, getBoxCentroid, const char*, 2, 2, "() - Return the center of the bounding box around the selection." ) { - char* buffer = Con::getReturnBuffer( 256 ); + static const U32 bufSize = 256; + char* buffer = Con::getReturnBuffer( bufSize ); const Point3F& boxCentroid = object->getBoxCentroid(); - dSprintf( buffer, 256, "%g %g %g", boxCentroid.x, boxCentroid.y, boxCentroid.z ); + dSprintf( buffer, bufSize, "%g %g %g", boxCentroid.x, boxCentroid.y, boxCentroid.z ); return buffer; } diff --git a/Engine/source/lighting/advanced/advancedLightBinManager.cpp b/Engine/source/lighting/advanced/advancedLightBinManager.cpp index d8620e856..c90d18bac 100644 --- a/Engine/source/lighting/advanced/advancedLightBinManager.cpp +++ b/Engine/source/lighting/advanced/advancedLightBinManager.cpp @@ -243,7 +243,7 @@ void AdvancedLightBinManager::render( SceneRenderState *state ) return; // Get the sunlight. If there's no sun, and no lights in the bins, no draw - LightInfo *sunLight = mLightManager->getSpecialLight( LightManager::slSunLightType ); + LightInfo *sunLight = mLightManager->getSpecialLight( LightManager::slSunLightType, false ); if( !sunLight && mLightBin.empty() ) return; diff --git a/Engine/source/lighting/advanced/advancedLightManager.cpp b/Engine/source/lighting/advanced/advancedLightManager.cpp index 9a911acfb..96a4b926c 100644 --- a/Engine/source/lighting/advanced/advancedLightManager.cpp +++ b/Engine/source/lighting/advanced/advancedLightManager.cpp @@ -606,7 +606,7 @@ GFXVertexBufferHandle AdvancedLightManager::g mConeIndices.lock( &idx ); // Build the cone U32 idxIdx = 0; - for( int i = 1; i < numPoints + 1; i++ ) + for( U32 i = 1; i < numPoints + 1; i++ ) { idx[idxIdx++] = 0; // Triangles on cone start at top point idx[idxIdx++] = i; @@ -614,7 +614,7 @@ GFXVertexBufferHandle AdvancedLightManager::g } // Build the bottom of the cone (reverse winding order) - for( int i = 1; i < numPoints - 1; i++ ) + for( U32 i = 1; i < numPoints - 1; i++ ) { idx[idxIdx++] = 1; idx[idxIdx++] = i + 2; @@ -664,8 +664,9 @@ ConsoleFunction( setShadowVizLight, const char*, 2, 2, "" ) const Point3I &size = texObject->getSize(); F32 aspect = (F32)size.x / (F32)size.y; - char *result = Con::getReturnBuffer( 64 ); - dSprintf( result, 64, "%d %d %g", size.x, size.y, aspect ); + static const U32 bufSize = 64; + char *result = Con::getReturnBuffer( bufSize ); + dSprintf( result, bufSize, "%d %d %g", size.x, size.y, aspect ); return result; } diff --git a/Engine/source/lighting/advanced/advancedLightingFeatures.cpp b/Engine/source/lighting/advanced/advancedLightingFeatures.cpp index fb61494b5..32deccc55 100644 --- a/Engine/source/lighting/advanced/advancedLightingFeatures.cpp +++ b/Engine/source/lighting/advanced/advancedLightingFeatures.cpp @@ -55,7 +55,7 @@ void AdvancedLightingFeatures::registerFeatures( const GFXFormat &prepassTargetF if(GFX->getAdapterType() == OpenGL) { #if defined( TORQUE_OS_MAC ) || defined( TORQUE_OS_LINUX ) - cond = new GBufferConditionerGLSL( prepassTargetFormat ); + cond = new GBufferConditionerGLSL( prepassTargetFormat, GBufferConditionerGLSL::ViewSpace ); FEATUREMGR->registerFeature(MFT_PrePassConditioner, cond); FEATUREMGR->registerFeature(MFT_RTLighting, new DeferredRTLightingFeatGLSL()); FEATUREMGR->registerFeature(MFT_NormalMap, new DeferredBumpFeatGLSL()); diff --git a/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp b/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp index 1da348f03..c5f85234a 100644 --- a/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp +++ b/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp @@ -35,16 +35,12 @@ void DeferredRTLightingFeatGLSL::processPixMacros( Vector ¯os, const MaterialFeatureData &fd ) { - /// TODO: This needs to be done via some sort of material - /// feature and not just allow all translucent elements to - /// read from the light prepass. - /* - if ( fd.features[MFT_IsTranslucent] ) + // Skip deferred features, and use forward shading instead + if ( fd.features[MFT_ForwardShading] ) { Parent::processPixMacros( macros, fd ); return; } - */ // Pull in the uncondition method for the light info buffer NamedTexTarget *texTarget = NamedTexTarget::find( AdvancedLightBinManager::smBufferName ); @@ -59,48 +55,42 @@ void DeferredRTLightingFeatGLSL::processPixMacros( Vector ¯o void DeferredRTLightingFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - /// TODO: This needs to be done via some sort of material - /// feature and not just allow all translucent elements to - /// read from the light prepass. - /* - if ( fd.features[MFT_IsTranslucent] ) + // Skip deferred features, and use forward shading instead + if ( fd.features[MFT_ForwardShading] ) { Parent::processVert( componentList, fd ); return; } - */ // Pass screen space position to pixel shader to compute a full screen buffer uv ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *ssPos = connectComp->getElement( RT_TEXCOORD ); ssPos->setName( "screenspacePos" ); + ssPos->setStructName( "OUT" ); ssPos->setType( "vec4" ); -// Var *outPosition = (Var*) LangElement::find( "hpos" ); -// AssertFatal( outPosition, "No hpos, ohnoes." ); + Var *outPosition = (Var*) LangElement::find( "gl_Position" ); + AssertFatal( outPosition, "No gl_Position, ohnoes." ); - output = new GenOp( " @ = gl_Position;\r\n", ssPos ); + output = new GenOp( " @ = @;\r\n", ssPos, outPosition ); } void DeferredRTLightingFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - /// TODO: This needs to be done via some sort of material - /// feature and not just allow all translucent elements to - /// read from the light prepass. - /* - if ( fd.features[MFT_IsTranslucent] ) + // Skip deferred features, and use forward shading instead + if ( fd.features[MFT_ForwardShading] ) { Parent::processPix( componentList, fd ); return; } - */ MultiLine *meta = new MultiLine; ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *ssPos = connectComp->getElement( RT_TEXCOORD ); ssPos->setName( "screenspacePos" ); + ssPos->setStructName( "IN" ); ssPos->setType( "vec4" ); Var *uvScene = new Var; @@ -108,18 +98,20 @@ void DeferredRTLightingFeatGLSL::processPix( Vector &component uvScene->setName( "uvScene" ); LangElement *uvSceneDecl = new DecOp( uvScene ); - Var *rtParams = (Var*) LangElement::find( "renderTargetParams" ); + String rtParamName = String::ToString( "rtParams%s", "lightInfoBuffer" ); + Var *rtParams = (Var*) LangElement::find( rtParamName ); if( !rtParams ) { rtParams = new Var; rtParams->setType( "vec4" ); - rtParams->setName( "renderTargetParams" ); + rtParams->setName( rtParamName ); rtParams->uniform = true; rtParams->constSortPos = cspPass; } meta->addStatement( new GenOp( " @ = @.xy / @.w;\r\n", uvSceneDecl, ssPos, ssPos ) ); // get the screen coord... its -1 to +1 meta->addStatement( new GenOp( " @ = ( @ + 1.0 ) / 2.0;\r\n", uvScene, uvScene ) ); // get the screen coord to 0 to 1 + meta->addStatement( new GenOp( " @.y = 1.0 - @.y;\r\n", uvScene, uvScene ) ); // flip the y axis meta->addStatement( new GenOp( " @ = ( @ * @.zw ) + @.xy;\r\n", uvScene, uvScene, rtParams, rtParams) ); // scale it down and offset it to the rt size Var *lightInfoSamp = new Var; @@ -134,36 +126,60 @@ void DeferredRTLightingFeatGLSL::processPix( Vector &component lightInfoBuffer->sampler = true; lightInfoBuffer->constNum = Var::getTexUnitNum(); // used as texture unit num here - String unconditionLightInfo = String::ToLower( AdvancedLightBinManager::smBufferName ) + "Uncondition"; - - meta->addStatement( new GenOp( " vec3 d_lightcolor;\r\n" ) ); - meta->addStatement( new GenOp( " float d_NL_Att;\r\n" ) ); - meta->addStatement( new GenOp( " float d_specular;\r\n" ) ); - meta->addStatement( new GenOp( avar( " %s(texture2D(@, @), d_lightcolor, d_NL_Att, d_specular);\r\n", unconditionLightInfo.c_str() ), - lightInfoBuffer, uvScene ) ); + // Declare the RTLighting variables in this feature, they will either be assigned + // in this feature, or in the tonemap/lightmap feature + Var *d_lightcolor = new Var( "d_lightcolor", "vec3" ); + meta->addStatement( new GenOp( " @;\r\n", new DecOp( d_lightcolor ) ) ); - Var *rtShading = new Var; - rtShading->setType( "vec4" ); - rtShading->setName( "rtShading" ); - LangElement *rtShadingDecl = new DecOp( rtShading ); - meta->addStatement( new GenOp( " @ = vec4( d_lightcolor, 1.0 );\r\n", rtShadingDecl ) ); + Var *d_NL_Att = new Var( "d_NL_Att", "float" ); + meta->addStatement( new GenOp( " @;\r\n", new DecOp( d_NL_Att ) ) ); + + Var *d_specular = new Var( "d_specular", "float" ); + meta->addStatement( new GenOp( " @;\r\n", new DecOp( d_specular ) ) ); + + + // Perform the uncondition here. + String unconditionLightInfo = String::ToLower( AdvancedLightBinManager::smBufferName ) + "Uncondition"; + meta->addStatement( new GenOp( avar( " %s(tex2D(@, @), @, @, @);\r\n", + unconditionLightInfo.c_str() ), lightInfoBuffer, uvScene, d_lightcolor, d_NL_Att, d_specular ) ); + + // If this has an interlaced pre-pass, do averaging here + if( fd.features[MFT_InterlacedPrePass] ) + { + Var *oneOverTargetSize = (Var*) LangElement::find( "oneOverTargetSize" ); + if( !oneOverTargetSize ) + { + oneOverTargetSize = new Var; + oneOverTargetSize->setType( "vec2" ); + oneOverTargetSize->setName( "oneOverTargetSize" ); + oneOverTargetSize->uniform = true; + oneOverTargetSize->constSortPos = cspPass; + } + + meta->addStatement( new GenOp( " float id_NL_Att, id_specular;\r\n float3 id_lightcolor;\r\n" ) ); + meta->addStatement( new GenOp( avar( " %s(tex2D(@, @ + float2(0.0, @.y)), id_lightcolor, id_NL_Att, id_specular);\r\n", + unconditionLightInfo.c_str() ), lightInfoBuffer, uvScene, oneOverTargetSize ) ); + + meta->addStatement( new GenOp(" @ = lerp(@, id_lightcolor, 0.5);\r\n", d_lightcolor, d_lightcolor ) ); + meta->addStatement( new GenOp(" @ = lerp(@, id_NL_Att, 0.5);\r\n", d_NL_Att, d_NL_Att ) ); + meta->addStatement( new GenOp(" @ = lerp(@, id_specular, 0.5);\r\n", d_specular, d_specular ) ); + } // This is kind of weak sauce - if( !fd.features[MFT_SubSurface] && !fd.features[MFT_ToneMap] && !fd.features[MFT_LightMap] ) - meta->addStatement( new GenOp( " @;\r\n", assignColor( rtShading, Material::Mul ) ) ); + if( !fd.features[MFT_VertLit] && !fd.features[MFT_ToneMap] && !fd.features[MFT_LightMap] && !fd.features[MFT_SubSurface] ) + meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(@, 1.0)", d_lightcolor ), Material::Mul ) ) ); output = meta; } ShaderFeature::Resources DeferredRTLightingFeatGLSL::getResources( const MaterialFeatureData &fd ) { - /// TODO: This needs to be done via some sort of material - /// feature and not just allow all translucent elements to - /// read from the light prepass. - /* - if( fd.features[MFT_IsTranslucent] ) + // Skip deferred features, and use forward shading instead + if ( fd.features[MFT_ForwardShading] ) return Parent::getResources( fd ); - */ + + // HACK: See DeferredRTLightingFeatGLSL::setTexData. + mLastTexIndex = 0; Resources res; res.numTex = 1; @@ -176,21 +192,22 @@ void DeferredRTLightingFeatGLSL::setTexData( Material::StageData &stageDat, RenderPassData &passData, U32 &texIndex ) { - /// TODO: This needs to be done via some sort of material - /// feature and not just allow all translucent elements to - /// read from the light prepass. - /* - if( fd.features[MFT_IsTranslucent] ) + // Skip deferred features, and use forward shading instead + if ( fd.features[MFT_ForwardShading] ) { Parent::setTexData( stageDat, fd, passData, texIndex ); return; } - */ NamedTexTarget *texTarget = NamedTexTarget::find( AdvancedLightBinManager::smBufferName ); if( texTarget ) { - passData.mTexType[ texIndex ] = Material::TexTarget; + // HACK: We store this for use in DeferredRTLightingFeatGLSL::processPix() + // which cannot deduce the texture unit itself. + mLastTexIndex = texIndex; + + passData.mTexType[ texIndex ] = Material::TexTarget; + passData.mSamplerNames[ texIndex ]= "lightInfoBuffer"; passData.mTexSlot[ texIndex++ ].texTarget = texTarget; } } @@ -205,92 +222,31 @@ void DeferredBumpFeatGLSL::processVert( Vector &componentLis // to the pixel shader. MultiLine *meta = new MultiLine; - // setup texture space matrix - Var *texSpaceMat = (Var*) LangElement::find( "objToTangentSpace" ); - if( !texSpaceMat ) - { - LangElement * texSpaceSetup = setupTexSpaceMat( componentList, &texSpaceMat ); - meta->addStatement( texSpaceSetup ); - texSpaceMat = (Var*) LangElement::find( "objToTangentSpace" ); - } - - // turn obj->tangent into world->tangent - Var *worldToTangent = new Var; - worldToTangent->setType( "mat3" ); - worldToTangent->setName( "worldToTangent" ); - LangElement *worldToTangentDecl = new DecOp( worldToTangent ); - - // Get the world->obj transform - Var *worldToObj = new Var; - worldToObj->setType( "mat4" ); - worldToObj->setName( "worldToObj" ); - worldToObj->uniform = true; - worldToObj->constSortPos = cspPrimitive; - - Var *mat3Conversion = new Var; - mat3Conversion->setType( "mat3" ); - mat3Conversion->setName( "worldToObjMat3" ); - LangElement* mat3Lang = new DecOp(mat3Conversion); - meta->addStatement( new GenOp( " @ = mat3(@[0].xyz, @[1].xyz, @[2].xyz);\r\n ", mat3Lang, worldToObj, worldToObj, worldToObj) ); - - // assign world->tangent transform - meta->addStatement( new GenOp( " @ = @ * @;\r\n", worldToTangentDecl, texSpaceMat, mat3Conversion ) ); - - // send transform to pixel shader - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - - Var *worldToTangentR1 = connectComp->getElement( RT_TEXCOORD ); - worldToTangentR1->setName( "worldToTangentR1" ); - worldToTangentR1->setType( "vec3" ); - meta->addStatement( new GenOp( " @ = @[0];\r\n", worldToTangentR1, worldToTangent ) ); - - Var *worldToTangentR2 = connectComp->getElement( RT_TEXCOORD ); - worldToTangentR2->setName( "worldToTangentR2" ); - worldToTangentR2->setType( "vec3" ); - meta->addStatement( new GenOp( " @ = @[1];\r\n", worldToTangentR2, worldToTangent ) ); - - Var *worldToTangentR3 = connectComp->getElement( RT_TEXCOORD ); - worldToTangentR3->setName( "worldToTangentR3" ); - worldToTangentR3->setType( "vec3" ); - meta->addStatement( new GenOp( " @ = @[2];\r\n", worldToTangentR3, worldToTangent ) ); + // We need the view to tangent space transform in the pixel shader. + getOutViewToTangent( componentList, meta, fd ); // Make sure there are texcoords - if( !fd.features[MFT_DiffuseMap] ) + if( !fd.features[MFT_Parallax] && !fd.features[MFT_DiffuseMap] ) { - // find incoming texture var - Var *inTex = getVertTexCoord( "texCoord" ); + const bool useTexAnim = fd.features[MFT_TexAnim]; - // grab connector texcoord register - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - Var *outTex = connectComp->getElement( RT_TEXCOORD ); - outTex->setName( "outTexCoord" ); - outTex->setType( "vec2" ); - outTex->mapsToSampler = true; + getOutTexCoord( "texCoord", + "vec2", + true, + useTexAnim, + meta, + componentList ); - if( fd.features[MFT_TexAnim] ) - { - inTex->setType( "vec4" ); - - // create texture mat var - Var *texMat = new Var; - texMat->setType( "mat4" ); - texMat->setName( "texMat" ); - texMat->uniform = true; - texMat->constSortPos = cspPotentialPrimitive; - - meta->addStatement( new GenOp( " @ = @ * @;\r\n", outTex, texMat, inTex ) ); - } - else - { - // setup language elements to output incoming tex coords to output - meta->addStatement( new GenOp( " @ = @;\r\n", outTex, inTex ) ); - } + if ( fd.features.hasFeature( MFT_DetailNormalMap ) ) + addOutDetailTexCoord( componentList, + meta, + useTexAnim ); } output = meta; } else if ( fd.materialFeatures[MFT_NormalsOut] || - fd.features[MFT_IsTranslucent] || + fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { Parent::processVert( componentList, fd ); @@ -312,52 +268,12 @@ void DeferredBumpFeatGLSL::processPix( Vector &componentList, { MultiLine *meta = new MultiLine; - // Pull the world->tangent transform from the vertex shader - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - - Var *worldToTangentR1 = connectComp->getElement( RT_TEXCOORD ); - worldToTangentR1->setName( "worldToTangentR1" ); - worldToTangentR1->setType( "vec3" ); - - Var *worldToTangentR2 = connectComp->getElement( RT_TEXCOORD ); - worldToTangentR2->setName( "worldToTangentR2" ); - worldToTangentR2->setType( "vec3" ); - - Var *worldToTangentR3 = connectComp->getElement( RT_TEXCOORD ); - worldToTangentR3->setName( "worldToTangentR3" ); - worldToTangentR3->setType( "vec3" ); - - Var *worldToTangent = new Var; - worldToTangent->setType( "mat3" ); - worldToTangent->setName( "worldToTangent" ); - LangElement *worldToTangentDecl = new DecOp( worldToTangent ); - - // Build world->tangent matrix - meta->addStatement( new GenOp( " @;\r\n", worldToTangentDecl ) ); - meta->addStatement( new GenOp( " @[0] = @;\r\n", worldToTangent, worldToTangentR1 ) ); - meta->addStatement( new GenOp( " @[1] = @;\r\n", worldToTangent, worldToTangentR2 ) ); - meta->addStatement( new GenOp( " @[2] = @;\r\n", worldToTangent, worldToTangentR3 ) ); + Var *viewToTangent = getInViewToTangent( componentList ); // create texture var - Var *bumpMap = new Var; - bumpMap->setType( "sampler2D" ); - bumpMap->setName( "bumpMap" ); - bumpMap->uniform = true; - bumpMap->sampler = true; - bumpMap->constNum = Var::getTexUnitNum(); // used as texture unit num here - - Var *texCoord = (Var*) LangElement::find( "outTexCoord" ); - if( !texCoord ) - { - // grab connector texcoord register - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - texCoord = connectComp->getElement( RT_TEXCOORD ); - texCoord->setName( "outTexCoord" ); - texCoord->setType( "vec2" ); - texCoord->mapsToSampler = true; - } - - LangElement * texOp = new GenOp( "texture2D(@, @)", bumpMap, texCoord ); + Var *bumpMap = getNormalMapTex(); + Var *texCoord = getInTexCoord( "texCoord", "vec2", true, componentList ); + LangElement *texOp = new GenOp( "tex2D(@, @)", bumpMap, texCoord ); // create bump normal Var *bumpNorm = new Var; @@ -367,56 +283,75 @@ void DeferredBumpFeatGLSL::processPix( Vector &componentList, LangElement *bumpNormDecl = new DecOp( bumpNorm ); meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) ); + // If we have a detail normal map we add the xy coords of + // it to the base normal map. This gives us the effect we + // want with few instructions and minial artifacts. + if ( fd.features.hasFeature( MFT_DetailNormalMap ) ) + { + bumpMap = new Var; + bumpMap->setType( "sampler2D" ); + bumpMap->setName( "detailBumpMap" ); + bumpMap->uniform = true; + bumpMap->sampler = true; + bumpMap->constNum = Var::getTexUnitNum(); + + texCoord = getInTexCoord( "detCoord", "vec2", true, componentList ); + texOp = new GenOp( "tex2D(@, @)", bumpMap, texCoord ); + + Var *detailBump = new Var; + detailBump->setName( "detailBump" ); + detailBump->setType( "vec4" ); + meta->addStatement( expandNormalMap( texOp, new DecOp( detailBump ), detailBump, fd ) ); + + Var *detailBumpScale = new Var; + detailBumpScale->setType( "float" ); + detailBumpScale->setName( "detailBumpStrength" ); + detailBumpScale->uniform = true; + detailBumpScale->constSortPos = cspPass; + meta->addStatement( new GenOp( " @.xy += @.xy * @;\r\n", bumpNorm, detailBump, detailBumpScale ) ); + } + // This var is read from GBufferConditionerHLSL and // used in the prepass output. + // + // By using the 'half' type here we get a bunch of partial + // precision optimized code on further operations on the normal + // which helps alot on older Geforce cards. + // Var *gbNormal = new Var; gbNormal->setName( "gbNormal" ); - gbNormal->setType( "vec3" ); + gbNormal->setType( "half3" ); LangElement *gbNormalDecl = new DecOp( gbNormal ); // Normalize is done later... // Note: The reverse mul order is intentional. Affine matrix. - meta->addStatement( new GenOp( " @ = @.xyz * @;\r\n", gbNormalDecl, bumpNorm, worldToTangent ) ); + meta->addStatement( new GenOp( " @ = half3(tMul( @.xyz, @ ));\r\n", gbNormalDecl, bumpNorm, viewToTangent ) ); output = meta; return; } else if ( fd.materialFeatures[MFT_NormalsOut] || - fd.features[MFT_IsTranslucent] || + fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { Parent::processPix( componentList, fd ); return; } - else if ( fd.features[MFT_PixSpecular] ) + else if ( fd.features[MFT_PixSpecular] && !fd.features[MFT_SpecularMap] ) { Var *bumpSample = (Var *)LangElement::find( "bumpSample" ); if( bumpSample == NULL ) { - Var *texCoord = (Var*) LangElement::find( "outTexCoord" ); - if( !texCoord ) - { - // grab connector texcoord register - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - texCoord = connectComp->getElement( RT_TEXCOORD ); - texCoord->setName( "outTexCoord" ); - texCoord->setType( "vec2" ); - texCoord->mapsToSampler = true; - } + Var *texCoord = getInTexCoord( "texCoord", "vec2", true, componentList ); - Var *bumpMap = new Var; - bumpMap->setType( "sampler2D" ); - bumpMap->setName( "bumpMap" ); - bumpMap->uniform = true; - bumpMap->sampler = true; - bumpMap->constNum = Var::getTexUnitNum(); // used as texture unit num here + Var *bumpMap = getNormalMapTex(); bumpSample = new Var; bumpSample->setType( "vec4" ); bumpSample->setName( "bumpSample" ); LangElement *bumpSampleDecl = new DecOp( bumpSample ); - output = new GenOp( " @ = texture2D(@, @);\r\n", bumpSampleDecl, bumpMap, texCoord ); + output = new GenOp( " @ = tex2D(@, @);\r\n", bumpSampleDecl, bumpMap, texCoord ); return; } } @@ -427,7 +362,7 @@ void DeferredBumpFeatGLSL::processPix( Vector &componentList, ShaderFeature::Resources DeferredBumpFeatGLSL::getResources( const MaterialFeatureData &fd ) { if ( fd.materialFeatures[MFT_NormalsOut] || - fd.features[MFT_IsTranslucent] || + fd.features[MFT_ForwardShading] || fd.features[MFT_Parallax] || !fd.features[MFT_RTLighting] ) return Parent::getResources( fd ); @@ -437,7 +372,16 @@ ShaderFeature::Resources DeferredBumpFeatGLSL::getResources( const MaterialFeatu { res.numTex = 1; res.numTexReg = 1; + + if ( fd.features[MFT_PrePassConditioner] && + fd.features.hasFeature( MFT_DetailNormalMap ) ) + { + res.numTex += 1; + if ( !fd.features.hasFeature( MFT_DetailMap ) ) + res.numTexReg += 1; + } } + return res; } @@ -447,21 +391,28 @@ void DeferredBumpFeatGLSL::setTexData( Material::StageData &stageDat, U32 &texIndex ) { if ( fd.materialFeatures[MFT_NormalsOut] || - fd.features[MFT_IsTranslucent] || + fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { Parent::setTexData( stageDat, fd, passData, texIndex ); return; } - GFXTextureObject *normalMap = stageDat.getTex( MFT_NormalMap ); if ( !fd.features[MFT_Parallax] && !fd.features[MFT_SpecularMap] && ( fd.features[MFT_PrePassConditioner] || - fd.features[MFT_PixSpecular] ) && - normalMap ) + fd.features[MFT_PixSpecular] ) ) { passData.mTexType[ texIndex ] = Material::Bump; - passData.mTexSlot[ texIndex++ ].texObject = normalMap; + passData.mSamplerNames[ texIndex ] = "bumpMap"; + passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_NormalMap ); + + if ( fd.features[MFT_PrePassConditioner] && + fd.features.hasFeature( MFT_DetailNormalMap ) ) + { + passData.mTexType[ texIndex ] = Material::DetailBump; + passData.mSamplerNames[ texIndex ] = "detailBumpMap"; + passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_DetailNormalMap ); + } } } @@ -469,7 +420,7 @@ void DeferredBumpFeatGLSL::setTexData( Material::StageData &stageDat, void DeferredPixelSpecularGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] ) + if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { Parent::processVert( componentList, fd ); return; @@ -480,7 +431,7 @@ void DeferredPixelSpecularGLSL::processVert( Vector &component void DeferredPixelSpecularGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] ) + if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { Parent::processPix( componentList, fd ); return; @@ -523,19 +474,18 @@ void DeferredPixelSpecularGLSL::processPix( Vector &component specStrength->uniform = true; specStrength->constSortPos = cspPotentialPrimitive; - Var *constSpecPow = new Var; - constSpecPow->setType( "float" ); - constSpecPow->setName( "constantSpecularPower" ); - constSpecPow->uniform = true; - constSpecPow->constSortPos = cspPass; - Var *lightInfoSamp = (Var *)LangElement::find( "lightInfoSample" ); - AssertFatal( lightInfoSamp, "Something hosed the deferred features! Can't find lightInfoSample" ); + Var *d_specular = (Var*)LangElement::find( "d_specular" ); + Var *d_NL_Att = (Var*)LangElement::find( "d_NL_Att" ); + + AssertFatal( lightInfoSamp && d_specular && d_NL_Att, + "DeferredPixelSpecularGLSL::processPix - Something hosed the deferred features!" ); // (a^m)^n = a^(m*n) - meta->addStatement( new GenOp( " @ = pow(d_specular, ceil(@ / @)) * @;\r\n", specDecl, specPow, constSpecPow, specStrength ) ); + meta->addStatement( new GenOp( " @ = pow( abs(@), max((@ / AL_ConstantSpecularPower),1.0f)) * @;\r\n", + specDecl, d_specular, specPow, specStrength ) ); - LangElement *specMul = new GenOp( "@ * @", specCol, specular ); + LangElement *specMul = new GenOp( "float4( @.rgb, 0 ) * @", specCol, specular ); LangElement *final = specMul; // We we have a normal map then mask the specular @@ -545,14 +495,15 @@ void DeferredPixelSpecularGLSL::processPix( Vector &component final = new GenOp( "@ * @.a", final, bumpSample ); } - // add to color meta->addStatement( new GenOp( " @;\r\n", assignColor( final, Material::Add ) ) ); + // add to color + meta->addStatement( new GenOp( " @;\r\n", assignColor( final, Material::Add ) ) ); output = meta; } ShaderFeature::Resources DeferredPixelSpecularGLSL::getResources( const MaterialFeatureData &fd ) { - if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] ) + if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) return Parent::getResources( fd ); Resources res; @@ -563,7 +514,7 @@ ShaderFeature::Resources DeferredPixelSpecularGLSL::getResources( const Material ShaderFeature::Resources DeferredMinnaertGLSL::getResources( const MaterialFeatureData &fd ) { Resources res; - if( !fd.features[MFT_IsTranslucent] && fd.features[MFT_RTLighting] ) + if( !fd.features[MFT_ForwardShading] && fd.features[MFT_RTLighting] ) { res.numTex = 1; res.numTexReg = 1; @@ -576,7 +527,7 @@ void DeferredMinnaertGLSL::setTexData( Material::StageData &stageDat, RenderPassData &passData, U32 &texIndex ) { - if( !fd.features[MFT_IsTranslucent] && fd.features[MFT_RTLighting] ) + if( !fd.features[MFT_ForwardShading] && fd.features[MFT_RTLighting] ) { NamedTexTarget *texTarget = NamedTexTarget::find(RenderPrePassMgr::BufferName); if ( texTarget ) @@ -590,7 +541,7 @@ void DeferredMinnaertGLSL::setTexData( Material::StageData &stageDat, void DeferredMinnaertGLSL::processPixMacros( Vector ¯os, const MaterialFeatureData &fd ) { - if( !fd.features[MFT_IsTranslucent] && fd.features[MFT_RTLighting] ) + if( !fd.features[MFT_ForwardShading] && fd.features[MFT_RTLighting] ) { // Pull in the uncondition method for the g buffer NamedTexTarget *texTarget = NamedTexTarget::find( RenderPrePassMgr::BufferName ); @@ -607,55 +558,24 @@ void DeferredMinnaertGLSL::processVert( Vector &componentLis const MaterialFeatureData &fd ) { // If there is no deferred information, bail on this feature - if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] ) + if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { output = NULL; return; } - // grab incoming vert position - Var *inVertPos = (Var*) LangElement::find( "position" ); - AssertFatal( inVertPos, "Something went bad with ShaderGen. The vertex position should be already defined." ); - - // grab output for gbuffer normal - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - Var *outWSEyeVec= connectComp->getElement( RT_TEXCOORD ); - outWSEyeVec->setName( "outWSViewVec" ); - outWSEyeVec->setType( "vec4" ); - - // create objToWorld variable - Var *objToWorld = (Var*) LangElement::find( "objTrans" ); - if( !objToWorld ) - { - objToWorld = new Var; - objToWorld->setType( "mat4x4" ); - objToWorld->setName( "objTrans" ); - objToWorld->uniform = true; - objToWorld->constSortPos = cspPrimitive; - } - - // Eye Pos world - Var *eyePosWorld = (Var*) LangElement::find( "eyePosWorld" ); - if( !eyePosWorld ) - { - eyePosWorld = new Var; - eyePosWorld->setType( "vec3" ); - eyePosWorld->setName( "eyePosWorld" ); - eyePosWorld->uniform = true; - eyePosWorld->constSortPos = cspPass; - } - - // Kick out the world-space normal - LangElement *statement = new GenOp( " @ = vec4(@, @) - vec4(@, 0.0);\r\n", - outWSEyeVec, objToWorld, inVertPos, eyePosWorld ); - output = statement; + // Make sure we pass the world space position to the + // pixel shader so we can calculate a view vector. + MultiLine *meta = new MultiLine; + addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta ); + output = meta; } void DeferredMinnaertGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { // If there is no deferred information, bail on this feature - if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] ) + if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { output = NULL; return; @@ -679,25 +599,19 @@ void DeferredMinnaertGLSL::processPix( Vector &componentList, Var *uvScene = (Var*) LangElement::find( "uvScene" ); AssertFatal(uvScene != NULL, "Unable to find UVScene, no RTLighting feature?"); - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - Var *wsViewVec = (Var*) LangElement::find( "wsPos" ); - if( !wsViewVec ) - { - wsViewVec = connectComp->getElement( RT_TEXCOORD ); - wsViewVec->setName( "outWSViewVec" ); - wsViewVec->setType( "vec4" ); - wsViewVec->mapsToSampler = false; - wsViewVec->uniform = false; - } + MultiLine *meta = new MultiLine; + + // Get the world space view vector. + Var *wsViewVec = getWsView( getInWsPosition( componentList ), meta ); String unconditionPrePassMethod = String::ToLower(RenderPrePassMgr::BufferName) + "Uncondition"; - MultiLine *meta = new MultiLine; - meta->addStatement( new GenOp( avar( " vec4 normalDepth = %s(texture2D(@, @));\r\n", unconditionPrePassMethod.c_str() ), prepassBuffer, uvScene ) ); - meta->addStatement( new GenOp( " vec3 worldViewVec = normalize(@.xyz / @.w);\r\n", wsViewVec, wsViewVec ) ); - meta->addStatement( new GenOp( " float vDotN = dot(normalDepth.xyz, worldViewVec);\r\n" ) ); - meta->addStatement( new GenOp( " float Minnaert = pow(d_NL_Att, @) * pow(vDotN, 1.0 - @);\r\n", minnaertConstant, minnaertConstant ) ); - meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(Minnaert, Minnaert, Minnaert, 1.0)" ), Material::Mul ) ) ); + Var *d_NL_Att = (Var*)LangElement::find( "d_NL_Att" ); + + meta->addStatement( new GenOp( avar( " float4 normalDepth = %s(@, @);\r\n", unconditionPrePassMethod.c_str() ), prepassBuffer, uvScene ) ); + meta->addStatement( new GenOp( " float vDotN = dot(normalDepth.xyz, @);\r\n", wsViewVec ) ); + meta->addStatement( new GenOp( " float Minnaert = pow( @, @) * pow(vDotN, 1.0 - @);\r\n", d_NL_Att, minnaertConstant, minnaertConstant ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(Minnaert, Minnaert, Minnaert, 1.0)" ), Material::Mul ) ) ); output = meta; } @@ -707,7 +621,7 @@ void DeferredSubSurfaceGLSL::processPix( Vector &componentLis const MaterialFeatureData &fd ) { // If there is no deferred information, bail on this feature - if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] ) + if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) { output = NULL; return; @@ -719,12 +633,13 @@ void DeferredSubSurfaceGLSL::processPix( Vector &componentLis subSurfaceParams->uniform = true; subSurfaceParams->constSortPos = cspPotentialPrimitive; - Var *inColor = (Var*) LangElement::find( "rtShading" ); + Var *d_lightcolor = (Var*)LangElement::find( "d_lightcolor" ); + Var *d_NL_Att = (Var*)LangElement::find( "d_NL_Att" ); MultiLine *meta = new MultiLine; - meta->addStatement( new GenOp( " float subLamb = smoothstep(-@.a, 1.0, d_NL_Att) - smoothstep(0.0, 1.0, d_NL_Att);\r\n", subSurfaceParams ) ); + meta->addStatement( new GenOp( " float subLamb = smoothstep(-@.a, 1.0, @) - smoothstep(0.0, 1.0, @);\r\n", subSurfaceParams, d_NL_Att, d_NL_Att ) ); meta->addStatement( new GenOp( " subLamb = max(0.0, subLamb);\r\n" ) ); - meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(@.rgb + (subLamb * @.rgb), 1.0)", inColor, subSurfaceParams ), Material::Mul ) ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(@ + (subLamb * @.rgb), 1.0)", d_lightcolor, subSurfaceParams ), Material::Mul ) ) ); output = meta; } diff --git a/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.h b/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.h index fb37848a8..0e326de6a 100644 --- a/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.h +++ b/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.h @@ -30,13 +30,25 @@ class ConditionerMethodDependency; -/// Lights the pixel by sampling from the light prepass buffer. It will -/// fall back to default vertex lighting functionality if +/// Lights the pixel by sampling from the light prepass +/// buffer. It will fall back to forward lighting +/// functionality for non-deferred rendered surfaces. +/// +/// Also note that this feature is only used in the +/// forward rendering pass. It is not used during the +/// prepass step. +/// class DeferredRTLightingFeatGLSL : public RTLightingFeatGLSL { typedef RTLightingFeatGLSL Parent; +protected: + + /// @see DeferredRTLightingFeatHLSL::processPix() + U32 mLastTexIndex; + public: + virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); @@ -57,12 +69,12 @@ public: virtual String getName() { - return "Deferred RT Lighting Feature"; + return "Deferred RT Lighting"; } }; -/// Used to write the normals during the depth/normal prepass. +/// This is used during the class DeferredBumpFeatGLSL : public BumpFeatGLSL { typedef BumpFeatGLSL Parent; diff --git a/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.cpp b/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.cpp index fd3b27d85..17a98c969 100644 --- a/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.cpp +++ b/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.cpp @@ -27,9 +27,10 @@ #include "gfx/gfxStringEnumTranslate.h" #include "materials/materialFeatureTypes.h" #include "materials/materialFeatureData.h" +#include "shaderGen/GLSL/shaderFeatureGLSL.h" -GBufferConditionerGLSL::GBufferConditionerGLSL( const GFXFormat bufferFormat ) : +GBufferConditionerGLSL::GBufferConditionerGLSL( const GFXFormat bufferFormat, const NormalSpace nrmSpace ) : Parent( bufferFormat ) { // Figure out how we should store the normal data. These are the defaults. @@ -39,20 +40,18 @@ GBufferConditionerGLSL::GBufferConditionerGLSL( const GFXFormat bufferFormat ) : // Note: We clear to a depth 1 (the w component) so // that the unrendered parts of the scene end up // farthest to the camera. - + const NormalStorage &twoCmpNrmStorageType = ( nrmSpace == WorldSpace ? Spherical : LambertAzimuthal ); switch(bufferFormat) { case GFXFormatR8G8B8A8: - // TODO: Some kind of logic here. Spherical is better, but is more - // expensive. - mNormalStorageType = Spherical; + mNormalStorageType = twoCmpNrmStorageType; mBitsPerChannel = 8; break; case GFXFormatR16G16B16A16F: // Floating point buffers don't need to encode negative values mCanWriteNegativeValues = true; - mNormalStorageType = Spherical; + mNormalStorageType = twoCmpNrmStorageType; mBitsPerChannel = 16; break; @@ -61,7 +60,7 @@ GBufferConditionerGLSL::GBufferConditionerGLSL( const GFXFormat bufferFormat ) : // precision and high quality normals within a 64bit // buffer format. case GFXFormatR16G16B16A16: - mNormalStorageType = Spherical; + mNormalStorageType = twoCmpNrmStorageType; mBitsPerChannel = 16; break; @@ -83,34 +82,43 @@ GBufferConditionerGLSL::~GBufferConditionerGLSL() void GBufferConditionerGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - output = NULL; + // If we have a normal map then that feature will + // take care of passing gbNormal to the pixel shader. + if ( fd.features[MFT_NormalMap] ) + return; - if( !fd.features[MFT_NormalMap] ) + MultiLine *meta = new MultiLine; + output = meta; + + // grab incoming vert normal + Var *inNormal = (Var*) LangElement::find( "normal" ); + AssertFatal( inNormal, "Something went bad with ShaderGen. The normal should be already defined." ); + + // grab output for gbuffer normal + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + Var *outNormal = connectComp->getElement( RT_TEXCOORD ); + outNormal->setName( "gbNormal" ); + outNormal->setStructName( "OUT" ); + outNormal->setType( "float3" ); + + if( !fd.features[MFT_ParticleNormal] ) { - // grab incoming vert normal - Var *inNormal = (Var*) LangElement::find( "normal" ); - AssertFatal( inNormal, "Something went bad with ShaderGen. The normal should be already defined." ); + // Kick out the view-space normal - // grab output for gbuffer normal - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - Var *outNormal = connectComp->getElement( RT_TEXCOORD ); - outNormal->setName( "gbNormal" ); - outNormal->setType( "vec3" ); + // TODO: Total hack because Conditioner is directly derived + // from ShaderFeature and not from ShaderFeatureGLSL. + NamedFeatureGLSL dummy( String::EmptyString ); + dummy.mInstancingFormat = mInstancingFormat; + Var *worldViewOnly = dummy.getWorldView( componentList, fd.features[MFT_UseInstancing], meta ); - // create objToWorld variable - Var *objToWorld = (Var*) LangElement::find( "objTrans" ); - if( !objToWorld ) - { - objToWorld = new Var; - objToWorld->setType( "mat4" ); - objToWorld->setName( "objTrans" ); - objToWorld->uniform = true; - objToWorld->constSortPos = cspPrimitive; - } - - // Kick out the world-space normal - LangElement *statement = new GenOp( " @ = vec3(@ * vec4(normalize(@), 0.0));\r\n", outNormal, objToWorld, inNormal ); - output = statement; + meta->addStatement( new GenOp(" @ = tMul(@, float4( normalize(@), 0.0 ) ).xyz;\r\n", + outNormal, worldViewOnly, inNormal ) ); + } + else + { + // Assume the particle normal generator has already put this in view space + // and normalized it + meta->addStatement( new GenOp( " @ = @;\r\n", outNormal, inNormal ) ); } } @@ -129,7 +137,8 @@ void GBufferConditionerGLSL::processPix( Vector &componentLis { gbNormal = connectComp->getElement( RT_TEXCOORD ); gbNormal->setName( "gbNormal" ); - gbNormal->setType( "vec3" ); + gbNormal->setStructName( "IN" ); + gbNormal->setType( "float3" ); gbNormal->mapsToSampler = false; gbNormal->uniform = false; } @@ -143,16 +152,45 @@ void GBufferConditionerGLSL::processPix( Vector &componentLis Var *unconditionedOut = new Var; - unconditionedOut->setType("vec4"); + unconditionedOut->setType("float4"); unconditionedOut->setName("normal_depth"); LangElement *outputDecl = new DecOp( unconditionedOut ); + // If we're doing prepass blending then we need + // to steal away the alpha channel before the + // conditioner stomps on it. + Var *alphaVal = NULL; + if ( fd.features[ MFT_IsTranslucentZWrite ] ) + { + alphaVal = new Var( "outAlpha", "float" ); + meta->addStatement( new GenOp( " @ = col.a; // MFT_IsTranslucentZWrite\r\n", new DecOp( alphaVal ) ) ); + } + + // If using interlaced normals, invert the normal + if(fd.features[MFT_InterlacedPrePass]) + { + // NOTE: Its safe to not call ShaderFeatureGLSL::addOutVpos() in the vertex + // shader as for SM 3.0 nothing is needed there. + Var *Vpos = (Var*) LangElement::find( "gl_Position" ); //Var *Vpos = ShaderFeatureGLSL::getInVpos( meta, componentList ); + + Var *iGBNormal = new Var( "interlacedGBNormal", "float3" ); + meta->addStatement(new GenOp(" @ = (frac(@.y * 0.5) < 0.1 ? reflect(@, float3(0.0, -1.0, 0.0)) : @);\r\n", new DecOp(iGBNormal), Vpos, gbNormal, gbNormal)); + gbNormal = iGBNormal; + } + // NOTE: We renormalize the normal here as they // will not stay normalized during interpolation. - meta->addStatement( new GenOp(" @ = @;", outputDecl, new GenOp( "vec4(normalize(@), @)", gbNormal, depth ) ) ); + meta->addStatement( new GenOp(" @ = @;", outputDecl, new GenOp( "float4(normalize(@), @)", gbNormal, depth ) ) ); meta->addStatement( assignOutput( unconditionedOut ) ); + // If we have an alpha var then we're doing prepass lerp blending. + if ( alphaVal ) + { + Var *outColor = (Var*)LangElement::find( getOutputTargetVarName( DefaultTarget ) ); + meta->addStatement( new GenOp( " @.ba = float2( 0, @ ); // MFT_IsTranslucentZWrite\r\n", outColor, alphaVal ) ); + } + output = meta; } @@ -180,7 +218,7 @@ Var* GBufferConditionerGLSL::printMethodHeader( MethodType methodType, const Str { Var *methodVar = new Var; methodVar->setName(methodName); - methodVar->setType("vec4"); + methodVar->setType("float4"); DecOp *methodDecl = new DecOp(methodVar); Var *prepassSampler = new Var; @@ -190,12 +228,12 @@ Var* GBufferConditionerGLSL::printMethodHeader( MethodType methodType, const Str Var *screenUV = new Var; screenUV->setName("screenUVVar"); - screenUV->setType("vec2"); + screenUV->setType("float2"); DecOp *screenUVDecl = new DecOp(screenUV); Var *bufferSample = new Var; bufferSample->setName("bufferSample"); - bufferSample->setType("vec4"); + bufferSample->setType("float4"); DecOp *bufferSampleDecl = new DecOp(bufferSample); meta->addStatement( new GenOp( "@(@, @)\r\n", methodDecl, prepassSamplerDecl, screenUVDecl ) ); @@ -204,9 +242,18 @@ Var* GBufferConditionerGLSL::printMethodHeader( MethodType methodType, const Str meta->addStatement( new GenOp( " // Sampler g-buffer\r\n" ) ); +#ifdef TORQUE_OS_XENON + meta->addStatement( new GenOp( " @;\r\n", bufferSampleDecl ) ); + meta->addStatement( new GenOp( " asm { tfetch2D @, @, @, MagFilter = point, MinFilter = point, MipFilter = point };\r\n", bufferSample, screenUV, prepassSampler ) ); +#else // The gbuffer has no mipmaps, so use tex2dlod when - // so that the shader compiler can optimize. - meta->addStatement( new GenOp( " @ = texture2DLod(@, @, 0.0);\r\n", bufferSampleDecl, prepassSampler, screenUV ) ); + // possible so that the shader compiler can optimize. + meta->addStatement( new GenOp( " #if TORQUE_SM >= 30\r\n" ) ); + meta->addStatement( new GenOp( " @ = tex2Dlod(@, float4(@,0,0));\r\n", bufferSampleDecl, prepassSampler, screenUV ) ); + meta->addStatement( new GenOp( " #else\r\n" ) ); + meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n", bufferSampleDecl, prepassSampler, screenUV ) ); + meta->addStatement( new GenOp( " #endif\r\n\r\n" ) ); +#endif // We don't use this way of passing var's around, so this should cause a crash // if something uses this improperly @@ -218,39 +265,67 @@ Var* GBufferConditionerGLSL::printMethodHeader( MethodType methodType, const Str GenOp* GBufferConditionerGLSL::_posnegEncode( GenOp *val ) { - return mCanWriteNegativeValues ? val : new GenOp("0.5 * (@ + 1.0)", val); + if(mNormalStorageType == LambertAzimuthal) + return mCanWriteNegativeValues ? val : new GenOp(avar("(%f * (@ + %f))", 1.0f/(M_SQRT2_F * 2.0f), M_SQRT2_F), val); + else + return mCanWriteNegativeValues ? val : new GenOp("(0.5 * (@ + 1.0))", val); } GenOp* GBufferConditionerGLSL::_posnegDecode( GenOp *val ) { - return mCanWriteNegativeValues ? val : new GenOp("@ * 2.0 - 1.0", val); + if(mNormalStorageType == LambertAzimuthal) + return mCanWriteNegativeValues ? val : new GenOp(avar("(@ * %f - %f)", M_SQRT2_F * 2.0f, M_SQRT2_F), val); + else + return mCanWriteNegativeValues ? val : new GenOp("(@ * 2.0 - 1.0)", val); } Var* GBufferConditionerGLSL::_conditionOutput( Var *unconditionedOutput, MultiLine *meta ) { Var *retVar = new Var; - retVar->setType("vec4"); + retVar->setType("float4"); retVar->setName("_gbConditionedOutput"); LangElement *outputDecl = new DecOp( retVar ); switch(mNormalStorageType) { case CartesianXYZ: - meta->addStatement( new GenOp( " // g-buffer conditioner: vec4(normal.xyz, depth)\r\n" ) ); - meta->addStatement( new GenOp( " @ = vec4(@, @.a);\r\n", outputDecl, + meta->addStatement( new GenOp( " // g-buffer conditioner: float4(normal.xyz, depth)\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4(@, @.a);\r\n", outputDecl, _posnegEncode(new GenOp("@.xyz", unconditionedOutput)), unconditionedOutput ) ); break; case CartesianXY: - meta->addStatement( new GenOp( " // g-buffer conditioner: vec4(normal.xy, depth Hi + z-sign, depth Lo)\r\n" ) ); - meta->addStatement( new GenOp( " @ = vec4(@, @.a);", outputDecl, - _posnegEncode(new GenOp("vec3(@.xy, sign(@.z))", unconditionedOutput, unconditionedOutput)), unconditionedOutput ) ); + meta->addStatement( new GenOp( " // g-buffer conditioner: float4(normal.xy, depth Hi + z-sign, depth Lo)\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4(@, @.a);", outputDecl, + _posnegEncode(new GenOp("float3(@.xy, sign(@.z))", unconditionedOutput, unconditionedOutput)), unconditionedOutput ) ); break; case Spherical: - meta->addStatement( new GenOp( " // g-buffer conditioner: vec4(normal.theta, normal.phi, depth Hi, depth Lo)\r\n" ) ); - meta->addStatement( new GenOp( " @ = vec4(@, 0.0, @.a);\r\n", outputDecl, - _posnegEncode(new GenOp("vec2(atan2(@.y, @.x) / 3.14159265358979323846f, @.z)", unconditionedOutput, unconditionedOutput, unconditionedOutput ) ), + meta->addStatement( new GenOp( " // g-buffer conditioner: float4(normal.theta, normal.phi, depth Hi, depth Lo)\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4(@, 0.0, @.a);\r\n", outputDecl, + _posnegEncode(new GenOp("float2(atan2(@.y, @.x) / 3.14159265358979323846f, @.z)", unconditionedOutput, unconditionedOutput, unconditionedOutput ) ), + unconditionedOutput ) ); + + // HACK: This fixes the noise present when using a floating point + // gbuffer on Geforce cards and the "flat areas unlit" issues. + // + // We need work around atan2() above to fix this issue correctly + // without the extra overhead of this test. + // + meta->addStatement( new GenOp( " if ( abs( dot( @.xyz, float3( 0.0, 0.0, 1.0 ) ) ) > 0.999f ) @ = float4( 0, 1 * sign( @.z ), 0, @.a );\r\n", + unconditionedOutput, retVar, unconditionedOutput, unconditionedOutput ) ); + break; + + case LambertAzimuthal: + //http://en.wikipedia.org/wiki/Lambert_azimuthal_equal-area_projection + // + // Note we're casting to half to use partial precision + // sqrt which is much faster on older Geforces while + // still being acceptable for normals. + // + meta->addStatement( new GenOp( " // g-buffer conditioner: float4(normal.X, normal.Y, depth Hi, depth Lo)\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4(@, 0.0, @.a);\r\n", outputDecl, + _posnegEncode(new GenOp("sqrt(half(2.0/(1.0 - @.y))) * half2(@.xz)", unconditionedOutput, unconditionedOutput)), unconditionedOutput ) ); break; } @@ -259,11 +334,10 @@ Var* GBufferConditionerGLSL::_conditionOutput( Var *unconditionedOutput, MultiLi if(mNormalStorageType != CartesianXYZ) { const U64 maxValPerChannel = 1 << mBitsPerChannel; - const U64 extraVal = (maxValPerChannel * maxValPerChannel - 1) - (maxValPerChannel - 1) * 2; meta->addStatement( new GenOp( " \r\n // Encode depth into hi/lo\r\n" ) ); - meta->addStatement( new GenOp( avar( " vec3 _tempDepth = fract(@.a * vec3(1.0, %llu.0, %llu.0));\r\n", maxValPerChannel - 1, extraVal ), + meta->addStatement( new GenOp( avar( " float2 _tempDepth = frac(@.a * float2(1.0, %llu.0));\r\n", maxValPerChannel - 1 ), unconditionedOutput ) ); - meta->addStatement( new GenOp( avar( " @.zw = _tempDepth.xy - _tempDepth.yz * vec2(1.0/%llu.0, 1.0/%llu.0);\r\n\r\n", maxValPerChannel - 1, maxValPerChannel - 1 ), + meta->addStatement( new GenOp( avar( " @.zw = _tempDepth.xy - _tempDepth.yy * float2(1.0/%llu.0, 0.0);\r\n\r\n", maxValPerChannel - 1 ), retVar ) ); } @@ -274,33 +348,43 @@ Var* GBufferConditionerGLSL::_conditionOutput( Var *unconditionedOutput, MultiLi Var* GBufferConditionerGLSL::_unconditionInput( Var *conditionedInput, MultiLine *meta ) { Var *retVar = new Var; - retVar->setType("vec4"); + retVar->setType("float4"); retVar->setName("_gbUnconditionedInput"); LangElement *outputDecl = new DecOp( retVar ); switch(mNormalStorageType) { case CartesianXYZ: - meta->addStatement( new GenOp( " // g-buffer unconditioner: vec4(normal.xyz, depth)\r\n" ) ); - meta->addStatement( new GenOp( " @ = vec4(@, @.a);\r\n", outputDecl, + meta->addStatement( new GenOp( " // g-buffer unconditioner: float4(normal.xyz, depth)\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4(@, @.a);\r\n", outputDecl, _posnegDecode(new GenOp("@.xyz", conditionedInput)), conditionedInput ) ); break; case CartesianXY: - meta->addStatement( new GenOp( " // g-buffer unconditioner: vec4(normal.xy, depth Hi + z-sign, depth Lo)\r\n" ) ); - meta->addStatement( new GenOp( " @ = vec4(@, @.a);\r\n", outputDecl, + meta->addStatement( new GenOp( " // g-buffer unconditioner: float4(normal.xy, depth Hi + z-sign, depth Lo)\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4(@, @.a);\r\n", outputDecl, _posnegDecode(new GenOp("@.xyz", conditionedInput)), conditionedInput ) ); meta->addStatement( new GenOp( " @.z *= sqrt(1.0 - dot(@.xy, @.xy));\r\n", retVar, retVar, retVar ) ); break; case Spherical: - meta->addStatement( new GenOp( " // g-buffer unconditioner: vec4(normal.theta, normal.phi, depth Hi, depth Lo)\r\n" ) ); - meta->addStatement( new GenOp( " vec2 spGPUAngles = @;\r\n", _posnegDecode(new GenOp("@.xy", conditionedInput)) ) ); - meta->addStatement( new GenOp( " vec2 sincosTheta;\r\n" ) ); - meta->addStatement( new GenOp( " sincosTheta.x = sin(spGPUAngles.x * 3.14159265358979323846);\r\n" ) ); - meta->addStatement( new GenOp( " sincosTheta.y = cos(spGPUAngles.x * 3.14159265358979323846);\r\n" ) ); - meta->addStatement( new GenOp( " vec2 sincosPhi = vec2(sqrt(1.0 - spGPUAngles.y * spGPUAngles.y), spGPUAngles.y);\r\n" ) ); - meta->addStatement( new GenOp( " @ = vec4(sincosTheta.y * sincosPhi.x, sincosTheta.x * sincosPhi.x, sincosPhi.y, @.a);\r\n", outputDecl, conditionedInput ) ); + meta->addStatement( new GenOp( " // g-buffer unconditioner: float4(normal.theta, normal.phi, depth Hi, depth Lo)\r\n" ) ); + meta->addStatement( new GenOp( " float2 spGPUAngles = @;\r\n", _posnegDecode(new GenOp("@.xy", conditionedInput)) ) ); + meta->addStatement( new GenOp( " float2 sincosTheta;\r\n" ) ); + meta->addStatement( new GenOp( " sincos(spGPUAngles.x * 3.14159265358979323846f, sincosTheta.x, sincosTheta.y);\r\n" ) ); + meta->addStatement( new GenOp( " float2 sincosPhi = float2(sqrt(1.0 - spGPUAngles.y * spGPUAngles.y), spGPUAngles.y);\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4(sincosTheta.y * sincosPhi.x, sincosTheta.x * sincosPhi.x, sincosPhi.y, @.a);\r\n", outputDecl, conditionedInput ) ); + break; + + case LambertAzimuthal: + // Note we're casting to half to use partial precision + // sqrt which is much faster on older Geforces while + // still being acceptable for normals. + // + meta->addStatement( new GenOp( " // g-buffer unconditioner: float4(normal.X, normal.Y, depth Hi, depth Lo)\r\n" ) ); + meta->addStatement( new GenOp( " float2 _inpXY = @;\r\n", _posnegDecode(new GenOp("@.xy", conditionedInput)) ) ); + meta->addStatement( new GenOp( " float _xySQ = dot(_inpXY, _inpXY);\r\n" ) ); + meta->addStatement( new GenOp( " @ = float4( sqrt(half(1.0 - (_xySQ / 4.0))) * _inpXY, -1.0 + (_xySQ / 2.0), @.a).xzyw;\r\n", outputDecl, conditionedInput ) ); break; } @@ -309,7 +393,7 @@ Var* GBufferConditionerGLSL::_unconditionInput( Var *conditionedInput, MultiLine { const U64 maxValPerChannel = 1 << mBitsPerChannel; meta->addStatement( new GenOp( " \r\n // Decode depth\r\n" ) ); - meta->addStatement( new GenOp( avar( " @.w = dot( @.zw, vec2(1.0, 1.0/%llu.0));\r\n", maxValPerChannel - 1 ), + meta->addStatement( new GenOp( avar( " @.w = dot( @.zw, float2(1.0, 1.0/%llu.0));\r\n", maxValPerChannel - 1 ), retVar, conditionedInput ) ); } diff --git a/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.h b/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.h index 9e9364c88..640891824 100644 --- a/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.h +++ b/Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.h @@ -42,6 +42,13 @@ public: CartesianXYZ, CartesianXY, Spherical, + LambertAzimuthal, + }; + + enum NormalSpace + { + WorldSpace, + ViewSpace, }; protected: @@ -52,7 +59,7 @@ protected: public: - GBufferConditionerGLSL( const GFXFormat bufferFormat ); + GBufferConditionerGLSL( const GFXFormat bufferFormat, const NormalSpace nrmSpace ); virtual ~GBufferConditionerGLSL(); diff --git a/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp b/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp index c2bf42834..9e04f3f76 100644 --- a/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp +++ b/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp @@ -479,7 +479,7 @@ void DeferredPixelSpecularHLSL::processPix( Vector &component "DeferredPixelSpecularHLSL::processPix - Something hosed the deferred features!" ); // (a^m)^n = a^(m*n) - meta->addStatement( new GenOp( " @ = pow( @, ceil(@ / AL_ConstantSpecularPower)) * @;\r\n", + meta->addStatement( new GenOp( " @ = pow( abs(@), max((@ / AL_ConstantSpecularPower),1.0f)) * @;\r\n", specDecl, d_specular, specPow, specStrength ) ); LangElement *specMul = new GenOp( "float4( @.rgb, 0 ) * @", specCol, specular ); diff --git a/Engine/source/lighting/advanced/hlsl/gBufferConditionerHLSL.cpp b/Engine/source/lighting/advanced/hlsl/gBufferConditionerHLSL.cpp index d4d30f9ad..ed946e944 100644 --- a/Engine/source/lighting/advanced/hlsl/gBufferConditionerHLSL.cpp +++ b/Engine/source/lighting/advanced/hlsl/gBufferConditionerHLSL.cpp @@ -333,7 +333,7 @@ Var* GBufferConditionerHLSL::_conditionOutput( Var *unconditionedOutput, MultiLi // Encode depth into two channels if(mNormalStorageType != CartesianXYZ) { - const U64 maxValPerChannel = 1 << mBitsPerChannel; + const U64 maxValPerChannel = (U64)1 << mBitsPerChannel; meta->addStatement( new GenOp( " \r\n // Encode depth into hi/lo\r\n" ) ); meta->addStatement( new GenOp( avar( " float2 _tempDepth = frac(@.a * float2(1.0, %llu.0));\r\n", maxValPerChannel - 1 ), unconditionedOutput ) ); @@ -391,7 +391,7 @@ Var* GBufferConditionerHLSL::_unconditionInput( Var *conditionedInput, MultiLine // Recover depth from encoding if(mNormalStorageType != CartesianXYZ) { - const U64 maxValPerChannel = 1 << mBitsPerChannel; + const U64 maxValPerChannel = (U64)1 << mBitsPerChannel; meta->addStatement( new GenOp( " \r\n // Decode depth\r\n" ) ); meta->addStatement( new GenOp( avar( " @.w = dot( @.zw, float2(1.0, 1.0/%llu.0));\r\n", maxValPerChannel - 1 ), retVar, conditionedInput ) ); diff --git a/Engine/source/lighting/common/projectedShadow.cpp b/Engine/source/lighting/common/projectedShadow.cpp index ed4a7b903..8918ddf5a 100644 --- a/Engine/source/lighting/common/projectedShadow.cpp +++ b/Engine/source/lighting/common/projectedShadow.cpp @@ -53,8 +53,8 @@ SimObjectPtr ProjectedShadow::smRenderPass = NULL; SimObjectPtr ProjectedShadow::smShadowFilter = NULL; F32 ProjectedShadow::smDepthAdjust = 10.0f; -float ProjectedShadow::smFadeStartPixelSize = 200.0f; -float ProjectedShadow::smFadeEndPixelSize = 35.0f; +F32 ProjectedShadow::smFadeStartPixelSize = 200.0f; +F32 ProjectedShadow::smFadeEndPixelSize = 35.0f; GFX_ImplementTextureProfile( BLProjectedShadowProfile, @@ -62,14 +62,14 @@ GFX_ImplementTextureProfile( BLProjectedShadowProfile, GFXTextureProfile::PreserveSize | GFXTextureProfile::RenderTarget | GFXTextureProfile::Pooled, - GFXTextureProfile::None ); + GFXTextureProfile::NONE ); GFX_ImplementTextureProfile( BLProjectedShadowZProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::PreserveSize | GFXTextureProfile::ZTarget | GFXTextureProfile::Pooled, - GFXTextureProfile::None ); + GFXTextureProfile::NONE ); ProjectedShadow::ProjectedShadow( SceneObject *object ) diff --git a/Engine/source/lighting/common/projectedShadow.h b/Engine/source/lighting/common/projectedShadow.h index 7b519f3ab..e43501a8d 100644 --- a/Engine/source/lighting/common/projectedShadow.h +++ b/Engine/source/lighting/common/projectedShadow.h @@ -109,8 +109,8 @@ protected: public: /// @see DecalData - static float smFadeStartPixelSize; - static float smFadeEndPixelSize; + static F32 smFadeStartPixelSize; + static F32 smFadeEndPixelSize; ProjectedShadow( SceneObject *object ); virtual ~ProjectedShadow(); diff --git a/Engine/source/lighting/common/sceneLighting.cpp b/Engine/source/lighting/common/sceneLighting.cpp index f542753ab..aa62782f8 100644 --- a/Engine/source/lighting/common/sceneLighting.cpp +++ b/Engine/source/lighting/common/sceneLighting.cpp @@ -859,7 +859,7 @@ struct CacheEntry { }; // object list sort methods: want list in reverse -static int QSORT_CALLBACK minSizeSort(const void * p1, const void * p2) +static S32 QSORT_CALLBACK minSizeSort(const void * p1, const void * p2) { const CacheEntry * entry1 = (const CacheEntry *)p1; const CacheEntry * entry2 = (const CacheEntry *)p2; @@ -867,7 +867,7 @@ static int QSORT_CALLBACK minSizeSort(const void * p1, const void * p2) return(entry2->mFileObject->getSize() - entry1->mFileObject->getSize()); } -static int QSORT_CALLBACK maxSizeSort(const void * p1, const void * p2) +static S32 QSORT_CALLBACK maxSizeSort(const void * p1, const void * p2) { const CacheEntry * entry1 = (const CacheEntry *)p1; const CacheEntry * entry2 = (const CacheEntry *)p2; @@ -875,7 +875,7 @@ static int QSORT_CALLBACK maxSizeSort(const void * p1, const void * p2) return(entry1->mFileObject->getSize() - entry2->mFileObject->getSize()); } -static int QSORT_CALLBACK lastCreatedSort(const void * p1, const void * p2) +static S32 QSORT_CALLBACK lastCreatedSort(const void * p1, const void * p2) { const CacheEntry * entry1 = (const CacheEntry *)p1; const CacheEntry * entry2 = (const CacheEntry *)p2; @@ -899,7 +899,7 @@ static int QSORT_CALLBACK lastCreatedSort(const void * p1, const void * p2) return(Platform::compareFileTimes(create[1], create[0])); } -static int QSORT_CALLBACK lastModifiedSort(const void * p1, const void * p2) +static S32 QSORT_CALLBACK lastModifiedSort(const void * p1, const void * p2) { const CacheEntry * entry1 = (const CacheEntry *)p1; const CacheEntry * entry2 = (const CacheEntry *)p2; @@ -1051,7 +1051,7 @@ U32 SceneLighting::calcMissionCRC() // of U32's, and so the result will be different on big/little endian hardware. // To fix this, swap endians on the CRC's in the vector. This must be done // _after_ the qsort. - for( int i = 0; i < crc.size(); i++ ) + for( S32 i = 0; i < crc.size(); i++ ) crc[i] = endianSwap( crc[i] ); #endif diff --git a/Engine/source/lighting/shadowMap/lightShadowMap.cpp b/Engine/source/lighting/shadowMap/lightShadowMap.cpp index a25b7e706..3a85a0b40 100644 --- a/Engine/source/lighting/shadowMap/lightShadowMap.cpp +++ b/Engine/source/lighting/shadowMap/lightShadowMap.cpp @@ -70,7 +70,7 @@ GFX_ImplementTextureProfile( ShadowMapProfile, GFXTextureProfile::PreserveSize | GFXTextureProfile::RenderTarget | GFXTextureProfile::Pooled, - GFXTextureProfile::None ); + GFXTextureProfile::NONE ); GFX_ImplementTextureProfile( ShadowMapZProfile, GFXTextureProfile::DiffuseMap, @@ -78,7 +78,7 @@ GFX_ImplementTextureProfile( ShadowMapZProfile, GFXTextureProfile::NoMipmap | GFXTextureProfile::ZTarget | GFXTextureProfile::Pooled, - GFXTextureProfile::None ); + GFXTextureProfile::NONE ); LightShadowMap::LightShadowMap( LightInfo *light ) diff --git a/Engine/source/lighting/shadowMap/pssmLightShadowMap.h b/Engine/source/lighting/shadowMap/pssmLightShadowMap.h index 8ced7b875..d2fffde8e 100644 --- a/Engine/source/lighting/shadowMap/pssmLightShadowMap.h +++ b/Engine/source/lighting/shadowMap/pssmLightShadowMap.h @@ -58,7 +58,7 @@ protected: Box3F _calcClipSpaceAABB(const Frustum& f, const MatrixF& transform, F32 farDist); void _roundProjection(const MatrixF& lightMat, const MatrixF& cropMatrix, Point3F &offset, U32 splitNum); - static const int MAX_SPLITS = 4; + static const S32 MAX_SPLITS = 4; U32 mNumSplits; F32 mSplitDist[MAX_SPLITS+1]; // +1 because we store a cap RectI mViewports[MAX_SPLITS]; diff --git a/Engine/source/lighting/shadowMap/shadowMapManager.cpp b/Engine/source/lighting/shadowMap/shadowMapManager.cpp index 078737db9..cfcf75f81 100644 --- a/Engine/source/lighting/shadowMap/shadowMapManager.cpp +++ b/Engine/source/lighting/shadowMap/shadowMapManager.cpp @@ -37,7 +37,7 @@ GFX_ImplementTextureProfile(ShadowMapTexProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::PreserveSize | GFXTextureProfile::Dynamic , - GFXTextureProfile::None); + GFXTextureProfile::NONE); MODULE_BEGIN( ShadowMapManager ) diff --git a/Engine/source/main/main.cpp b/Engine/source/main/main.cpp index 86907b5e5..1638b5b33 100644 --- a/Engine/source/main/main.cpp +++ b/Engine/source/main/main.cpp @@ -25,48 +25,77 @@ #ifdef WIN32 #include -#include +#include extern "C" { int (*torque_winmain)( HINSTANCE hInstance, HINSTANCE h, LPSTR lpszCmdLine, int nShow) = NULL; }; +bool getDllName(std::wstring& dllName, const std::wstring suffix) +{ + wchar_t filenameBuf[MAX_PATH]; + DWORD length = GetModuleFileNameW( NULL, filenameBuf, MAX_PATH ); + if(length == 0) return false; + dllName = std::wstring(filenameBuf); + size_t dotPos = dllName.find_last_of(L"."); + if(dotPos == std::wstring::npos) + { + dllName.clear(); + return false; + } + dllName.erase(dotPos); + dllName += suffix + L".dll"; + return true; +} + int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCommandShow) { - char filename[4096]; - char gameLib[4096]; + // Try to find the game DLL, which may have one of several file names. + HMODULE hGame = NULL; + std::wstring dllName = std::wstring(); + // The file name is the same as this executable's name, plus a suffix. + const std::wstring dllSuffices[] = {L" DLL", L""}; + const unsigned int numSuffices = sizeof(dllSuffices) / sizeof(std::wstring); - GetModuleFileNameA(NULL, filename, 4096); - filename[strlen(filename)-4] = 0; - sprintf(gameLib, "%s.dll", filename); + for (unsigned int i = 0; i < numSuffices; i++) + { + // Attempt to glue the suffix onto the current filename. + if(!getDllName(dllName, dllSuffices[i])) + continue; + // Load the DLL at that address. + hGame = LoadLibraryW(dllName.c_str()); + if (hGame) + break; + } - HMODULE hGame = LoadLibraryA(gameLib); + if(!dllName.length()) + { + MessageBoxW(NULL, L"Unable to find game dll", L"Error", MB_OK|MB_ICONWARNING); + return -1; + } - if (hGame) - torque_winmain = (int (*)(HINSTANCE hInstance, HINSTANCE h, LPSTR lpszCmdLine, int nShow))GetProcAddress(hGame, "torque_winmain"); - - char error[4096]; if (!hGame) { - sprintf(error, "Unable to load game library: %s. Please make sure it exists and the latest DirectX is installed.", gameLib); - MessageBoxA(NULL, error, "Error", MB_OK|MB_ICONWARNING); + wchar_t error[4096]; + _swprintf_l(error, sizeof(error), L"Unable to load game library: %s. Please make sure it exists and the latest DirectX is installed.", _get_current_locale(), dllName.c_str()); + MessageBoxW(NULL, error, L"Error", MB_OK|MB_ICONWARNING); return -1; } + torque_winmain = (int (*)(HINSTANCE hInstance, HINSTANCE h, LPSTR lpszCmdLine, int nShow))GetProcAddress(hGame, "torque_winmain"); if (!torque_winmain) { - sprintf(error, "Missing torque_winmain export in game library: %s. Please make sure that it exists and the latest DirectX is installed.", gameLib); - MessageBoxA(NULL, error, "Error", MB_OK|MB_ICONWARNING); + wchar_t error[4096]; + _swprintf_l(error, sizeof(error), L"Missing torque_winmain export in game library: %s. Please make sure that it exists and the latest DirectX is installed.", _get_current_locale(), dllName.c_str()); + MessageBoxW(NULL, error, L"Error", MB_OK|MB_ICONWARNING); return -1; } - int ret = torque_winmain(hInstance, hPrevInstance, lpszCmdLine, nCommandShow ); + int ret = torque_winmain(hInstance, hPrevInstance, lpszCmdLine, nCommandShow); FreeLibrary(hGame); - return ret; - } #endif // WIN32 diff --git a/Engine/source/materials/miscShdrDat.h b/Engine/source/materials/miscShdrDat.h index 6441f1b07..25422008d 100644 --- a/Engine/source/materials/miscShdrDat.h +++ b/Engine/source/materials/miscShdrDat.h @@ -41,6 +41,7 @@ enum RegisterType RT_NORMAL, RT_BINORMAL, RT_TANGENT, + RT_TANGENTW, RT_COLOR, RT_TEXCOORD, RT_VPOS, diff --git a/Engine/source/materials/processedMaterial.cpp b/Engine/source/materials/processedMaterial.cpp index 34ce285a0..9e82c65b1 100644 --- a/Engine/source/materials/processedMaterial.cpp +++ b/Engine/source/materials/processedMaterial.cpp @@ -41,7 +41,10 @@ RenderPassData::RenderPassData() void RenderPassData::reset() { for( U32 i = 0; i < Material::MAX_TEX_PER_PASS; ++ i ) + { destructInPlace( &mTexSlot[ i ] ); + mSamplerNames[ i ].clear(); + } dMemset( &mTexSlot, 0, sizeof(mTexSlot) ); dMemset( &mTexType, 0, sizeof(mTexType) ); diff --git a/Engine/source/materials/processedMaterial.h b/Engine/source/materials/processedMaterial.h index 841825aab..b72422cf9 100644 --- a/Engine/source/materials/processedMaterial.h +++ b/Engine/source/materials/processedMaterial.h @@ -68,6 +68,7 @@ public: } mTexSlot[Material::MAX_TEX_PER_PASS]; U32 mTexType[Material::MAX_TEX_PER_PASS]; + String mSamplerNames[Material::MAX_TEX_PER_PASS]; /// The cubemap to use when the texture type is /// set to Material::Cube. diff --git a/Engine/source/materials/processedShaderMaterial.cpp b/Engine/source/materials/processedShaderMaterial.cpp index 01741f496..410773d7e 100644 --- a/Engine/source/materials/processedShaderMaterial.cpp +++ b/Engine/source/materials/processedShaderMaterial.cpp @@ -285,7 +285,7 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum, { PROFILE_SCOPE( ProcessedShaderMaterial_DetermineFeatures ); - const float shaderVersion = GFX->getPixelShaderVersion(); + const F32 shaderVersion = GFX->getPixelShaderVersion(); AssertFatal(shaderVersion > 0.0 , "Cannot create a shader material if we don't support shaders"); bool lastStage = stageNum == (mMaxStages-1); diff --git a/Engine/source/math/mBox.cpp b/Engine/source/math/mBox.cpp index 2cdd730e3..c37e091c3 100644 --- a/Engine/source/math/mBox.cpp +++ b/Engine/source/math/mBox.cpp @@ -61,7 +61,7 @@ bool Box3F::collideLine(const Point3F& start, const Point3F& end, F32* t, Point3 static const Point3F na[3] = { Point3F(1.0f, 0.0f, 0.0f), Point3F(0.0f, 1.0f, 0.0f), Point3F(0.0f, 0.0f, 1.0f) }; Point3F finalNormal(0.0f, 0.0f, 0.0f); - for (int i = 0; i < 3; i++) { + for (S32 i = 0; i < 3; i++) { bool n_neg = false; if (si[i] < ei[i]) { if (si[i] > bmax[i] || ei[i] < bmin[i]) diff --git a/Engine/source/math/mBox.h b/Engine/source/math/mBox.h index e0c028b60..379d5291a 100644 --- a/Engine/source/math/mBox.h +++ b/Engine/source/math/mBox.h @@ -334,10 +334,18 @@ inline Box3F Box3F::getOverlap( const Box3F& otherBox ) const Box3F overlap; for( U32 i = 0; i < 3; ++ i ) + { if( minExtents[ i ] > otherBox.maxExtents[ i ] || otherBox.minExtents[ i ] > maxExtents[ i ] ) + { overlap.minExtents[ i ] = 0.f; + overlap.maxExtents[ i ] = 0.f; + } else + { overlap.minExtents[ i ] = getMax( minExtents[ i ], otherBox.minExtents[ i ] ); + overlap.maxExtents[ i ] = getMin( maxExtents[ i ], otherBox.maxExtents[ i ] ); + } + } return overlap; } diff --git a/Engine/source/math/mConsoleFunctions.cpp b/Engine/source/math/mConsoleFunctions.cpp index 0bb171fad..89d8bd6e2 100644 --- a/Engine/source/math/mConsoleFunctions.cpp +++ b/Engine/source/math/mConsoleFunctions.cpp @@ -41,8 +41,9 @@ DefineConsoleFunction( mSolveQuadratic, const char*, ( F32 a, F32 b, F32 c ),, F32 x[2]; U32 sol = mSolveQuadratic( a, b, c, x ); - char * retBuffer = Con::getReturnBuffer(256); - dSprintf(retBuffer, 256, "%d %g %g", sol, x[0], x[1]); + static const U32 bufSize = 256; + char * retBuffer = Con::getReturnBuffer(bufSize); + dSprintf(retBuffer, bufSize, "%d %g %g", sol, x[0], x[1]); return retBuffer; } @@ -59,8 +60,9 @@ DefineConsoleFunction( mSolveCubic, const char*, ( F32 a, F32 b, F32 c, F32 d ), F32 x[3]; U32 sol = mSolveCubic( a, b, c, d, x ); - char * retBuffer = Con::getReturnBuffer(256); - dSprintf(retBuffer, 256, "%d %g %g %g", sol, x[0], x[1], x[2]); + static const U32 bufSize = 256; + char * retBuffer = Con::getReturnBuffer(bufSize); + dSprintf(retBuffer, bufSize, "%d %g %g %g", sol, x[0], x[1], x[2]); return retBuffer; } @@ -76,9 +78,10 @@ DefineConsoleFunction( mSolveQuartic, const char*, ( F32 a, F32 b, F32 c, F32 d, "@ingroup Math" ) { F32 x[4]; - char * retBuffer = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char * retBuffer = Con::getReturnBuffer(bufSize); U32 sol = mSolveQuartic(a, b, c, d, e, x); - dSprintf(retBuffer, 256, "%d %g %g %g %g", sol, x[0], x[1], x[2], x[3]); + dSprintf(retBuffer, bufSize, "%d %g %g %g %g", sol, x[0], x[1], x[2], x[3]); return retBuffer; } @@ -121,8 +124,9 @@ DefineConsoleFunction( mFloatLength, const char*, ( F32 v, U32 precision ),, precision = 9; fmtString[2] = '0' + precision; - char * outBuffer = Con::getReturnBuffer(256); - dSprintf(outBuffer, 255, fmtString, v); + static const U32 bufSize = 256; + char * outBuffer = Con::getReturnBuffer(bufSize); + dSprintf(outBuffer, bufSize, fmtString, v); return outBuffer; } diff --git a/Engine/source/math/mMathAltivec.cpp b/Engine/source/math/mMathAltivec.cpp index 6bdc9d752..c056a6449 100644 --- a/Engine/source/math/mMathAltivec.cpp +++ b/Engine/source/math/mMathAltivec.cpp @@ -38,9 +38,9 @@ /// because we get a much better speed gain if we can assume the data is aligned. void vec_MatrixF_x_MatrixF(const F32 *matA, const F32 *matB, F32 *result) { - vector float A[4][1]; - vector float B[4][1]; - vector float C[4][1]; + vector F32 A[4][1]; + vector F32 B[4][1]; + vector F32 C[4][1]; /// If the incoming pointers are not 16-byte aligned, we have to load & store the slow way. if((int)matA & 0xF || (int)matB & 0xF || (int)result & 0xF) diff --git a/Engine/source/math/mMathFn.h b/Engine/source/math/mMathFn.h index cdeb4b4f5..6b41cfa89 100644 --- a/Engine/source/math/mMathFn.h +++ b/Engine/source/math/mMathFn.h @@ -442,7 +442,7 @@ inline bool mIsNaN_F( const F32 x ) inline bool mIsInf_F( const F32 x ) { - return ( x == std::numeric_limits< float >::infinity() ); + return ( x == std::numeric_limits< F32 >::infinity() ); } inline F32 mSign( const F32 n ) diff --git a/Engine/source/math/mPolyhedron.h b/Engine/source/math/mPolyhedron.h index 00723466f..dbb874817 100644 --- a/Engine/source/math/mPolyhedron.h +++ b/Engine/source/math/mPolyhedron.h @@ -229,7 +229,7 @@ struct PolyhedronUnmanagedVectorData : public PolyhedronData }; /// Polyhedron data stored in fixed size arrays. -template< int NUM_PLANES, int NUM_POINTS, int NUM_EDGES > +template< S32 NUM_PLANES, S32 NUM_POINTS, S32 NUM_EDGES > struct PolyhedronFixedVectorData : public PolyhedronData { typedef FixedSizeVector< PlaneF, NUM_PLANES > PlaneListType; @@ -479,7 +479,7 @@ inline PolyhedronVectorData::operator AnyPolyhedron() const //----------------------------------------------------------------------------- -template< int NUM_PLANES, int NUM_POINTS, int NUM_EDGES > +template< S32 NUM_PLANES, S32 NUM_POINTS, S32 NUM_EDGES > inline PolyhedronFixedVectorData< NUM_PLANES, NUM_POINTS, NUM_EDGES >::operator AnyPolyhedron() const { return AnyPolyhedron( diff --git a/Engine/source/math/mQuadPatch.cpp b/Engine/source/math/mQuadPatch.cpp index 24e67dd33..efb300e0b 100644 --- a/Engine/source/math/mQuadPatch.cpp +++ b/Engine/source/math/mQuadPatch.cpp @@ -52,7 +52,7 @@ void QuadPatch::submitControlPoints( SplCtrlPts &points ) //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -void QuadPatch::setControlPoint( Point3F &point, int index ) +void QuadPatch::setControlPoint( Point3F &point, S32 index ) { ( (SplCtrlPts*) getControlPoints() )->setPoint( point, index ); calcABC( getControlPoint(0) ); diff --git a/Engine/source/math/mQuadPatch.h b/Engine/source/math/mQuadPatch.h index 22dcb1ffc..d579ca367 100644 --- a/Engine/source/math/mQuadPatch.h +++ b/Engine/source/math/mQuadPatch.h @@ -51,7 +51,7 @@ public: virtual void calc( F32 t, Point3F &result ); virtual void calc( Point3F *points, F32 t, Point3F &result ); - virtual void setControlPoint( Point3F &point, int index ); + virtual void setControlPoint( Point3F &point, S32 index ); virtual void submitControlPoints( SplCtrlPts &points ); diff --git a/Engine/source/math/mQuat.cpp b/Engine/source/math/mQuat.cpp index 78c9fb100..c78252bc2 100644 --- a/Engine/source/math/mQuat.cpp +++ b/Engine/source/math/mQuat.cpp @@ -262,12 +262,12 @@ QuatF & QuatF::interpolate( const QuatF & q1, const QuatF & q2, F32 t ) //----------------------------------- // calculate interpolating coeffs: - double scale1, scale2; + F64 scale1, scale2; if ( (1.0 - cosOmega) > 0.00001 ) { // standard case - double omega = mAcos(cosOmega); - double sinOmega = mSin(omega); + F64 omega = mAcos(cosOmega); + F64 sinOmega = mSin(omega); scale1 = mSin((1.0 - t) * omega) / sinOmega; scale2 = sign2 * mSin(t * omega) / sinOmega; } diff --git a/Engine/source/math/mQuat.h b/Engine/source/math/mQuat.h index 34cae7e84..433b30155 100644 --- a/Engine/source/math/mQuat.h +++ b/Engine/source/math/mQuat.h @@ -55,8 +55,8 @@ public: QuatF& set( const AngAxisF & a ); QuatF& set( const EulerF & e ); - int operator ==( const QuatF & c ) const; - int operator !=( const QuatF & c ) const; + S32 operator ==( const QuatF & c ) const; + S32 operator !=( const QuatF & c ) const; QuatF& operator *=( const QuatF & c ); QuatF& operator /=( const QuatF & c ); QuatF& operator +=( const QuatF & c ); @@ -75,7 +75,7 @@ public: QuatF& normalize(); QuatF& inverse(); QuatF& identity(); - int isIdentity() const; + S32 isIdentity() const; QuatF& slerp( const QuatF & q, F32 t ); QuatF& extrapolate( const QuatF & q1, const QuatF & q2, F32 t ); QuatF& interpolate( const QuatF & q1, const QuatF & q2, F32 t ); diff --git a/Engine/source/math/mSplinePatch.cpp b/Engine/source/math/mSplinePatch.cpp index 467feb9df..9d52c5150 100644 --- a/Engine/source/math/mSplinePatch.cpp +++ b/Engine/source/math/mSplinePatch.cpp @@ -68,7 +68,7 @@ void SplCtrlPts::submitPoints( Point3F *pts, U32 num ) { mPoints.clear(); - for( int i=0; ix, pt->y); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%d %d", pt->x, pt->y); return returnBuffer; } @@ -147,8 +148,9 @@ ImplementConsoleTypeCasters( TypePoint2F, Point2F ) ConsoleGetType( TypePoint2F ) { Point2F *pt = (Point2F *) dptr; - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%g %g", pt->x, pt->y); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%g %g", pt->x, pt->y); return returnBuffer; } @@ -171,8 +173,9 @@ ImplementConsoleTypeCasters(TypePoint3I, Point3I) ConsoleGetType( TypePoint3I ) { Point3I *pt = (Point3I *) dptr; - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%d %d %d", pt->x, pt->y, pt->z); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%d %d %d", pt->x, pt->y, pt->z); return returnBuffer; } @@ -195,8 +198,9 @@ ImplementConsoleTypeCasters(TypePoint3F, Point3F) ConsoleGetType( TypePoint3F ) { Point3F *pt = (Point3F *) dptr; - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%g %g %g", pt->x, pt->y, pt->z); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%g %g %g", pt->x, pt->y, pt->z); return returnBuffer; } @@ -219,8 +223,9 @@ ImplementConsoleTypeCasters( TypePoint4F, Point4F ) ConsoleGetType( TypePoint4F ) { Point4F *pt = (Point4F *) dptr; - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%g %g %g %g", pt->x, pt->y, pt->z, pt->w); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%g %g %g %g", pt->x, pt->y, pt->z, pt->w); return returnBuffer; } @@ -243,8 +248,9 @@ ImplementConsoleTypeCasters( TypeRectI, RectI ) ConsoleGetType( TypeRectI ) { RectI *rect = (RectI *) dptr; - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%d %d %d %d", rect->point.x, rect->point.y, + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%d %d %d %d", rect->point.x, rect->point.y, rect->extent.x, rect->extent.y); return returnBuffer; } @@ -269,8 +275,9 @@ ImplementConsoleTypeCasters( TypeRectF, RectF ) ConsoleGetType( TypeRectF ) { RectF *rect = (RectF *) dptr; - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%g %g %g %g", rect->point.x, rect->point.y, + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%g %g %g %g", rect->point.x, rect->point.y, rect->extent.x, rect->extent.y); return returnBuffer; } @@ -303,8 +310,9 @@ ConsoleGetType( TypeMatrixF ) mat->getColumn(0, &col0); mat->getColumn(1, &col1); mat->getColumn(2, &col2); - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer,256,"%g %g %g %g %g %g %g %g %g", + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer,bufSize,"%g %g %g %g %g %g %g %g %g", col0.x, col0.y, col0.z, col1.x, col1.y, col1.z, col2.x, col2.y, col2.z); return returnBuffer; } @@ -336,11 +344,12 @@ ConsoleType( MatrixPosition, TypeMatrixPosition, MatrixF ) ConsoleGetType( TypeMatrixPosition ) { F32 *col = (F32 *) dptr + 3; - char* returnBuffer = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); if(col[12] == 1.f) - dSprintf(returnBuffer, 256, "%g %g %g", col[0], col[4], col[8]); + dSprintf(returnBuffer, bufSize, "%g %g %g", col[0], col[4], col[8]); else - dSprintf(returnBuffer, 256, "%g %g %g %g", col[0], col[4], col[8], col[12]); + dSprintf(returnBuffer, bufSize, "%g %g %g %g", col[0], col[4], col[8], col[12]); return returnBuffer; } @@ -371,8 +380,9 @@ ConsoleGetType( TypeMatrixRotation ) { AngAxisF aa(*(MatrixF *) dptr); aa.axis.normalize(); - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer,256,"%g %g %g %g",aa.axis.x,aa.axis.y,aa.axis.z,mRadToDeg(aa.angle)); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer,bufSize,"%g %g %g %g",aa.axis.x,aa.axis.y,aa.axis.z,mRadToDeg(aa.angle)); return returnBuffer; } @@ -415,8 +425,9 @@ ImplementConsoleTypeCasters( TypeAngAxisF, AngAxisF ) ConsoleGetType( TypeAngAxisF ) { AngAxisF* aa = ( AngAxisF* ) dptr; - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer,256,"%g %g %g %g",aa->axis.x,aa->axis.y,aa->axis.z,mRadToDeg(aa->angle)); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer,bufSize,"%g %g %g %g",aa->axis.x,aa->axis.y,aa->axis.z,mRadToDeg(aa->angle)); return returnBuffer; } @@ -453,8 +464,9 @@ ImplementConsoleTypeCasters( TypeTransformF, TransformF ) ConsoleGetType( TypeTransformF ) { TransformF* aa = ( TransformF* ) dptr; - char* returnBuffer = Con::getReturnBuffer( 256 ); - dSprintf( returnBuffer, 256, "%g %g %g %g %g %g %g", + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf( returnBuffer, bufSize, "%g %g %g %g %g %g %g", aa->mPosition.x, aa->mPosition.y, aa->mPosition.z, aa->mOrientation.axis.x, aa->mOrientation.axis.y, aa->mOrientation.axis.z, aa->mOrientation.angle ); return returnBuffer; @@ -497,8 +509,9 @@ ConsoleGetType( TypeBox3F ) { const Box3F* pBox = (const Box3F*)dptr; - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%g %g %g %g %g %g", + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%g %g %g %g %g %g", pBox->minExtents.x, pBox->minExtents.y, pBox->minExtents.z, pBox->maxExtents.x, pBox->maxExtents.y, pBox->maxExtents.z); @@ -533,8 +546,9 @@ ConsoleGetType( TypeEaseF ) { const EaseF* pEase = (const EaseF*)dptr; - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf(returnBuffer, 256, "%d %d %g %g", + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%d %d %g %g", pEase->dir, pEase->type, pEase->param[0], pEase->param[1]); return returnBuffer; diff --git a/Engine/source/math/mathUtils.cpp b/Engine/source/math/mathUtils.cpp index 2540191fb..71c8508f9 100644 --- a/Engine/source/math/mathUtils.cpp +++ b/Engine/source/math/mathUtils.cpp @@ -819,7 +819,7 @@ U32 greatestCommonDivisor( U32 u, U32 v ) { // http://en.wikipedia.org/wiki/Binary_GCD_algorithm - int shift; + S32 shift; /* GCD(0,x) := x */ if (u == 0 || v == 0) @@ -845,7 +845,7 @@ U32 greatestCommonDivisor( U32 u, U32 v ) if (u < v) { v -= u; } else { - unsigned int diff = u - v; + U32 diff = u - v; u = v; v = diff; } @@ -1086,7 +1086,7 @@ struct QuadSortPoint }; // Used by sortQuadWindingOrder. -int QSORT_CALLBACK cmpAngleAscending( const void *a, const void *b ) +S32 QSORT_CALLBACK cmpAngleAscending( const void *a, const void *b ) { const QuadSortPoint *p0 = (const QuadSortPoint*)a; const QuadSortPoint *p1 = (const QuadSortPoint*)b; @@ -1102,7 +1102,7 @@ int QSORT_CALLBACK cmpAngleAscending( const void *a, const void *b ) } // Used by sortQuadWindingOrder. -int QSORT_CALLBACK cmpAngleDescending( const void *a, const void *b ) +S32 QSORT_CALLBACK cmpAngleDescending( const void *a, const void *b ) { const QuadSortPoint *p0 = (const QuadSortPoint*)a; const QuadSortPoint *p1 = (const QuadSortPoint*)b; diff --git a/Engine/source/unit/consoleTest.cpp b/Engine/source/math/test/mBoxTest.cpp similarity index 66% rename from Engine/source/unit/consoleTest.cpp rename to Engine/source/math/test/mBoxTest.cpp index 2a159ca0c..cd09a0109 100644 --- a/Engine/source/unit/consoleTest.cpp +++ b/Engine/source/math/test/mBoxTest.cpp @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC +// Copyright (c) 2014 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to @@ -20,20 +20,23 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "core/strings/stringFunctions.h" +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "math/mBox.h" -#include "unit/test.h" -#include "console/console.h" - -using namespace UnitTesting; - -ConsoleFunction(unitTest_runTests, void, 1, 3, "([searchString[, bool skipInteractive]])" - "@brief Run unit tests, or just the tests that prefix match against the searchString.\n\n" - "@ingroup Console") +TEST(Box3F, GetOverlap) { - const char *searchString = (argc > 1 ? argv[1] : ""); - bool skip = (argc > 2 ? dAtob(argv[2]) : false); + Box3F b1(Point3F(-1, -1, -1), Point3F(1, 1, 1)); + EXPECT_EQ(b1.getOverlap(b1), b1) + << "A box's overlap with itself should be itself."; - TestRun tr; - tr.test(searchString, skip); -} \ No newline at end of file + Box3F b2(Point3F(0, 0, 0), Point3F(1, 1, 1)); + EXPECT_EQ(b1.getOverlap(b2), b2) + << "Box's overlap should be the intersection of two boxes."; + + Box3F b3(Point3F(10, 10, 10), Point3F(11, 11, 11)); + EXPECT_TRUE(b1.getOverlap(b3).isEmpty()) + << "Overlap of boxes that do not overlap should be empty."; +} + +#endif \ No newline at end of file diff --git a/Engine/source/math/test/mMatrixTest.cpp b/Engine/source/math/test/mMatrixTest.cpp new file mode 100644 index 000000000..c582c0932 --- /dev/null +++ b/Engine/source/math/test/mMatrixTest.cpp @@ -0,0 +1,106 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "platform/platform.h" +#include "math/mMatrix.h" +#include "math/mRandom.h" + +extern void default_matF_x_matF_C(const F32 *a, const F32 *b, F32 *mresult); +extern void mInstallLibrary_ASM(); + +// If we're x86 and not Mac, then include these. There's probably a better way to do this. +#if defined(TORQUE_CPU_X86) && !defined(TORQUE_OS_MAC) +extern "C" void Athlon_MatrixF_x_MatrixF(const F32 *matA, const F32 *matB, F32 *result); +extern "C" void SSE_MatrixF_x_MatrixF(const F32 *matA, const F32 *matB, F32 *result); +#endif + +#if defined( __VEC__ ) +extern void vec_MatrixF_x_MatrixF(const F32 *matA, const F32 *matB, F32 *result); +#endif + +TEST(MatrixF, MultiplyImplmentations) +{ + F32 m1[16], m2[16], mrC[16]; + + // I am not positive that the best way to do this is to use random numbers + // but I think that using some kind of standard matrix may not always catch + // all problems. + for (S32 i = 0; i < 16; i++) + { + m1[i] = gRandGen.randF(); + m2[i] = gRandGen.randF(); + } + + // C will be the baseline + default_matF_x_matF_C(m1, m2, mrC); + +#if defined(TORQUE_CPU_X86) && !defined(TORQUE_OS_MAC) + // Check the CPU info + U32 cpuProperties = Platform::SystemInfo.processor.properties; + bool same; + + // Test 3D NOW! if it is available + F32 mrAMD[16]; + if (cpuProperties & CPU_PROP_3DNOW) + { + Athlon_MatrixF_x_MatrixF(m1, m2, mrAMD); + + same = true; + for (S32 i = 0; i < 16; i++) + same &= mIsEqual(mrC[i], mrAMD[i]); + + EXPECT_TRUE(same) << "Matrix multiplication verification failed. (C vs. 3D NOW!)"; + } + + // Test SSE if it is available + F32 mrSSE[16]; + if (cpuProperties & CPU_PROP_SSE) + { + SSE_MatrixF_x_MatrixF(m1, m2, mrSSE); + + same = true; + for (S32 i = 0; i < 16; i++) + same &= mIsEqual(mrC[i], mrSSE[i]); + + EXPECT_TRUE(same) << "Matrix multiplication verification failed. (C vs. SSE)"; + } + + same = true; +#endif + + // If Altivec exists, test it! +#if defined(__VEC__) + bool same = false; + F32 mrVEC[16]; + + vec_MatrixF_x_MatrixF(m1, m2, mrVEC); + + for (S32 i = 0; i < 16; i++) + same &= isEqual(mrC[i], mrVEC[i]); + + EXPECT_TRUE(same) << "Matrix multiplication verification failed. (C vs. Altivec)"; +#endif +} + +#endif \ No newline at end of file diff --git a/Engine/source/math/test/mPlaneTest.cpp b/Engine/source/math/test/mPlaneTest.cpp new file mode 100644 index 000000000..777296184 --- /dev/null +++ b/Engine/source/math/test/mPlaneTest.cpp @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "math/mPlane.h" + +// Static test data. All combinations of position and normal are tested in each +// test case. This allows a large number of tests without introducing non- +// deterministic test behavior. + +static const Point3F positions[] = {Point3F(0, 0, 0), Point3F(1, -2, 3), Point3F(1e-2, -2e-2, 1)}; +static const U32 numPositions = sizeof(positions) / sizeof(Point3F); + +static const Point3F normals[] = {Point3F(1, 0, 0), Point3F(-4, -2, 6)}; +static const U32 numNormals = sizeof(normals) / sizeof(Point3F); + +/// Tests that points in the direction of the normal are in 'Front' of the +/// plane, while points in the reverse direction of the normal are in +/// 'Back' of the plane. +TEST(Plane, WhichSide) +{ + for(U32 i = 0; i < numPositions; i++) { + for(U32 j = 0; j < numNormals; j++) { + Point3F position = positions[i]; + Point3F normal = normals[j]; + + PlaneF p(position, normal); + + EXPECT_EQ(p.whichSide(position + normal), PlaneF::Front ); + EXPECT_EQ(p.whichSide(position - normal), PlaneF::Back ); + EXPECT_EQ(p.whichSide(position), PlaneF::On ); + } + } +} + +/// Tests that the distToPlane method returns the exact length that the test +/// point is offset by in the direction of the normal. +TEST(Plane, DistToPlane) +{ + for(U32 i = 0; i < numPositions; i++) { + for(U32 j = 0; j < numNormals; j++) { + Point3F position = positions[i]; + Point3F normal = normals[j]; + + PlaneF p(position, normal); + + EXPECT_FLOAT_EQ(p.distToPlane(position + normal), normal.len()); + EXPECT_FLOAT_EQ(p.distToPlane(position - normal), -normal.len()); + EXPECT_FLOAT_EQ(p.distToPlane(position), 0); + } + } +} + +#endif diff --git a/Engine/source/math/test/mPolyhedronTest.cpp b/Engine/source/math/test/mPolyhedronTest.cpp new file mode 100644 index 000000000..c2a949573 --- /dev/null +++ b/Engine/source/math/test/mPolyhedronTest.cpp @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "math/mPolyhedron.h" + +FIXTURE(Polyhedron) +{ +protected: + Vector planes; + + virtual void SetUp() + { + // Build planes for a unit cube centered at the origin. + // Note that the normals must be facing inwards. + planes.push_back(PlaneF(Point3F(-0.5f, 0.f, 0.f ), Point3F( 1.f, 0.f, 0.f))); + planes.push_back(PlaneF(Point3F( 0.5f, 0.f, 0.f ), Point3F(-1.f, 0.f, 0.f))); + planes.push_back(PlaneF(Point3F( 0.f, -0.5f, 0.f ), Point3F( 0.f, 1.f, 0.f))); + planes.push_back(PlaneF(Point3F( 0.f, 0.5f, 0.f ), Point3F( 0.f, -1.f, 0.f))); + planes.push_back(PlaneF(Point3F( 0.f, 0.f, -0.5f), Point3F( 0.f, 0.f, 1.f))); + planes.push_back(PlaneF(Point3F( 0.f, 0.f, 0.5f), Point3F( 0.f, 0.f, -1.f))); + } +}; + +TEST_FIX(Polyhedron, BuildFromPlanes) +{ + // Turn planes into a polyhedron. + Polyhedron p1; + p1.buildFromPlanes(PlaneSetF(planes.address(), planes.size())); + + // Check if we got a cube back. + EXPECT_EQ(p1.getNumPoints(), 8); + EXPECT_EQ(p1.getNumPlanes(), 6); + EXPECT_EQ(p1.getNumEdges(), 12); + + // Add extra plane that doesn't contribute a new edge. + Vector planes2 = planes; + planes2.push_back( PlaneF( Point3F( 0.5f, 0.5f, 0.5f ), Point3F( -1.f, -1.f, -1.f ) ) ); + + // Turn them into another polyhedron. + Polyhedron p2; + p2.buildFromPlanes(PlaneSetF(planes2.address(), planes2.size())); + + // Check if we got a cube back. + EXPECT_EQ(p2.getNumPoints(), 8); + EXPECT_EQ(p2.getNumPlanes(), 6); + EXPECT_EQ(p2.getNumEdges(), 12); +} + +#endif diff --git a/Engine/source/math/test/mQuatTest.cpp b/Engine/source/math/test/mQuatTest.cpp new file mode 100644 index 000000000..4b4027e4d --- /dev/null +++ b/Engine/source/math/test/mQuatTest.cpp @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "math/mQuat.h" +#include "math/mAngAxis.h" +#include "math/mMatrix.h" + +/// For testing things that should be close to 0, but accounting for floating- +/// point inaccuracy. +static const F32 epsilon = 1e-3f; + +/// Test quaternions for equality by expecting the angle between them to be +/// close to 0. +#define EXPECT_QUAT_EQ(q1, q2) EXPECT_LT(q1.angleBetween(q2), epsilon) + +TEST(QuatF, AngleBetween) +{ + QuatF p(QuatF::Identity), q(QuatF::Identity); + EXPECT_LT(p.angleBetween(q), epsilon) + << "Angle between identity quaternions should be ~0."; + + p.set(EulerF(0.1, 0.15, -0.2)); + q = p; + EXPECT_LT(p.angleBetween(q), epsilon) + << "Angle between identical quaternions should be ~0."; +} + +/// Test conversion from EulerF. +TEST(QuatF, Construction) +{ + EulerF eId(0, 0, 0); + EXPECT_QUAT_EQ(QuatF(eId), QuatF::Identity) + << "Quaternions constructed from identity EulerF and QuatF::Identity not equal."; + + EulerF eRot(0.0f, -0.0f, 1.5707963267948966f); + MatrixF mat(eRot); + AngAxisF aaRot(mat); + EXPECT_QUAT_EQ(QuatF(eRot), QuatF(aaRot)) + << "Quaternions constructed from EulerF and AngAxisF not equal."; +} + +#endif \ No newline at end of file diff --git a/Engine/source/math/test/testMathPlane.cpp b/Engine/source/math/test/testMathPlane.cpp deleted file mode 100644 index 6600c235e..000000000 --- a/Engine/source/math/test/testMathPlane.cpp +++ /dev/null @@ -1,79 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "unit/test.h" -#include "math/mPlane.h" -#include "math/mRandom.h" - - -#ifndef TORQUE_SHIPPING - -using namespace UnitTesting; - -#define TEST( x ) test( ( x ), "FAIL: " #x ) -#define XTEST( t, x ) t->test( ( x ), "FAIL: " #x ) - -CreateUnitTest( TestMathPlane, "Math/Plane" ) -{ - static F32 randF() - { - return gRandGen.randF( -1.f, 1.f ); - } - - void test_whichSide() - { - for( U32 i = 0; i < 100; ++ i ) - { - Point3F position( randF(), randF(), randF() ); - Point3F normal( randF(), randF(), randF() ); - - PlaneF p1( position, normal ); - - TEST( p1.whichSide( position + normal ) == PlaneF::Front ); - TEST( p1.whichSide( position + ( - normal ) ) == PlaneF::Back ); - TEST( p1.whichSide( position ) == PlaneF::On ); - } - } - - void test_distToPlane() - { - for( U32 i = 0; i < 100; ++ i ) - { - Point3F position( randF(), randF(), randF() ); - Point3F normal( randF(), randF(), randF() ); - - PlaneF p1( position, normal ); - - TEST( mIsEqual( p1.distToPlane( position + normal ), normal.len() ) ); - TEST( mIsEqual( p1.distToPlane( position + ( - normal ) ), - normal.len() ) ); - TEST( mIsZero( p1.distToPlane( position ) ) ); - } - } - - void run() - { - test_whichSide(); - test_distToPlane(); - } -}; - -#endif // !TORQUE_SHIPPING diff --git a/Engine/source/math/test/testPolyhedron.cpp b/Engine/source/math/test/testPolyhedron.cpp deleted file mode 100644 index 2bfe9b13f..000000000 --- a/Engine/source/math/test/testPolyhedron.cpp +++ /dev/null @@ -1,104 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "unit/test.h" -#include "math/mPolyhedron.h" - - -#ifndef TORQUE_SHIPPING - -using namespace UnitTesting; - -#define TEST( x ) test( ( x ), "FAIL: " #x ) -#define XTEST( t, x ) t->test( ( x ), "FAIL: " #x ) - - -CreateUnitTest( TestMathPolyhedronBuildFromPlanes, "Math/Polyhedron/BuildFromPlanes" ) -{ - void test_unitCube() - { - Vector< PlaneF > planes; - - // Build planes for a unit cube centered at the origin. - // Note that the normals must be facing inwards. - - planes.push_back( PlaneF( Point3F( -0.5f, 0.f, 0.f ), Point3F( 1.f, 0.f, 0.f ) ) ); - planes.push_back( PlaneF( Point3F( 0.5f, 0.f, 0.f ), Point3F( -1.f, 0.f, 0.f ) ) ); - planes.push_back( PlaneF( Point3F( 0.f, -0.5f, 0.f ), Point3F( 0.f, 1.f, 0.f ) ) ); - planes.push_back( PlaneF( Point3F( 0.f, 0.5f, 0.f ), Point3F( 0.f, -1.f, 0.f ) ) ); - planes.push_back( PlaneF( Point3F( 0.f, 0.f, -0.5f ), Point3F( 0.f, 0.f, 1.f ) ) ); - planes.push_back( PlaneF( Point3F( 0.f, 0.f, 0.5f ), Point3F( 0.f, 0.f, -1.f ) ) ); - - // Turn it into a polyhedron. - - Polyhedron polyhedron; - polyhedron.buildFromPlanes( - PlaneSetF( planes.address(), planes.size() ) - ); - - // Check if we got a cube back. - - TEST( polyhedron.getNumPoints() == 8 ); - TEST( polyhedron.getNumPlanes() == 6 ); - TEST( polyhedron.getNumEdges() == 12 ); - } - - void test_extraPlane() - { - Vector< PlaneF > planes; - - // Build planes for a unit cube centered at the origin. - // Note that the normals must be facing inwards. - - planes.push_back( PlaneF( Point3F( -0.5f, 0.f, 0.f ), Point3F( 1.f, 0.f, 0.f ) ) ); - planes.push_back( PlaneF( Point3F( 0.5f, 0.f, 0.f ), Point3F( -1.f, 0.f, 0.f ) ) ); - planes.push_back( PlaneF( Point3F( 0.f, -0.5f, 0.f ), Point3F( 0.f, 1.f, 0.f ) ) ); - planes.push_back( PlaneF( Point3F( 0.f, 0.5f, 0.f ), Point3F( 0.f, -1.f, 0.f ) ) ); - planes.push_back( PlaneF( Point3F( 0.f, 0.f, -0.5f ), Point3F( 0.f, 0.f, 1.f ) ) ); - planes.push_back( PlaneF( Point3F( 0.f, 0.f, 0.5f ), Point3F( 0.f, 0.f, -1.f ) ) ); - - // Add extra plane that doesn't contribute a new edge. - - planes.push_back( PlaneF( Point3F( 0.5f, 0.5f, 0.5f ), Point3F( -1.f, -1.f, -1.f ) ) ); - - // Turn it into a polyhedron. - - Polyhedron polyhedron; - polyhedron.buildFromPlanes( - PlaneSetF( planes.address(), planes.size() ) - ); - - // Check if we got a cube back. - - TEST( polyhedron.getNumPoints() == 8 ); - TEST( polyhedron.getNumPlanes() == 6 ); - TEST( polyhedron.getNumEdges() == 12 ); - } - - void run() - { - test_unitCube(); - //test_extraPlane(); - } -}; - -#endif // !TORQUE_SHIPPING diff --git a/Engine/source/navigation/navMesh.cpp b/Engine/source/navigation/navMesh.cpp index bdbde4f7e..17040b3a6 100644 --- a/Engine/source/navigation/navMesh.cpp +++ b/Engine/source/navigation/navMesh.cpp @@ -401,10 +401,9 @@ void NavMesh::buildNextTile() nm->removeTile(nm->getTileRefAt(tile.x, tile.y, 0), 0, 0); // Add new data (navmesh owns and deletes the data). dtStatus status = nm->addTile(data, dataSize, DT_TILE_FREE_DATA, 0, 0); - int success = 1; + if(dtStatusFailed(status)) { - success = 0; dtFree(data); } } diff --git a/Engine/source/navigation/navPath.cpp b/Engine/source/navigation/navPath.cpp index 5e4978afc..93c1a7a28 100644 --- a/Engine/source/navigation/navPath.cpp +++ b/Engine/source/navigation/navPath.cpp @@ -44,7 +44,8 @@ NavPath::NavPath() : mFrom(0.0f, 0.0f, 0.0f), mTo(0.0f, 0.0f, 0.0f) { - mTypeMask |= MarkerObjectType; + mTypeMask |= StaticShapeObjectType | MarkerObjectType; + mNetFlags.clear(Ghostable); mMesh = NULL; mWaypoints = NULL; @@ -162,6 +163,25 @@ const char *NavPath::getProtectedTo(void *obj, const char *data) return ""; } +bool NavPath::setProtectedAlwaysRender(void *obj, const char *index, const char *data) +{ + NavPath *path = static_cast(obj); + bool always = dAtob(data); + if(always) + { + if(!gEditingMission) + path->mNetFlags.set(Ghostable); + } + else + { + if(!gEditingMission) + path->mNetFlags.clear(Ghostable); + } + path->mAlwaysRender = always; + path->setMaskBits(PathMask); + return true; +} + static IRangeValidator NaturalNumber(1, S32_MAX); void NavPath::initPersistFields() @@ -188,9 +208,10 @@ void NavPath::initPersistFields() endGroup("NavPath"); addGroup("NavPath Render"); - - addField("alwaysRender", TypeBool, Offset(mAlwaysRender, NavPath), - "Render this NavPath even when not selected."); + + addProtectedField("alwaysRender", TypeBool, Offset(mAlwaysRender, NavMesh), + &setProtectedAlwaysRender, &defaultProtectedGetFn, + "Display this NavPath even outside the editor."); addField("xray", TypeBool, Offset(mXray, NavPath), "Render this NavPath through other objects."); @@ -204,8 +225,10 @@ bool NavPath::onAdd() if(!Parent::onAdd()) return false; + addToScene(); + // Ghost immediately if the editor's already open. - if(gEditingMission) + if(gEditingMission || mAlwaysRender) mNetFlags.set(Ghostable); // Automatically find a path if we can. @@ -215,18 +238,15 @@ bool NavPath::onAdd() // Set initial world bounds and stuff. resize(); - // Finally, add us to the simulation. - addToScene(); - return true; } void NavPath::onRemove() { - Parent::onRemove(); - // Remove from simulation. removeFromScene(); + + Parent::onRemove(); } bool NavPath::init() @@ -324,7 +344,9 @@ bool NavPath::plan() if(!init()) return false; - visitNext(); + if(!visitNext()) + return false; + while(update()); if(!finalise()) @@ -476,11 +498,18 @@ S32 NavPath::getCount() void NavPath::onEditorEnable() { mNetFlags.set(Ghostable); + if(isClientObject() && !mAlwaysRender) + addToScene(); } void NavPath::onEditorDisable() { - mNetFlags.clear(Ghostable); + if(!mAlwaysRender) + { + mNetFlags.clear(Ghostable); + if(isClientObject()) + removeFromScene(); + } } void NavPath::inspectPostApply() @@ -501,7 +530,7 @@ void NavPath::prepRenderImage(SceneRenderState *state) { ObjectRenderInst *ri = state->getRenderPass()->allocInst(); ri->renderDelegate.bind(this, &NavPath::renderSimple); - ri->type = RenderPassManager::RIT_Editor; + ri->type = RenderPassManager::RIT_Object; ri->translucentSort = true; ri->defaultKey = 1; state->getRenderPass()->addInst(ri); diff --git a/Engine/source/navigation/navPath.h b/Engine/source/navigation/navPath.h index 123a625d3..d7ba3d917 100644 --- a/Engine/source/navigation/navPath.h +++ b/Engine/source/navigation/navPath.h @@ -155,6 +155,8 @@ private: static const char *getProtectedMesh(void *obj, const char *data); static bool setProtectedWaypoints(void *obj, const char *index, const char *data); + static bool setProtectedAlwaysRender(void *obj, const char *index, const char *data); + static bool setProtectedFrom(void *obj, const char *index, const char *data); static const char *getProtectedFrom(void *obj, const char *data); diff --git a/Engine/source/platform/test/testAsyncPacketQueue.cpp b/Engine/source/platform/async/test/asyncPacketQueueTest.cpp similarity index 99% rename from Engine/source/platform/test/testAsyncPacketQueue.cpp rename to Engine/source/platform/async/test/asyncPacketQueueTest.cpp index 7c2d72333..f928b4da2 100644 --- a/Engine/source/platform/test/testAsyncPacketQueue.cpp +++ b/Engine/source/platform/async/test/asyncPacketQueueTest.cpp @@ -19,7 +19,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- - +/* #include "unit/test.h" #include "platform/async/asyncPacketQueue.h" #include "console/console.h" @@ -149,3 +149,4 @@ CreateUnitTest( TestAsyncPacketQueue, "Platform/AsyncPacketQueue" ) }; #endif // !TORQUE_SHIPPING +*/ \ No newline at end of file diff --git a/Engine/source/platform/input/event.cpp b/Engine/source/platform/input/event.cpp index 254aca29d..45b89e85f 100644 --- a/Engine/source/platform/input/event.cpp +++ b/Engine/source/platform/input/event.cpp @@ -381,7 +381,7 @@ CodeMapping gVirtualMap[] = { "lpov2", SI_POV, SI_LPOV2 }, { "rpov2", SI_POV, SI_RPOV2 }, -#if defined( TORQUE_OS_WIN32 ) || defined( TORQUE_OS_XENON ) +#if defined( TORQUE_OS_WIN ) || defined( TORQUE_OS_XENON ) //-------------------------------------- XINPUT EVENTS // Controller connect / disconnect: { "connect", SI_BUTTON, XI_CONNECT }, @@ -500,7 +500,7 @@ void InputEventManager::buildInputEvent(U32 deviceType, U32 deviceInst, InputEve newEvent.postToSignal(Input::smInputEvent); } -void InputEventManager::buildInputEvent(U32 deviceType, U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, float fValue) +void InputEventManager::buildInputEvent(U32 deviceType, U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, F32 fValue) { InputEventInfo newEvent; diff --git a/Engine/source/platform/input/event.h b/Engine/source/platform/input/event.h index 965dc0ac6..916d1910f 100644 --- a/Engine/source/platform/input/event.h +++ b/Engine/source/platform/input/event.h @@ -496,7 +496,7 @@ public: void buildInputEvent(U32 deviceType, U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, S32 iValue); /// Build an input event based on a single fValue - void buildInputEvent(U32 deviceType, U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, float fValue); + void buildInputEvent(U32 deviceType, U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, F32 fValue); /// Build an input event based on a Point3F void buildInputEvent(U32 deviceType, U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, Point3F& pValue); diff --git a/Engine/source/platform/input/razerHydra/razerHydraDevice.cpp b/Engine/source/platform/input/razerHydra/razerHydraDevice.cpp index 89dd771f3..8a36bd9d6 100644 --- a/Engine/source/platform/input/razerHydra/razerHydraDevice.cpp +++ b/Engine/source/platform/input/razerHydra/razerHydraDevice.cpp @@ -260,7 +260,7 @@ bool RazerHydraDevice::enable() #endif const char* dllName; -#ifdef TORQUE_OS_WIN32 +#ifdef TORQUE_OS_WIN #ifdef TORQUE_DEBUG dllName = "sixensed.dll"; #else diff --git a/Engine/source/platform/platform.h b/Engine/source/platform/platform.h index eeda303b9..d390eef5c 100644 --- a/Engine/source/platform/platform.h +++ b/Engine/source/platform/platform.h @@ -212,7 +212,7 @@ namespace Platform void debugBreak(); // Random - float getRandom(); + F32 getRandom(); // Window state void setWindowLocked(bool locked); @@ -338,6 +338,9 @@ namespace Platform // display Splash Window bool displaySplashWindow( String path ); + // close Splash Window + bool closeSplashWindow(); + void openFolder( const char* path ); // Open file at the OS level, according to registered file-types. @@ -412,7 +415,7 @@ namespace Platform //------------------------------------------------------------------------------ // Misc StdLib functions #define QSORT_CALLBACK FN_CDECL -inline void dQsort(void *base, U32 nelem, U32 width, int (QSORT_CALLBACK *fcmp)(const void *, const void *)) +inline void dQsort(void *base, U32 nelem, U32 width, S32 (QSORT_CALLBACK *fcmp)(const void *, const void *)) { qsort(base, nelem, width, fcmp); } @@ -507,7 +510,7 @@ extern void* dRealloc_r(void* in_pResize, dsize_t in_size, const char*, const ds extern void* dRealMalloc(dsize_t); extern void dRealFree(void*); -extern void *dMalloc_aligned(dsize_t in_size, int alignment); +extern void *dMalloc_aligned(dsize_t in_size, S32 alignment); extern void dFree_aligned(void *); @@ -525,8 +528,8 @@ template void dCopyArray(T *dst, const S *src, dsize_t size) extern void* dMemcpy(void *dst, const void *src, dsize_t size); extern void* dMemmove(void *dst, const void *src, dsize_t size); -extern void* dMemset(void *dst, int c, dsize_t size); -extern int dMemcmp(const void *ptr1, const void *ptr2, dsize_t size); +extern void* dMemset(void *dst, S32 c, dsize_t size); +extern S32 dMemcmp(const void *ptr1, const void *ptr2, dsize_t size); // Special case of the above function when the arrays are the same type (use memcpy) template void dCopyArray(T *dst, const T *src, dsize_t size) @@ -565,8 +568,8 @@ enum DFILE_STATUS extern FILE_HANDLE dOpenFileRead(const char *name, DFILE_STATUS &error); extern FILE_HANDLE dOpenFileReadWrite(const char *name, bool append, DFILE_STATUS &error); -extern int dFileRead(FILE_HANDLE handle, U32 bytes, char *dst, DFILE_STATUS &error); -extern int dFileWrite(FILE_HANDLE handle, U32 bytes, const char *dst, DFILE_STATUS &error); +extern S32 dFileRead(FILE_HANDLE handle, U32 bytes, char *dst, DFILE_STATUS &error); +extern S32 dFileWrite(FILE_HANDLE handle, U32 bytes, const char *dst, DFILE_STATUS &error); extern void dFileClose(FILE_HANDLE handle); extern StringTableEntry osGetTemporaryDirectory(); diff --git a/Engine/source/platform/platformAssert.h b/Engine/source/platform/platformAssert.h index 4865d387c..60ed7d3d5 100644 --- a/Engine/source/platform/platformAssert.h +++ b/Engine/source/platform/platformAssert.h @@ -96,8 +96,8 @@ public: { if ( ::PlatformAssert::processAssert(::PlatformAssert::Fatal, __FILE__, __LINE__, y) ) { ::Platform::debugBreak(); } } } #else - #define AssertFatal(x, y) { (void)sizeof(x); (void)sizeof(y); } - #define AssertWarn(x, y) { (void)sizeof(x); (void)sizeof(y); } + #define AssertFatal(x, y) { TORQUE_UNUSED(x); TORQUE_UNUSED(y); } + #define AssertWarn(x, y) { TORQUE_UNUSED(x); TORQUE_UNUSED(y); } #endif /*! diff --git a/Engine/source/platform/platformCPUCount.cpp b/Engine/source/platform/platformCPUCount.cpp index 116251e08..026cdbabf 100644 --- a/Engine/source/platform/platformCPUCount.cpp +++ b/Engine/source/platform/platformCPUCount.cpp @@ -24,6 +24,8 @@ #include "platform/platform.h" #include "platform/platformCPUCount.h" +#if defined(TORQUE_OS_LINUX) || defined(TORQUE_OS_OSX) || defined(TORQUE_OS_XENON) || defined(TORQUE_OS_PS3) + // Consoles don't need this #if defined(TORQUE_OS_XENON) || defined(TORQUE_OS_PS3) namespace CPUInfo @@ -53,7 +55,7 @@ EConfig CPUCount(U32& TotAvailLogical, U32& TotAvailCore, U32& PhysicalNum) #include #include #define DWORD unsigned long -#elif defined( TORQUE_OS_WIN32 ) +#elif defined( TORQUE_OS_WIN ) #include #elif defined( TORQUE_OS_MAC ) # include @@ -80,13 +82,13 @@ namespace CPUInfo { #ifndef TORQUE_OS_MAC - static unsigned int CpuIDSupported(void); - static unsigned int find_maskwidth(unsigned int); - static unsigned int HWD_MTSupported(void); - static unsigned int MaxLogicalProcPerPhysicalProc(void); - static unsigned int MaxCorePerPhysicalProc(void); - static unsigned char GetAPIC_ID(void); - static unsigned char GetNzbSubID(unsigned char, unsigned char, unsigned char); + static U32 CpuIDSupported(void); + static U32 find_maskwidth(unsigned int); + static U32 HWD_MTSupported(void); + static U32 MaxLogicalProcPerPhysicalProc(void); + static U32 MaxCorePerPhysicalProc(void); + static U8 GetAPIC_ID(void); + static U8 GetNzbSubID(U8, U8, U8); #endif static char g_s3Levels[2048]; @@ -97,14 +99,13 @@ namespace CPUInfo { // CpuIDSupported will return 0 if CPUID instruction is unavailable. Otherwise, it will return // the maximum supported standard function. // - static unsigned int CpuIDSupported(void) + static U32 CpuIDSupported(void) { - unsigned int MaxInputValue; + U32 maxInputValue = 0; // If CPUID instruction is supported #ifdef TORQUE_COMPILER_GCC try { - MaxInputValue = 0; // call cpuid with eax = 0 asm ( @@ -112,7 +113,7 @@ namespace CPUInfo { "xorl %%eax,%%eax\n\t" "cpuid\n\t" "popl %%ebx\n\t" - : "=a" (MaxInputValue) + : "=a" (maxInputValue) : : "%ecx", "%edx" ); @@ -124,25 +125,23 @@ namespace CPUInfo { #elif defined( TORQUE_COMPILER_VISUALC ) try { - MaxInputValue = 0; // call cpuid with eax = 0 __asm { xor eax, eax cpuid - mov MaxInputValue, eax + mov maxInputValue, eax } } catch (...) { - return(0); // cpuid instruction is unavailable + // cpuid instruction is unavailable } #else # error Not implemented. #endif - return MaxInputValue; - + return maxInputValue; } @@ -153,12 +152,12 @@ namespace CPUInfo { // maximum value. // - static unsigned int MaxCorePerPhysicalProc(void) + static U32 MaxCorePerPhysicalProc(void) { - unsigned int Regeax = 0; + U32 Regeax = 0; - if (!HWD_MTSupported()) return (unsigned int) 1; // Single core + if (!HWD_MTSupported()) return (U32) 1; // Single core #ifdef TORQUE_COMPILER_GCC { asm @@ -209,7 +208,7 @@ multi_core: #else # error Not implemented. #endif - return (unsigned int)((Regeax & NUM_CORE_BITS) >> 26)+1; + return (U32)((Regeax & NUM_CORE_BITS) >> 26)+1; } @@ -218,11 +217,11 @@ multi_core: // // The function returns 0 when the hardware multi-threaded bit is not set. // - static unsigned int HWD_MTSupported(void) + static U32 HWD_MTSupported(void) { - unsigned int Regedx = 0; + U32 Regedx = 0; if ((CpuIDSupported() >= 1)) @@ -262,12 +261,12 @@ multi_core: // AVAILABLE logical processors per physical to be used by an application might be less than this // maximum value. // - static unsigned int MaxLogicalProcPerPhysicalProc(void) + static U32 MaxLogicalProcPerPhysicalProc(void) { - unsigned int Regebx = 0; + U32 Regebx = 0; - if (!HWD_MTSupported()) return (unsigned int) 1; + if (!HWD_MTSupported()) return (U32) 1; #ifdef TORQUE_COMPILER_GCC asm ( @@ -292,10 +291,10 @@ multi_core: } - static unsigned char GetAPIC_ID(void) + static U8 GetAPIC_ID(void) { - unsigned int Regebx = 0; + U32 Regebx = 0; #ifdef TORQUE_COMPILER_GCC asm ( @@ -324,9 +323,9 @@ multi_core: // // Determine the width of the bit field that can represent the value count_item. // - unsigned int find_maskwidth(unsigned int CountItem) + U32 find_maskwidth(U32 CountItem) { - unsigned int MaskWidth, + U32 MaskWidth, count = CountItem; #ifdef TORQUE_COMPILER_GCC asm @@ -392,16 +391,16 @@ next: // // Extract the subset of bit field from the 8-bit value FullID. It returns the 8-bit sub ID value // - static unsigned char GetNzbSubID(unsigned char FullID, - unsigned char MaxSubIDValue, - unsigned char ShiftCount) + static U8 GetNzbSubID(U8 FullID, + U8 MaxSubIDValue, + U8 ShiftCount) { - unsigned int MaskWidth; - unsigned char MaskBits; + U32 MaskWidth; + U8 MaskBits; - MaskWidth = find_maskwidth((unsigned int) MaxSubIDValue); + MaskWidth = find_maskwidth((U32) MaxSubIDValue); MaskBits = (0xff << ShiftCount) ^ - ((unsigned char) (0xff << (ShiftCount + MaskWidth))); + ((U8) (0xff << (ShiftCount + MaskWidth))); return (FullID & MaskBits); } @@ -420,8 +419,8 @@ next: TotAvailCore = 1; PhysicalNum = 1; - unsigned int numLPEnabled = 0; - int MaxLPPerCore = 1; + U32 numLPEnabled = 0; + S32 MaxLPPerCore = 1; #ifdef TORQUE_OS_MAC @@ -430,8 +429,8 @@ next: // like there isn't a way to do this that's working across all OSX incarnations // and machine configurations anyway. - int numCPUs; - int numPackages; + S32 numCPUs; + S32 numPackages; // Get the number of CPUs. @@ -450,9 +449,9 @@ next: #else U32 dwAffinityMask; - int j = 0; - unsigned char apicID, PackageIDMask; - unsigned char tblPkgID[256], tblCoreID[256], tblSMTID[256]; + S32 j = 0; + U8 apicID, PackageIDMask; + U8 tblPkgID[256], tblCoreID[256], tblSMTID[256]; char tmp[256]; #ifdef TORQUE_OS_LINUX @@ -464,19 +463,19 @@ next: // Linux doesn't easily allow us to look at the Affinity Bitmask directly, // but it does provide an API to test affinity maskbits of the current process // against each logical processor visible under OS. - int sysNumProcs = sysconf(_SC_NPROCESSORS_CONF); //This will tell us how many + S32 sysNumProcs = sysconf(_SC_NPROCESSORS_CONF); //This will tell us how many //CPUs are currently enabled. //this will tell us which processors this process can run on. cpu_set_t allowedCPUs; sched_getaffinity(0, sizeof(allowedCPUs), &allowedCPUs); - for (int i = 0; i < sysNumProcs; i++ ) + for (S32 i = 0; i < sysNumProcs; i++ ) { if ( CPU_ISSET(i, &allowedCPUs) == 0 ) return CONFIG_UserConfigIssue; } -#elif defined( TORQUE_OS_WIN32 ) +#elif defined( TORQUE_OS_WIN ) DWORD dwProcessAffinity, dwSystemAffinity; GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinity, @@ -504,7 +503,7 @@ next: if ( sched_setaffinity (0, sizeof(currentCPU), ¤tCPU) == 0 ) { sleep(0); // Ensure system to switch to the right CPU -#elif defined( TORQUE_OS_WIN32 ) +#elif defined( TORQUE_OS_WIN ) while (dwAffinityMask && dwAffinityMask <= dwSystemAffinity) { if (SetThreadAffinityMask(GetCurrentThread(), dwAffinityMask)) @@ -522,8 +521,8 @@ next: // processors per core tblSMTID[j] = GetNzbSubID(apicID, MaxLPPerCore, 0); - unsigned char maxCorePPP = MaxCorePerPhysicalProc(); - unsigned char maskWidth = find_maskwidth(MaxLPPerCore); + U8 maxCorePPP = MaxCorePerPhysicalProc(); + U8 maskWidth = find_maskwidth(MaxLPPerCore); tblCoreID[j] = GetNzbSubID(apicID, maxCorePPP, maskWidth); // Extract package ID, assume single cluster. @@ -549,7 +548,7 @@ next: #ifdef TORQUE_OS_LINUX sched_setaffinity (0, sizeof(allowedCPUs), &allowedCPUs); sleep(0); -#elif defined( TORQUE_OS_WIN32 ) +#elif defined( TORQUE_OS_WIN ) SetThreadAffinityMask(GetCurrentThread(), dwProcessAffinity); Sleep(0); #else @@ -560,9 +559,9 @@ next: // // Count available cores (TotAvailCore) in the system // - unsigned char CoreIDBucket[256]; + U8 CoreIDBucket[256]; DWORD ProcessorMask, pCoreMask[256]; - unsigned int i, ProcessorNum; + U32 i, ProcessorNum; CoreIDBucket[0] = tblPkgID[0] | tblCoreID[0]; ProcessorMask = 1; @@ -598,7 +597,7 @@ next: // // Count physical processor (PhysicalNum) in the system // - unsigned char PackageIDBucket[256]; + U8 PackageIDBucket[256]; DWORD pPackageMask[256]; PackageIDBucket[0] = tblPkgID[0]; @@ -664,4 +663,6 @@ next: } } // namespace CPUInfo -#endif \ No newline at end of file +#endif + +#endif diff --git a/Engine/source/platform/platformFileIO.cpp b/Engine/source/platform/platformFileIO.cpp index 0209f239e..fc42c0565 100644 --- a/Engine/source/platform/platformFileIO.cpp +++ b/Engine/source/platform/platformFileIO.cpp @@ -140,7 +140,7 @@ inline void catPath(char *dst, const char *src, U32 len) // converts the posix root path "/" to "c:/" for win32 // FIXME: this is not ideal. the c: drive is not guaranteed to exist. -#if defined(TORQUE_OS_WIN32) +#if defined(TORQUE_OS_WIN) static inline void _resolveLeadingSlash(char* buf, U32 size) { if(buf[0] != '/') @@ -227,7 +227,7 @@ char * Platform::makeFullPathName(const char *path, char *buffer, U32 size, cons if(Platform::isFullPath(bspath)) { // Already a full path - #if defined(TORQUE_OS_WIN32) + #if defined(TORQUE_OS_WIN) _resolveLeadingSlash(bspath, sizeof(bspath)); #endif dStrncpy(buffer, bspath, size); diff --git a/Engine/source/platform/platformFont.h b/Engine/source/platform/platformFont.h index a0deffc82..63a47d95a 100644 --- a/Engine/source/platform/platformFont.h +++ b/Engine/source/platform/platformFont.h @@ -88,10 +88,10 @@ public: /// This is just for createPlatformFont to call. /// /// @todo Rethink this so we don't have a private public. - virtual bool create(const char *name, U32 size, U32 charset = TGE_ANSI_CHARSET) = 0; + virtual bool create( const char *name, dsize_t size, U32 charset = TGE_ANSI_CHARSET ) = 0; static void enumeratePlatformFonts( Vector& fonts, UTF16* fontFamily = NULL ); }; -extern PlatformFont *createPlatformFont(const char *name, U32 size, U32 charset = TGE_ANSI_CHARSET); +extern PlatformFont *createPlatformFont(const char *name, dsize_t size, U32 charset = TGE_ANSI_CHARSET); #endif // _PLATFORMFONT_H_ diff --git a/Engine/source/platform/platformIntrinsics.h b/Engine/source/platform/platformIntrinsics.h index fd2e11916..b63a987be 100644 --- a/Engine/source/platform/platformIntrinsics.h +++ b/Engine/source/platform/platformIntrinsics.h @@ -40,7 +40,7 @@ template< typename T > inline bool dCompareAndSwap( T* volatile& refPtr, T* oldPtr, T* newPtr ) { - return dCompareAndSwap( *reinterpret_cast< volatile U32* >( &refPtr ), ( U32 ) oldPtr, ( U32 ) newPtr ); + return dCompareAndSwap( *reinterpret_cast< volatile size_t* >( &refPtr ), ( size_t ) oldPtr, ( size_t ) newPtr ); } // Test-And-Set diff --git a/Engine/source/platform/platformMemory.cpp b/Engine/source/platform/platformMemory.cpp index 925a15422..44a68d8a7 100644 --- a/Engine/source/platform/platformMemory.cpp +++ b/Engine/source/platform/platformMemory.cpp @@ -367,7 +367,7 @@ static U32 validateTreeRecurse(TreeNode *tree) if(tree == NIL) return 1; // check my left tree - int lcount, rcount, nc = 0; + S32 lcount, rcount, nc = 0; if(tree->color == Red) { @@ -798,19 +798,17 @@ void checkPtr( void* ptr ) AllocatedHeader* header = ( AllocatedHeader* ) *iter; if( header->getUserPtr() == ptr ) { - char buffer[ 1024 ]; - #ifdef TORQUE_DEBUG_GUARD + char buffer[ 1024 ]; if( !checkGuard( *iter, true ) ) { dSprintf( buffer, sizeof( buffer ), "0x%x is a valid heap pointer but has its guards corrupted", ptr ); Platform::outputDebugString( buffer ); return; } -#endif - //dSprintf( buffer, sizeof( buffer ), "0x%x is a valid heap pointer", ptr ); //Platform::outputDebugString( buffer ); +#endif return; } } @@ -1588,7 +1586,7 @@ dsize_t getMemoryUsed() } #ifdef TORQUE_DEBUG_GUARD -DefineEngineFunction( dumpAlloc, void, ( int allocNum ),, +DefineEngineFunction( dumpAlloc, void, ( S32 allocNum ),, "@brief Dumps information about the given allocated memory block.\n\n" "@param allocNum Memory block to dump information about." "@note Available in debug builds only. " diff --git a/Engine/source/platform/platformNet.cpp b/Engine/source/platform/platformNet.cpp index 786fcf62d..acc4e9905 100644 --- a/Engine/source/platform/platformNet.cpp +++ b/Engine/source/platform/platformNet.cpp @@ -23,14 +23,18 @@ #include "platform/platformNet.h" #include "core/strings/stringFunctions.h" -#if defined (TORQUE_OS_WIN32) +#if defined (TORQUE_OS_WIN) #define TORQUE_USE_WINSOCK #include #include + +#ifndef EINPROGRESS #define EINPROGRESS WSAEINPROGRESS +#endif // EINPROGRESS + #define ioctl ioctlsocket -typedef int socklen_t; +typedef S32 socklen_t; #elif defined ( TORQUE_OS_MAC ) @@ -84,7 +88,7 @@ typedef in_addr IN_ADDR; #define TORQUE_USE_WINSOCK #define EINPROGRESS WSAEINPROGRESS #define ioctl ioctlsocket -typedef int socklen_t; +typedef S32 socklen_t; DWORD _getLastErrorAndClear() { @@ -99,7 +103,7 @@ DWORD _getLastErrorAndClear() #endif #if defined(TORQUE_USE_WINSOCK) -static const char* strerror_wsa( int code ) +static const char* strerror_wsa( S32 code ) { switch( code ) { @@ -137,7 +141,7 @@ static const char* strerror_wsa( int code ) static Net::Error getLastError(); static S32 defaultPort = 28000; static S32 netPort = 0; -static int udpSocket = InvalidSocket; +static S32 udpSocket = InvalidSocket; ConnectionNotifyEvent Net::smConnectionNotify; ConnectionAcceptedEvent Net::smConnectionAccept; @@ -441,7 +445,7 @@ void Net::closeConnectTo(NetSocket sock) return; // if this socket is in the list of polled sockets, remove it - for (int i = 0; i < gPolledSockets.size(); ++i) + for (S32 i = 0; i < gPolledSockets.size(); ++i) { if (gPolledSockets[i]->fd == sock) { @@ -454,7 +458,7 @@ void Net::closeConnectTo(NetSocket sock) closeSocket(sock); } -Net::Error Net::sendtoSocket(NetSocket socket, const U8 *buffer, int bufferSize) +Net::Error Net::sendtoSocket(NetSocket socket, const U8 *buffer, S32 bufferSize) { if(Journal::IsPlaying()) { @@ -480,7 +484,7 @@ bool Net::openPort(S32 port, bool doBind) // we turn off VDP in non-release builds because VDP does not support broadcast packets // which are required for LAN queries (PC->Xbox connectivity). The wire protocol still // uses the VDP packet structure, though. - int protocol = 0; + S32 protocol = 0; bool useVDP = false; #ifdef TORQUE_DISABLE_PC_CONNECTIVITY // Xbox uses a VDP (voice/data protocol) socket for networking @@ -617,7 +621,7 @@ void Net::process() sockaddr_in ipAddr; NetSocket incoming = InvalidSocket; char out_h_addr[1024]; - int out_h_length = 0; + S32 out_h_length = 0; RawData readBuff; for (S32 i = 0; i < gPolledSockets.size(); @@ -727,7 +731,7 @@ void Net::process() if(::connect(currentSock->fd, (struct sockaddr *)&ipAddr, sizeof(ipAddr)) == -1) { - int errorCode; + S32 errorCode; #if defined(TORQUE_USE_WINSOCK) errorCode = WSAGetLastError(); if( errorCode == WSAEINPROGRESS || errorCode == WSAEWOULDBLOCK ) @@ -786,7 +790,7 @@ void Net::process() NetSocket Net::openSocket() { - int retSocket; + S32 retSocket; retSocket = socket(AF_INET, SOCK_STREAM, 0); if(retSocket == InvalidSocket) @@ -831,7 +835,7 @@ NetSocket Net::accept(NetSocket acceptSocket, NetAddress *remoteAddress) sockaddr_in socketAddress; socklen_t addrLen = sizeof(socketAddress); - int retVal = ::accept(acceptSocket, (sockaddr *) &socketAddress, &addrLen); + S32 retVal = ::accept(acceptSocket, (sockaddr *) &socketAddress, &addrLen); if(retVal != InvalidSocket) { IPSocketToNetAddress(&socketAddress, remoteAddress); diff --git a/Engine/source/platform/platformNet.h b/Engine/source/platform/platformNet.h index b37558ebd..16a809927 100644 --- a/Engine/source/platform/platformNet.h +++ b/Engine/source/platform/platformNet.h @@ -31,14 +31,14 @@ #define MAXPACKETSIZE 1500 #endif -typedef int NetConnectionId; +typedef S32 NetConnectionId; /// Generic network address /// /// This is used to represent IP addresses. struct NetAddress { - int type; ///< Type of address (IPAddress currently) + S32 type; ///< Type of address (IPAddress currently) /// Acceptable NetAddress types. enum @@ -93,7 +93,7 @@ struct Net TCPProtocol }; - static const int MaxPacketDataSize = MAXPACKETSIZE; + static const S32 MaxPacketDataSize = MAXPACKETSIZE; static ConnectionNotifyEvent smConnectionNotify; static ConnectionAcceptedEvent smConnectionAccept; diff --git a/Engine/source/platform/platformNetAsync.cpp b/Engine/source/platform/platformNetAsync.cpp index 8f246d39f..701410e38 100644 --- a/Engine/source/platform/platformNetAsync.cpp +++ b/Engine/source/platform/platformNetAsync.cpp @@ -25,7 +25,7 @@ #include "platform/threads/threadPool.h" #include "console/console.h" -#if defined(TORQUE_OS_WIN32) +#if defined(TORQUE_OS_WIN) # include #elif defined(TORQUE_OS_XENON) # include @@ -48,7 +48,7 @@ struct NetAsync::NameLookupRequest NetSocket sock; char remoteAddr[4096]; char out_h_addr[4096]; - int out_h_length; + S32 out_h_length; bool complete; NameLookupRequest() @@ -140,7 +140,7 @@ void NetAsync::queueLookup(const char* remoteAddr, NetSocket socket) { // do we have it already? - unsigned int i = 0; + U32 i = 0; for (i = 0; i < mLookupRequests.size(); ++i) { if (mLookupRequests[i].sock == socket) @@ -160,7 +160,7 @@ void NetAsync::queueLookup(const char* remoteAddr, NetSocket socket) } bool NetAsync::checkLookup(NetSocket socket, char* out_h_addr, - int* out_h_length, int out_h_addr_size) + S32* out_h_length, S32 out_h_addr_size) { bool found = false; diff --git a/Engine/source/platform/platformNetAsync.h b/Engine/source/platform/platformNetAsync.h index ddeff56f3..dc59a1a87 100644 --- a/Engine/source/platform/platformNetAsync.h +++ b/Engine/source/platform/platformNetAsync.h @@ -54,7 +54,7 @@ class NetAsync // out_h_length will be set appropriately. if out_h_length is -1, then // name could not be resolved. otherwise, it provides the number of // address bytes copied into out_h_addr. - bool checkLookup(NetSocket socket, char* out_h_addr, int* out_h_length, int out_h_addr_size); + bool checkLookup(NetSocket socket, char* out_h_addr, int* out_h_length, S32 out_h_addr_size); }; // the global net async object diff --git a/Engine/source/platform/platformVolume.cpp b/Engine/source/platform/platformVolume.cpp index 526e5d0a3..9304ea891 100644 --- a/Engine/source/platform/platformVolume.cpp +++ b/Engine/source/platform/platformVolume.cpp @@ -22,7 +22,7 @@ #include "platform/platform.h" -#if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) +#if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) #include #else #include @@ -84,7 +84,7 @@ bool MountZips(const String &root) bool Touch( const Path &path ) { -#if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) +#if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) return( utime( path.getFullPath(), 0 ) != -1 ); #else return( utimes( path.getFullPath(), NULL) == 0 ); // utimes returns 0 on success. diff --git a/Engine/source/platform/profiler.cpp b/Engine/source/platform/profiler.cpp index f97100f09..8284ffb34 100644 --- a/Engine/source/platform/profiler.cpp +++ b/Engine/source/platform/profiler.cpp @@ -22,7 +22,7 @@ #include "platform/platform.h" -#if defined(TORQUE_OS_WIN32) +#if defined(TORQUE_OS_WIN) #include // for SetThreadAffinityMask #endif @@ -462,7 +462,7 @@ void Profiler::hashPop(ProfilerRootData *expected) if(!mEnabled && mNextEnable) startHighResolutionTimer(mCurrentProfilerData->mStartTime); -#if defined(TORQUE_OS_WIN32) +#if defined(TORQUE_OS_WIN) // The high performance counters under win32 are unreliable when running on multiple // processors. When the profiler is enabled, we restrict Torque to a single processor. if(mNextEnable != mEnabled) @@ -476,8 +476,8 @@ void Profiler::hashPop(ProfilerRootData *expected) else { Con::warnf("Warning: the Torque profiler thread may now run on any cpu."); - DWORD procMask; - DWORD sysMask; + DWORD_PTR procMask; + DWORD_PTR sysMask; GetProcessAffinityMask( GetCurrentProcess(), &procMask, &sysMask); SetThreadAffinityMask( GetCurrentThread(), procMask); } diff --git a/Engine/source/platform/test/netTest.cpp b/Engine/source/platform/test/netTest.cpp new file mode 100644 index 000000000..63c38229a --- /dev/null +++ b/Engine/source/platform/test/netTest.cpp @@ -0,0 +1,174 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "platform/platformNet.h" +#include "core/util/journal/process.h" + +TEST(Net, TCPRequest) +{ + struct handle + { + NetSocket mSocket; + S32 mDataReceived; + + void notify(NetSocket sock, U32 state) + { + // Only consider our own socket. + if(mSocket != sock) + return; + + // Ok - what's the state? We do some dumb responses to given states + // in order to fulfill the request. + if(state == Net::Connected) + { + U8 reqBuffer[] = { + "GET / HTTP/1.0\nUser-Agent: Torque/1.0\n\n" + }; + + Net::Error e = Net::sendtoSocket(mSocket, reqBuffer, sizeof(reqBuffer)); + + ASSERT_EQ(Net::NoError, e) + << "Got an error sending our HTTP request!"; + } + else + { + Process::requestShutdown(); + mSocket = NULL; + ASSERT_EQ(Net::Disconnected, state) + << "Ended with a network error!"; + } + } + + void receive(NetSocket sock, RawData incomingData) + { + // Only consider our own socket. + if(mSocket != sock) + return; + + mDataReceived += incomingData.size; + } + } handler; + + handler.mSocket = InvalidSocket; + handler.mDataReceived = 0; + + // Hook into the signals. + Net::smConnectionNotify. notify(&handler, &handle::notify); + Net::smConnectionReceive.notify(&handler, &handle::receive); + + // Open a TCP connection to garagegames.com + handler.mSocket = Net::openConnectTo("72.246.107.193:80"); + const U32 limit = Platform::getRealMilliseconds() + (5*1000); + while(Process::processEvents() && (Platform::getRealMilliseconds() < limit) ) {} + + // Unhook from the signals. + Net::smConnectionNotify. remove(&handler, &handle::notify); + Net::smConnectionReceive.remove(&handler, &handle::receive); + + EXPECT_GT(handler.mDataReceived, 0) + << "Didn't get any data back!"; +} + +TEST(Net, JournalTCPRequest) +{ + struct handle + { + NetSocket mSocket; + S32 mDataReceived; + + void notify(NetSocket sock, U32 state) + { + // Only consider our own socket. + if(mSocket != sock) + return; + + // Ok - what's the state? We do some dumb responses to given states + // in order to fulfill the request. + if(state == Net::Connected) + { + U8 reqBuffer[] = { + "GET / HTTP/1.0\nUser-Agent: Torque/1.0\n\n" + }; + + Net::Error e = Net::sendtoSocket(mSocket, reqBuffer, sizeof(reqBuffer)); + + ASSERT_EQ(Net::NoError, e) + << "Got an error sending our HTTP request!"; + } + else + { + Process::requestShutdown(); + mSocket = NULL; + ASSERT_EQ(Net::Disconnected, state) + << "Ended with a network error!"; + } + } + + void receive(NetSocket sock, RawData incomingData) + { + // Only consider our own socket. + if(mSocket != sock) + return; + mDataReceived += incomingData.size; + } + + void makeRequest() + { + mSocket = InvalidSocket; + mDataReceived = 0; + + // Hook into the signals. + Net::smConnectionNotify. notify(this, &handle::notify); + Net::smConnectionReceive.notify(this, &handle::receive); + + // Open a TCP connection to garagegames.com + mSocket = Net::openConnectTo("72.246.107.193:80"); + + // Let the callbacks enable things to process. + while(Process::processEvents()) {} + + // Unhook from the signals. + Net::smConnectionNotify. remove(this, &handle::notify); + Net::smConnectionReceive.remove(this, &handle::receive); + + EXPECT_GT(mDataReceived, 0) + << "Didn't get any data back!"; + } + } handler; + + Journal::Record("journalTCP.jrn"); + ASSERT_TRUE(Journal::IsRecording()); + handler.makeRequest(); + S32 bytesRead = handler.mDataReceived; + Journal::Stop(); + + Journal::Play("journalTCP.jrn"); + handler.makeRequest(); + Journal::Stop(); + + EXPECT_EQ(bytesRead, handler.mDataReceived) + << "Didn't get same data back from journal playback."; +} + +#endif \ No newline at end of file diff --git a/Engine/source/platform/test/platformFileIOTest.cpp b/Engine/source/platform/test/platformFileIOTest.cpp new file mode 100644 index 000000000..c27278431 --- /dev/null +++ b/Engine/source/platform/test/platformFileIOTest.cpp @@ -0,0 +1,118 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "platform/platform.h" +#include "core/fileio.h" +#include "core/util/tVector.h" +#include "console/console.h" + +TEST(Platform, ExcludedDirectories) +{ + // Just dump everything under the current directory. We should + // find at least one file. + + // Exclude .svn and CVS + Platform::clearExcludedDirectories(); + Platform::addExcludedDirectory(".svn"); + Platform::addExcludedDirectory("CVS"); + + EXPECT_TRUE(Platform::isExcludedDirectory(".svn")) + << "On list, should be excluded."; + EXPECT_TRUE(Platform::isExcludedDirectory("CVS")) + << "On list, should be excluded."; + EXPECT_FALSE(Platform::isExcludedDirectory("foo")) + << "Doesn't match list, shouldn't be excluded."; + EXPECT_FALSE(Platform::isExcludedDirectory(".svnCVS")) + << "Looks like a duck, but it shouldn't be excluded cuz it's distinct from all entries on the exclusion list."; + + // Ok, now our exclusion list is setup, so let's dump some paths. + Vector pathInfo; + Platform::dumpPath(Platform::getCurrentDirectory(), pathInfo, 2); + EXPECT_GT(pathInfo.size(), 0) + << "Should find at least SOMETHING in the current directory!"; + + // This'll nuke info if we run it in a live situation... so don't run unit + // tests in a live situation. ;) + Platform::clearExcludedDirectories(); +}; + +TEST(File, TouchAndTime) +{ + FileTime create[2], modify[2]; + + // Create a file and sleep for a second. + File f; + f.open("testTouch.file", File::WriteAppend); + f.close(); + + // Touch a file and note its last-modified. + dFileTouch("testTouch.file"); + EXPECT_TRUE(Platform::isFile("testTouch.file")) + << "We just touched this file - it should exist."; + EXPECT_TRUE(Platform::getFileTimes("testTouch.file", &create[0], &modify[0])) + << "Failed to get filetimes for a file we just created."; + + // Sleep for a tick + Platform::sleep(10); + + // Touch it again, and compare the last-modifieds. + EXPECT_TRUE(Platform::isFile("testTouch.file")) + << "We just touched this file - it should exist."; + dFileTouch("testTouch.file"); + EXPECT_TRUE(Platform::isFile("testTouch.file")) + << "We just touched this file - it should exist."; + EXPECT_TRUE(Platform::getFileTimes("testTouch.file", &create[1], &modify[1])) + << "Failed to get filetimes for a file we just created."; + + // Now compare the times... + EXPECT_LT(Platform::compareFileTimes(modify[0], modify[1]), 0) + << "Timestamps are wrong - modify[0] should be before modify[1]!"; + EXPECT_EQ(Platform::compareFileTimes(create[0], create[1]), 0) + << "Create timestamps should match - we didn't delete the file during this test."; + + // Clean up.. + dFileDelete("testTouch.file"); + EXPECT_FALSE(Platform::isFile("testTouch.file")) + << "Somehow failed to delete our test file."; +}; + +// Mac has no implementations for these functions, so we 'def it out for now. +#ifndef __MACOSX__ +TEST(Platform, Volumes) +{ + Vector names; + Platform::getVolumeNamesList(names); + + EXPECT_GT(names.size(), 0) + << "We should have at least one volume..."; + + Vector info; + Platform::getVolumeInformationList(info); + + EXPECT_EQ(names.size(), info.size()) + << "Got inconsistent number of volumes back from info vs. name list functions!"; +}; +#endif + +#endif diff --git a/Engine/source/platform/test/platformTimerTest.cpp b/Engine/source/platform/test/platformTimerTest.cpp new file mode 100644 index 000000000..c8f4db09f --- /dev/null +++ b/Engine/source/platform/test/platformTimerTest.cpp @@ -0,0 +1,93 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "platform/platformTimer.h" +#include "core/util/journal/process.h" +#include "math/mMath.h" + +TEST(Platform, AdvanceTime) +{ + U32 time = Platform::getVirtualMilliseconds(); + Platform::advanceTime(10); + U32 newTime = Platform::getVirtualMilliseconds(); + EXPECT_EQ(10, newTime - time) + << "We advanced 10ms but didn't get a 10ms delta!"; +} + +TEST(Platform, Sleep) +{ + U32 start = Platform::getRealMilliseconds(); + Platform::sleep(500); + U32 end = Platform::getRealMilliseconds(); + EXPECT_GE(end - start, 500-10) // account for clock resolution + << "We didn't sleep at least as long as we requested!"; +}; + +TEST(TimeManager, BasicAPI) +{ + struct handle + { + S32 mElapsedTime; + S32 mNumberCalls; + + void timeEvent(S32 timeDelta) + { + mElapsedTime += timeDelta; + mNumberCalls++; + + if(mElapsedTime >= 1000) + Process::requestShutdown(); + } + } handler; + + handler.mElapsedTime = handler.mNumberCalls = 0; + + // Initialize the time manager... + TimeManager time; + time.timeEvent.notify(&handler, &handle::timeEvent); + + // Event loop till at least one second has passed. + const U32 start = Platform::getRealMilliseconds(); + + while(Process::processEvents()) + { + // If we go too long, kill it off... + if(Platform::getRealMilliseconds() - start > 30*1000) + { + EXPECT_TRUE(false) + << "Terminated process loop due to watchdog, not due to time manager event, after 30 seconds."; + Process::requestShutdown(); + } + } + const U32 end = Platform::getRealMilliseconds(); + + // Now, confirm we have approximately similar elapsed times. + S32 elapsedRealTime = end - start; + EXPECT_LT(mAbs(elapsedRealTime - handler.mElapsedTime), 50) + << "Failed to elapse time to within the desired tolerance."; + EXPECT_GT(handler.mNumberCalls, 0) + << "Somehow got no event callbacks from TimeManager?"; +}; + +#endif \ No newline at end of file diff --git a/Engine/source/platform/test/platformTypesTest.cpp b/Engine/source/platform/test/platformTypesTest.cpp new file mode 100644 index 000000000..b08194c24 --- /dev/null +++ b/Engine/source/platform/test/platformTypesTest.cpp @@ -0,0 +1,118 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "platform/platform.h" +#include "core/util/endian.h" + +TEST(PlatformTypes, Sizes) +{ + // Run through all the types and ensure they're the right size. +#define CheckType(typeName, expectedSize) \ + EXPECT_EQ( sizeof(typeName), expectedSize) \ + << "Wrong size for a " #typeName ", expected " #expectedSize; + + // One byte types. + CheckType(bool, 1); + CheckType(U8, 1); + CheckType(S8, 1); + CheckType(UTF8, 1); + + // Two byte types. + CheckType(U16, 2); + CheckType(S16, 2); + CheckType(UTF16, 2); + + // Four byte types. + CheckType(U32, 4); + CheckType(S32, 4); + CheckType(F32, 4); + CheckType(UTF32, 4); + + // Eight byte types. + CheckType(U64, 8); + CheckType(S64, 8); + CheckType(F64, 8); + + // 16 byte (128bit) types will go here, when we get some. +#undef CheckType +}; + +TEST(PlatformTypes, EndianConversion) +{ + // Convenient and non-palindrome byte patterns to test with. + const U16 U16Test = 0xA1B2; + const S16 S16Test = 0x52A1; + + const U32 U32Test = 0xA1B2C3D4; + const S32 S32Test = 0xD4C3B2A1; + const F32 F32Test = 1234.5678f; + + //const U64 U64Test = 0xA1B2C3D4E3F2E10A; + //const S64 S64Test = 0x1A2B3C4D3E2F1EA0; + const F64 F64Test = 12345678.9101112131415; + + // Run through all the conversions - bump stuff from host to little or big + // endian and back again. +#define CheckEndianRoundTrip(type, b_or_l) \ + EXPECT_EQ( type##Test, convert##b_or_l##EndianToHost(convertHostTo##b_or_l##Endian(type##Test))) \ + << "Failed to convert the " #type " test value to " #b_or_l " endian and back to host endian order."; + +#define CheckTypeBothWays(type) \ + CheckEndianRoundTrip(type, B); \ + CheckEndianRoundTrip(type, L); + +#define CheckIntsForBitSize(bits) \ + CheckTypeBothWays( U##bits ); \ + CheckTypeBothWays( S##bits ); + + // Don't check 8-bit types - they aren't affected by endian issues. + + // Check the >1 byte int types, though. + CheckIntsForBitSize(16); + CheckIntsForBitSize(32); + // CheckIntsForBitSize(64); // don't have convertHostToLEndian(const U64/S64) so this doesn't work + + // And check the float types. + CheckTypeBothWays(F32); + CheckTypeBothWays(F64); + + // We'd check 128bit types here, if we had any. + +#undef CheckIntsForBitSize +#undef CheckTypeBothWays +#undef CheckEndianRoundTrip +}; + +TEST(PlatformTypes, EndianSwap) +{ + U32 swap32 = 0xABCDEF12; + U16 swap16 = 0xABCD; + + EXPECT_EQ(endianSwap(swap32), 0x12EFCDAB) + << "32 bit endianSwap should reverse byte order, but didn't."; + EXPECT_EQ(endianSwap(swap16), 0xCDAB) + << "16 bit endianSwap should reverse byte order, but didn't."; +}; + +#endif \ No newline at end of file diff --git a/Engine/source/unit/memoryTester.cpp b/Engine/source/platform/test/profilerTest.cpp similarity index 69% rename from Engine/source/unit/memoryTester.cpp rename to Engine/source/platform/test/profilerTest.cpp index 15b646bbb..64ccc36d3 100644 --- a/Engine/source/unit/memoryTester.cpp +++ b/Engine/source/platform/test/profilerTest.cpp @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC +// Copyright (c) 2014 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to @@ -20,18 +20,30 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "platform/platform.h" -#include "unit/memoryTester.h" +#ifdef TORQUE_TESTS_ENABLED +#include "platform/platform.h" // Allows us to see TORQUE_ENABLE_PROFILER -using namespace UnitTesting; +#ifdef TORQUE_ENABLE_PROFILER +#include "testing/unitTesting.h" +#include "platform/profiler.h" -void MemoryTester::mark() +TEST(Profiler, ProfileStartEnd) { - + PROFILE_START(ProfileStartEndTest); + // Do work. + if(true) + { + PROFILE_END(ProfileStartEndTest); + return; + } + PROFILE_END(ProfileStartEndTest); } -bool MemoryTester::check() +TEST(Profiler, ProfileScope) { - //UnitTesting::UnitPrint("MemoryTester::check - unavailable w/o TORQUE_DEBUG_GUARD defined!"); - return true; + PROFILE_SCOPE(ScopedProfilerTest); + // Do work and return whenever you want. } + +#endif +#endif \ No newline at end of file diff --git a/Engine/source/platform/test/testAlerts.cpp b/Engine/source/platform/test/testAlerts.cpp deleted file mode 100644 index c79d9ff44..000000000 --- a/Engine/source/platform/test/testAlerts.cpp +++ /dev/null @@ -1,50 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "unit/test.h" - -using namespace UnitTesting; - -CreateInteractiveTest(CheckPlatformAlerts, "Platform/Alerts") -{ - void run() - { - // Run through all the alert types. - Platform::AlertOK("Test #1 - AlertOK", "This is a test of Platform::AlertOK. I am a blocking dialog with an OK button. Please hit OK to continue."); - test(true, "AlertOK should return when the user clicks on it..."); // <-- gratuitous test point. - - bool res; - - res = Platform::AlertOKCancel("Test #2 - AlertOKCancel", "This is a test of Platform::alertOKCancel. I am a blocking dialog with an OK and a Cancel button. Please hit Cancel to continue."); - test(res==false,"AlertOKCancel - Didn't get cancel. User error, or just bad code?"); - - res = Platform::AlertOKCancel("Test #3 - AlertOKCancel", "This is a test of Platform::alertOKCancel. I am a blocking dialog with an OK and a Cancel button. Please hit OK to continue."); - test(res==true,"AlertOKCancel - Didn't get ok. User error, or just bad code?"); - - res = Platform::AlertRetry("Test #4 - AlertRetry", "This is a test of Platform::AlertRetry. I am a blocking dialog with an Retry and a Cancel button. Please hit Retry to continue."); - test(res==true,"AlertRetry - Didn't get retry. User error, or just bad code?"); - - res = Platform::AlertRetry("Test #5 - AlertRetry", "This is a test of Platform::AlertRetry. I am a blocking dialog with an Retry and a Cancel button. Please hit Cancel to continue."); - test(res==false,"AlertRetry - Didn't get cancel. User error, or just bad code?"); - } -}; \ No newline at end of file diff --git a/Engine/source/platform/test/testBasicTypes.cpp b/Engine/source/platform/test/testBasicTypes.cpp deleted file mode 100644 index 848356e2f..000000000 --- a/Engine/source/platform/test/testBasicTypes.cpp +++ /dev/null @@ -1,124 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "core/util/endian.h" -#include "unit/test.h" - -using namespace UnitTesting; - -CreateUnitTest(CheckTypeSizes, "Platform/Types/Sizes") -{ - void run() - { - // Run through all the types and ensure they're the right size. - -#define CheckType(typeName, expectedSize) \ - test( sizeof(typeName) == expectedSize, "Wrong size for a " #typeName ", expected " #expectedSize); - - // One byte types. - CheckType(bool, 1); - CheckType(U8, 1); - CheckType(S8, 1); - CheckType(UTF8, 1); - - // Two byte types. - CheckType(U16, 2); - CheckType(S16, 2); - CheckType(UTF16, 2); - - // Four byte types. - CheckType(U32, 4); - CheckType(S32, 4); - CheckType(F32, 4); - CheckType(UTF32, 4); - - // Eight byte types. - CheckType(U64, 8); - CheckType(S64, 8); - CheckType(F64, 8); - - // 16 byte (128bit) types will go here, when we get some. -#undef CheckType - } -}; - -CreateUnitTest(CheckEndianConversion, "Platform/Types/EndianRoundTrip") -{ - void run() - { - // Convenient and non-palindrome byte patterns to test with. - const U16 U16Test = 0xA1B2; - const S16 S16Test = 0x52A1; - - const U32 U32Test = 0xA1B2C3D4; - const S32 S32Test = 0xD4C3B2A1; - const F32 F32Test = 1234.5678f; - - //const U64 U64Test = 0xA1B2C3D4E3F2E10A; - //const S64 S64Test = 0x1A2B3C4D3E2F1EA0; - const F64 F64Test = 12345678.9101112131415; - - // Run through all the conversions - bump stuff from host to little or big - // endian and back again. -#define CheckEndianRoundTrip(type, b_or_l) \ - test( type##Test == convert##b_or_l##EndianToHost(convertHostTo##b_or_l##Endian(type##Test)), "Failed to convert the " #type " test value to " #b_or_l " endian and back to host endian order."); - -#define CheckTypeBothWays(type) \ - CheckEndianRoundTrip(type, B); \ - CheckEndianRoundTrip(type, L); - -#define CheckIntsForBitSize(bits) \ - CheckTypeBothWays( U##bits ); \ - CheckTypeBothWays( S##bits ); - - // Don't check 8-bit types - they aren't affected by endian issues. - - // Check the >1 byte int types, though. - CheckIntsForBitSize(16); - CheckIntsForBitSize(32); - // CheckIntsForBitSize(64); // don't have convertHostToLEndian(const U64/S64) so this doesn't work - - // And check the float types. - CheckTypeBothWays(F32); - CheckTypeBothWays(F64); - - // We'd check 128bit types here, if we had any. - -#undef CheckIntsForBitSize -#undef CheckTypeBothWays -#undef CheckEndianRoundTrip - } -}; - -CreateUnitTest(CheckEndianSwap, "Platform/Types/EndianSwap") -{ - void run() - { - U32 swap32 = 0xABCDEF12; - U16 swap16 = 0xABCD; - - test(endianSwap(swap32) == 0x12EFCDAB, "32 bit endianSwap should reverse byte order, but didn't."); - test(endianSwap(swap16) == 0xCDAB, "16 bit endianSwap should reverse byte order, but didn't."); - } -}; - diff --git a/Engine/source/platform/test/testFile.cpp b/Engine/source/platform/test/testFile.cpp deleted file mode 100644 index 667f9fbee..000000000 --- a/Engine/source/platform/test/testFile.cpp +++ /dev/null @@ -1,150 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "core/fileio.h" -#include "unit/test.h" -#include "core/util/tVector.h" -#include "console/console.h" - -using namespace UnitTesting; - -CreateUnitTest(CheckFileListingAndExclusion, "File/ListDirectoryAndExclusions") -{ - void run() - { - // Just dump everything under the current directory. We should - // find at least one file. - - // Exclude .svn and CVS - Platform::clearExcludedDirectories(); - Platform::addExcludedDirectory(".svn"); - Platform::addExcludedDirectory("CVS"); - - test(Platform::isExcludedDirectory("foo") == false, "Doesn't match list, shouldn't be excluded."); - test(Platform::isExcludedDirectory(".svn") == true, "On list, should be excluded."); - test(Platform::isExcludedDirectory("CVS") == true, "On list, should be excluded."); - test(Platform::isExcludedDirectory(".svnCVS") == false, "Looks like a duck, but it shouldn't be excluded cuz it's distinct from all entries on the exclusion list."); - - // Ok, now our exclusion list is setup, so let's dump some paths. - Vector < Platform::FileInfo > pathInfo; - Platform::dumpPath (Platform::getCurrentDirectory(), pathInfo, 2); - - Con::printf("Dump of files in '%s', up to 2 levels deep...", Platform::getCurrentDirectory()); - for(S32 i=0; i 0, "Should find at least SOMETHING in the current directory!"); - - // This'll nuke info if we run it in a live situation... so don't run unit - // tests in a live situation. ;) - Platform::clearExcludedDirectories(); - } -}; - -CreateUnitTest(CheckFileTouchAndTime, "File/TouchAndTime") -{ - void run() - { - FileTime create[2], modify[2]; - - // Create a file and sleep for a second. - File f; - f.open("testTouch.file", File::WriteAppend); - f.close(); - - Platform::sleep(2000); - - // Touch a file and note its last-modified. - dFileTouch("testTouch.file"); - test(Platform::isFile("testTouch.file"), "We just touched this file - it should exist."); - test(Platform::getFileTimes("testTouch.file", &create[0], &modify[0]), "Failed to get filetimes for a file we just created."); - - // Sleep for a few seconds... - Platform::sleep(5000); - - // Touch it again, and compare the last-modifieds. - test(Platform::isFile("testTouch.file"), "We just touched this file - it should exist."); - dFileTouch("testTouch.file"); - test(Platform::isFile("testTouch.file"), "We just touched this file - it should exist."); - test(Platform::getFileTimes("testTouch.file", &create[1], &modify[1]), "Failed to get filetimes for a file we just created."); - - // Now compare the times... - test(Platform::compareFileTimes(modify[0], modify[1]) < 0, "Timestamps are wrong - modify[0] should be before modify[1]!"); - - // This seems to fail even on a valid case... - // test(Platform::compareFileTimes(create[0], create[1]) == 0, "Create timestamps should match - we didn't delete the file during this test."); - - // Clean up.. - dFileDelete("testTouch.file"); - test(!Platform::isFile("testTouch.file"), "Somehow failed to delete our test file."); - } -}; - -// Mac has no implementations for these functions, so we 'def it out for now. -#if 0 -CreateUnitTest(CheckVolumes, "File/Volumes") -{ - void run() - { - Con::printf("Dumping volumes by name:"); - - Vector names; - Platform::getVolumeNamesList(names); - - test(names.size() > 0, "We should have at least one volume..."); - - for(S32 i=0; i info; - Platform::getVolumeInformationList(info); - - test(names.size() == info.size(), "Got inconsistent number of volumes back from info vs. name list functions!"); - - for(S32 i=0; i 0, "Didn't get any data back!"); - } -}; - -CreateUnitTest( TestTCPRequestJournal, "Platform/Net/JournalTCPRequest") -{ - NetSocket mSocket; - S32 mDataRecved; - - void handleNotify(NetSocket sock, U32 state) - { - // Only consider our own socket. - if(mSocket != sock) - return; - - // Ok - what's the state? We do some dumb responses to given states - // in order to fulfill the request. - if(state == Net::Connected) - { - U8 reqBuffer[] = { - "GET / HTTP/1.0\nUser-Agent: Torque/1.0\n\n" - }; - - Net::Error e = Net::sendtoSocket(mSocket, reqBuffer, sizeof(reqBuffer)); - - test(e == Net::NoError, "Got an error sending our HTTP request!"); - } - else if(state == Net::Disconnected) - { - Process::requestShutdown(); - mSocket = NULL; - } - } - - void handleReceive(NetSocket sock, RawData incomingData) - { - // Only consider our own socket. - if(mSocket != sock) - return; - - char buff[4096]; - dMemcpy(buff, incomingData.data, incomingData.size); - buff[incomingData.size] = 0; - - UnitPrint("Got a message...\n"); - UnitPrint(buff); - UnitPrint("------\n"); - - mDataRecved += incomingData.size; - } - - void makeRequest() - { - mSocket = InvalidSocket; - mDataRecved = 0; - - // Initialize networking - done by initLibraries currently - //test(Net::init(), "Failed to initialize networking!"); - - // Hook into the signals. - Net::smConnectionNotify. notify(this, &TestTCPRequestJournal::handleNotify); - Net::smConnectionReceive.notify(this, &TestTCPRequestJournal::handleReceive); - - // Open a TCP connection to garagegames.com - mSocket = Net::openConnectTo("ip:72.246.107.193:80"); - - // Let the callbacks enable things to process. - while(Process::processEvents()) - ; - - // Unhook from the signals. - Net::smConnectionNotify. remove(this, &TestTCPRequestJournal::handleNotify); - Net::smConnectionReceive.remove(this, &TestTCPRequestJournal::handleReceive); - - test(mDataRecved > 0, "Didn't get any data back!"); - } - - void run() - { - Journal::Record("journalTCP.jrn"); - - makeRequest(); - - S32 bytesRead = mDataRecved; - - Journal::Stop(); - - Journal::Play("journalTCP.jrn"); - - makeRequest(); - - Journal::Stop(); - - test(bytesRead == mDataRecved, "Didn't get same data back from journal playback."); - - } -}; \ No newline at end of file diff --git a/Engine/source/platform/test/testThreadSafeDeque.cpp b/Engine/source/platform/test/testThreadSafeDeque.cpp deleted file mode 100644 index 8b3e019a4..000000000 --- a/Engine/source/platform/test/testThreadSafeDeque.cpp +++ /dev/null @@ -1,403 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "unit/test.h" -#include "platform/threads/threadSafeDeque.h" -#include "platform/threads/thread.h" -#include "core/util/tVector.h" -#include "console/console.h" - - -#ifndef TORQUE_SHIPPING - -using namespace UnitTesting; - -#define TEST( x ) test( ( x ), "FAIL: " #x ) -#define XTEST( t, x ) t->test( ( x ), "FAIL: " #x ) - - -// Test deque without concurrency. - -CreateUnitTest( TestThreadSafeDequeSerial, "Platform/ThreadSafeDeque/Serial" ) -{ - void test1() - { - ThreadSafeDeque< char > deque; - String str = "teststring"; - - for( U32 i = 0; i < str.length(); ++ i ) - deque.pushBack( str[ i ] ); - - TEST( !deque.isEmpty() ); - - for( U32 i = 0; i < str.length(); ++ i ) - { - char ch; - TEST( deque.tryPopFront( ch ) && ch == str[ i ] ); - } - } - - void test2() - { - ThreadSafeDeque< char > deque; - String str = "teststring"; - - const char* p1 = str.c_str() + 4; - const char* p2 = p1 + 1; - while( *p2 ) - { - deque.pushFront( *p1 ); - deque.pushBack( *p2 ); - - -- p1; - ++ p2; - } - -#ifdef TORQUE_DEBUG - deque.dumpDebug(); -#endif - - for( U32 i = 0; i < str.length(); ++ i ) - { - char ch; - TEST( deque.tryPopFront( ch ) && ch == str[ i ] ); - } - } - - void test3() - { - ThreadSafeDeque< char > deque; - String str = "teststring"; - - const char* p1 = str.c_str() + 4; - const char* p2 = p1 + 1; - while( *p2 ) - { - deque.pushFront( *p1 ); - deque.pushBack( *p2 ); - - -- p1; - ++ p2; - } - -#ifdef TORQUE_DEBUG - deque.dumpDebug(); -#endif - - for( S32 i = ( str.length() - 1 ); i >= 0; -- i ) - { - char ch; - TEST( deque.tryPopBack( ch ) && ch == str[ i ] ); - } - } - - void test4() - { - ThreadSafeDeque< char > deque; - char ch; - - TEST( deque.isEmpty() ); - - deque.pushFront( 'a' ); - TEST( !deque.isEmpty() ); - TEST( deque.tryPopFront( ch ) ); - TEST( ch == 'a' ); - - deque.pushBack( 'a' ); - TEST( !deque.isEmpty() ); - TEST( deque.tryPopFront( ch ) ); - TEST( ch == 'a' ); - - deque.pushBack( 'a' ); - TEST( !deque.isEmpty() ); - TEST( deque.tryPopBack( ch ) ); - TEST( ch == 'a' ); - - deque.pushFront( 'a' ); - TEST( !deque.isEmpty() ); - TEST( deque.tryPopBack( ch ) ); - TEST( ch == 'a' ); - } - - void run() - { - test1(); - test2(); - test3(); - test4(); - } -}; - -// Test deque in a concurrent setting. - -CreateUnitTest( TestThreadSafeDequeConcurrentSimple, "Platform/ThreadSafeDeque/ConcurrentSimple" ) -{ -public: - typedef TestThreadSafeDequeConcurrentSimple TestType; - - enum - { - DEFAULT_NUM_VALUES = 100000, - }; - - struct Value : public ThreadSafeRefCount< Value > - { - U32 mIndex; - U32 mTick; - - Value() {} - Value( U32 index, U32 tick ) - : mIndex( index ), mTick( tick ) {} - }; - - typedef ThreadSafeRef< Value > ValueRef; - - struct Deque : public ThreadSafeDeque< ValueRef > - { - typedef ThreadSafeDeque Parent; - - U32 mPushIndex; - U32 mPopIndex; - - Deque() - : mPushIndex( 0 ), mPopIndex( 0 ) {} - - void pushBack( const ValueRef& value ) - { - AssertFatal( value->mIndex == mPushIndex, "index out of line" ); - mPushIndex ++; - Parent::pushBack( value ); - } - bool tryPopFront( ValueRef& outValue ) - { - if( Parent::tryPopFront( outValue ) ) - { - AssertFatal( outValue->mIndex == mPopIndex, "index out of line" ); - mPopIndex ++; - return true; - } - else - return false; - } - }; - - Deque mDeque; - Vector< U32 > mValues; - - struct ProducerThread : public Thread - { - ProducerThread( TestType* test ) - : Thread( 0, test ) {} - - virtual void run( void* arg ) - { - _setName( "ProducerThread" ); - Platform::outputDebugString( "Starting ProducerThread" ); - - TestType* test = ( TestType* ) arg; - - for( U32 i = 0; i < test->mValues.size(); ++ i ) - { - U32 tick = Platform::getRealMilliseconds(); - test->mValues[ i ] = tick; - - ValueRef val = new Value( i, tick ); - test->mDeque.pushBack( val ); - } - Platform::outputDebugString( "Stopping ProducerThread" ); - } - }; - struct ConsumerThread : public Thread - { - ConsumerThread( TestType* test ) - : Thread( 0, test ) {} - - virtual void run( void* arg ) - { - _setName( "ConsumerThread" ); - Platform::outputDebugString( "Starting CosumerThread" ); - TestType* t = ( TestType* ) arg; - - for( U32 i = 0; i < t->mValues.size(); ++ i ) - { - ValueRef value; - while( !t->mDeque.tryPopFront( value ) ); - - XTEST( t, value->mIndex == i ); - XTEST( t, t->mValues[ i ] == value->mTick ); - } - Platform::outputDebugString( "Stopping ConsumerThread" ); - } - }; - - void run() - { - U32 numValues = Con::getIntVariable( "$testThreadSafeDeque::numValues", DEFAULT_NUM_VALUES ); - mValues.setSize( numValues ); - - ProducerThread pThread( this ); - ConsumerThread cThread( this ); - - pThread.start(); - cThread.start(); - - pThread.join(); - cThread.join(); - - mValues.clear(); - } -}; - -CreateUnitTest( TestThreadSafeDequeConcurrent, "Platform/ThreadSafeDeque/Concurrent" ) -{ -public: - typedef TestThreadSafeDequeConcurrent TestType; - - enum - { - DEFAULT_NUM_VALUES = 100000, - DEFAULT_NUM_CONSUMERS = 10, - DEFAULT_NUM_PRODUCERS = 10 - }; - - struct Value : public ThreadSafeRefCount< Value > - { - U32 mIndex; - U32 mTick; - - Value() {} - Value( U32 index, U32 tick ) - : mIndex( index ), mTick( tick ) {} - }; - - typedef ThreadSafeRef< Value > ValueRef; - - U32 mProducerIndex; - U32 mConsumerIndex; - ThreadSafeDeque< ValueRef > mDeque; - Vector< U32 > mValues; - - struct ProducerThread : public Thread - { - ProducerThread( TestType* test ) - : Thread( 0, test ) {} - - virtual void run( void* arg ) - { - _setName( "ProducerThread" ); - Platform::outputDebugString( "Starting ProducerThread" ); - TestType* test = ( TestType* ) arg; - - while( 1 ) - { - U32 index = test->mProducerIndex; - if( index == test->mValues.size() ) - break; - - if( dCompareAndSwap( test->mProducerIndex, index, index + 1 ) ) - { - U32 tick = Platform::getRealMilliseconds(); - test->mValues[ index ] = tick; - - ValueRef val = new Value( index, tick ); - test->mDeque.pushBack( val ); - } - } - Platform::outputDebugString( "Stopping ProducerThread" ); - } - }; - struct ConsumerThread : public Thread - { - ConsumerThread( TestType* test ) - : Thread( 0, test ) {} - - virtual void run( void* arg ) - { - _setName( "ConsumerThread" ); - Platform::outputDebugString( "Starting ConsumerThread" ); - TestType* t = ( TestType* ) arg; - - while( t->mConsumerIndex < t->mValues.size() ) - { - ValueRef value; - if( t->mDeque.tryPopFront( value ) ) - { - dFetchAndAdd( t->mConsumerIndex, 1 ); - XTEST( t, t->mValues[ value->mIndex ] == value->mTick ); - t->mValues[ value->mIndex ] = 0; - } - } - - Platform::outputDebugString( "Stopping ConsumerThread" ); - } - }; - - void run() - { - U32 numValues = Con::getIntVariable( "$testThreadSafeDeque::numValues", DEFAULT_NUM_VALUES ); - U32 numConsumers = Con::getIntVariable( "$testThreadSafeDeque::numConsumers", DEFAULT_NUM_CONSUMERS ); - U32 numProducers = Con::getIntVariable( "$testThreadSafeDeque::numProducers", DEFAULT_NUM_PRODUCERS ); - - mProducerIndex = 0; - mConsumerIndex = 0; - mValues.setSize( numValues ); - - U32 tick = Platform::getRealMilliseconds(); - for( U32 i = 0; i < numValues; ++ i ) - mValues[ i ] = tick; - - Vector< ProducerThread* > producers; - Vector< ConsumerThread* > consumers; - - producers.setSize( numProducers ); - consumers.setSize( numConsumers ); - - for( U32 i = 0; i < numProducers; ++ i ) - { - producers[ i ] = new ProducerThread( this ); - producers[ i ]->start(); - } - for( U32 i = 0; i < numConsumers; ++ i ) - { - consumers[ i ] = new ConsumerThread( this ); - consumers[ i ]->start(); - } - - for( U32 i = 0; i < numProducers; ++ i ) - { - producers[ i ]->join(); - delete producers[ i ]; - } - for( U32 i = 0; i < numConsumers; ++ i ) - { - consumers[ i ]->join(); - delete consumers[ i ]; - } - - for( U32 i = 0; i < mValues.size(); ++ i ) - TEST( mValues[ i ] == 0 ); - - mValues.clear(); - } -}; - -#endif // !TORQUE_SHIPPING diff --git a/Engine/source/platform/test/testThreadSafePriorityQueue.cpp b/Engine/source/platform/test/testThreadSafePriorityQueue.cpp deleted file mode 100644 index 5933eae2e..000000000 --- a/Engine/source/platform/test/testThreadSafePriorityQueue.cpp +++ /dev/null @@ -1,245 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "unit/test.h" -#include "platform/threads/threadSafePriorityQueue.h" -#include "platform/threads/thread.h" -#include "core/util/tVector.h" -#include "console/console.h" - - -#ifndef TORQUE_SHIPPING - -using namespace UnitTesting; - -#define TEST( x ) test( ( x ), "FAIL: " #x ) -#define XTEST( t, x ) t->test( ( x ), "FAIL: " #x ) - - -// Test queue without concurrency. - -CreateUnitTest( TestThreadSafePriorityQueueSerial, "Platform/ThreadSafePriorityQueue/Serial" ) -{ - struct Value - { - F32 mPriority; - U32 mIndex; - - Value() {} - Value( F32 priority, U32 index ) - : mPriority( priority ), mIndex( index ) {} - }; - - template< bool SORT_MIN_TO_MAX > - void test1() - { - Vector< Value > values; - - values.push_back( Value( 0.2f, 2 ) ); - values.push_back( Value( 0.7f, 7 ) ); - values.push_back( Value( 0.4f, 4 ) ); - values.push_back( Value( 0.6f, 6 ) ); - values.push_back( Value( 0.1f, 1 ) ); - values.push_back( Value( 0.5f, 5 ) ); - values.push_back( Value( 0.3f, 3 ) ); - values.push_back( Value( 0.8f, 8 ) ); - values.push_back( Value( 0.6f, 6 ) ); - values.push_back( Value( 0.9f, 9 ) ); - values.push_back( Value( 0.0f, 0 ) ); - - const S32 min = 0; - const S32 max = 9; - - ThreadSafePriorityQueue< U32, F32, SORT_MIN_TO_MAX > queue; - - for( U32 i = 0; i < values.size(); ++ i ) - queue.insert( values[ i ].mPriority, values[ i ].mIndex ); - - TEST( !queue.isEmpty() ); - - S32 index; - if( SORT_MIN_TO_MAX ) - index = min - 1; - else - index = max + 1; - - for( U32 i = 0; i < values.size(); ++ i ) - { - U32 value; - TEST( queue.takeNext( value ) ); - - if( value != index ) - { - if( SORT_MIN_TO_MAX ) - index ++; - else - index --; - } - - TEST( value == index ); - } - } - - void run() - { - test1< true >(); - test1< false >(); - } -}; - -// Test queue with concurrency. - -CreateUnitTest( TestThreadSafePriorityQueueConcurrent, "Platform/ThreadSafePriorityQueue/Concurrent" ) -{ -public: - typedef TestThreadSafePriorityQueueConcurrent TestType; - - enum - { - DEFAULT_NUM_VALUES = 100000, - DEFAULT_NUM_CONSUMERS = 10, - DEFAULT_NUM_PRODUCERS = 10 - }; - - struct Value : public ThreadSafeRefCount< Value > - { - U32 mIndex; - F32 mPriority; - bool mCheck; - - Value() : mCheck( false ) {} - Value( U32 index, F32 priority ) - : mIndex( index ), mPriority( priority ), mCheck( false ) {} - }; - - typedef ThreadSafeRef< Value > ValueRef; - - U32 mProducerIndex; - U32 mConsumerIndex; - ThreadSafePriorityQueue< ValueRef > mQueue; - Vector< ValueRef > mValues; - - struct ProducerThread : public Thread - { - ProducerThread( TestType* test ) - : Thread( 0, test ) {} - - virtual void run( void* arg ) - { - _setName( "ProducerThread" ); - Platform::outputDebugString( "Starting ProducerThread" ); - TestType* test = ( TestType* ) arg; - - while( 1 ) - { - U32 index = test->mProducerIndex; - if( index == test->mValues.size() ) - break; - - if( dCompareAndSwap( test->mProducerIndex, index, index + 1 ) ) - { - F32 priority = Platform::getRandom(); - ValueRef val = new Value( index, priority ); - test->mValues[ index ] = val; - test->mQueue.insert( priority, val ); - } - } - Platform::outputDebugString( "Stopping ProducerThread" ); - } - }; - struct ConsumerThread : public Thread - { - ConsumerThread( TestType* test ) - : Thread( 0, test ) {} - - virtual void run( void* arg ) - { - _setName( "ConsumerThread" ); - Platform::outputDebugString( "Starting ConsumerThread" ); - TestType* t = ( TestType* ) arg; - - while( t->mConsumerIndex < t->mValues.size() ) - { - ValueRef value; - if( t->mQueue.takeNext( value ) ) - { - dFetchAndAdd( t->mConsumerIndex, 1 ); - XTEST( t, t->mValues[ value->mIndex ] == value ); - value->mCheck = true; - } - else - Platform::sleep( 5 ); - } - Platform::outputDebugString( "Stopping ConsumerThread" ); - } - }; - - void run() - { - U32 numValues = Con::getIntVariable( "$testThreadSafePriorityQueue::numValues", DEFAULT_NUM_VALUES ); - U32 numConsumers = Con::getIntVariable( "$testThreadSafePriorityQueue::numConsumers", DEFAULT_NUM_CONSUMERS ); - U32 numProducers = Con::getIntVariable( "$testThreadSafePriorityQueue::numProducers", DEFAULT_NUM_PRODUCERS ); - - mProducerIndex = 0; - mConsumerIndex = 0; - mValues.setSize( numValues ); - - Vector< ProducerThread* > producers; - Vector< ConsumerThread* > consumers; - - producers.setSize( numProducers ); - consumers.setSize( numConsumers ); - - for( U32 i = 0; i < numProducers; ++ i ) - { - producers[ i ] = new ProducerThread( this ); - producers[ i ]->start(); - } - for( U32 i = 0; i < numConsumers; ++ i ) - { - consumers[ i ] = new ConsumerThread( this ); - consumers[ i ]->start(); - } - - for( U32 i = 0; i < numProducers; ++ i ) - { - producers[ i ]->join(); - delete producers[ i ]; - } - for( U32 i = 0; i < numConsumers; ++ i ) - { - consumers[ i ]->join(); - delete consumers[ i ]; - } - - for( U32 i = 0; i < mValues.size(); ++ i ) - { - TEST( mValues[ i ] != NULL ); - if( mValues[ i ] != NULL ) - TEST( mValues[ i ]->mCheck ); - } - - mValues.clear(); - } -}; - -#endif // !TORQUE_SHIPPING diff --git a/Engine/source/platform/test/testThreadSafeRefCount.cpp b/Engine/source/platform/test/testThreadSafeRefCount.cpp deleted file mode 100644 index 8ad371797..000000000 --- a/Engine/source/platform/test/testThreadSafeRefCount.cpp +++ /dev/null @@ -1,227 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "unit/test.h" -#include "platform/threads/threadSafeRefCount.h" -#include "platform/threads/thread.h" -#include "core/util/tVector.h" -#include "console/console.h" - -#ifndef TORQUE_SHIPPING - -using namespace UnitTesting; - -#define TEST( x ) test( ( x ), "FAIL: " #x ) - -CreateUnitTest( TestThreadSafeRefCountSerial, "Platform/ThreadSafeRefCount/Serial" ) -{ - struct TestObject : public ThreadSafeRefCount< TestObject > - { - static bool smDeleted; - - TestObject() - { - smDeleted = false; - } - ~TestObject() - { - smDeleted = true; - } - }; - - typedef ThreadSafeRef< TestObject > TestObjectRef; - - void run() - { - TestObjectRef ref1 = new TestObject; - TEST( !ref1->isShared() ); - TEST( ref1 != NULL ); - - TestObjectRef ref2 = ref1; - TEST( ref1->isShared() ); - TEST( ref2->isShared() ); - TEST( ref1 == ref2 ); - - ref1 = NULL; - TEST( !ref2->isShared() ); - - ref2 = NULL; - TEST( TestObject::smDeleted ); - } -}; - -bool TestThreadSafeRefCountSerial::TestObject::smDeleted; - -CreateUnitTest( TestThreadSafeRefCountConcurrent, "Platform/ThreadSafeRefCount/Concurrent" ) -{ -public: - typedef TestThreadSafeRefCountConcurrent TestType; - enum - { - NUM_ADD_REFS_PER_THREAD = 1000, - NUM_EXTRA_REFS_PER_THREAD = 1000, - NUM_THREADS = 10 - }; - - class TestObject : public ThreadSafeRefCount< TestObject > - { - public: - }; - - ThreadSafeRef< TestObject > mRef; - - class TestThread : public Thread - { - public: - TestType* mTest; - Vector< ThreadSafeRef< TestObject > > mExtraRefs; - - TestThread( TestType* test ) - : mTest( test ) {} - - void run( void* arg ) - { - if( !arg ) - { - for( U32 i = 0; i < NUM_ADD_REFS_PER_THREAD; ++ i ) - mTest->mRef->addRef(); - - mExtraRefs.setSize( NUM_EXTRA_REFS_PER_THREAD ); - for( U32 i = 0; i < NUM_EXTRA_REFS_PER_THREAD; ++ i ) - mExtraRefs[ i ] = mTest->mRef; - } - else - { - mExtraRefs.clear(); - - for( U32 i = 0; i < NUM_ADD_REFS_PER_THREAD; ++ i ) - mTest->mRef->release(); - } - } - }; - - void run() - { - mRef = new TestObject; - TEST( mRef->getRefCount() == 2 ); // increments of 2 - - Vector< TestThread* > threads; - threads.setSize( NUM_THREADS ); - - // Create threads. - for( U32 i = 0; i < NUM_THREADS; ++ i ) - threads[ i ] = new TestThread( this ); - - // Run phase 1: create references. - for( U32 i = 0; i < NUM_THREADS; ++ i ) - threads[ i ]->start( NULL ); - - // Wait for completion. - for( U32 i = 0; i < NUM_THREADS; ++ i ) - threads[ i ]->join(); - - Con::printf( "REF: %i", mRef->getRefCount() ); - TEST( mRef->getRefCount() == 2 + ( ( NUM_ADD_REFS_PER_THREAD + NUM_EXTRA_REFS_PER_THREAD ) * NUM_THREADS * 2 ) ); - - // Run phase 2: release references. - for( U32 i = 0; i < NUM_THREADS; ++ i ) - threads[ i ]->start( ( void* ) 1 ); - - // Wait for completion. - for( U32 i = 0; i < NUM_THREADS; ++ i ) - { - threads[ i ]->join(); - delete threads[ i ]; - } - - TEST( mRef->getRefCount() == 2 ); // increments of two - - mRef = NULL; - } -}; - -CreateUnitTest( TestThreadSafeRefCountTagging, "Platform/ThreadSafeRefCount/Tagging" ) -{ - struct TestObject : public ThreadSafeRefCount< TestObject > {}; - - typedef ThreadSafeRef< TestObject > TestObjectRef; - - void run() - { - TestObjectRef ref; - - TEST( !ref.isTagged() ); - TEST( !ref ); - TEST( !ref.ptr() ); - - TEST( ref.trySetFromTo( ref, NULL ) ); - TEST( !ref.isTagged() ); - - TEST( ref.trySetFromTo( ref, NULL, TestObjectRef::TAG_Set ) ); - TEST( ref.isTagged() ); - TEST( ref.trySetFromTo( ref, NULL, TestObjectRef::TAG_Set ) ); - TEST( ref.isTagged() ); - - TEST( ref.trySetFromTo( ref, NULL, TestObjectRef::TAG_Unset ) ); - TEST( !ref.isTagged() ); - TEST( ref.trySetFromTo( ref, NULL, TestObjectRef::TAG_Unset ) ); - TEST( !ref.isTagged() ); - - TEST( ref.trySetFromTo( ref, NULL, TestObjectRef::TAG_SetOrFail ) ); - TEST( ref.isTagged() ); - TEST( !ref.trySetFromTo( ref, NULL, TestObjectRef::TAG_SetOrFail ) ); - TEST( ref.isTagged() ); - TEST( !ref.trySetFromTo( ref, NULL, TestObjectRef::TAG_FailIfSet ) ); - - TEST( ref.trySetFromTo( ref, NULL, TestObjectRef::TAG_UnsetOrFail ) ); - TEST( !ref.isTagged() ); - TEST( !ref.trySetFromTo( ref, NULL, TestObjectRef::TAG_UnsetOrFail ) ); - TEST( !ref.isTagged() ); - TEST( !ref.trySetFromTo( ref, NULL, TestObjectRef::TAG_FailIfUnset ) ); - - TestObjectRef objectA = new TestObject; - TestObjectRef objectB = new TestObject; - - TEST( !objectA->isShared() ); - TEST( !objectB->isShared() ); - - ref = objectA; - TEST( !ref.isTagged() ); - TEST( ref == objectA ); - TEST( ref == objectA.ptr() ); - TEST( objectA->isShared() ); - - TEST( ref.trySetFromTo( objectA, objectB, TestObjectRef::TAG_Set ) ); - TEST( ref.isTagged() ); - TEST( ref == objectB ); - TEST( ref == objectB.ptr() ); - TEST( objectB->isShared() ); - TEST( !objectA->isShared() ); - - TEST( ref.trySetFromTo( ref, objectA ) ); - TEST( ref.isTagged() ); - TEST( ref == objectA ); - TEST( ref == objectA.ptr() ); - } -}; - -#endif // !TORQUE_SHIPPING diff --git a/Engine/source/platform/test/testThreading.cpp b/Engine/source/platform/test/testThreading.cpp deleted file mode 100644 index ede62a507..000000000 --- a/Engine/source/platform/test/testThreading.cpp +++ /dev/null @@ -1,417 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "platform/threads/thread.h" -#include "platform/threads/semaphore.h" -#include "platform/threads/mutex.h" -#include "unit/test.h" -#include "core/util/tVector.h" -#include "console/console.h" - -using namespace UnitTesting; - -class ThreadTestHarness -{ - U32 mStartTime, mEndTime, mCleanupTime; - void (*mThreadBody)(void*); - S32 mThreadCount; - Thread **mThreads; - -public: - ThreadTestHarness() - { - mStartTime = mEndTime = mCleanupTime = 0; - mThreadBody = NULL; - mThreadCount = 1; - mThreads = NULL; - } - - void startThreads(void (*threadBody)(void*), void *arg, U32 threadCount) - { - mThreadCount = threadCount; - mThreadBody = threadBody; - - // Start up threadCount threads... - mThreads = new Thread*[threadCount]; - - mStartTime = Platform::getRealMilliseconds(); - - //Con::printf(" Running with %d threads...", threadCount); - for(S32 i=0; istart(); - } - } - - void waitForThreadExit(U32 checkFrequencyMs) - { - // And wait for them to complete. - bool someAlive = true; - S32 liveCount = mThreadCount; - - while(someAlive) - { - //Con::printf(" - Sleeping for %dms with %d live threads.", checkFrequencyMs, liveCount); - Platform::sleep(checkFrequencyMs); - - someAlive = false; - liveCount = 0; - - for(S32 i=0; iisAlive()) - continue; - - someAlive = true; - liveCount++; - } - - } - - mEndTime = Platform::getRealMilliseconds(); - - // Clean up memory at this point. - for(S32 i=0; iacquire(false), "Should succeed at acquiring a new semaphore with count 1."); - test(sem2->acquire(false), "This one should succeed too, see previous test."); - - // Test that we can do non-blocking acquires that fail. - test(sem1->acquire(false)==false, "Should failed, as we've already got the sem."); - sem1->release(); - test(sem2->acquire(false)==false, "Should also fail."); - sem2->release(); - - // Test that we can do blocking acquires that succeed. - test(sem1->acquire(true)==true, "Should succeed as we just released."); - test(sem2->acquire(true)==true, "Should succeed as we just released."); - - // Can't test blocking acquires that never happen... :) - - // Clean up. - delete sem1; - delete sem2; - } -}; - -CreateUnitTest( SemaphoreWaitTest, "Platform/Threads/SemaphoreWaitTest") -{ - static void threadBody(void *self) - { - SemaphoreWaitTest *me = (SemaphoreWaitTest*)self; - - // Wait for the semaphore to get released. - me->mSemaphore->acquire(); - - // Increment the counter. - Mutex::lockMutex(me->mMutex); - me->mDoneCount++; - Mutex::unlockMutex(me->mMutex); - - // Signal back to the main thread we're done. - me->mPostbackSemaphore->release(); - } - - Semaphore *mSemaphore; - Semaphore *mPostbackSemaphore; - void *mMutex; - U32 mDoneCount; - - const static int csmThreadCount = 10; - - void run() - { - ThreadTestHarness tth; - - mDoneCount = 0; - mSemaphore = new Semaphore(0); - mPostbackSemaphore = new Semaphore(0); - mMutex = Mutex::createMutex(); - - tth.startThreads(&threadBody, this, csmThreadCount); - - Platform::sleep(500); - - Mutex::lockMutex(mMutex); - test(mDoneCount == 0, "no threads should have touched the counter yet."); - Mutex::unlockMutex(mMutex); - - // Let 500 come out. - for(S32 i=0; irelease(); - - // And wait for 500 postbacks. - for(S32 i=0; iacquire(); - - Mutex::lockMutex(mMutex); - test(mDoneCount == csmThreadCount / 2, "Didn't get expected number of done threads! (a)"); - Mutex::unlockMutex(mMutex); - - // Ok, now do the rest. - // Let 500 come out. - for(S32 i=0; irelease(); - - // And wait for 500 postbacks. - for(S32 i=0; iacquire(); - - Mutex::lockMutex(mMutex); - test(mDoneCount == csmThreadCount, "Didn't get expected number of done threads! (b)"); - Mutex::unlockMutex(mMutex); - - // Wait for the threads to exit - shouldn't have to wait ever though. - tth.waitForThreadExit(10); - - // Make sure no one touched our data after shutdown time. - Mutex::lockMutex(mMutex); - test(mDoneCount == csmThreadCount, "Didn't get expected number of done threads! (c)"); - Mutex::unlockMutex(mMutex); - } -}; - -CreateUnitTest( MutexWaitTest, "Platform/Threads/MutexWaitTest") -{ - static void threadBody(void *self) - { - MutexWaitTest *me = (MutexWaitTest*)self; - - // Increment the counter. We'll block until the mutex - // is open. - Mutex::lockMutex(me->mMutex); - me->mDoneCount++; - Mutex::unlockMutex(me->mMutex); - } - - void *mMutex; - U32 mDoneCount; - - const static int csmThreadCount = 10; - - void run() - { - mMutex = Mutex::createMutex(); - mDoneCount = 0; - - // We lock the mutex before we create any threads, so that all the threads - // block on the mutex. Then we unlock it and let them all work their way - // through the increment. - Mutex::lockMutex(mMutex); - - ThreadTestHarness tth; - tth.startThreads(&threadBody, this, csmThreadCount); - - Platform::sleep(5000); - - // Check count is still zero. - test(mDoneCount == 0, "Uh oh - a thread somehow didn't get blocked by the locked mutex!"); - - // Open the flood gates... - Mutex::unlockMutex(mMutex); - - // Wait for the threads to all finish executing. - tth.waitForThreadExit(10); - - Mutex::lockMutex(mMutex); - test(mDoneCount == csmThreadCount, "Hmm - all threads reported done, but we didn't get the expected count."); - Mutex::unlockMutex(mMutex); - - // Kill the mutex. - Mutex::destroyMutex(mMutex); - } -}; \ No newline at end of file diff --git a/Engine/source/platform/test/testTimeManager.cpp b/Engine/source/platform/test/testTimeManager.cpp deleted file mode 100644 index 7b157035c..000000000 --- a/Engine/source/platform/test/testTimeManager.cpp +++ /dev/null @@ -1,105 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "platform/platformTimer.h" -#include "core/util/journal/journaledSignal.h" -#include "core/util/journal/process.h" -#include "math/mMath.h" -#include "console/console.h" - -#include "unit/test.h" -using namespace UnitTesting; - -CreateUnitTest(Check_advanceTime, "Platform/Time/advanceTime") -{ - void run() - { - U32 time = Platform::getVirtualMilliseconds(); - Platform::advanceTime(10); - U32 newTime = Platform::getVirtualMilliseconds(); - - test(newTime - time == 10, "Platform::advanceTime is borked, we advanced 10ms but didn't get a 10ms delta!"); - } -}; - -CreateUnitTest(Check_platformSleep, "Platform/Time/Sleep") -{ - const static S32 sleepTimeMs = 500; - void run() - { - U32 start = Platform::getRealMilliseconds(); - Platform::sleep(sleepTimeMs); - U32 end = Platform::getRealMilliseconds(); - - test(end - start >= sleepTimeMs, "We didn't sleep at least as long as we requested!"); - } -}; - -CreateUnitTest(Check_timeManager, "Platform/Time/Manager") -{ - void handleTimeEvent(S32 timeDelta) - { - mElapsedTime += timeDelta; - mNumberCalls++; - - if(mElapsedTime >= 1000) - Process::requestShutdown(); - } - - S32 mElapsedTime; - S32 mNumberCalls; - - void run() - { - mElapsedTime = mNumberCalls = 0; - - // Initialize the time manager... - TimeManager time; - time.timeEvent.notify(this, &Check_timeManager::handleTimeEvent); - - // Event loop till at least one second has passed. - const U32 start = Platform::getRealMilliseconds(); - - while(Process::processEvents()) - { - // If we go too long, kill it off... - if(Platform::getRealMilliseconds() - start > 30*1000) - { - test(false, "Terminated process loop due to watchdog, not due to time manager event, after 30 seconds."); - Process::requestShutdown(); - } - } - - const U32 end = Platform::getRealMilliseconds(); - - // Now, confirm we have approximately similar elapsed times. - S32 elapsedRealTime = end - start; - test(mAbs(elapsedRealTime - mElapsedTime) < 50, "Failed to elapse time to within the desired tolerance."); - - test(mNumberCalls > 0, "Somehow got no event callbacks from TimeManager?"); - - Con::printf(" Got %d time events, and elapsed %dms from TimeManager, " - "%dms according to Platform::getRealMilliseconds()", - mNumberCalls, mElapsedTime, elapsedRealTime); - } -}; \ No newline at end of file diff --git a/Engine/source/platform/test/threadStaticTest.cpp b/Engine/source/platform/test/threadStaticTest.cpp new file mode 100644 index 000000000..ec4c5f2ad --- /dev/null +++ b/Engine/source/platform/test/threadStaticTest.cpp @@ -0,0 +1,139 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" + +// This unit test will blow up without thread static support +#include "core/threadStatic.h" +#ifdef TORQUE_ENABLE_THREAD_STATICS + +// Declare a test thread static +DITTS(U32, gUnitTestFoo, 42); +DITTS(F32, gUnitTestF32, 1.0); + +TEST(ThreadStatic, BasicAPI) +{ + // ThreadStatic list should be initialized right now, so lets see if it has + // any entries. + EXPECT_FALSE(_TorqueThreadStaticReg::getStaticList().empty()) + << "Self-registration has failed, or no statics declared"; + + // Spawn a new copy. + TorqueThreadStaticListHandle testInstance = _TorqueThreadStaticReg::spawnThreadStaticsInstance(); + + // Test the copy + ASSERT_EQ(_TorqueThreadStaticReg::getStaticList(0).size(), testInstance->size()) + << "Spawned static list has a different size from master copy."; + + // Traverse the list and compare it to the initial value copy (index 0) + for(S32 i = 0; i < _TorqueThreadStaticReg::getStaticList().size(); i++) + { + _TorqueThreadStatic *master = _TorqueThreadStaticReg::getStaticList()[i]; + _TorqueThreadStatic *cpy = (*testInstance)[i]; + + // Make sure it is not the same memory + EXPECT_NE(master, cpy) + << "Copy not spawned properly."; + + // Make sure the sizes are the same + ASSERT_EQ(master->getMemInstSize(), cpy->getMemInstSize()) + << "Size mismatch between master and copy"; + + // Make sure the initialization occurred properly + EXPECT_EQ(0, dMemcmp(master->getMemInstPtr(), cpy->getMemInstPtr(), master->getMemInstSize())) + << "Initial value for spawned list is not correct"; + } + + // Test metrics if enabled +#ifdef TORQUE_ENABLE_THREAD_STATIC_METRICS + U32 fooHitCount = (*testInstance)[_gUnitTestFooTorqueThreadStatic::getListIndex()]->getHitCount(); +#endif + + // Set/get some values (If we test static metrics, this is hit 1) + ATTS_(gUnitTestFoo, 1) = 55; + + // Test to see that the master copy and the spawned copy differ + // (If we test metrics, this is hit 2, for the instance, and hit 1 for the master) + EXPECT_NE(ATTS_(gUnitTestFoo, 0), ATTS_(gUnitTestFoo, 1)) + << "Assignment for spawned instanced memory failed"; + +#ifdef TORQUE_ENABLE_THREAD_STATIC_METRICS + U32 fooHitCount2 = (*testInstance)[_gUnitTestFooTorqueThreadStatic::getListIndex()]->getHitCount(); + EXPECT_EQ(fooHitCount2, (fooHitCount + 2)) + << "Thread static metric hit count failed"; +#endif + + // Destroy instances + _TorqueThreadStaticReg::destroyInstance(testInstance); +} + +#ifdef TORQUE_ENABLE_PROFILER +#include "math/mRandom.h" +#include "platform/profiler.h" + +// Declare a test thread static +DITTS(U32, gInstancedStaticFoo, 42); +static U32 gTrueStaticFoo = 42; + +TEST(ThreadStatic, StressThreadStatic) +{ + ASSERT_FALSE(gProfiler->isEnabled()) + << "Profiler is currently enabled, test cannot continue"; + + // Spawn an instance + TorqueThreadStaticListHandle testInstance = _TorqueThreadStaticReg::spawnThreadStaticsInstance(); + + static const dsize_t TEST_SIZE = 100000; + + // What we are going to do in this test is to test some U32 static + // performance. The test will be run TEST_SIZE times, and so first create + // an array of values to standardize the tests on. + U32 testValue[TEST_SIZE]; + + for(S32 i = 0; i < TEST_SIZE; i++) + testValue[i] = gRandGen.randI(); + + // Reset the profiler, tell it to dump to console when done + gProfiler->dumpToConsole(); + gProfiler->enable(true); + + // Value array is initialized, so lets put the foo's through the paces + PROFILE_START(ThreadStaticPerf_TrueStaticAssign); + for(int i = 0; i < TEST_SIZE; i++) + gTrueStaticFoo = testValue[i]; + PROFILE_END(); + + PROFILE_START(ThreadStaticPerf_InstanceStaticAssign); + for(S32 i = 0; i < TEST_SIZE; i++) + ATTS_(gInstancedStaticFoo, 1) = testValue[i]; + PROFILE_END(); + + gProfiler->enable(false); + + // Clean up instance + _TorqueThreadStaticReg::destroyInstance(testInstance); +} +#endif + +#endif +#endif \ No newline at end of file diff --git a/Engine/source/platform/threads/test/mutexTest.cpp b/Engine/source/platform/threads/test/mutexTest.cpp new file mode 100644 index 000000000..53379651b --- /dev/null +++ b/Engine/source/platform/threads/test/mutexTest.cpp @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "platform/threads/mutex.h" +#include "platform/threads/thread.h" + +TEST(Mutex, BasicSynchronization) +{ + // We test various scenarios wrt to locking and unlocking, in a single + // thread, just to make sure our basic primitives are working in the + // most basic case. + void *mutex1 = Mutex::createMutex(); + EXPECT_TRUE(mutex1 != NULL) + << "First Mutex::createMutex call failed - that's pretty bad!"; + + // This mutex is intentionally unused. + void *mutex2 = Mutex::createMutex(); + EXPECT_TRUE(mutex2 != NULL) + << "Second Mutex::createMutex call failed - that's pretty bad, too!"; + + EXPECT_TRUE(Mutex::lockMutex(mutex1, false)) + << "Nonblocking call to brand new mutex failed - should not be."; + EXPECT_TRUE(Mutex::lockMutex(mutex1, true)) + << "Failed relocking a mutex from the same thread - should be able to do this."; + + // Try to acquire the mutex from another thread. + struct thread + { + static void body(void* mutex) + { + // We should not be able to lock the mutex from a separate thread, but + // we don't want to block either. + EXPECT_FALSE(Mutex::lockMutex(mutex, false)); + } + }; + Thread thread(&thread::body, mutex1); + thread.start(); + thread.join(); + + // Unlock & kill mutex 1 + Mutex::unlockMutex(mutex1); + Mutex::unlockMutex(mutex1); + Mutex::destroyMutex(mutex1); + + // Kill mutex2, which was never touched. + Mutex::destroyMutex(mutex2); +} + +#endif \ No newline at end of file diff --git a/Engine/source/platform/threads/test/semaphoreTest.cpp b/Engine/source/platform/threads/test/semaphoreTest.cpp new file mode 100644 index 000000000..d74971074 --- /dev/null +++ b/Engine/source/platform/threads/test/semaphoreTest.cpp @@ -0,0 +1,90 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "platform/threads/semaphore.h" +#include "platform/threads/thread.h" + +TEST(Semaphore, BasicSynchronization) +{ + Semaphore *sem1 = new Semaphore(1); + Semaphore *sem2 = new Semaphore(1); + + // Test that we can do non-blocking acquires that succeed. + EXPECT_TRUE(sem1->acquire(false)) + << "Should succeed at acquiring a new semaphore with count 1."; + EXPECT_TRUE(sem2->acquire(false)) + << "This one should succeed too, see previous test."; + + // Test that we can do non-blocking acquires that fail. + EXPECT_FALSE(sem1->acquire(false)) + << "Should failed, as we've already got the sem."; + sem1->release(); + EXPECT_FALSE(sem2->acquire(false)) + << "Should also fail."; + sem2->release(); + + // Test that we can do blocking acquires that succeed. + EXPECT_TRUE(sem1->acquire(true)) + << "Should succeed as we just released."; + EXPECT_TRUE(sem2->acquire(true)) + << "Should succeed as we just released."; + + // Clean up. + delete sem1; + delete sem2; +} + +TEST(Semaphore, MultiThreadSynchronization) +{ + Semaphore semaphore(1); + + struct thread + { + // Try to acquire the semaphore from another thread. + static void body1(void* sem) + { + Semaphore *semaphore = reinterpret_cast(sem); + EXPECT_TRUE(semaphore->acquire(true)); + // Note that this semaphore is never released. Bad programmer! + } + // One more acquisition should fail! + static void body2(void* sem) + { + Semaphore *semaphore = reinterpret_cast(sem); + EXPECT_FALSE(semaphore->acquire(false)); + } + }; + + Thread thread1(&thread::body1, &semaphore); + EXPECT_TRUE(semaphore.acquire(true)); + thread1.start(); + semaphore.release(); + thread1.join(); + + Thread thread2(&thread::body2, &semaphore); + thread2.start(); + thread2.join(); +} + +#endif \ No newline at end of file diff --git a/Engine/source/platform/test/testThreadPool.cpp b/Engine/source/platform/threads/test/threadPoolTest.cpp similarity index 51% rename from Engine/source/platform/test/testThreadPool.cpp rename to Engine/source/platform/threads/test/threadPoolTest.cpp index 4055ce3fb..cfb5c5dd4 100644 --- a/Engine/source/platform/test/testThreadPool.cpp +++ b/Engine/source/platform/threads/test/threadPoolTest.cpp @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC +// Copyright (c) 2014 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to @@ -20,66 +20,56 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "unit/test.h" +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" #include "platform/threads/threadPool.h" #include "console/console.h" #include "core/util/tVector.h" -#ifndef TORQUE_SHIPPING - -using namespace UnitTesting; - -#define TEST( x ) test( ( x ), "FAIL: " #x ) - -// Simple test that creates and verifies an array of numbers using -// thread pool work items. - -CreateUnitTest( TestThreadPool, "Platform/ThreadPool/Simple" ) +FIXTURE(ThreadPool) { - enum { DEFAULT_NUM_ITEMS = 4000 }; - - static Vector< U32 > results; - +public: + // Represents a single unit of work. In this test we just set an element in + // a result vector. struct TestItem : public ThreadPool::WorkItem { - typedef ThreadPool::WorkItem Parent; - - U32 mIndex; - - TestItem( U32 index ) - : mIndex( index ) {} - - protected: - virtual void execute() - { - results[ mIndex ] = mIndex; - } - }; - - void run() - { - U32 numItems = Con::getIntVariable( "$testThreadPool::numValues", DEFAULT_NUM_ITEMS ); - ThreadPool* pool = &ThreadPool::GLOBAL(); - results.setSize( numItems ); + U32 mIndex; + Vector& mResults; + TestItem(U32 index, Vector& results) + : mIndex(index), mResults(results) {} - for( U32 i = 0; i < numItems; ++ i ) - results[ i ] = U32( -1 ); - - for( U32 i = 0; i < numItems; ++ i ) + protected: + virtual void execute() { - ThreadSafeRef< TestItem > item( new TestItem( i ) ); - pool->queueWorkItem( item ); + mResults[mIndex] = mIndex; } - - pool->flushWorkItems(); - - for( U32 i = 0; i < numItems; ++ i ) - test( results[ i ] == i, "result mismatch" ); - - results.clear(); - } + }; }; -Vector< U32 > TestThreadPool::results( __FILE__, __LINE__ ); +TEST_FIX(ThreadPool, BasicAPI) +{ + // Construct the vector of results from the work items. + const U32 numItems = 100; + Vector results(__FILE__, __LINE__); + results.setSize(numItems); + for (U32 i = 0; i < numItems; i++) + results[i] = U32(-1); -#endif // !TORQUE_SHIPPING + // Launch the work items. + ThreadPool* pool = &ThreadPool::GLOBAL(); + for (U32 i = 0; i < numItems; i++) + { + ThreadSafeRef item(new TestItem(i, results)); + pool->queueWorkItem(item); + } + + // Wait for all items to complete. + pool->flushWorkItems(); + + // Verify. + for (U32 i = 0; i < numItems; i++) + EXPECT_EQ(results[i], i) << "result mismatch"; + results.clear(); +} + +#endif \ No newline at end of file diff --git a/Engine/source/platform/threads/test/threadSafeDequeTest.cpp b/Engine/source/platform/threads/test/threadSafeDequeTest.cpp new file mode 100644 index 000000000..54df89ad4 --- /dev/null +++ b/Engine/source/platform/threads/test/threadSafeDequeTest.cpp @@ -0,0 +1,186 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" + +#include "platform/threads/threadSafeDeque.h" +#include "platform/threads/thread.h" +#include "core/util/tVector.h" +#include "console/console.h" + +FIXTURE(ThreadSafeDeque) +{ +public: + // Used by the concurrent test. + struct Value : public ThreadSafeRefCount + { + U32 mIndex; + U32 mTick; + + Value() {} + Value(U32 index, U32 tick) + : mIndex(index), mTick(tick) {} + }; + + typedef ThreadSafeRef ValueRef; + + struct Deque : public ThreadSafeDeque + { + typedef ThreadSafeDeque Parent; + + U32 mPushIndex; + U32 mPopIndex; + + Deque() + : mPushIndex(0), mPopIndex(0) {} + + void pushBack(const ValueRef& value) + { + EXPECT_EQ(value->mIndex, mPushIndex) << "index out of line"; + mPushIndex++; + Parent::pushBack(value); + } + + bool tryPopFront(ValueRef& outValue) + { + if(Parent::tryPopFront(outValue)) + { + EXPECT_EQ(outValue->mIndex, mPopIndex) << "index out of line"; + mPopIndex++; + return true; + } + else + return false; + } + }; + + struct ProducerThread : public Thread + { + Vector& mValues; + Deque& mDeque; + ProducerThread(Vector& values, Deque& deque) + : mValues(values), mDeque(deque) {} + + virtual void run(void*) + { + for(U32 i = 0; i < mValues.size(); i++) + { + U32 tick = Platform::getRealMilliseconds(); + mValues[i] = tick; + + ValueRef val = new Value(i, tick); + mDeque.pushBack(val); + } + } + }; + + struct ConsumerThread : public Thread + { + Vector& mValues; + Deque& mDeque; + ConsumerThread(Vector& values, Deque& deque) + : mValues(values), mDeque(deque) {} + + virtual void run(void*) + { + for(U32 i = 0; i < mValues.size(); i++) + { + ValueRef value; + while(!mDeque.tryPopFront(value)); + + EXPECT_EQ(i, value->mIndex); + EXPECT_EQ(value->mTick, mValues[i]); + } + } + }; +}; + +// Test deque without concurrency. +TEST_FIX(ThreadSafeDeque, PopFront) +{ + ThreadSafeDeque deque; + String str = "teststring"; + + for(U32 i = 0; i < str.length(); i++) + deque.pushBack(str[i]); + + EXPECT_FALSE(deque.isEmpty()); + + char ch; + for(U32 i = 0; i < str.length(); i++) + { + EXPECT_TRUE(deque.tryPopFront(ch)); + EXPECT_EQ(str[i], ch); + } + + ASSERT_TRUE(deque.isEmpty()); +} + +TEST_FIX(ThreadSafeDeque, PopBack) +{ + ThreadSafeDeque deque; + String str = "teststring"; + + const char* p1 = str.c_str() + 4; + const char* p2 = p1 + 1; + while(*p2) + { + deque.pushFront(*p1); + deque.pushBack(*p2); + --p1; + ++p2; + } + + char ch; + for(S32 i = str.length()-1; i >= 0; i--) + { + EXPECT_TRUE(deque.tryPopBack(ch)); + EXPECT_EQ(str[i], ch); + } + + ASSERT_TRUE(deque.isEmpty()); +} + +// Test deque in a concurrent setting. +TEST_FIX(ThreadSafeDeque, Concurrent1) +{ + const U32 NumValues = 100; + + Deque mDeque; + Vector mValues; + + mValues.setSize(NumValues); + + ProducerThread pThread(mValues, mDeque); + ConsumerThread cThread(mValues, mDeque); + + pThread.start(); + cThread.start(); + + pThread.join(); + cThread.join(); + + mValues.clear(); +}; + +#endif \ No newline at end of file diff --git a/Engine/source/platform/threads/test/threadSafePriorityQueueTest.cpp b/Engine/source/platform/threads/test/threadSafePriorityQueueTest.cpp new file mode 100644 index 000000000..668117633 --- /dev/null +++ b/Engine/source/platform/threads/test/threadSafePriorityQueueTest.cpp @@ -0,0 +1,146 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "platform/threads/threadSafePriorityQueue.h" +#include "platform/threads/thread.h" +#include "core/util/tVector.h" +#include "console/console.h" + +// Test queue without concurrency. +TEST(ThreadSafePriorityQueue, Serial) +{ + const U32 min = 0; + const U32 max = 9; + const U32 len = 11; + + U32 indices[len] = { 2, 7, 4, 6, 1, 5, 3, 8, 6, 9, 0}; + F32 priorities[len] = {0.2, 0.7, 0.4, 0.6, 0.1, 0.5, 0.3, 0.8, 0.6, 0.9, 0}; + + ThreadSafePriorityQueue minQueue; + ThreadSafePriorityQueue maxQueue; + + for(U32 i = 0; i < len; i++) + { + minQueue.insert(priorities[i], indices[i]); + maxQueue.insert(priorities[i], indices[i]); + } + + EXPECT_FALSE(minQueue.isEmpty()); + EXPECT_FALSE(maxQueue.isEmpty()); + + U32 index = min; + for(U32 i = 0; i < len; i++) + { + U32 popped; + EXPECT_TRUE(minQueue.takeNext(popped)) + << "Failed to pop element from minQueue"; + EXPECT_LE(index, popped) + << "Element from minQueue was not in sort order"; + index = popped; + } + + index = max; + for(U32 i = 0; i < len; i++) + { + U32 popped; + EXPECT_TRUE(maxQueue.takeNext(popped)) + << "Failed to pop element from maxQueue"; + EXPECT_GE(index, popped) + << "Element from maxQueue was not in sort order"; + index = popped; + } +} + +// Test queue with concurrency. +TEST(ThreadSafePriorityQueue, Concurrent) +{ +#define MIN 0 +#define MAX 9 +#define LEN 11 + + typedef ThreadSafePriorityQueue MinQueue; + typedef ThreadSafePriorityQueue MaxQueue; + + struct ProducerThread : public Thread + { + MinQueue& minQueue; + MaxQueue& maxQueue; + ProducerThread(MinQueue& min, MaxQueue& max) + : minQueue(min), maxQueue(max) {} + + virtual void run(void*) + { + U32 indices[LEN] = { 2, 7, 4, 6, 1, 5, 3, 8, 6, 9, 0}; + F32 priorities[LEN] = {0.2, 0.7, 0.4, 0.6, 0.1, 0.5, 0.3, 0.8, 0.6, 0.9, 0}; + + for(U32 i = 0; i < LEN; i++) + { + minQueue.insert(priorities[i], indices[i]); + maxQueue.insert(priorities[i], indices[i]); + } + } + }; + + MinQueue minQueue; + MaxQueue maxQueue; + ProducerThread producers[] = { + ProducerThread(minQueue, maxQueue), + ProducerThread(minQueue, maxQueue), + ProducerThread(minQueue, maxQueue) + }; + + const U32 len = sizeof(producers) / sizeof(ProducerThread); + for(U32 i = 0; i < len; i++) + producers[i].start(); + for(U32 i = 0; i < len; i++) + producers[i].join(); + + U32 index = MIN; + for(U32 i = 0; i < LEN * len; i++) + { + U32 popped; + EXPECT_TRUE(minQueue.takeNext(popped)) + << "Failed to pop element from minQueue"; + EXPECT_LE(index, popped) + << "Element from minQueue was not in sort order"; + index = popped; + } + + index = MAX; + for(U32 i = 0; i < LEN * len; i++) + { + U32 popped; + EXPECT_TRUE(maxQueue.takeNext(popped)) + << "Failed to pop element from maxQueue"; + EXPECT_GE(index, popped) + << "Element from maxQueue was not in sort order"; + index = popped; + } + +#undef MIN +#undef MAX +#undef LEN +} + +#endif \ No newline at end of file diff --git a/Engine/source/platform/threads/test/threadSafeRefCountTest.cpp b/Engine/source/platform/threads/test/threadSafeRefCountTest.cpp new file mode 100644 index 000000000..28c6bf0a7 --- /dev/null +++ b/Engine/source/platform/threads/test/threadSafeRefCountTest.cpp @@ -0,0 +1,205 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "platform/threads/threadSafeRefCount.h" +#include "platform/threads/thread.h" +#include "core/util/tVector.h" +#include "console/console.h" + +FIXTURE(ThreadSafeRefCount) +{ +public: + struct TestObjectDtor : public ThreadSafeRefCount + { + bool &flag; + TestObjectDtor(bool &f) : flag(f) + { + flag = false; + } + ~TestObjectDtor() + { + flag = true; + } + }; + typedef ThreadSafeRef TestObjectDtorRef; + + enum + { + NUM_ADD_REFS_PER_THREAD = 10, + NUM_EXTRA_REFS_PER_THREAD = 10, + NUM_THREADS = 10 + }; + + class TestObject : public ThreadSafeRefCount {}; + typedef ThreadSafeRef TestObjectRef; + + class TestThread : public Thread + { + public: + TestObjectRef mRef; + Vector mExtraRefs; + + TestThread(TestObjectRef ref) : mRef(ref) {} + + void run(void* arg) + { + if (!arg) + { + // Create references. + for (U32 i = 0; i < NUM_ADD_REFS_PER_THREAD; i++) + mRef->addRef(); + + mExtraRefs.setSize(NUM_EXTRA_REFS_PER_THREAD); + for (U32 i = 0; i < NUM_EXTRA_REFS_PER_THREAD; i++) + mExtraRefs[i] = mRef; + } + else + { + // Clear references. + mExtraRefs.clear(); + for (U32 i = 0; i < NUM_ADD_REFS_PER_THREAD; i++) + mRef->release(); + } + } + }; + +}; + +TEST_FIX(ThreadSafeRefCount, Serial) +{ + bool deleted = false; + TestObjectDtorRef ref1 = new TestObjectDtor(deleted); + ASSERT_FALSE(deleted); + EXPECT_FALSE(ref1->isShared()); + EXPECT_TRUE(ref1 != NULL); + + TestObjectDtorRef ref2 = ref1; + EXPECT_TRUE(ref1->isShared()); + EXPECT_TRUE(ref2->isShared()); + EXPECT_EQ(ref1, ref2); + + ref1 = NULL; + EXPECT_FALSE(ref2->isShared()); + + ref2 = NULL; + ASSERT_TRUE(deleted); +} + +TEST_FIX(ThreadSafeRefCount, Concurrent) +{ + TestObjectRef mRef = new TestObject; + EXPECT_EQ(2, mRef->getRefCount()); // increments of 2 + + Vector threads; + threads.setSize(NUM_THREADS); + + // Create threads. + for (U32 i = 0; i < NUM_THREADS; i++) + threads[i] = new TestThread(mRef); + + // Run phase 1: create references. + for (U32 i = 0; i < NUM_THREADS; i++) + threads[i]->start(NULL); + + // Wait for completion. + for (U32 i = 0; i < NUM_THREADS; i++) + threads[i]->join(); + + EXPECT_EQ(2 + ((1 + NUM_ADD_REFS_PER_THREAD + NUM_EXTRA_REFS_PER_THREAD) * NUM_THREADS * 2), + mRef->getRefCount()); + + // Run phase 2: release references. + for (U32 i = 0; i < NUM_THREADS; i++) + threads[i]->start((void*) 1); + + // Wait for completion. + for (U32 i = 0; i < NUM_THREADS; i++) + { + threads[i]->join(); + delete threads[i]; + } + + EXPECT_EQ(2, mRef->getRefCount()); // increments of two + + mRef = NULL; +} + +TEST_FIX(ThreadSafeRefCount, Tagging) +{ + TestObjectRef ref; + EXPECT_FALSE(ref.isTagged()); + EXPECT_FALSE(bool(ref)); + EXPECT_FALSE(bool(ref.ptr())); + + EXPECT_TRUE(ref.trySetFromTo(ref, NULL)); + EXPECT_FALSE(ref.isTagged()); + + EXPECT_TRUE(ref.trySetFromTo(ref, NULL, TestObjectRef::TAG_Set)); + EXPECT_TRUE(ref.isTagged()); + EXPECT_TRUE(ref.trySetFromTo(ref, NULL, TestObjectRef::TAG_Set)); + EXPECT_TRUE(ref.isTagged()); + + EXPECT_TRUE(ref.trySetFromTo(ref, NULL, TestObjectRef::TAG_Unset)); + EXPECT_FALSE(ref.isTagged()); + EXPECT_TRUE(ref.trySetFromTo(ref, NULL, TestObjectRef::TAG_Unset)); + EXPECT_FALSE(ref.isTagged()); + + EXPECT_TRUE(ref.trySetFromTo(ref, NULL, TestObjectRef::TAG_SetOrFail)); + EXPECT_TRUE(ref.isTagged()); + EXPECT_FALSE(ref.trySetFromTo(ref, NULL, TestObjectRef::TAG_SetOrFail)); + EXPECT_TRUE(ref.isTagged()); + EXPECT_FALSE(ref.trySetFromTo(ref, NULL, TestObjectRef::TAG_FailIfSet)); + + EXPECT_TRUE(ref.trySetFromTo(ref, NULL, TestObjectRef::TAG_UnsetOrFail)); + EXPECT_FALSE(ref.isTagged()); + EXPECT_FALSE(ref.trySetFromTo(ref, NULL, TestObjectRef::TAG_UnsetOrFail)); + EXPECT_FALSE(ref.isTagged()); + EXPECT_FALSE(ref.trySetFromTo(ref, NULL, TestObjectRef::TAG_FailIfUnset)); + + TestObjectRef objectA = new TestObject; + TestObjectRef objectB = new TestObject; + + EXPECT_FALSE(objectA->isShared()); + EXPECT_FALSE(objectB->isShared()); + + ref = objectA; + EXPECT_FALSE(ref.isTagged()); + EXPECT_TRUE(ref == objectA); + EXPECT_TRUE(ref == objectA.ptr()); + EXPECT_TRUE(objectA->isShared()); + + EXPECT_TRUE(ref.trySetFromTo(objectA, objectB, TestObjectRef::TAG_Set)); + EXPECT_TRUE(ref.isTagged()); + EXPECT_EQ(ref, objectB); + EXPECT_EQ(ref, objectB.ptr()); + EXPECT_TRUE(objectB->isShared()); + EXPECT_FALSE(objectA->isShared()); + + EXPECT_TRUE(ref.trySetFromTo(ref, objectA)); + EXPECT_TRUE(ref.isTagged()); + EXPECT_EQ(ref, objectA); + EXPECT_EQ(ref, objectA.ptr()); +} + +#endif \ No newline at end of file diff --git a/Engine/source/platform/threads/test/threadTest.cpp b/Engine/source/platform/threads/test/threadTest.cpp new file mode 100644 index 000000000..2c5015686 --- /dev/null +++ b/Engine/source/platform/threads/test/threadTest.cpp @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "platform/threads/thread.h" + +TEST(Thread, CallbackAPI) +{ +#define VALUE_TO_SET 10 + + // This struct exists just so we can define run as a local function. + struct thread + { + // Do some work we can observe. + static void body(void* arg) + { + U32* value = reinterpret_cast(arg); + *value = VALUE_TO_SET; + } + }; + + // Test most basic Thread API functions. + U32 value = ~VALUE_TO_SET; + Thread thread(&thread::body, reinterpret_cast(&value)); + thread.start(); + EXPECT_TRUE(thread.isAlive()); + thread.join(); + EXPECT_FALSE(thread.isAlive()); + + EXPECT_EQ(value, VALUE_TO_SET) + << "Thread did not set expected value!"; + +#undef VALUE_TO_SET +} + +TEST(Thread, InheritanceAPI) +{ +#define VALUE_TO_SET 10 + + // This struct exists just so we can define run as a local function. + struct thread : public Thread + { + U32* mPtr; + thread(U32* ptr): mPtr(ptr) {} + + // Do some work we can observe. + virtual void run(void*) + { + *mPtr = VALUE_TO_SET; + } + }; + + // Test most basic Thread API functions. + U32 value = ~VALUE_TO_SET; + thread thread(&value); + thread.start(); + EXPECT_TRUE(thread.isAlive()); + thread.join(); + EXPECT_FALSE(thread.isAlive()); + + EXPECT_EQ(value, VALUE_TO_SET) + << "Thread did not set expected value!"; + +#undef VALUE_TO_SET +} + +#endif \ No newline at end of file diff --git a/Engine/source/platform/types.codewarrior.h b/Engine/source/platform/types.codewarrior.h index 64912784d..db0d60400 100644 --- a/Engine/source/platform/types.codewarrior.h +++ b/Engine/source/platform/types.codewarrior.h @@ -51,10 +51,16 @@ typedef unsigned long long U64; ///< Compiler independent Unsigned 64-bit in //-------------------------------------- // Identify the Operating System +#if defined(_WIN64) +# define TORQUE_OS_STRING "Win64" +# define TORQUE_OS_WIN +# define TORQUE_OS_WIN64 +# include "platform/types.win.h" #if defined(_WIN32) # define TORQUE_OS_STRING "Win32" +# define TORQUE_OS_WIN # define TORQUE_OS_WIN32 -# include "platform/types.win32.h" +# include "platform/types.win.h" #elif defined(macintosh) || defined(__APPLE__) # define TORQUE_OS_STRING "Mac" diff --git a/Engine/source/platform/types.gcc.h b/Engine/source/platform/types.gcc.h index 406b07ef1..1d49feacc 100644 --- a/Engine/source/platform/types.gcc.h +++ b/Engine/source/platform/types.gcc.h @@ -55,12 +55,18 @@ typedef unsigned long long U64; //-------------------------------------- // Identify the Operating System -#if defined(__WIN32__) || defined(_WIN32) +#if defined(_WIN64) +# define TORQUE_OS_STRING "Win64" +# define TORQUE_OS_WIN +# define TORQUE_OS_WIN64 +# include "platform/types.win.h" +#elif defined(__WIN32__) || defined(_WIN32) # define TORQUE_OS_STRING "Win32" +# define TORQUE_OS_WIN # define TORQUE_OS_WIN32 # define TORQUE_SUPPORTS_NASM # define TORQUE_SUPPORTS_GCC_INLINE_X86_ASM -# include "platform/types.win32.h" +# include "platform/types.win.h" #elif defined(SN_TARGET_PS3) # define TORQUE_OS_STRING "PS3" diff --git a/Engine/source/platform/types.h b/Engine/source/platform/types.h index c53bd87fc..3e0a508fa 100644 --- a/Engine/source/platform/types.h +++ b/Engine/source/platform/types.h @@ -40,7 +40,7 @@ typedef double F64; ///< Compiler independent 64-bit float struct EmptyType {}; ///< "Null" type used by templates -#define TORQUE_UNUSED(var) (void)var +#define TORQUE_UNUSED(var) (void)sizeof(var) //------------------------------------------------------------------------------ //------------------------------------- String Types @@ -109,7 +109,7 @@ static const F32 F32_MAX = F32(3.402823466e+38F); ///< Constant #endif /// Integral type matching the host's memory address width. -#ifdef TORQUE_64BITS +#ifdef TORQUE_CPU_X64 typedef U64 MEM_ADDRESS; #else typedef U32 MEM_ADDRESS; @@ -218,13 +218,13 @@ inline S8 getMin(S8 a, S8 b) } /// Returns the lesser of the two parameters: a & b. -inline float getMin(float a, float b) +inline F32 getMin(F32 a, F32 b) { return a>b ? b : a; } /// Returns the lesser of the two parameters: a & b. -inline double getMin(double a, double b) +inline F64 getMin(F64 a, F64 b) { return a>b ? b : a; } @@ -266,13 +266,13 @@ inline S8 getMax(S8 a, S8 b) } /// Returns the greater of the two parameters: a & b. -inline float getMax(float a, float b) +inline F32 getMax(F32 a, F32 b) { return a>b ? a : b; } /// Returns the greater of the two parameters: a & b. -inline double getMax(double a, double b) +inline F64 getMax(F64 a, F64 b) { return a>b ? a : b; } @@ -290,7 +290,7 @@ inline double getMax(double a, double b) #define BIT(x) (1 << (x)) ///< Returns value with bit x set (2^x) -#if defined(TORQUE_OS_WIN32) +#if defined(TORQUE_OS_WIN) #define STDCALL __stdcall #else #define STDCALL diff --git a/Engine/source/platform/types.lint.h b/Engine/source/platform/types.lint.h index fff33d28d..f2268e9a2 100644 --- a/Engine/source/platform/types.lint.h +++ b/Engine/source/platform/types.lint.h @@ -39,7 +39,7 @@ struct FileTime #define TORQUE_LITTLE_ENDIAN #define TORQUE_SUPPORTS_NASM #define TORQUE_SUPPORTS_VC_INLINE_X86_ASM -#define TORQUE_OS_WIN32 +#define TORQUE_OS_WIN #define TORQUE_COMPILER_VISUALC 1500 #ifndef FN_CDECL diff --git a/Engine/source/platform/types.visualc.h b/Engine/source/platform/types.visualc.h index 4379e8a57..e383c1ea7 100644 --- a/Engine/source/platform/types.visualc.h +++ b/Engine/source/platform/types.visualc.h @@ -58,11 +58,17 @@ typedef unsigned _int64 U64; #elif defined( _XBOX_VER ) # define TORQUE_OS_STRING "Xbox" # define TORQUE_OS_XBOX -# include "platform/types.win32.h" -#elif defined(_WIN32) +# include "platform/types.win.h" +#elif defined( _WIN32 ) && !defined ( _WIN64 ) # define TORQUE_OS_STRING "Win32" +# define TORQUE_OS_WIN # define TORQUE_OS_WIN32 -# include "platform/types.win32.h" +# include "platform/types.win.h" +#elif defined( _WIN64 ) +# define TORQUE_OS_STRING "Win64" +# define TORQUE_OS_WIN +# define TORQUE_OS_WIN64 +# include "platform/types.win.h" #else # error "VC: Unsupported Operating System" #endif @@ -70,13 +76,17 @@ typedef unsigned _int64 U64; //-------------------------------------- // Identify the CPU -#if defined(_M_IX86) +#if defined( _M_X64 ) +# define TORQUE_CPU_STRING "x64" +# define TORQUE_CPU_X64 +# define TORQUE_LITTLE_ENDIAN +#elif defined( _M_IX86 ) # define TORQUE_CPU_STRING "x86" # define TORQUE_CPU_X86 # define TORQUE_LITTLE_ENDIAN # define TORQUE_SUPPORTS_NASM # define TORQUE_SUPPORTS_VC_INLINE_X86_ASM -#elif defined(TORQUE_OS_XENON) +#elif defined( TORQUE_OS_XENON ) # define TORQUE_CPU_STRING "ppc" # define TORQUE_CPU_PPC # define TORQUE_BIG_ENDIAN diff --git a/Engine/source/platform/types.win32.h b/Engine/source/platform/types.win.h similarity index 94% rename from Engine/source/platform/types.win32.h rename to Engine/source/platform/types.win.h index d95d3cec5..68e0e3a63 100644 --- a/Engine/source/platform/types.win32.h +++ b/Engine/source/platform/types.win.h @@ -29,7 +29,12 @@ // size_t is needed to overload new // size_t tends to be OS and compiler specific and may need to // be if/def'ed in the future -typedef unsigned int dsize_t; + +#ifdef _WIN64 +typedef unsigned long long dsize_t; +#else +typedef unsigned int dsize_t; +#endif // _WIN64 /// Platform dependent file date-time structure. The definition of this structure diff --git a/Engine/source/platform/typesWin32.h b/Engine/source/platform/typesWin32.h index c4b2aa2b2..029b1a341 100644 --- a/Engine/source/platform/typesWin32.h +++ b/Engine/source/platform/typesWin32.h @@ -76,7 +76,12 @@ typedef double F64; ///< Compiler independent 64-bit float // size_t is needed to overload new // size_t tends to be OS and compiler specific and may need to // be if/def'ed in the future + +#ifdef _WIN64 +typedef unsigned long long dsize_t; +#else typedef unsigned int dsize_t; +#endif // _WIN64 typedef const char* StringTableEntry; diff --git a/Engine/source/platform/typetraits.h b/Engine/source/platform/typetraits.h index a686ab782..4183a3f8f 100644 --- a/Engine/source/platform/typetraits.h +++ b/Engine/source/platform/typetraits.h @@ -222,11 +222,11 @@ struct _TypeTraits< T* > typedef _DestructPtr Destruct; template< typename A > - static bool isTaggedPtr( A* ptr ) { return ( U32( ptr ) & 0x1 ); } //TODO: 64bits + static bool isTaggedPtr( A* ptr ) { return ( size_t( ptr ) & 0x1 ); } //TODO: 64bits template< typename A > - static A* getTaggedPtr( A* ptr ) { return ( A* ) ( U32( ptr ) | 0x1 ); } //TODO: 64bits + static A* getTaggedPtr( A* ptr ) { return ( A* ) ( size_t( ptr ) | 0x1 ); } //TODO: 64bits template< typename A > - static A* getUntaggedPtr( A* ptr ) { return ( A* ) ( U32( ptr ) & 0xFFFFFFFE ); } //TODO: 64bit + static A* getUntaggedPtr( A* ptr ) { return ( A* ) ( size_t( ptr ) & (~0x1) ); } //TODO: 64bit }; template< typename T > diff --git a/Engine/source/platformMac/macCocoaPlatform.mm b/Engine/source/platformMac/macCocoaPlatform.mm index 24b8808e9..286aa44e2 100644 --- a/Engine/source/platformMac/macCocoaPlatform.mm +++ b/Engine/source/platformMac/macCocoaPlatform.mm @@ -70,6 +70,11 @@ bool Platform::displaySplashWindow() return false; } +bool Platform::closeSplashWindow() +{ + return false; +} + #pragma mark ---- File IO ---- //----------------------------------------------------------------------------- bool dPathCopy(const char* source, const char* dest, bool nooverwrite) diff --git a/Engine/source/platformPOSIX/posixVolume.cpp b/Engine/source/platformPOSIX/posixVolume.cpp index 604611543..a5d0871d0 100644 --- a/Engine/source/platformPOSIX/posixVolume.cpp +++ b/Engine/source/platformPOSIX/posixVolume.cpp @@ -251,7 +251,7 @@ Path PosixFile::getName() const return _path; } -FileNode::Status PosixFile::getStatus() const +FileNode::NodeStatus PosixFile::getStatus() const { return _status; } @@ -536,7 +536,7 @@ bool PosixDirectory::getAttributes(Attributes* attr) return true; } -FileNode::Status PosixDirectory::getStatus() const +FileNode::NodeStatus PosixDirectory::getStatus() const { return _status; } diff --git a/Engine/source/platformPOSIX/posixVolume.h b/Engine/source/platformPOSIX/posixVolume.h index 3f6b48cf0..4445ed38e 100644 --- a/Engine/source/platformPOSIX/posixVolume.h +++ b/Engine/source/platformPOSIX/posixVolume.h @@ -68,7 +68,7 @@ class PosixFile: public File Path _path; String _name; FILE* _handle; - Status _status; + NodeStatus _status; PosixFile(const Path& path,String name); bool _updateInfo(); @@ -78,7 +78,7 @@ public: ~PosixFile(); Path getName() const; - Status getStatus() const; + NodeStatus getStatus() const; bool getAttributes(Attributes*); U32 getPosition(); @@ -103,7 +103,7 @@ class PosixDirectory: public Directory Path _path; String _name; DIR* _handle; - Status _status; + NodeStatus _status; PosixDirectory(const Path& path,String name); void _updateStatus(); @@ -112,7 +112,7 @@ public: ~PosixDirectory(); Path getName() const; - Status getStatus() const; + NodeStatus getStatus() const; bool getAttributes(Attributes*); bool open(); diff --git a/Engine/source/platformWin32/minidump/winMiniDump.cpp b/Engine/source/platformWin32/minidump/winMiniDump.cpp index fd1ad9ab2..fbe2b96f6 100644 --- a/Engine/source/platformWin32/minidump/winMiniDump.cpp +++ b/Engine/source/platformWin32/minidump/winMiniDump.cpp @@ -191,9 +191,9 @@ INT CreateMiniDump( LPEXCEPTION_POINTERS ExceptionInfo) //----------------------------------------------------------------------------------------------------------------------------------------- // MiniDumpDialogProc - Used By DisplayMiniDumpDialog //----------------------------------------------------------------------------------------------------------------------------------------- -const int ID_TEXT=200; -const int ID_USERTEXT=300; -const int ID_DONE=400; +const S32 ID_TEXT=200; +const S32 ID_USERTEXT=300; +const S32 ID_DONE=400; BOOL CALLBACK MiniDumpDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { char text[128]= ""; @@ -259,7 +259,7 @@ LRESULT DisplayMiniDumpDialog(HINSTANCE hinst, HWND hwndOwner) *lpw++ = 0; // Predefined dialog box class (by default) LPWSTR lpwsz = (LPWSTR)lpw; - int nchar = 1 + MultiByteToWideChar(CP_ACP, 0, "MiniDump Crash Report", -1, lpwsz, 50); + S32 nchar = 1 + MultiByteToWideChar(CP_ACP, 0, "MiniDump Crash Report", -1, lpwsz, 50); lpw += nchar; //----------------------------------------------------------------- diff --git a/Engine/source/platformWin32/minidump/winStackWalker.cpp b/Engine/source/platformWin32/minidump/winStackWalker.cpp index a533aa97f..c4b72211d 100644 --- a/Engine/source/platformWin32/minidump/winStackWalker.cpp +++ b/Engine/source/platformWin32/minidump/winStackWalker.cpp @@ -48,7 +48,7 @@ #endif // Entry for each Callstack-Entry -const int STACKWALK_MAX_NAMELEN = 1024; // max name length for symbols +const S32 STACKWALK_MAX_NAMELEN = 1024; // max name length for symbols struct CallstackEntry { DWORD64 offset; // if 0, we have no valid entry @@ -393,7 +393,7 @@ bool StackWalker::ShowCallstack(HANDLE hThread, CONTEXT const & context, PReadPr IMAGEHLP_SYMBOL64 *pSym = NULL; IMAGEHLP_MODULE64 Module; IMAGEHLP_LINE64 Line; - int frameNum; + S32 frameNum; if (!m_modulesLoaded) LoadModules(); @@ -687,7 +687,7 @@ bool StackWalker::GetModuleListTH32(HANDLE hProcess, DWORD pid) return false; keepGoing = !!pM32F( hSnap, &me ); - int cnt = 0; + S32 cnt = 0; while (keepGoing) { this->LoadModule(hProcess, me.szExePath, me.szModule, (DWORD64) me.modBaseAddr, me.modBaseSize); @@ -715,7 +715,7 @@ bool StackWalker::GetModuleListPSAPI(HANDLE hProcess) char *tt = NULL; char *tt2 = NULL; const SIZE_T TTBUFLEN = 8096; - int cnt = 0; + S32 cnt = 0; hMods = (HMODULE*) malloc(sizeof(HMODULE) * (TTBUFLEN / sizeof HMODULE)); tt = (char*) malloc(sizeof(char) * TTBUFLEN); diff --git a/Engine/source/platformWin32/minidump/winStackWalker.h b/Engine/source/platformWin32/minidump/winStackWalker.h index d39219de4..a7341ace1 100644 --- a/Engine/source/platformWin32/minidump/winStackWalker.h +++ b/Engine/source/platformWin32/minidump/winStackWalker.h @@ -76,7 +76,7 @@ private: DWORD m_dwProcessId; bool m_modulesLoaded; LPSTR m_szSymPath; - int m_options; + S32 m_options; char * m_pOutputBuffer; static BOOL __stdcall myReadProcMem(HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead); diff --git a/Engine/source/platformWin32/nativeDialogs/fileDialog.cpp b/Engine/source/platformWin32/nativeDialogs/fileDialog.cpp index 5dce1a87f..5db038332 100644 --- a/Engine/source/platformWin32/nativeDialogs/fileDialog.cpp +++ b/Engine/source/platformWin32/nativeDialogs/fileDialog.cpp @@ -113,7 +113,7 @@ static UINT_PTR CALLBACK FolderHookProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPA SendMessage(hParent, CDM_HIDECONTROL, cmb1, 0); SendMessage(hParent, CDM_HIDECONTROL, stc2, 0); - LONG oldProc = SetWindowLong(hParent, GWL_WNDPROC, (LONG)OKBtnFolderHackProc); + LONG oldProc = SetWindowLong(hParent, GWLP_WNDPROC, (LONG)OKBtnFolderHackProc); SetProp(hParent, dT("OldWndProc"), (HANDLE)oldProc); SetProp(hParent, dT("OFN"), (HANDLE)lpofn); } diff --git a/Engine/source/platformWin32/threads/thread.cpp b/Engine/source/platformWin32/threads/thread.cpp index 6e66ddc6d..d1ba59cc2 100644 --- a/Engine/source/platformWin32/threads/thread.cpp +++ b/Engine/source/platformWin32/threads/thread.cpp @@ -68,7 +68,7 @@ public: // Neccesary because Thread::run() is provided as a non-threaded // way to execute the thread's run function. So we have to keep // track of the thread's lock here. -static unsigned int __stdcall ThreadRunHandler(void * arg) +static U32 __stdcall ThreadRunHandler(void * arg) { PlatformThreadData* mData = reinterpret_cast(arg); mData->mThreadID = GetCurrentThreadId(); @@ -164,7 +164,7 @@ U32 Thread::getId() void Thread::_setName( const char* name ) { -#if defined( TORQUE_DEBUG ) && defined( TORQUE_COMPILER_VISUALC ) && defined( TORQUE_OS_WIN32 ) +#if defined( TORQUE_DEBUG ) && defined( TORQUE_COMPILER_VISUALC ) && defined( TORQUE_OS_WIN ) // See http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx diff --git a/Engine/source/platformWin32/winConsole.cpp b/Engine/source/platformWin32/winConsole.cpp index 339c41b2b..25f172abb 100644 --- a/Engine/source/platformWin32/winConsole.cpp +++ b/Engine/source/platformWin32/winConsole.cpp @@ -130,7 +130,7 @@ WinConsole::~WinConsole() void WinConsole::printf(const char *s, ...) { // Get the line into a buffer. - static const int BufSize = 4096; + static const S32 BufSize = 4096; static char buffer[4096]; DWORD bytes; va_list args; diff --git a/Engine/source/platformWin32/winDInputDevice.cpp b/Engine/source/platformWin32/winDInputDevice.cpp index 759a34643..8d036352f 100644 --- a/Engine/source/platformWin32/winDInputDevice.cpp +++ b/Engine/source/platformWin32/winDInputDevice.cpp @@ -896,8 +896,8 @@ bool DInputDevice::buildEvent( DWORD offset, S32 newData, S32 oldData ) // Scale to the range -1.0 to 1.0: if ( objInfo.mMin != DIPROPRANGE_NOMIN && objInfo.mMax != DIPROPRANGE_NOMAX ) { - float range = float( objInfo.mMax - objInfo.mMin ); - newEvent.fValue = float( ( 2 * newData ) - objInfo.mMax - objInfo.mMin ) / range; + F32 range = F32( objInfo.mMax - objInfo.mMin ); + newEvent.fValue = F32( ( 2 * newData ) - objInfo.mMax - objInfo.mMin ) / range; } else newEvent.fValue = (F32)newData; @@ -1041,7 +1041,7 @@ bool DInputDevice::buildEvent( DWORD offset, S32 newData, S32 oldData ) return true; } -void DInputDevice::rumble(float x, float y) +void DInputDevice::rumble(F32 x, F32 y) { LONG rglDirection[2] = { 0, 0 }; DICONSTANTFORCE cf = { 0 }; diff --git a/Engine/source/platformWin32/winDInputDevice.h b/Engine/source/platformWin32/winDInputDevice.h index e8cd13e66..b242df789 100644 --- a/Engine/source/platformWin32/winDInputDevice.h +++ b/Engine/source/platformWin32/winDInputDevice.h @@ -117,7 +117,7 @@ class DInputDevice : public InputDevice const char* getProductName(); // Constant Effect Force Feedback - void rumble( float x, float y ); + void rumble( F32 x, F32 y ); // Console interface functions: const char* getJoystickAxesString(); diff --git a/Engine/source/platformWin32/winDirectInput.cpp b/Engine/source/platformWin32/winDirectInput.cpp index 86bb52bd2..fa02285b0 100644 --- a/Engine/source/platformWin32/winDirectInput.cpp +++ b/Engine/source/platformWin32/winDirectInput.cpp @@ -437,14 +437,14 @@ bool DInputManager::isXInputEnabled() } //------------------------------------------------------------------------------ -bool DInputManager::isXInputConnected(int controllerID) +bool DInputManager::isXInputConnected(S32 controllerID) { return( mXInputStateNew[controllerID].bConnected ); } -int DInputManager::getXInputState(int controllerID, int property, bool current) +int DInputManager::getXInputState(S32 controllerID, S32 property, bool current) { - int retVal; + S32 retVal; switch(property) { @@ -511,7 +511,7 @@ void DInputManager::deactivateXInput() } //------------------------------------------------------------------------------ -bool DInputManager::rumble( const char *pDeviceName, float x, float y ) +bool DInputManager::rumble( const char *pDeviceName, F32 x, F32 y ) { // Determine the device U32 deviceType; @@ -566,7 +566,7 @@ bool DInputManager::rumble( const char *pDeviceName, float x, float y ) } } -void DInputManager::buildXInputEvent( U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, float fValue ) +void DInputManager::buildXInputEvent( U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, F32 fValue ) { InputEventInfo newEvent; @@ -586,7 +586,7 @@ void DInputManager::buildXInputEvent( U32 deviceInst, InputEventType objType, In // "mXInputStateReset" is the exception and is true whenever DirectInput gets reset (because // the user ALT-TABBED away, for example). That means that after every context switch, // you will get a full set of updates on the "true" state of the controller. -inline void DInputManager::fireXInputConnectEvent( int controllerID, bool condition, bool connected ) +inline void DInputManager::fireXInputConnectEvent( S32 controllerID, bool condition, bool connected ) { if ( mXInputStateReset || condition ) { @@ -597,7 +597,7 @@ inline void DInputManager::fireXInputConnectEvent( int controllerID, bool condit } } -inline void DInputManager::fireXInputMoveEvent( int controllerID, bool condition, InputObjectInstances objInst, float fValue ) +inline void DInputManager::fireXInputMoveEvent( S32 controllerID, bool condition, InputObjectInstances objInst, F32 fValue ) { if ( mXInputStateReset || condition ) { @@ -620,7 +620,7 @@ inline void DInputManager::fireXInputMoveEvent( int controllerID, bool condition } } -inline void DInputManager::fireXInputButtonEvent( int controllerID, bool forceFire, int button, InputObjectInstances objInst ) +inline void DInputManager::fireXInputButtonEvent( S32 controllerID, bool forceFire, S32 button, InputObjectInstances objInst ) { if ( mXInputStateReset || forceFire || ((mXInputStateNew[controllerID].state.Gamepad.wButtons & button) != (mXInputStateOld[controllerID].state.Gamepad.wButtons & button)) ) { @@ -663,7 +663,7 @@ void DInputManager::processXInput( void ) if ( mfnXInputGetState ) { - for ( int i=0; i<4; i++ ) + for ( S32 i=0; i<4; i++ ) { // Calling XInputGetState on a disconnected controller takes a fair // amount of time (probably because it tries to locate it), so we @@ -855,7 +855,7 @@ ConsoleFunction( isXInputConnected, bool, 2, 2, "( int controllerID )" } //------------------------------------------------------------------------------ -ConsoleFunction( getXInputState, int, 3, 4, "( int controllerID, string property, bool current )" +ConsoleFunction( getXInputState, S32, 3, 4, "( int controllerID, string property, bool current )" "@brief Queries the current state of a connected Xbox 360 controller.\n\n" "XInput Properties:\n\n" " - XI_THUMBLX, XI_THUMBLY - X and Y axes of the left thumbstick. \n" diff --git a/Engine/source/platformWin32/winDirectInput.h b/Engine/source/platformWin32/winDirectInput.h index 378cbec03..d7ebd1b70 100644 --- a/Engine/source/platformWin32/winDirectInput.h +++ b/Engine/source/platformWin32/winDirectInput.h @@ -85,10 +85,10 @@ class DInputManager : public InputManager void unacquire( U8 deviceType, U8 deviceID ); // XInput worker functions - void buildXInputEvent( U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, float fValue ); - void fireXInputConnectEvent( int controllerID, bool condition, bool connected ); - void fireXInputMoveEvent( int controllerID, bool condition, InputObjectInstances objInst, float fValue ); - void fireXInputButtonEvent( int controllerID, bool forceFire, int button, InputObjectInstances objInst ); + void buildXInputEvent( U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, F32 fValue ); + void fireXInputConnectEvent( S32 controllerID, bool condition, bool connected ); + void fireXInputMoveEvent( S32 controllerID, bool condition, InputObjectInstances objInst, F32 fValue ); + void fireXInputButtonEvent( S32 controllerID, bool forceFire, S32 button, InputObjectInstances objInst ); void processXInput(); public: @@ -120,13 +120,13 @@ class DInputManager : public InputManager void deactivateXInput(); bool isXInputActive() { return( mXInputActive ); } void resetXInput() { mXInputStateReset = true; } - bool isXInputConnected(int controllerID); - int getXInputState(int controllerID, int property, bool current); + bool isXInputConnected(S32 controllerID); + S32 getXInputState(S32 controllerID, S32 property, bool current); // Console interface: const char* getJoystickAxesString( U32 deviceID ); - bool rumble( const char *pDeviceName, float x, float y ); + bool rumble( const char *pDeviceName, F32 x, F32 y ); }; #endif // _H_WINDIRECTINPUT_ diff --git a/Engine/source/platformWin32/winFileio.cpp b/Engine/source/platformWin32/winFileio.cpp index 0d9c7c132..7296ed32e 100644 --- a/Engine/source/platformWin32/winFileio.cpp +++ b/Engine/source/platformWin32/winFileio.cpp @@ -248,7 +248,7 @@ File::~File() // Sets capability appropriate to the openMode. // Returns the currentStatus of the file. //----------------------------------------------------------------------------- -File::Status File::open(const char *filename, const AccessMode openMode) +File::FileStatus File::open(const char *filename, const AccessMode openMode) { AssertFatal(NULL != filename, "File::open: NULL fname"); AssertWarn(INVALID_HANDLE_VALUE == (HANDLE)handle, "File::open: handle already valid"); @@ -363,7 +363,7 @@ U32 File::getPosition() const // // Returns the currentStatus of the file. //----------------------------------------------------------------------------- -File::Status File::setPosition(S32 position, bool absolutePos) +File::FileStatus File::setPosition(S32 position, bool absolutePos) { AssertFatal(Closed != currentStatus, "File::setPosition: file closed"); AssertFatal(INVALID_HANDLE_VALUE != (HANDLE)handle, "File::setPosition: invalid file handle"); @@ -425,7 +425,7 @@ U32 File::getSize() const // It is an error to flush a read-only file. // Returns the currentStatus of the file. //----------------------------------------------------------------------------- -File::Status File::flush() +File::FileStatus File::flush() { AssertFatal(Closed != currentStatus, "File::flush: file closed"); AssertFatal(INVALID_HANDLE_VALUE != (HANDLE)handle, "File::flush: invalid file handle"); @@ -442,7 +442,7 @@ File::Status File::flush() // // Returns the currentStatus //----------------------------------------------------------------------------- -File::Status File::close() +File::FileStatus File::close() { // check if it's already closed... if (Closed == currentStatus) @@ -461,7 +461,7 @@ File::Status File::close() //----------------------------------------------------------------------------- // Self-explanatory. //----------------------------------------------------------------------------- -File::Status File::getStatus() const +File::FileStatus File::getStatus() const { return currentStatus; } @@ -469,7 +469,7 @@ File::Status File::getStatus() const //----------------------------------------------------------------------------- // Sets and returns the currentStatus when an error has been encountered. //----------------------------------------------------------------------------- -File::Status File::setStatus() +File::FileStatus File::setStatus() { switch (GetLastError()) { @@ -489,7 +489,7 @@ File::Status File::setStatus() //----------------------------------------------------------------------------- // Sets and returns the currentStatus to status. //----------------------------------------------------------------------------- -File::Status File::setStatus(File::Status status) +File::FileStatus File::setStatus(File::FileStatus status) { return currentStatus = status; } @@ -500,7 +500,7 @@ File::Status File::setStatus(File::Status status) // The number of bytes read is available in bytesRead if a non-Null pointer is // provided. //----------------------------------------------------------------------------- -File::Status File::read(U32 size, char *dst, U32 *bytesRead) +File::FileStatus File::read(U32 size, char *dst, U32 *bytesRead) { AssertFatal(Closed != currentStatus, "File::read: file closed"); AssertFatal(INVALID_HANDLE_VALUE != (HANDLE)handle, "File::read: invalid file handle"); @@ -531,7 +531,7 @@ File::Status File::read(U32 size, char *dst, U32 *bytesRead) // The number of bytes written is available in bytesWritten if a non-Null // pointer is provided. //----------------------------------------------------------------------------- -File::Status File::write(U32 size, const char *src, U32 *bytesWritten) +File::FileStatus File::write(U32 size, const char *src, U32 *bytesWritten) { AssertFatal(Closed != currentStatus, "File::write: file closed"); AssertFatal(INVALID_HANDLE_VALUE != (HANDLE)handle, "File::write: invalid file handle"); @@ -1140,7 +1140,7 @@ void Platform::getVolumeNamesList( Vector& out_rNameVector, bool bO out_rNameVector.clear(); - for(int i = 0; i < 32; i++ ) + for(S32 i = 0; i < 32; i++ ) { dMemset(driveLetter,0,12); if( dwDrives & dwMask ) diff --git a/Engine/source/platformWin32/winFont.cpp b/Engine/source/platformWin32/winFont.cpp index 1a625d2bc..ff179be5f 100644 --- a/Engine/source/platformWin32/winFont.cpp +++ b/Engine/source/platformWin32/winFont.cpp @@ -116,7 +116,7 @@ void PlatformFont::enumeratePlatformFonts( Vector& fonts, UTF1 EnumFontFamilies( fontHDC, fontFamily, (FONTENUMPROC)EnumFamCallBack, (LPARAM)&fonts ); } -PlatformFont *createPlatformFont(const char *name, U32 size, U32 charset /* = TGE_ANSI_CHARSET */) +PlatformFont *createPlatformFont(const char *name, dsize_t size, U32 charset /* = TGE_ANSI_CHARSET */) { PlatformFont *retFont = new WinFont; @@ -139,7 +139,7 @@ WinFont::~WinFont() } } -bool WinFont::create(const char *name, U32 size, U32 charset /* = TGE_ANSI_CHARSET */) +bool WinFont::create(const char *name, dsize_t size, U32 charset /* = TGE_ANSI_CHARSET */) { if(name == NULL || size < 1) return false; diff --git a/Engine/source/platformWin32/winMath_ASM.cpp b/Engine/source/platformWin32/winMath_ASM.cpp index 0bc373494..53150afa0 100644 --- a/Engine/source/platformWin32/winMath_ASM.cpp +++ b/Engine/source/platformWin32/winMath_ASM.cpp @@ -92,6 +92,23 @@ void Platform::setMathControlStateKnown() } } +#else + +U32 Platform::getMathControlState( ) +{ + // @todo x64 See http://msdn.microsoft.com/en-us/library/c9676k6h.aspx + return 0; +} + +void Platform::setMathControlState( U32 state ) +{ + // @todo x64 See http://msdn.microsoft.com/en-us/library/c9676k6h.aspx +} + +void Platform::setMathControlStateKnown( ) +{ + // @todo x64 See http://msdn.microsoft.com/en-us/library/c9676k6h.aspx +} #endif diff --git a/Engine/source/platformWin32/winMemory.cpp b/Engine/source/platformWin32/winMemory.cpp index c4cb821bc..106871c2a 100644 --- a/Engine/source/platformWin32/winMemory.cpp +++ b/Engine/source/platformWin32/winMemory.cpp @@ -23,26 +23,26 @@ #include "platformWin32/platformWin32.h" #include -void* dMemcpy(void *dst, const void *src, unsigned size) +void* dMemcpy(void *dst, const void *src, dsize_t size) { return memcpy(dst,src,size); } //-------------------------------------- -void* dMemmove(void *dst, const void *src, unsigned size) +void* dMemmove(void *dst, const void *src, dsize_t size) { return memmove(dst,src,size); } //-------------------------------------- -void* dMemset(void *dst, S32 c, unsigned size) +void* dMemset(void *dst, S32 c, dsize_t size) { return memset(dst,c,size); } //-------------------------------------- -S32 dMemcmp(const void *ptr1, const void *ptr2, unsigned len) +S32 dMemcmp(const void *ptr1, const void *ptr2, dsize_t len) { return memcmp(ptr1, ptr2, len); } @@ -63,7 +63,7 @@ void dRealFree(void* p) free(p); } -void *dMalloc_aligned(dsize_t in_size, int alignment) +void *dMalloc_aligned(dsize_t in_size, S32 alignment) { return _mm_malloc(in_size, alignment); } diff --git a/Engine/source/platformWin32/winPlatformCPUCount.cpp b/Engine/source/platformWin32/winPlatformCPUCount.cpp new file mode 100644 index 000000000..e4a5d54d6 --- /dev/null +++ b/Engine/source/platformWin32/winPlatformCPUCount.cpp @@ -0,0 +1,119 @@ +// Original code is: +// Copyright (c) 2005 Intel Corporation +// All Rights Reserved +// +// CPUCount.cpp : Detects three forms of hardware multi-threading support across IA-32 platform +// The three forms of HW multithreading are: Multi-processor, Multi-core, and +// HyperThreading Technology. +// This application enumerates all the logical processors enabled by OS and BIOS, +// determine the HW topology of these enabled logical processors in the system +// using information provided by CPUID instruction. +// A multi-processing system can support any combination of the three forms of HW +// multi-threading support. The relevant topology can be identified using a +// three level decomposition of the "initial APIC ID" into +// Package_id, core_id, and SMT_id. Such decomposition provides a three-level map of +// the topology of hardware resources and +// allow multi-threaded software to manage shared hardware resources in +// the platform to reduce resource contention + +// Multicore detection algorithm for processor and cache topology requires +// all leaf functions of CPUID instructions be available. System administrator +// must ensure BIOS settings is not configured to restrict CPUID functionalities. +//------------------------------------------------------------------------------------------------- + +#include "platform/platform.h" + +#if defined( TORQUE_OS_WIN ) + +#include "platform/platformCPUCount.h" +#include +#include +#include +#include + +namespace CPUInfo { + + // based on http://msdn.microsoft.com/en-us/library/ms683194.aspx + + // Helper function to count set bits in the processor mask. + DWORD CountSetBits( ULONG_PTR bitMask ) + { + DWORD LSHIFT = sizeof( ULONG_PTR ) * 8 - 1; + DWORD bitSetCount = 0; + ULONG_PTR bitTest = (ULONG_PTR)1 << LSHIFT; + DWORD i; + + for( i = 0; i <= LSHIFT; ++i ) + { + bitSetCount += ((bitMask & bitTest) ? 1 : 0); + bitTest /= 2; + } + + return bitSetCount; + } + + EConfig CPUCount( U32& TotAvailLogical, U32& TotAvailCore, U32& PhysicalNum ) + { + EConfig StatusFlag = CONFIG_UserConfigIssue; + TotAvailLogical = 0; + TotAvailCore = 0; + PhysicalNum = 0; + + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL; + DWORD returnLength = 0; + + // get buffer length + DWORD rc = GetLogicalProcessorInformation( buffer, &returnLength ); + buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc( returnLength ); + + rc = GetLogicalProcessorInformation( buffer, &returnLength ); + + if( FALSE == rc ) + { + free( buffer ); + return StatusFlag; + } + + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = buffer; + + DWORD byteOffset = 0; + while( byteOffset + sizeof( SYSTEM_LOGICAL_PROCESSOR_INFORMATION ) <= returnLength ) + { + switch( ptr->Relationship ) + { + + case RelationProcessorCore: + TotAvailCore++; + + // A hyperthreaded core supplies more than one logical processor. + TotAvailLogical += CountSetBits( ptr->ProcessorMask ); + break; + + case RelationProcessorPackage: + // Logical processors share a physical package. + PhysicalNum++; + break; + + default: + break; + } + byteOffset += sizeof( SYSTEM_LOGICAL_PROCESSOR_INFORMATION ); + ptr++; + } + + free( buffer ); + + StatusFlag = CONFIG_SingleCoreAndHTNotCapable; + + if( TotAvailCore == 1 && TotAvailLogical > TotAvailCore ) + StatusFlag = CONFIG_SingleCoreHTEnabled; + else if( TotAvailCore > 1 && TotAvailLogical == TotAvailCore ) + StatusFlag = CONFIG_MultiCoreAndHTNotCapable; + else if( TotAvailCore > 1 && TotAvailLogical > TotAvailCore ) + StatusFlag = CONFIG_MultiCoreAndHTEnabled; + + return StatusFlag; + } + +} // namespace CPUInfo +#endif diff --git a/Engine/source/platformWin32/winTime.cpp b/Engine/source/platformWin32/winTime.cpp index e4174eb83..4c27f5ffd 100644 --- a/Engine/source/platformWin32/winTime.cpp +++ b/Engine/source/platformWin32/winTime.cpp @@ -66,7 +66,7 @@ String Platform::localTimeToString( const LocalTime < ) TCHAR buffer[1024] = {0}; - int result = 0; + S32 result = 0; String outStr; diff --git a/Engine/source/platformWin32/winUser.cpp b/Engine/source/platformWin32/winUser.cpp index 666b0858b..c82a273a3 100644 --- a/Engine/source/platformWin32/winUser.cpp +++ b/Engine/source/platformWin32/winUser.cpp @@ -25,7 +25,10 @@ #include "core/stringTable.h" #include "core/strings/unicode.h" +#ifndef TORQUE_OS_WIN64 typedef long SHANDLE_PTR; +#endif + #include #include #include diff --git a/Engine/source/platformWin32/winVolume.cpp b/Engine/source/platformWin32/winVolume.cpp index 1df04e3ca..04422d9eb 100644 --- a/Engine/source/platformWin32/winVolume.cpp +++ b/Engine/source/platformWin32/winVolume.cpp @@ -333,7 +333,7 @@ Path Win32File::getName() const return mPath; } -FileNode::Status Win32File::getStatus() const +FileNode::NodeStatus Win32File::getStatus() const { return mStatus; } @@ -620,7 +620,7 @@ bool Win32Directory::getAttributes(Attributes* attr) return true; } -FileNode::Status Win32Directory::getStatus() const +FileNode::NodeStatus Win32Directory::getStatus() const { return mStatus; } diff --git a/Engine/source/platformWin32/winVolume.h b/Engine/source/platformWin32/winVolume.h index b41b6938c..b4211898d 100644 --- a/Engine/source/platformWin32/winVolume.h +++ b/Engine/source/platformWin32/winVolume.h @@ -65,7 +65,7 @@ public: ~Win32File(); Path getName() const; - Status getStatus() const; + NodeStatus getStatus() const; bool getAttributes(Attributes*); U64 getSize(); @@ -86,7 +86,7 @@ private: Path mPath; String mName; void *mHandle; - Status mStatus; + NodeStatus mStatus; Win32File(const Path &path, String name); @@ -103,7 +103,7 @@ public: ~Win32Directory(); Path getName() const; - Status getStatus() const; + NodeStatus getStatus() const; bool getAttributes(Attributes*); bool open(); @@ -118,7 +118,7 @@ private: Path mPath; String mName; void *mHandle; - Status mStatus; + NodeStatus mStatus; Win32Directory(const Path &path,String name); diff --git a/Engine/source/platformWin32/winWindow.cpp b/Engine/source/platformWin32/winWindow.cpp index 53b3a2b48..8af7079b2 100644 --- a/Engine/source/platformWin32/winWindow.cpp +++ b/Engine/source/platformWin32/winWindow.cpp @@ -311,18 +311,10 @@ S32 main(S32 argc, const char **argv) //-------------------------------------- -#include "unit/test.h" #include "app/mainLoop.h" S32 PASCAL WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, S32) { -#if 0 - // Run a unit test. - StandardMainLoop::initCore(); - UnitTesting::TestRun tr; - tr.test("Platform", true); -#else - Vector argv( __FILE__, __LINE__ ); char moduleName[256]; @@ -350,7 +342,7 @@ S32 PASCAL WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, S32) // Add the word to the argument list. if (*word) { - int len = ptr - word; + S32 len = ptr - word; char *arg = (char *) dMalloc(len + 1); dStrncpy(arg, word, len); arg[len] = 0; @@ -366,19 +358,18 @@ S32 PASCAL WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, S32) dFree(argv[j]); return retVal; -#endif } #else //TORQUE_SHARED extern "C" { - bool torque_engineinit(int argc, const char **argv); - int torque_enginetick(); + bool torque_engineinit(S32 argc, const char **argv); + S32 torque_enginetick(); bool torque_engineshutdown(); }; -int TorqueMain(int argc, const char **argv) +S32 TorqueMain(int argc, const char **argv) { if (!torque_engineinit(argc, argv)) return 1; @@ -442,7 +433,7 @@ S32 torque_winmain( HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, S32) // Add the word to the argument list. if (*word) { - int len = ptr - word; + S32 len = ptr - word; char *arg = (char *) dMalloc(len + 1); dStrncpy(arg, word, len); arg[len] = 0; @@ -499,7 +490,7 @@ bool Platform::openWebBrowser( const char* webAddress ) return( false ); } - if ( RegQueryValueEx( regKey, dT(""), NULL, NULL, (unsigned char *)sWebKey, &size ) != ERROR_SUCCESS ) + if ( RegQueryValueEx( regKey, dT(""), NULL, NULL, (U8 *)sWebKey, &size ) != ERROR_SUCCESS ) { Con::errorf( ConsoleLogEntry::General, "Platform::openWebBrowser - Failed to query the open command registry key!!!" ); return( false ); diff --git a/Engine/source/platformX86UNIX/x86UNIXConsole.cpp b/Engine/source/platformX86UNIX/x86UNIXConsole.cpp index 859b420fa..50a319562 100644 --- a/Engine/source/platformX86UNIX/x86UNIXConsole.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXConsole.cpp @@ -217,7 +217,7 @@ void StdConsole::process() // mojo for select call fd_set rfds; struct timeval tv; - int retval; + FD_ZERO(&rfds); FD_SET(stdIn, &rfds); // don't wait at all in select diff --git a/Engine/source/platformX86UNIX/x86UNIXFileio.cpp b/Engine/source/platformX86UNIX/x86UNIXFileio.cpp index 680faf822..22c40a187 100644 --- a/Engine/source/platformX86UNIX/x86UNIXFileio.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXFileio.cpp @@ -469,7 +469,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) // Sets capability appropriate to the openMode. // Returns the currentStatus of the file. //----------------------------------------------------------------------------- - File::Status File::open(const char *filename, const AccessMode openMode) + File::FileStatus File::open(const char *filename, const AccessMode openMode) { AssertFatal(NULL != filename, "File::open: NULL filename"); AssertWarn(NULL == handle, "File::open: handle already valid"); @@ -584,7 +584,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) // // Returns the currentStatus of the file. //----------------------------------------------------------------------------- - File::Status File::setPosition(S32 position, bool absolutePos) + File::FileStatus File::setPosition(S32 position, bool absolutePos) { AssertFatal(Closed != currentStatus, "File::setPosition: file closed"); AssertFatal(NULL != handle, "File::setPosition: invalid file handle"); @@ -645,7 +645,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) // It is an error to flush a read-only file. // Returns the currentStatus of the file. //----------------------------------------------------------------------------- - File::Status File::flush() + File::FileStatus File::flush() { AssertFatal(Closed != currentStatus, "File::flush: file closed"); AssertFatal(NULL != handle, "File::flush: invalid file handle"); @@ -662,7 +662,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) // // Returns the currentStatus //----------------------------------------------------------------------------- - File::Status File::close() + File::FileStatus File::close() { // if the handle is non-NULL, close it if necessary and free it if (NULL != handle) @@ -684,7 +684,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) //----------------------------------------------------------------------------- // Self-explanatory. //----------------------------------------------------------------------------- - File::Status File::getStatus() const + File::FileStatus File::getStatus() const { return currentStatus; } @@ -692,7 +692,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) //----------------------------------------------------------------------------- // Sets and returns the currentStatus when an error has been encountered. //----------------------------------------------------------------------------- - File::Status File::setStatus() + File::FileStatus File::setStatus() { Con::printf("File IO error: %s", strerror(errno)); return currentStatus = IOError; @@ -701,7 +701,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) //----------------------------------------------------------------------------- // Sets and returns the currentStatus to status. //----------------------------------------------------------------------------- - File::Status File::setStatus(File::Status status) + File::FileStatus File::setStatus(File::FileStatus status) { return currentStatus = status; } @@ -712,7 +712,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) // The number of bytes read is available in bytesRead if a non-Null pointer is // provided. //----------------------------------------------------------------------------- - File::Status File::read(U32 size, char *dst, U32 *bytesRead) + File::FileStatus File::read(U32 size, char *dst, U32 *bytesRead) { #ifdef DEBUG // fprintf(stdout,"reading %d bytes\n",size);fflush(stdout); @@ -770,7 +770,7 @@ bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite) // The number of bytes written is available in bytesWritten if a non-Null // pointer is provided. //----------------------------------------------------------------------------- - File::Status File::write(U32 size, const char *src, U32 *bytesWritten) + File::FileStatus File::write(U32 size, const char *src, U32 *bytesWritten) { // JMQ: despite the U32 parameters, the maximum filesize supported by this // function is probably the max value of S32, due to the unix syscall diff --git a/Engine/source/platformX86UNIX/x86UNIXStub.dedicated.cpp b/Engine/source/platformX86UNIX/x86UNIXStub.dedicated.cpp index 770fd0680..39948914b 100644 --- a/Engine/source/platformX86UNIX/x86UNIXStub.dedicated.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXStub.dedicated.cpp @@ -93,6 +93,7 @@ void Platform::openFile(const char *path) { } // window bool Platform::displaySplashWindow(String path) { return false; } +bool Platform::closeSplashWindow() { return false; } // font PlatformFont *createPlatformFont(const char *name, U32 size, U32 charset) { return NULL; } diff --git a/Engine/source/postFx/postEffect.cpp b/Engine/source/postFx/postEffect.cpp index aff1e6f2c..0638a5fe4 100644 --- a/Engine/source/postFx/postEffect.cpp +++ b/Engine/source/postFx/postEffect.cpp @@ -134,7 +134,7 @@ GFX_ImplementTextureProfile( PostFxTargetProfile, GFXTextureProfile::PreserveSize | GFXTextureProfile::RenderTarget | GFXTextureProfile::Pooled, - GFXTextureProfile::None ); + GFXTextureProfile::NONE ); IMPLEMENT_CONOBJECT(PostEffect); @@ -142,7 +142,7 @@ IMPLEMENT_CONOBJECT(PostEffect); GFX_ImplementTextureProfile( PostFxTextureProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::Static | GFXTextureProfile::PreserveSize | GFXTextureProfile::NoMipmap, - GFXTextureProfile::None ); + GFXTextureProfile::NONE ); void PostEffect::EffectConst::set( const String &newVal ) @@ -374,7 +374,7 @@ bool PostEffect::onAdd() scriptPath.setExtension( String::EmptyString ); // Find additional textures - for( int i = 0; i < NumTextures; i++ ) + for( S32 i = 0; i < NumTextures; i++ ) { String texFilename = mTexFilename[i]; diff --git a/Engine/source/renderInstance/renderFormatChanger.cpp b/Engine/source/renderInstance/renderFormatChanger.cpp index bba53ed53..c9042c766 100644 --- a/Engine/source/renderInstance/renderFormatChanger.cpp +++ b/Engine/source/renderInstance/renderFormatChanger.cpp @@ -243,7 +243,7 @@ void RenderFormatToken::_teardownTargets() { mTarget.release(); - for(int i = 0; i < TargetChainLength; i++) + for(S32 i = 0; i < TargetChainLength; i++) { mTargetColorTexture[i] = NULL; mTargetDepthStencilTexture[i] = NULL; diff --git a/Engine/source/renderInstance/renderGlowMgr.cpp b/Engine/source/renderInstance/renderGlowMgr.cpp index 86bbadcbc..e3801e85e 100644 --- a/Engine/source/renderInstance/renderGlowMgr.cpp +++ b/Engine/source/renderInstance/renderGlowMgr.cpp @@ -54,6 +54,7 @@ RenderGlowMgr::GlowMaterialHook::GlowMaterialHook( BaseMatInstance *matInst ) { mGlowMatInst = (MatInstance*)matInst->getMaterial()->createMatInstance(); mGlowMatInst->getFeaturesDelegate().bind( &GlowMaterialHook::_overrideFeatures ); + mGlowMatInst->setUserObject(matInst->getUserObject()); mGlowMatInst->init( matInst->getRequestedFeatures(), matInst->getVertexFormat() ); } diff --git a/Engine/source/renderInstance/renderOcclusionMgr.cpp b/Engine/source/renderInstance/renderOcclusionMgr.cpp index 4e9839eb5..126d375a8 100644 --- a/Engine/source/renderInstance/renderOcclusionMgr.cpp +++ b/Engine/source/renderInstance/renderOcclusionMgr.cpp @@ -106,7 +106,7 @@ void RenderOcclusionMgr::init() U32 vertexIndex = 0; U32 idx; - for(int i = 0; i < 6; i++) + for(S32 i = 0; i < 6; i++) { idx = cubeFaces[i][0]; verts[vertexIndex].point = cubePoints[idx]; diff --git a/Engine/source/renderInstance/renderParticleMgr.cpp b/Engine/source/renderInstance/renderParticleMgr.cpp index 76c3ec2ff..d1d36f39e 100644 --- a/Engine/source/renderInstance/renderParticleMgr.cpp +++ b/Engine/source/renderInstance/renderParticleMgr.cpp @@ -157,7 +157,7 @@ void RenderParticleMgr::addElement( RenderInst *inst ) pri->bbModelViewProj->mul(tempPt); tempPt = tempPt / tempPt.w; - for(int i = 0; i < 1; i++) + for(S32 i = 0; i < 1; i++) { screenClipper.mPlaneList.push_back(planes[i]); screenClipper.mPlaneList.last() += tempPt.asPoint3F(); @@ -167,7 +167,7 @@ void RenderParticleMgr::addElement( RenderInst *inst ) screenSpaceBoundingBox.minExtents = Point3F::Zero; screenSpaceBoundingBox.maxExtents = Point3F::Zero; - for(int i = 0; i < 8; i++) + for(S32 i = 0; i < 8; i++) { tempPt = cubePoints[i]; pri->bbModelViewProj->mul(tempPt); diff --git a/Engine/source/renderInstance/renderPassManager.h b/Engine/source/renderInstance/renderPassManager.h index 5547b723c..1f07a8ac7 100644 --- a/Engine/source/renderInstance/renderPassManager.h +++ b/Engine/source/renderInstance/renderPassManager.h @@ -65,12 +65,17 @@ protected: public: - RenderInstType( const RenderInstType &type = Invalid ) + RenderInstType() + : mName( Invalid.mName ) + { + } + + RenderInstType( const RenderInstType &type ) : mName( type.mName ) { } - RenderInstType( const String &name ) + RenderInstType( const String &name ) : mName( name ) { } diff --git a/Engine/source/scene/reflectionManager.cpp b/Engine/source/scene/reflectionManager.cpp index c6b78ad65..2c86a700f 100644 --- a/Engine/source/scene/reflectionManager.cpp +++ b/Engine/source/scene/reflectionManager.cpp @@ -59,14 +59,14 @@ MODULE_END; GFX_ImplementTextureProfile( ReflectRenderTargetProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::PreserveSize | GFXTextureProfile::NoMipmap | GFXTextureProfile::RenderTarget | GFXTextureProfile::Pooled, - GFXTextureProfile::None ); + GFXTextureProfile::NONE ); GFX_ImplementTextureProfile( RefractTextureProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::PreserveSize | GFXTextureProfile::RenderTarget | GFXTextureProfile::Pooled, - GFXTextureProfile::None ); + GFXTextureProfile::NONE ); static S32 QSORT_CALLBACK compareReflectors( const void *a, const void *b ) { @@ -189,11 +189,8 @@ void ReflectionManager::update( F32 timeSlice, break; } - U32 totalElapsed = mTimer->getElapsedMs(); - // Set metric/debug related script variables... - U32 numEnabled = mReflectors.size(); U32 numVisible = 0; U32 numOccluded = 0; @@ -208,6 +205,8 @@ void ReflectionManager::update( F32 timeSlice, } #ifdef TORQUE_GATHER_METRICS + U32 numEnabled = mReflectors.size(); + U32 totalElapsed = mTimer->getElapsedMs(); const GFXTextureProfileStats &stats = ReflectRenderTargetProfile.getStats(); F32 mb = ( stats.activeBytes / 1024.0f ) / 1024.0f; diff --git a/Engine/source/scene/reflector.cpp b/Engine/source/scene/reflector.cpp index 2b96737e6..f224a913a 100644 --- a/Engine/source/scene/reflector.cpp +++ b/Engine/source/scene/reflector.cpp @@ -760,7 +760,7 @@ MatrixF PlaneReflector::getCameraReflection( const MatrixF &camTrans ) return newTrans; } -inline float sgn(float a) +inline F32 sgn(F32 a) { if (a > 0.0F) return (1.0F); if (a < 0.0F) return (-1.0F); diff --git a/Engine/source/scene/sceneContainer.cpp b/Engine/source/scene/sceneContainer.cpp index e99f5be11..5d81cc0bd 100644 --- a/Engine/source/scene/sceneContainer.cpp +++ b/Engine/source/scene/sceneContainer.cpp @@ -1197,7 +1197,7 @@ void SceneContainer::cleanupSearchVectors() //----------------------------------------------------------------------------- static Point3F sgSortReferencePoint; -static int QSORT_CALLBACK cmpSearchPointers(const void* inP1, const void* inP2) +static S32 QSORT_CALLBACK cmpSearchPointers(const void* inP1, const void* inP2) { SimObjectPtr** p1 = (SimObjectPtr**)inP1; SimObjectPtr** p2 = (SimObjectPtr**)inP2; @@ -1631,10 +1631,11 @@ DefineEngineFunction( containerRayCast, const char*, pExempt->enableCollision(); // add the hit position and normal? - char *returnBuffer = Con::getReturnBuffer(256); + static const U32 bufSize = 256; + char *returnBuffer = Con::getReturnBuffer(bufSize); if(ret) { - dSprintf(returnBuffer, 256, "%d %g %g %g %g %g %g %g", + dSprintf(returnBuffer, bufSize, "%d %g %g %g %g %g %g %g", ret, rinfo.point.x, rinfo.point.y, rinfo.point.z, rinfo.normal.x, rinfo.normal.y, rinfo.normal.z, rinfo.distance); } diff --git a/Engine/source/scene/sceneManager.cpp b/Engine/source/scene/sceneManager.cpp index 3fcd37422..d07e9fb9a 100644 --- a/Engine/source/scene/sceneManager.cpp +++ b/Engine/source/scene/sceneManager.cpp @@ -156,9 +156,7 @@ void SceneManager::renderScene( ScenePassType passType, U32 objectMask ) { // Store the camera state so if we lock, this will become the // locked state. - - if( passType == SPT_Diffuse ) - smLockedDiffuseCamera = cameraState; + smLockedDiffuseCamera = cameraState; } // Create the render state. @@ -607,6 +605,7 @@ bool SceneManager::addObjectToScene( SceneObject* object ) void SceneManager::removeObjectFromScene( SceneObject* obj ) { + AssertFatal( obj, "SceneManager::removeObjectFromScene - Object is not declared" ); AssertFatal( obj->getSceneManager() == this, "SceneManager::removeObjectFromScene - Object not part of SceneManager" ); // Notify the object. @@ -615,7 +614,8 @@ void SceneManager::removeObjectFromScene( SceneObject* obj ) // Remove the object from the container. - getContainer()->removeObject( obj ); + if( getContainer() ) + getContainer()->removeObject( obj ); // Remove the object from the zoning system. diff --git a/Engine/source/scene/zones/sceneZoneSpaceManager.h b/Engine/source/scene/zones/sceneZoneSpaceManager.h index 51b696326..1c7631949 100644 --- a/Engine/source/scene/zones/sceneZoneSpaceManager.h +++ b/Engine/source/scene/zones/sceneZoneSpaceManager.h @@ -79,7 +79,7 @@ class SceneZoneSpaceManager { public: - ZoneContentIterator( SceneZoneSpaceManager* manager, int zoneId, bool upToDate = true ) + ZoneContentIterator( SceneZoneSpaceManager* manager, S32 zoneId, bool upToDate = true ) { AssertFatal( zoneId < manager->getNumZones(), "SceneZoneSpaceManager::ZoneContentIterator - Zone ID out of range" ); diff --git a/Engine/source/sfx/fmod/sfxFMODDevice.h b/Engine/source/sfx/fmod/sfxFMODDevice.h index df90eae0d..f710faa20 100644 --- a/Engine/source/sfx/fmod/sfxFMODDevice.h +++ b/Engine/source/sfx/fmod/sfxFMODDevice.h @@ -59,7 +59,7 @@ // This doesn't appear to exist in some contexts, so let's just add it. -#if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XENON) +#if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XENON) #ifndef WINAPI #define WINAPI __stdcall #endif diff --git a/Engine/source/sfx/fmod/sfxFMODProvider.cpp b/Engine/source/sfx/fmod/sfxFMODProvider.cpp index f11996c97..a55609a89 100644 --- a/Engine/source/sfx/fmod/sfxFMODProvider.cpp +++ b/Engine/source/sfx/fmod/sfxFMODProvider.cpp @@ -169,7 +169,7 @@ void SFXFMODProvider::init() const char* pDllName; // plugin-based DLL const char* eventDllName; -#ifdef TORQUE_OS_WIN32 +#ifdef TORQUE_OS_WIN dllName = "fmodex.dll"; pDllName = "fmodexp.dll"; eventDllName = "fmod_event.dll"; diff --git a/Engine/source/sfx/media/sfxVorbisStream.cpp b/Engine/source/sfx/media/sfxVorbisStream.cpp index 7ed1c51ec..789f136e2 100644 --- a/Engine/source/sfx/media/sfxVorbisStream.cpp +++ b/Engine/source/sfx/media/sfxVorbisStream.cpp @@ -91,7 +91,7 @@ size_t SFXVorbisStream::_read_func( void *ptr, size_t size, size_t nmemb, void * return readItems; } -int SFXVorbisStream::_seek_func( void *datasource, ogg_int64_t offset, int whence ) +S32 SFXVorbisStream::_seek_func( void *datasource, ogg_int64_t offset, S32 whence ) { Stream *stream = reinterpret_cast( datasource ); @@ -133,7 +133,7 @@ bool SFXVorbisStream::_openVorbis() cb.tell_func = canSeek ? _tell_func : NULL; // Open it. - int ovResult = ov_open_callbacks( mStream, mVF, NULL, 0, cb ); + S32 ovResult = ov_open_callbacks( mStream, mVF, NULL, 0, cb ); if( ovResult != 0 ) return false; @@ -196,9 +196,9 @@ S32 SFXVorbisStream::read( U8 *buffer, mBitstream = *bitstream; #ifdef TORQUE_BIG_ENDIAN - static const int isBigEndian = 1; + static const S32 isBigEndian = 1; #else - static const int isBigEndian = 0; + static const S32 isBigEndian = 0; #endif // Vorbis doesn't seem to like reading diff --git a/Engine/source/sfx/media/sfxVorbisStream.h b/Engine/source/sfx/media/sfxVorbisStream.h index 680d550fa..74b9d0964 100644 --- a/Engine/source/sfx/media/sfxVorbisStream.h +++ b/Engine/source/sfx/media/sfxVorbisStream.h @@ -56,7 +56,7 @@ class SFXVorbisStream : public SFXFileStream, // The ov_callbacks. static size_t _read_func( void *ptr, size_t size, size_t nmemb, void *datasource ); - static int _seek_func( void *datasource, ogg_int64_t offset, int whence ); + static S32 _seek_func( void *datasource, ogg_int64_t offset, S32 whence ); static long _tell_func( void *datasource ); // SFXStream diff --git a/Engine/source/sfx/openal/aldlist.cpp b/Engine/source/sfx/openal/aldlist.cpp index e3991a7ee..13ee1409c 100644 --- a/Engine/source/sfx/openal/aldlist.cpp +++ b/Engine/source/sfx/openal/aldlist.cpp @@ -161,9 +161,9 @@ const char *ALDeviceList::GetDeviceName(int index) void ALDeviceList::GetDeviceVersion(int index, int *major, int *minor) { if (index < GetNumDevices()) { - if (*major) + if (major) *major = vDeviceInfo[index].iMajorVersion; - if (*minor) + if (minor) *minor = vDeviceInfo[index].iMinorVersion; } return; @@ -172,7 +172,7 @@ void ALDeviceList::GetDeviceVersion(int index, int *major, int *minor) /* * Returns the maximum number of Sources that can be generate on the given device */ -unsigned int ALDeviceList::GetMaxNumSources(int index) +U32 ALDeviceList::GetMaxNumSources(S32 index) { if (index < GetNumDevices()) return vDeviceInfo[index].uiSourceCount; @@ -204,10 +204,10 @@ int ALDeviceList::GetDefaultDevice() /* * Deselects devices which don't have the specified minimum version */ -void ALDeviceList::FilterDevicesMinVer(int major, int minor) +void ALDeviceList::FilterDevicesMinVer(S32 major, S32 minor) { int dMajor, dMinor; - for (unsigned int i = 0; i < vDeviceInfo.size(); i++) { + for (U32 i = 0; i < vDeviceInfo.size(); i++) { GetDeviceVersion(i, &dMajor, &dMinor); if ((dMajor < major) || ((dMajor == major) && (dMinor < minor))) { vDeviceInfo[i].bSelected = false; @@ -218,10 +218,10 @@ void ALDeviceList::FilterDevicesMinVer(int major, int minor) /* * Deselects devices which don't have the specified maximum version */ -void ALDeviceList::FilterDevicesMaxVer(int major, int minor) +void ALDeviceList::FilterDevicesMaxVer(S32 major, S32 minor) { - int dMajor, dMinor; - for (unsigned int i = 0; i < vDeviceInfo.size(); i++) { + S32 dMajor, dMinor; + for (U32 i = 0; i < vDeviceInfo.size(); i++) { GetDeviceVersion(i, &dMajor, &dMinor); if ((dMajor > major) || ((dMajor == major) && (dMinor > minor))) { vDeviceInfo[i].bSelected = false; @@ -234,7 +234,7 @@ void ALDeviceList::FilterDevicesMaxVer(int major, int minor) */ void ALDeviceList::FilterDevicesExtension(SFXALCaps cap) { - for (unsigned int i = 0; i < vDeviceInfo.size(); i++) + for (U32 i = 0; i < vDeviceInfo.size(); i++) vDeviceInfo[i].bSelected = vDeviceInfo[i].iCapsFlags & cap; } @@ -243,7 +243,7 @@ void ALDeviceList::FilterDevicesExtension(SFXALCaps cap) */ void ALDeviceList::ResetFilters() { - for (int i = 0; i < GetNumDevices(); i++) { + for (S32 i = 0; i < GetNumDevices(); i++) { vDeviceInfo[i].bSelected = true; } filterIndex = 0; @@ -287,7 +287,7 @@ int ALDeviceList::GetNextFilteredDevice() unsigned int ALDeviceList::GetMaxNumSources() { ALuint uiSources[256]; - unsigned int iSourceCount = 0; + U32 iSourceCount = 0; // Clear AL Error Code ALFunction.alGetError(); @@ -304,7 +304,7 @@ unsigned int ALDeviceList::GetMaxNumSources() ALFunction.alDeleteSources(iSourceCount, uiSources); if (ALFunction.alGetError() != AL_NO_ERROR) { - for (unsigned int i = 0; i < 256; i++) + for (U32 i = 0; i < 256; i++) { ALFunction.alDeleteSources(1, &uiSources[i]); } diff --git a/Engine/source/sfx/openal/aldlist.h b/Engine/source/sfx/openal/aldlist.h index 00b0eaec3..3b2d7e948 100644 --- a/Engine/source/sfx/openal/aldlist.h +++ b/Engine/source/sfx/openal/aldlist.h @@ -32,10 +32,10 @@ typedef struct { char strDeviceName[256]; - int iMajorVersion; - int iMinorVersion; - unsigned int uiSourceCount; - int iCapsFlags; + S32 iMajorVersion; + S32 iMinorVersion; + U32 uiSourceCount; + S32 iCapsFlags; bool bSelected; } ALDEVICEINFO, *LPALDEVICEINFO; @@ -44,27 +44,27 @@ class ALDeviceList private: OPENALFNTABLE ALFunction; Vector vDeviceInfo; - int defaultDeviceIndex; - int filterIndex; + S32 defaultDeviceIndex; + S32 filterIndex; public: ALDeviceList ( const OPENALFNTABLE &oalft ); ~ALDeviceList (); - int GetNumDevices(); - const char *GetDeviceName(int index); - void GetDeviceVersion(int index, int *major, int *minor); - unsigned int GetMaxNumSources(int index); - bool IsExtensionSupported(int index, SFXALCaps caps); - int GetDefaultDevice(); - void FilterDevicesMinVer(int major, int minor); - void FilterDevicesMaxVer(int major, int minor); + S32 GetNumDevices(); + const char *GetDeviceName(S32 index); + void GetDeviceVersion(S32 index, S32 *major, S32 *minor); + U32 GetMaxNumSources(S32 index); + bool IsExtensionSupported(S32 index, SFXALCaps caps); + S32 GetDefaultDevice(); + void FilterDevicesMinVer(S32 major, S32 minor); + void FilterDevicesMaxVer(S32 major, S32 minor); void FilterDevicesExtension(SFXALCaps caps); void ResetFilters(); - int GetFirstFilteredDevice(); - int GetNextFilteredDevice(); + S32 GetFirstFilteredDevice(); + S32 GetNextFilteredDevice(); private: - unsigned int GetMaxNumSources(); + U32 GetMaxNumSources(); }; #endif // ALDEVICELIST_H diff --git a/Engine/source/sfx/openal/sfxALProvider.cpp b/Engine/source/sfx/openal/sfxALProvider.cpp index 7570500d6..bd4f8cfdd 100644 --- a/Engine/source/sfx/openal/sfxALProvider.cpp +++ b/Engine/source/sfx/openal/sfxALProvider.cpp @@ -93,18 +93,18 @@ void SFXALProvider::init() const char *deviceFormat = "OpenAL v%d.%d %s"; char temp[256]; - for( int i = 0; i < mALDL->GetNumDevices(); i++ ) + for( S32 i = 0; i < mALDL->GetNumDevices(); i++ ) { ALDeviceInfo* info = new ALDeviceInfo; info->name = String( mALDL->GetDeviceName( i ) ); - int major, minor, eax = 0; + S32 major, minor, eax = 0; mALDL->GetDeviceVersion( i, &major, &minor ); // Apologies for the blatent enum hack -patw - for( int j = SFXALEAX2; j < SFXALEAXRAM; j++ ) + for( S32 j = SFXALEAX2; j < SFXALEAXRAM; j++ ) eax += (int)mALDL->IsExtensionSupported( i, (SFXALCaps)j ); if( eax > 0 ) diff --git a/Engine/source/sfx/sfxCommon.h b/Engine/source/sfx/sfxCommon.h index 587672ca0..956f24055 100644 --- a/Engine/source/sfx/sfxCommon.h +++ b/Engine/source/sfx/sfxCommon.h @@ -561,7 +561,7 @@ class SFXMaterialProperties /// An array of float values with optional random variances. -template< int NUM_VALUES > +template< S32 NUM_VALUES > struct SFXVariantFloat { /// Base value. diff --git a/Engine/source/sfx/sfxSource.h b/Engine/source/sfx/sfxSource.h index 83e31d0d2..e47b179d0 100644 --- a/Engine/source/sfx/sfxSource.h +++ b/Engine/source/sfx/sfxSource.h @@ -434,7 +434,7 @@ class SFXSource : public SimGroup virtual bool isVirtualized() const { return false; } /// Returns true if this is a looping source. - bool isLooping() const { return mDescription->mIsLooping; } + bool isLooping() const { return mDescription.isValid() && mDescription->mIsLooping; } /// @} diff --git a/Engine/source/sfx/sfxSystem.cpp b/Engine/source/sfx/sfxSystem.cpp index c43a44b2f..5c425038a 100644 --- a/Engine/source/sfx/sfxSystem.cpp +++ b/Engine/source/sfx/sfxSystem.cpp @@ -686,7 +686,8 @@ void SFXSystem::_onRemoveSource( SFXSource* source ) if( dynamic_cast< SFXSound* >( source ) ) { SFXSoundVector::iterator iter = find( mSounds.begin(), mSounds.end(), static_cast< SFXSound* >( source ) ); - mSounds.erase_fast( iter ); + if( iter != mSounds.end() ) + mSounds.erase_fast( iter ); mStatNumSounds = mSounds.size(); } @@ -854,7 +855,7 @@ void SFXSystem::_updateSources() if( source->getLastStatus() == SFXStatusStopped && source->getSavedStatus() != SFXStatusPlaying ) { - int index = iter - mPlayOnceSources.begin(); + S32 index = iter - mPlayOnceSources.begin(); // Erase it from the vector first, so that onRemoveSource // doesn't do it during cleanup and screw up our loop here! diff --git a/Engine/source/sfx/sfxWorld.h b/Engine/source/sfx/sfxWorld.h index 2806cc4c8..289455b69 100644 --- a/Engine/source/sfx/sfxWorld.h +++ b/Engine/source/sfx/sfxWorld.h @@ -101,7 +101,7 @@ enum SFXObjectFlags /// 3D voices active on the device at any one point is defined as the set of /// current sound sources. /// -template< int NUM_DIMENSIONS > +template< S32 NUM_DIMENSIONS > class SFXObject : public ScopeTrackerObject< NUM_DIMENSIONS > { public: @@ -184,7 +184,7 @@ class SFXObject : public ScopeTrackerObject< NUM_DIMENSIONS > /// occlusion manager installed on the system and tracking the listener traveling through /// the ambient spaces is /// -template< int NUM_DIMENSIONS, typename Object > +template< S32 NUM_DIMENSIONS, typename Object > class SFXWorld : public ScopeTracker< NUM_DIMENSIONS, Object > { public: @@ -250,7 +250,7 @@ class SFXWorld : public ScopeTracker< NUM_DIMENSIONS, Object > //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > SFXWorld< NUM_DIMENSIONS, Object >::SFXWorld() { VECTOR_SET_ASSOCIATION( mScopeStack ); @@ -258,7 +258,7 @@ SFXWorld< NUM_DIMENSIONS, Object >::SFXWorld() //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > void SFXWorld< NUM_DIMENSIONS, Object >::update() { if( !this->mReferenceObject ) @@ -320,7 +320,7 @@ void SFXWorld< NUM_DIMENSIONS, Object >::update() //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > void SFXWorld< NUM_DIMENSIONS, Object >::notifyChanged( Object object ) { SFXAmbience* ambience = Deref( object ).getAmbience(); @@ -369,7 +369,7 @@ void SFXWorld< NUM_DIMENSIONS, Object >::_onScopeIn( Object object ) //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > void SFXWorld< NUM_DIMENSIONS, Object >::_onScopeOut( Object object ) { #ifdef DEBUG_SPEW @@ -393,7 +393,7 @@ void SFXWorld< NUM_DIMENSIONS, Object >::_onScopeOut( Object object ) //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > F32 SFXWorld< NUM_DIMENSIONS, Object >::_getSortValue( Object object ) { //RDTODO: probably need to work with the overlap here instead of the full volumes @@ -414,7 +414,7 @@ F32 SFXWorld< NUM_DIMENSIONS, Object >::_getSortValue( Object object ) //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > S32 SFXWorld< NUM_DIMENSIONS, Object >::_findScope( Object object ) { for( U32 i = 0; i < mScopeStack.size(); ++ i ) diff --git a/Engine/source/shaderGen/GLSL/bumpGLSL.cpp b/Engine/source/shaderGen/GLSL/bumpGLSL.cpp index 737ddcbaf..1b1cd0437 100644 --- a/Engine/source/shaderGen/GLSL/bumpGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/bumpGLSL.cpp @@ -64,14 +64,14 @@ void BumpFeatGLSL::processPix( Vector &componentList, output = meta; // Get the texture coord. - Var *texCoord = getInTexCoord( "out_texCoord", "vec2", true, componentList ); + Var *texCoord = getInTexCoord( "texCoord", "vec2", true, componentList ); // Sample the bumpmap. Var *bumpMap = getNormalMapTex(); - LangElement *texOp = NULL; //Handle atlased textures + // http://www.infinity-universe.com/Infinity/index.php?option=com_content&task=view&id=65&Itemid=47 if(fd.features[MFT_NormalMapAtlas]) { // This is a big block of code, so put a comment in the shader code @@ -79,52 +79,49 @@ void BumpFeatGLSL::processPix( Vector &componentList, Var *atlasedTex = new Var; atlasedTex->setName("atlasedBumpCoord"); - atlasedTex->setType("vec2"); + atlasedTex->setType( "vec2" ); LangElement *atDecl = new DecOp(atlasedTex); // Parameters of the texture atlas Var *atParams = new Var; - atParams->setType("vec4"); + atParams->setType( "float4" ); atParams->setName("bumpAtlasParams"); atParams->uniform = true; atParams->constSortPos = cspPotentialPrimitive; // Parameters of the texture (tile) this object is using in the atlas Var *tileParams = new Var; - tileParams->setType("vec4"); + tileParams->setType( "float4" ); tileParams->setName("bumpAtlasTileParams"); tileParams->uniform = true; tileParams->constSortPos = cspPotentialPrimitive; const bool is_sm3 = (GFX->getPixelShaderVersion() > 2.0f); - // getPixelShaderVersion() on Mac currently returns 2.0, - // or 3.0 if Advanced Lighting is enabled if(is_sm3) { // Figure out the mip level - meta->addStatement(new GenOp(" vec2 _dx_bump = dFdx(@ * @.z);\r\n", texCoord, atParams)); - meta->addStatement(new GenOp(" vec2 _dy_bump = dFdy(@ * @.z);\r\n", texCoord, atParams)); - meta->addStatement(new GenOp(" float mipLod_bump = 0.5 * log2(max(dot(_dx_bump, _dx_bump), dot(_dy_bump, _dy_bump)));\r\n")); - meta->addStatement(new GenOp(" mipLod_bump = clamp(mipLod_bump, 0.0, @.w);\r\n", atParams)); + meta->addStatement( new GenOp( " float2 _dx_bump = ddx(@ * @.z);\r\n", texCoord, atParams ) ); + meta->addStatement( new GenOp( " float2 _dy_bump = ddy(@ * @.z);\r\n", texCoord, atParams ) ); + meta->addStatement( new GenOp( " float mipLod_bump = 0.5 * log2(max(dot(_dx_bump, _dx_bump), dot(_dy_bump, _dy_bump)));\r\n")); + meta->addStatement( new GenOp( " mipLod_bump = clamp(mipLod_bump, 0.0, @.w);\r\n", atParams)); // And the size of the mip level meta->addStatement(new GenOp(" float mipPixSz_bump = pow(2.0, @.w - mipLod_bump);\r\n", atParams)); - meta->addStatement(new GenOp(" vec2 mipSz_bump = mipPixSz_bump / @.xy;\r\n", atParams)); + meta->addStatement( new GenOp( " float2 mipSz_bump = mipPixSz_bump / @.xy;\r\n", atParams ) ); } else { - meta->addStatement(new GenOp(" vec2 mipSz = float2(1.0, 1.0);\r\n")); + meta->addStatement(new GenOp(" float2 mipSz = float2(1.0, 1.0);\r\n")); } // Tiling mode - // TODO: Select wrap or clamp somehow if( true ) // Wrap - meta->addStatement(new GenOp(" @ = fract(@);\r\n", atDecl, texCoord)); + meta->addStatement( new GenOp( " @ = frac(@);\r\n", atDecl, texCoord ) ); else // Clamp meta->addStatement(new GenOp(" @ = saturate(@);\r\n", atDecl, texCoord)); // Finally scale/offset, and correct for filtering - meta->addStatement(new GenOp(" @ = @ * ((mipSz_bump * @.xy - 1.0) / mipSz_bump) + 0.5 / mipSz_bump + @.xy * @.xy;\r\n", + meta->addStatement( new GenOp( " @ = @ * ((mipSz_bump * @.xy - 1.0) / mipSz_bump) + 0.5 / mipSz_bump + @.xy * @.xy;\r\n", atlasedTex, atlasedTex, atParams, atParams, tileParams)); // Add a newline @@ -132,19 +129,19 @@ void BumpFeatGLSL::processPix( Vector &componentList, if(is_sm3) { - texOp = new GenOp( "texture2DLod(@, vec4(@, 0.0, mipLod_bump)", bumpMap, texCoord ); + texOp = new GenOp( "tex2Dlod(@, float4(@, 0.0, mipLod_bump))", bumpMap, texCoord ); } else { - texOp = new GenOp( "texture2D(@, @)", bumpMap, texCoord ); + texOp = new GenOp( "tex2D(@, @)", bumpMap, texCoord ); } } else { - texOp = new GenOp( "texture2D(@, @)", bumpMap, texCoord ); + texOp = new GenOp( "tex2D(@, @)", bumpMap, texCoord ); } - Var *bumpNorm = new Var( "bumpNormal", "vec4" ); + Var *bumpNorm = new Var( "bumpNormal", "float4" ); meta->addStatement( expandNormalMap( texOp, new DecOp( bumpNorm ), bumpNorm, fd ) ); // If we have a detail normal map we add the xy coords of @@ -160,11 +157,11 @@ void BumpFeatGLSL::processPix( Vector &componentList, bumpMap->constNum = Var::getTexUnitNum(); texCoord = getInTexCoord( "detCoord", "vec2", true, componentList ); - texOp = new GenOp( "texture2D(@, @)", bumpMap, texCoord ); + texOp = new GenOp( "tex2D(@, @)", bumpMap, texCoord ); Var *detailBump = new Var; detailBump->setName( "detailBump" ); - detailBump->setType( "vec4" ); + detailBump->setType( "float4" ); meta->addStatement( expandNormalMap( texOp, new DecOp( detailBump ), detailBump, fd ) ); Var *detailBumpScale = new Var; @@ -175,13 +172,11 @@ void BumpFeatGLSL::processPix( Vector &componentList, meta->addStatement( new GenOp( " @.xy += @.xy * @;\r\n", bumpNorm, detailBump, detailBumpScale ) ); } - // We transform it into world space by reversing the // multiplication by the worldToTanget transform. Var *wsNormal = new Var( "wsNormal", "vec3" ); Var *worldToTanget = getInWorldToTangent( componentList ); - meta->addStatement( new GenOp( " @ = normalize( vec3( @.xyz * @ ) );\r\n", new DecOp( wsNormal ), bumpNorm, worldToTanget ) ); - + meta->addStatement( new GenOp( " @ = normalize( tMul( @.xyz, @ ) );\r\n", new DecOp( wsNormal ), bumpNorm, worldToTanget ) ); } ShaderFeature::Resources BumpFeatGLSL::getResources( const MaterialFeatureData &fd ) @@ -227,20 +222,26 @@ void BumpFeatGLSL::setTexData( Material::StageData &stageDat, if ( fd.features[MFT_NormalMap] ) { passData.mTexType[ texIndex ] = Material::Bump; + passData.mSamplerNames[ texIndex ] = "bumpMap"; passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_NormalMap ); } - if ( fd.features[ MFT_DetailNormalMap ] ) { passData.mTexType[ texIndex ] = Material::DetailBump; + passData.mSamplerNames[ texIndex ] = "detailBumpMap"; passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_DetailNormalMap ); } } -// -Var* ParallaxFeatGLSL::_getUniformVar( const char *name, const char *type ) +ParallaxFeatGLSL::ParallaxFeatGLSL() + : mIncludeDep( "shaders/common/gl/torque.glsl" ) +{ + addDependency( &mIncludeDep ); +} + +Var* ParallaxFeatGLSL::_getUniformVar( const char *name, const char *type, ConstantSortPosition csp ) { Var *theVar = (Var*)LangElement::find( name ); if ( !theVar ) @@ -249,7 +250,7 @@ Var* ParallaxFeatGLSL::_getUniformVar( const char *name, const char *type ) theVar->setType( type ); theVar->setName( name ); theVar->uniform = true; - theVar->constSortPos = cspPass; + theVar->constSortPos = csp; } return theVar; @@ -259,13 +260,13 @@ void ParallaxFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { AssertFatal( GFX->getPixelShaderVersion() >= 2.0, - "ParallaxFeatGLSL::processVert - We don't support SM 1.x!" ); + "ParallaxFeatGLSL::processVert - We don't support SM 1.x!" ); MultiLine *meta = new MultiLine; // Add the texture coords. getOutTexCoord( "texCoord", - "vec2", + "vec2", true, fd.features[MFT_TexAnim], meta, @@ -276,18 +277,36 @@ void ParallaxFeatGLSL::processVert( Vector &componentList, if ( !inPos ) inPos = (Var*)LangElement::find( "position" ); - // Get the object space eye position and the world - // to tangent transform. - Var *eyePos = _getUniformVar( "eyePos", "vec3" ); + // Get the object space eye position and the + // object to tangent space transform. + Var *eyePos = _getUniformVar( "eyePos", "vec3", cspPrimitive ); Var *objToTangentSpace = getOutObjToTangentSpace( componentList, meta, fd ); - // send transform to pixel shader + // Now send the negative view vector in tangent space to the pixel shader. ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - Var *outViewTS = connectComp->getElement( RT_TEXCOORD, 1 ); - outViewTS->setName( "outViewTS" ); - outViewTS->setType( "vec3" ); - meta->addStatement( new GenOp( " @ = ( @ - @.xyz ) * transpose( @ );\r\n", - outViewTS, inPos, eyePos, objToTangentSpace ) ); + Var *outNegViewTS = connectComp->getElement( RT_TEXCOORD ); + outNegViewTS->setName( "outNegViewTS" ); + outNegViewTS->setStructName( "OUT" ); + outNegViewTS->setType( "vec3" ); + meta->addStatement( new GenOp( " @ = tMul( @, float3( @.xyz - @ ) );\r\n", + outNegViewTS, objToTangentSpace, inPos, eyePos ) ); + + // TODO: I'm at a loss at why i need to flip the binormal/y coord + // to get a good view vector for parallax. Lighting works properly + // with the TS matrix as is... but parallax does not. + // + // Someone figure this out! + // + meta->addStatement( new GenOp( " @.y = -@.y;\r\n", outNegViewTS, outNegViewTS ) ); + + // If we have texture anim matrix the tangent + // space view vector may need to be rotated. + Var *texMat = (Var*)LangElement::find( "texMat" ); + if ( texMat ) + { + meta->addStatement( new GenOp( " @ = tMul(@, float4(@,0)).xyz;\r\n", + outNegViewTS, texMat, outNegViewTS ) ); + } output = meta; } @@ -296,7 +315,7 @@ void ParallaxFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { AssertFatal( GFX->getPixelShaderVersion() >= 2.0, - "ParallaxFeatGLSL::processPix - We don't support SM 1.x!" ); + "ParallaxFeatGLSL::processPix - We don't support SM 1.x!" ); MultiLine *meta = new MultiLine; @@ -310,38 +329,28 @@ void ParallaxFeatGLSL::processPix( Vector &componentList, Var *negViewTS = (Var*)LangElement::find( "negViewTS" ); if ( !negViewTS ) { - Var *inViewTS = (Var*)LangElement::find( "outViewTS" ); - if ( !inViewTS ) + Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" ); + if ( !inNegViewTS ) { - inViewTS = connectComp->getElement( RT_TEXCOORD, 1 ); - inViewTS->setName( "outViewTS" ); - inViewTS->setType( "vec3" ); + inNegViewTS = connectComp->getElement( RT_TEXCOORD ); + inNegViewTS->setName( "outNegViewTS" ); + inNegViewTS->setStructName( "IN" ); + inNegViewTS->setType( "vec3" ); } negViewTS = new Var( "negViewTS", "vec3" ); - meta->addStatement( new GenOp( " @ = -normalize( @ );\r\n", new DecOp( negViewTS ), inViewTS ) ); + meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) ); } // Get the rest of our inputs. - Var *parallaxInfo = _getUniformVar( "parallaxInfo", "float" ); + Var *parallaxInfo = _getUniformVar( "parallaxInfo", "float", cspPotentialPrimitive ); Var *normalMap = getNormalMapTex(); - // Do 3 parallax samples to get acceptable - // quality without too much overhead. - Var *pdepth = findOrCreateLocal( "pdepth", "float", meta ); - Var *poffset = findOrCreateLocal( "poffset", "vec2", meta ); - meta->addStatement( new GenOp( " @ = texture2D( @, @.xy ).a;\r\n", pdepth, normalMap, texCoord ) ); - meta->addStatement( new GenOp( " @ = @.xy * ( @ * @ );\r\n", poffset, negViewTS, pdepth, parallaxInfo ) ); - - meta->addStatement( new GenOp( " @ = ( @ + texture2D( @, @.xy + @ ).a ) * 0.5;\r\n", pdepth, pdepth, normalMap, texCoord, poffset ) ); - meta->addStatement( new GenOp( " @ = @.xy * ( @ * @ );\r\n", poffset, negViewTS, pdepth, parallaxInfo ) ); - - meta->addStatement( new GenOp( " @ = ( @ + texture2D( @, @.xy + @ ).a ) * 0.5;\r\n", pdepth, pdepth, normalMap, texCoord, poffset ) ); - meta->addStatement( new GenOp( " @ = @.xy * ( @ * @ );\r\n", poffset, negViewTS, pdepth, parallaxInfo ) ); - - meta->addStatement( new GenOp( " @.xy += @;\r\n", texCoord, poffset ) ); + // Call the library function to do the rest. + meta->addStatement( new GenOp( " @.xy += parallaxOffset( @, @.xy, @, @ );\r\n", + texCoord, normalMap, texCoord, negViewTS, parallaxInfo ) ); - // TODO: Fix second UV. + // TODO: Fix second UV maybe? output = meta; } @@ -349,7 +358,7 @@ void ParallaxFeatGLSL::processPix( Vector &componentList, ShaderFeature::Resources ParallaxFeatGLSL::getResources( const MaterialFeatureData &fd ) { AssertFatal( GFX->getPixelShaderVersion() >= 2.0, - "ParallaxFeatGLSL::getResources - We don't support SM 1.x!" ); + "ParallaxFeatGLSL::getResources - We don't support SM 1.x!" ); Resources res; @@ -370,7 +379,7 @@ void ParallaxFeatGLSL::setTexData( Material::StageData &stageDat, U32 &texIndex ) { AssertFatal( GFX->getPixelShaderVersion() >= 2.0, - "ParallaxFeatGLSL::setTexData - We don't support SM 1.x!" ); + "ParallaxFeatGLSL::setTexData - We don't support SM 1.x!" ); GFXTextureObject *tex = stageDat.getTex( MFT_NormalMap ); if ( tex ) @@ -381,7 +390,6 @@ void ParallaxFeatGLSL::setTexData( Material::StageData &stageDat, } -// void NormalsOutFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { @@ -397,6 +405,7 @@ void NormalsOutFeatGLSL::processVert( Vector &componentList, Var *outNormal = connectComp->getElement( RT_TEXCOORD ); outNormal->setName( "wsNormal" ); + outNormal->setStructName( "OUT" ); outNormal->setType( "vec3" ); outNormal->mapsToSampler = false; @@ -406,13 +415,13 @@ void NormalsOutFeatGLSL::processVert( Vector &componentList, { // Transform the normal to world space. Var *objTrans = getObjTrans( componentList, fd.features[MFT_UseInstancing], meta ); - meta->addStatement( new GenOp( " @ = @ * normalize( @ );\r\n", outNormal, objTrans, inNormal ) ); + meta->addStatement( new GenOp( " @ = tMul( @, normalize( vec4(@, 0.0) ) ).xyz;\r\n", outNormal, objTrans, inNormal ) ); } else { // If we don't have a vertex normal... just pass the // camera facing normal to the pixel shader. - meta->addStatement( new GenOp( " @ = vec3( 0.0, 0.0, 1.0 );\r\n", outNormal ) ); + meta->addStatement( new GenOp( " @ = float3( 0.0, 0.0, 1.0 );\r\n", outNormal ) ); } } @@ -428,20 +437,26 @@ void NormalsOutFeatGLSL::processPix( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); wsNormal = connectComp->getElement( RT_TEXCOORD ); wsNormal->setName( "wsNormal" ); + wsNormal->setStructName( "IN" ); wsNormal->setType( "vec3" ); // If we loaded the normal its our resposibility // to normalize it... the interpolators won't. // - meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", wsNormal, wsNormal ) ); + // Note we cast to half here to get partial precision + // optimized code which is an acceptable loss of + // precision for normals and performs much better + // on older Geforce cards. + // + meta->addStatement( new GenOp( " @ = normalize( half3( @ ) );\r\n", wsNormal, wsNormal ) ); } LangElement *normalOut; Var *outColor = (Var*)LangElement::find( "col" ); - if ( outColor ) - normalOut = new GenOp( "vec4( ( -@ + 1 ) * 0.5, @.a )", wsNormal, outColor ); + if ( outColor && !fd.features[MFT_AlphaTest] ) + normalOut = new GenOp( "float4( ( -@ + 1 ) * 0.5, @.a )", wsNormal, outColor ); else - normalOut = new GenOp( "vec4( ( -@ + 1 ) * 0.5, 1 )", wsNormal ); + normalOut = new GenOp( "float4( ( -@ + 1 ) * 0.5, 1 )", wsNormal ); meta->addStatement( new GenOp( " @;\r\n", assignColor( normalOut, Material::None ) ) ); diff --git a/Engine/source/shaderGen/GLSL/bumpGLSL.h b/Engine/source/shaderGen/GLSL/bumpGLSL.h index 899434f15..b37bb9099 100644 --- a/Engine/source/shaderGen/GLSL/bumpGLSL.h +++ b/Engine/source/shaderGen/GLSL/bumpGLSL.h @@ -26,6 +26,9 @@ #ifndef _SHADERGEN_GLSL_SHADERFEATUREGLSL_H_ #include "shaderGen/GLSL/shaderFeatureGLSL.h" #endif +#ifndef _LANG_ELEMENT_H_ +#include "shaderGen/langElement.h" +#endif struct RenderPassData; class MultiLine; @@ -50,7 +53,6 @@ public: const MaterialFeatureData &fd, RenderPassData &passData, U32 &texIndex ); - virtual String getName() { return "Bumpmap"; } }; @@ -62,10 +64,16 @@ class ParallaxFeatGLSL : public ShaderFeatureGLSL { protected: - static Var* _getUniformVar( const char *name, const char *type ); + static Var* _getUniformVar( const char *name, + const char *type, + ConstantSortPosition csp ); + + ShaderIncludeDependency mIncludeDep; public: + ParallaxFeatGLSL(); + // ShaderFeatureGLSL virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); @@ -80,7 +88,6 @@ public: }; - /// This feature is used to render normals to the /// diffuse target for imposter rendering. class NormalsOutFeatGLSL : public ShaderFeatureGLSL diff --git a/Engine/source/shaderGen/GLSL/depthGLSL.cpp b/Engine/source/shaderGen/GLSL/depthGLSL.cpp index 4c5f1b837..71bdbb96e 100644 --- a/Engine/source/shaderGen/GLSL/depthGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/depthGLSL.cpp @@ -24,36 +24,36 @@ #include "shaderGen/GLSL/depthGLSL.h" #include "materials/materialFeatureTypes.h" +#include "materials/materialFeatureData.h" void EyeSpaceDepthOutGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - - MultiLine *meta = new MultiLine; + MultiLine *meta = new MultiLine; output = meta; - // grab output + // grab output ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *outWSEyeVec = connectComp->getElement( RT_TEXCOORD ); - outWSEyeVec->setName( "outWSEyeVec" ); - - - // grab incoming vert position - Var *wsPosition = new Var( "depthPos", "vec3" ); + outWSEyeVec->setName( "wsEyeVec" ); + outWSEyeVec->setStructName( "OUT" ); + + // grab incoming vert position + Var *wsPosition = new Var( "depthPos", "float3" ); getWsPosition( componentList, fd.features[MFT_UseInstancing], meta, new DecOp( wsPosition ) ); Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); if( !eyePos ) { eyePos = new Var; - eyePos->setType("vec3"); + eyePos->setType("float3"); eyePos->setName("eyePosWorld"); eyePos->uniform = true; eyePos->constSortPos = cspPass; } -meta->addStatement( new GenOp( " @ = vec4( @.xyz - @, 1 );\r\n", outWSEyeVec, wsPosition, eyePos ) ); + meta->addStatement( new GenOp( " @ = float4( @.xyz - @, 1 );\r\n", outWSEyeVec, wsPosition, eyePos ) ); } void EyeSpaceDepthOutGLSL::processPix( Vector &componentList, @@ -64,14 +64,15 @@ void EyeSpaceDepthOutGLSL::processPix( Vector &componentList, // grab connector position ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *wsEyeVec = connectComp->getElement( RT_TEXCOORD ); - wsEyeVec->setName( "outWSEyeVec" ); - wsEyeVec->setType( "vec4" ); + wsEyeVec->setName( "wsEyeVec" ); + wsEyeVec->setStructName( "IN" ); + wsEyeVec->setType( "float4" ); wsEyeVec->mapsToSampler = false; wsEyeVec->uniform = false; // get shader constants Var *vEye = new Var; - vEye->setType("vec3"); + vEye->setType("float3"); vEye->setName("vEye"); vEye->uniform = true; vEye->constSortPos = cspPass; @@ -83,12 +84,27 @@ void EyeSpaceDepthOutGLSL::processPix( Vector &componentList, LangElement *depthOutDecl = new DecOp( depthOut ); + meta->addStatement( new GenOp( "#ifndef CUBE_SHADOW_MAP\r\n" ) ); meta->addStatement( new GenOp( " @ = dot(@, (@.xyz / @.w));\r\n", depthOutDecl, vEye, wsEyeVec, wsEyeVec ) ); + meta->addStatement( new GenOp( "#else\r\n" ) ); + + Var *farDist = (Var*)Var::find( "oneOverFarplane" ); + if ( !farDist ) + { + farDist = new Var; + farDist->setType("float4"); + farDist->setName("oneOverFarplane"); + farDist->uniform = true; + farDist->constSortPos = cspPass; + } + + meta->addStatement( new GenOp( " @ = length( @.xyz / @.w ) * @.x;\r\n", depthOutDecl, wsEyeVec, wsEyeVec, farDist ) ); + meta->addStatement( new GenOp( "#endif\r\n" ) ); // If there isn't an output conditioner for the pre-pass, than just write // out the depth to rgba and return. if( !fd.features[MFT_PrePassConditioner] ) - meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(@)", depthOut ), Material::None ) ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(float3(@),1)", depthOut ), Material::None ) ) ); output = meta; } @@ -111,11 +127,12 @@ void DepthOutGLSL::processVert( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); // Grab the output vert. - Var *outPosition = (Var*)LangElement::find( "gl_Position" ); + Var *outPosition = (Var*)LangElement::find( "gl_Position" ); //hpos // Grab our output depth. Var *outDepth = connectComp->getElement( RT_TEXCOORD ); - outDepth->setName( "outDepth" ); + outDepth->setName( "depth" ); + outDepth->setStructName( "OUT" ); outDepth->setType( "float" ); output = new GenOp( " @ = @.z / @.w;\r\n", outDepth, outPosition, outPosition ); @@ -128,7 +145,8 @@ void DepthOutGLSL::processPix( Vector &componentList, // grab connector position Var *depthVar = connectComp->getElement( RT_TEXCOORD ); - depthVar->setName( "outDepth" ); + depthVar->setName( "depth" ); + depthVar->setStructName( "IN" ); depthVar->setType( "float" ); depthVar->mapsToSampler = false; depthVar->uniform = false; @@ -140,7 +158,7 @@ void DepthOutGLSL::processPix( Vector &componentList, depthOut->setName(getOutputVarName()); */ - LangElement *depthOut = new GenOp( "vec4( @, @ * @, 0, 1 )", depthVar, depthVar, depthVar ); + LangElement *depthOut = new GenOp( "float4( @, 0, 0, 1 )", depthVar ); output = new GenOp( " @;\r\n", assignColor( depthOut, Material::None ) ); } diff --git a/Engine/source/shaderGen/GLSL/depthGLSL.h b/Engine/source/shaderGen/GLSL/depthGLSL.h index 97cb62095..c92326415 100644 --- a/Engine/source/shaderGen/GLSL/depthGLSL.h +++ b/Engine/source/shaderGen/GLSL/depthGLSL.h @@ -54,7 +54,7 @@ public: virtual Resources getResources( const MaterialFeatureData &fd ); virtual String getName() { return "Depth (Out)"; } virtual Material::BlendOp getBlendOp() { return Material::None; } - virtual const char* getOutputVarName() const { return "outDepth"; } + virtual const char* getOutputVarName() const { return "IN_depth"; } }; #endif // _DEPTH_GLSL_H_ \ No newline at end of file diff --git a/Engine/source/shaderGen/GLSL/paraboloidGLSL.cpp b/Engine/source/shaderGen/GLSL/paraboloidGLSL.cpp index 373712c36..61e56d215 100644 --- a/Engine/source/shaderGen/GLSL/paraboloidGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/paraboloidGLSL.cpp @@ -65,7 +65,7 @@ void ParaboloidVertTransformGLSL::processVert( Vector &compon // http://www.gamedev.net/reference/articles/article2308.asp // Swizzle z and y post-transform - meta->addStatement( new GenOp( " @ = vec4(@ * vec4(@.xyz,1)).xzyw;\r\n", outPosition, worldViewOnly, inPosition ) ); + meta->addStatement( new GenOp( " @ = tMul(@, float4(@.xyz,1)).xzyw;\r\n", outPosition, worldViewOnly, inPosition ) ); meta->addStatement( new GenOp( " float L = length(@.xyz);\r\n", outPosition ) ); if ( isSinglePass ) @@ -73,7 +73,8 @@ void ParaboloidVertTransformGLSL::processVert( Vector &compon // Flip the z in the back case Var *outIsBack = connectComp->getElement( RT_TEXCOORD ); outIsBack->setType( "float" ); - outIsBack->setName( "outIsBack" ); + outIsBack->setName( "isBack" ); + outIsBack->setStructName( "OUT" ); meta->addStatement( new GenOp( " bool isBack = @.z < 0.0;\r\n", outPosition ) ); meta->addStatement( new GenOp( " @ = isBack ? -1.0 : 1.0;\r\n", outIsBack ) ); @@ -94,15 +95,16 @@ void ParaboloidVertTransformGLSL::processVert( Vector &compon // TODO: If we change other shadow shaders to write out // linear depth, than fix this as well! // - // (L - 1.0)/(lightParams.x - 1.0); + // (L - zNear)/(lightParams.x - zNear); // meta->addStatement( new GenOp( " @.z = L / @.x;\r\n", outPosition, lightParams ) ); meta->addStatement( new GenOp( " @.w = 1.0;\r\n", outPosition ) ); // Pass unmodified to pixel shader to allow it to clip properly. Var *outPosXY = connectComp->getElement( RT_TEXCOORD ); - outPosXY->setType( "vec2" ); - outPosXY->setName( "outPosXY" ); + outPosXY->setType( "float2" ); + outPosXY->setName( "posXY" ); + outPosXY->setStructName( "OUT" ); meta->addStatement( new GenOp( " @ = @.xy;\r\n", outPosXY, outPosition ) ); // Scale and offset so it shows up in the atlas properly. @@ -136,16 +138,18 @@ void ParaboloidVertTransformGLSL::processPix( Vector &compon { // Cull things on the back side of the map. Var *isBack = connectComp->getElement( RT_TEXCOORD ); - isBack->setName( "outIsBack" ); + isBack->setName( "isBack" ); + isBack->setStructName( "IN" ); isBack->setType( "float" ); meta->addStatement( new GenOp( " if ( ( abs( @ ) - 0.999 ) < 0 ) discard;\r\n", isBack ) ); } // Cull pixels outside of the valid paraboloid. Var *posXY = connectComp->getElement( RT_TEXCOORD ); - posXY->setName( "outPosXY" ); - posXY->setType( "vec2" ); - meta->addStatement( new GenOp( " if ( ( 1.0 - length( @ ) ) < 0 ) discard;\r\n", posXY ) ); + posXY->setName( "posXY" ); + posXY->setStructName( "IN" ); + posXY->setType( "float2" ); + meta->addStatement( new GenOp( " clip( 1.0 - abs(@.x) );\r\n", posXY ) ); output = meta; } diff --git a/Engine/source/shaderGen/GLSL/pixSpecularGLSL.cpp b/Engine/source/shaderGen/GLSL/pixSpecularGLSL.cpp index ac313a103..4e34e2116 100644 --- a/Engine/source/shaderGen/GLSL/pixSpecularGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/pixSpecularGLSL.cpp @@ -38,98 +38,35 @@ PixelSpecularGLSL::PixelSpecularGLSL() void PixelSpecularGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - /* AssertFatal( fd.features[MFT_RTLighting], "PixelSpecularHLSL requires RTLighting to be enabled!" ); - MultiLine *meta = new MultiLine; - - // Get the eye world position. - Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); - if( !eyePos ) - { - eyePos = new Var; - eyePos->setType( "float3" ); - eyePos->setName( "eyePosWorld" ); - eyePos->uniform = true; - eyePos->constSortPos = cspPass; - } - - // Grab a register for passing the - // world space view vector. - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - Var *wsView = connectComp->getElement( RT_TEXCOORD ); - wsView->setName( "wsView" ); - wsView->setStructName( "OUT" ); - wsView->setType( "float3" ); - - // Get the input position. - Var *position = (Var*)LangElement::find( "inPosition" ); - if ( !position ) - position = (Var*)LangElement::find( "position" ); - - // Get the object to world transform. - Var *objTrans = (Var*) LangElement::find( "objTrans" ); - if ( !objTrans ) - { - objTrans = new Var; - objTrans->setType( "float4x4" ); - objTrans->setName( "objTrans" ); - objTrans->uniform = true; - objTrans->constSortPos = cspPrimitive; - } - - meta->addStatement( new GenOp( " @ = @ - mul( @, float4( @.xyz,1 ) ).xyz;\r\n", - wsView, eyePos, objTrans, position ) ); - - output = meta; - */ + // Nothing to do here... MFT_RTLighting should have + // taken care of passing everything to the pixel shader. } void PixelSpecularGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) -{ - /* +{ AssertFatal( fd.features[MFT_RTLighting], "PixelSpecularHLSL requires RTLighting to be enabled!" ); - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + // RTLighting should have spit out the 4 specular + // powers for the 4 potential lights on this pass. + // + // This can sometimes be NULL if RTLighting skips out + // on us for lightmaps or missing normals. + Var *specular = (Var*)LangElement::find( "specular" ); + if ( !specular ) + return; MultiLine *meta = new MultiLine; - // Get the normal and light vectors from which the - // RTLighting feature should have already setup. - Var *wsNormal = (Var*)LangElement::find( "wsNormal" ); - Var *inLightVec = (Var*)LangElement::find( "inLightVec" ); - - // Grab the world space position to eye vector. - Var *wsView = connectComp->getElement( RT_TEXCOORD ); - wsView->setName( "wsView" ); - wsView->setStructName( "IN" ); - wsView->setType( "float3" ); - - // Get the specular power and color. - Var *specPow = new Var( "specularPower", "float" ); - specPow->uniform = true; - specPow->constSortPos = cspPass; - Var *specCol = (Var*)LangElement::find("specularColor"); - if(specCol == NULL) - { - specCol = new Var( "specularColor", "vec4" ); - specCol->uniform = true; - specCol->constSortPos = cspPass; - } - - // Calcuate the specular factor. - Var *specular = new Var( "specular", "float" ); - meta->addStatement( new GenOp( " @ = calcSpecular( -@, normalize( @ ), normalize( @ ), @ );\r\n", - new DecOp( specular ), inLightVec, wsNormal, wsView, specPow ) ); - - LangElement *specMul = new GenOp( "float4(@.rgb,0) * @", specCol, specular ); + LangElement *specMul = new GenOp( "@", specular ); LangElement *final = specMul; // mask out with lightmap if present - if( fd.features[MFT_LightMap] ) + if ( fd.features[MFT_LightMap] ) { LangElement *lmColor = NULL; @@ -141,37 +78,44 @@ void PixelSpecularGLSL::processPix( Vector &componentList, LangElement * lightMap = LangElement::find( "lightMap" ); LangElement * lmCoord = LangElement::find( "texCoord2" ); - lmColor = new GenOp( "tex2D(@, @)", lightMap, lmCoord ); + lmColor = new GenOp( "texture(@, @)", lightMap, lmCoord ); } - final = new GenOp( "@ * float4(@.rgb,0)", specMul, lmColor ); + final = new GenOp( "@ * vec4(@.rgb,0)", specMul, lmColor ); } - // We we have a normal map then mask the specular - if ( !fd.features[MFT_SpecularMap] && fd.features[MFT_NormalMap] ) + // If we have a normal map then mask the specular + if ( fd.features[MFT_SpecularMap] ) + { + Var *specularColor = (Var*)LangElement::find( "specularColor" ); + if (specularColor) + final = new GenOp( "@ * @", final, specularColor ); + } + else if ( fd.features[MFT_NormalMap] && !fd.features[MFT_IsDXTnm] ) { Var *bumpColor = (Var*)LangElement::find( "bumpNormal" ); final = new GenOp( "@ * @.a", final, bumpColor ); } - // Add the specular to the final color. - meta->addStatement( new GenOp( " @;\r\n", assignColor( final, Material::Add ) ) ); + // Add the specular to the final color. + // search for color var + Var *color = (Var*)LangElement::find( "col" ); + meta->addStatement( new GenOp( " @.rgb += ( @ ).rgb;\r\n", color, final ) ); output = meta; - */ } ShaderFeature::Resources PixelSpecularGLSL::getResources( const MaterialFeatureData &fd ) { Resources res; - res.numTexReg = 1; return res; } + void SpecularMapGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { // Get the texture coord. - Var *texCoord = getInTexCoord( "out_texCoord", "vec2", true, componentList ); + Var *texCoord = getInTexCoord( "texCoord", "vec2", true, componentList ); // create texture var Var *specularMap = new Var; @@ -180,7 +124,7 @@ void SpecularMapGLSL::processPix( Vector &componentList, const specularMap->uniform = true; specularMap->sampler = true; specularMap->constNum = Var::getTexUnitNum(); - LangElement *texOp = new GenOp( "texture2D(@, @)", specularMap, texCoord ); + LangElement *texOp = new GenOp( "texture(@, @)", specularMap, texCoord ); Var *specularColor = new Var( "specularColor", "vec4" ); @@ -203,6 +147,7 @@ void SpecularMapGLSL::setTexData( Material::StageData &stageDat, if ( tex ) { passData.mTexType[ texIndex ] = Material::Standard; + passData.mSamplerNames[ texIndex ] = "specularMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; } } \ No newline at end of file diff --git a/Engine/source/shaderGen/GLSL/pixSpecularGLSL.h b/Engine/source/shaderGen/GLSL/pixSpecularGLSL.h index eb49b4504..2b7c92b95 100644 --- a/Engine/source/shaderGen/GLSL/pixSpecularGLSL.h +++ b/Engine/source/shaderGen/GLSL/pixSpecularGLSL.h @@ -53,7 +53,6 @@ public: } }; - /// A texture source for the PixSpecular feature class SpecularMapGLSL : public ShaderFeatureGLSL { @@ -75,5 +74,4 @@ public: } }; - -#endif // _PIXSPECULAR_GLSL_H_ \ No newline at end of file +#endif // _PIXSPECULAR_HLSL_H_ \ No newline at end of file diff --git a/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp b/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp index 7a476ff3b..faf5f92e1 100644 --- a/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/shaderCompGLSL.cpp @@ -38,7 +38,7 @@ Var * AppVertConnectorGLSL::getElement( RegisterType type, { Var *newVar = new Var; mElementList.push_back( newVar ); - newVar->setConnectName( "gl_Vertex" ); + newVar->setConnectName( "vPosition" ); return newVar; } @@ -46,28 +46,49 @@ Var * AppVertConnectorGLSL::getElement( RegisterType type, { Var *newVar = new Var; mElementList.push_back( newVar ); - newVar->setConnectName( "gl_Normal" ); + newVar->setConnectName( "vNormal" ); return newVar; } - + + case RT_BINORMAL: + { + Var *newVar = new Var; + mElementList.push_back( newVar ); + newVar->setConnectName( "vBinormal" ); + return newVar; + } case RT_COLOR: { Var *newVar = new Var; mElementList.push_back( newVar ); - newVar->setConnectName( "gl_Color" ); + newVar->setConnectName( "vColor" ); + return newVar; + } + + case RT_TANGENT: + { + Var *newVar = new Var; + mElementList.push_back( newVar ); + newVar->setConnectName( "vTangent" ); + return newVar; + } + + case RT_TANGENTW: + { + Var *newVar = new Var; + mElementList.push_back( newVar ); + newVar->setConnectName( "vTangentW" ); return newVar; } case RT_TEXCOORD: - case RT_BINORMAL: - case RT_TANGENT: { Var *newVar = new Var; mElementList.push_back( newVar ); char out[32]; - dSprintf( (char*)out, sizeof(out), "gl_MultiTexCoord%d", mCurTexElem ); + dSprintf( (char*)out, sizeof(out), "vTexCoord%d", mCurTexElem ); newVar->setConnectName( out ); newVar->constNum = mCurTexElem; newVar->arraySize = numElements; @@ -108,29 +129,55 @@ void AppVertConnectorGLSL::reset() mCurTexElem = 0; } -void AppVertConnectorGLSL::print( Stream &stream ) +void AppVertConnectorGLSL::print( Stream &stream, bool isVertexShader ) { - // print out elements + if(!isVertexShader) + return; + + U8 output[256]; + + // print struct + dSprintf( (char*)output, sizeof(output), "struct VertexData\r\n" ); + stream.write( dStrlen((char*)output), output ); + dSprintf( (char*)output, sizeof(output), "{\r\n" ); + stream.write( dStrlen((char*)output), output ); + for( U32 i=0; itype, "float")) - swizzle = "x"; - else if(!dStrcmp((const char*)var->type, "vec2")) - swizzle = "xy"; - else if(!dStrcmp((const char*)var->type, "vec3")) - swizzle = "xyz"; + + if( var->arraySize == 1) + { + dSprintf( (char*)output, sizeof(output), " %s %s;\r\n", var->type, (char*)var->name ); + stream.write( dStrlen((char*)output), output ); + } else - swizzle = "xyzw"; + { + dSprintf( (char*)output, sizeof(output), " %s %s[%d];\r\n", var->type, (char*)var->name, var->arraySize ); + stream.write( dStrlen((char*)output), output ); + } + } - // This is ugly. We use #defines to match user defined names with - // built in vars. There is no cleaner way to do this. - dSprintf( (char*)output, sizeof(output), "#define %s %s.%s\r\n", var->name, var->connectName, swizzle ); + dSprintf( (char*)output, sizeof(output), "} IN;\r\n\r\n" ); + stream.write( dStrlen((char*)output), output ); + // print in elements + for( U32 i=0; iarraySize; ++j) + { + const char *name = j == 0 ? var->connectName : avar("vTexCoord%d", var->constNum + j) ; + dSprintf( (char*)output, sizeof(output), "in %s %s;\r\n", var->type, name ); + stream.write( dStrlen((char*)output), output ); + } + + dSprintf( (char*)output, sizeof(output), "#define IN_%s IN.%s\r\n", var->name, var->name ); // TODO REMOVE stream.write( dStrlen((char*)output), output ); } + const char* newLine ="\r\n"; + stream.write( dStrlen((char*)newLine), newLine ); } Var * VertPixelConnectorGLSL::getElement( RegisterType type, @@ -140,14 +187,45 @@ Var * VertPixelConnectorGLSL::getElement( RegisterType type, switch( type ) { case RT_POSITION: + { + Var *newVar = new Var; + mElementList.push_back( newVar ); + newVar->setConnectName( "POSITION" ); + return newVar; + } + case RT_NORMAL: + { + Var *newVar = new Var; + mElementList.push_back( newVar ); + newVar->setConnectName( "NORMAL" ); + return newVar; + } + case RT_COLOR: { Var *newVar = new Var; mElementList.push_back( newVar ); + newVar->setConnectName( "COLOR" ); return newVar; } + /*case RT_BINORMAL: + { + Var *newVar = new Var; + mElementList.push_back( newVar ); + newVar->setConnectName( "BINORMAL" ); + return newVar; + } + + case RT_TANGENT: + { + Var *newVar = new Var; + mElementList.push_back( newVar ); + newVar->setConnectName( "TANGENT" ); + return newVar; + } */ + case RT_TEXCOORD: case RT_BINORMAL: case RT_TANGENT: @@ -155,6 +233,10 @@ Var * VertPixelConnectorGLSL::getElement( RegisterType type, Var *newVar = new Var; newVar->arraySize = numElements; + char out[32]; + dSprintf( (char*)out, sizeof(out), "TEXCOORD%d", mCurTexElem ); + newVar->setConnectName( out ); + if ( numRegisters != -1 ) mCurTexElem += numRegisters; else @@ -192,7 +274,7 @@ void VertPixelConnectorGLSL::reset() mCurTexElem = 0; } -void VertPixelConnectorGLSL::print( Stream &stream ) +void VertPixelConnectorGLSL::print( Stream &stream, bool isVerterShader ) { // print out elements for( U32 i=0; iarraySize <= 1) - dSprintf((char*)output, sizeof(output), "varying %s %s;\r\n", var->type, var->name); + dSprintf((char*)output, sizeof(output), "%s %s _%s_;\r\n", (isVerterShader ? "out" : "in"), var->type, var->connectName); else - dSprintf((char*)output, sizeof(output), "varying %s %s[%d];\r\n", var->type, var->name, var->arraySize); + dSprintf((char*)output, sizeof(output), "%s %s _%s_[%d];\r\n", (isVerterShader ? "out" : "in"),var->type, var->connectName, var->arraySize); stream.write( dStrlen((char*)output), output ); } + + printStructDefines(stream, !isVerterShader); } -void VertexParamsDefGLSL::print( Stream &stream ) +void VertPixelConnectorGLSL::printOnMain( Stream &stream, bool isVerterShader ) +{ + if(isVerterShader) + return; + + const char *newLine = "\r\n"; + const char *header = " //-------------------------\r\n"; + stream.write( dStrlen((char*)newLine), newLine ); + stream.write( dStrlen((char*)header), header ); + + // print out elements + for( U32 i=0; iname, "gl_Position")) + continue; + + dSprintf((char*)output, sizeof(output), " %s IN_%s = _%s_;\r\n", var->type, var->name, var->connectName); + + stream.write( dStrlen((char*)output), output ); + } + + stream.write( dStrlen((char*)header), header ); + stream.write( dStrlen((char*)newLine), newLine ); +} + + +void AppVertConnectorGLSL::printOnMain( Stream &stream, bool isVerterShader ) +{ + if(!isVerterShader) + return; + + const char *newLine = "\r\n"; + const char *header = " //-------------------------\r\n"; + stream.write( dStrlen((char*)newLine), newLine ); + stream.write( dStrlen((char*)header), header ); + + // print out elements + for( U32 i=0; iarraySize <= 1) + { + dSprintf((char*)output, sizeof(output), " IN.%s = %s;\r\n", var->name, var->connectName); + stream.write( dStrlen((char*)output), output ); + } + else + { + for(int j = 0; j < var->arraySize; ++j) + { + const char *name = j == 0 ? var->connectName : avar("vTexCoord%d", var->constNum + j) ; + dSprintf((char*)output, sizeof(output), " IN.%s[%d] = %s;\r\n", var->name, j, name ); + stream.write( dStrlen((char*)output), output ); + } + } + } + + stream.write( dStrlen((char*)header), header ); + stream.write( dStrlen((char*)newLine), newLine ); +} + + + + +Vector initDeprecadedDefines() +{ + Vector vec; + vec.push_back( "isBack"); + return vec; +} + +void VertPixelConnectorGLSL::printStructDefines( Stream &stream, bool in ) +{ + const char* connectionDir; + + if(in) + { + connectionDir = "IN"; + } + else + { + + connectionDir = "OUT"; + } + + static Vector deprecatedDefines = initDeprecadedDefines(); + + const char *newLine = "\r\n"; + const char *header = "// Struct defines\r\n"; + stream.write( dStrlen((char*)newLine), newLine ); + stream.write( dStrlen((char*)header), header ); + + // print out elements + for( U32 i=0; iname, "gl_Position")) + continue; + + if(!in) + { + dSprintf((char*)output, sizeof(output), "#define %s_%s _%s_\r\n", connectionDir, var->name, var->connectName); + stream.write( dStrlen((char*)output), output ); + } + + if( deprecatedDefines.contains((char*)var->name)) + continue; + + dSprintf((char*)output, sizeof(output), "#define %s %s_%s\r\n", var->name, connectionDir, var->name); + stream.write( dStrlen((char*)output), output ); + } + + stream.write( dStrlen((char*)newLine), newLine ); +} + +void VertexParamsDefGLSL::print( Stream &stream, bool isVerterShader ) { // find all the uniform variables and print them out for( U32 i=0; i(LangElement::elementList[i]); + if( var ) + { + if( var->uniform && !var->sampler) + { + U8 output[256]; + if(var->arraySize <= 1) + dSprintf((char*)output, sizeof(output), " %s %s = %s;\r\n", var->type, var->name, var->name); + else + dSprintf((char*)output, sizeof(output), " %s %s[%d] = %s;\r\n", var->type, var->name, var->arraySize, var->name); + + stream.write( dStrlen((char*)output), output ); + } + } + } } diff --git a/Engine/source/shaderGen/GLSL/shaderCompGLSL.h b/Engine/source/shaderGen/GLSL/shaderCompGLSL.h index 5b306c0c8..12cd4ae93 100644 --- a/Engine/source/shaderGen/GLSL/shaderCompGLSL.h +++ b/Engine/source/shaderGen/GLSL/shaderCompGLSL.h @@ -40,7 +40,10 @@ public: virtual void reset(); virtual void sortVars(); - virtual void print( Stream &stream ); + virtual void print( Stream &stream) {} // TODO OPENGL temporal fix for dedicated build on Linux + virtual void print( Stream &stream, bool isVerterShader ); + void printStructDefines( Stream &stream, bool in ); + virtual void printOnMain( Stream &stream, bool isVerterShader ); }; class AppVertConnectorGLSL : public ShaderConnector @@ -53,21 +56,23 @@ public: virtual void reset(); virtual void sortVars(); - virtual void print( Stream &stream ); + virtual void print( Stream &stream) {} // TODO OPENGL temporal fix for dedicated build on Linux + virtual void print( Stream &stream, bool isVerterShader ); + virtual void printOnMain( Stream &stream, bool isVerterShader ); }; class VertexParamsDefGLSL : public ParamsDef { public: - virtual void print( Stream &stream ); + virtual void print( Stream &stream, bool isVerterShader ); }; class PixelParamsDefGLSL : public ParamsDef { public: - virtual void print( Stream &stream ); + virtual void print( Stream &stream, bool isVerterShader ); }; -#endif // _SHADERCOMP_GLSL_H_ \ No newline at end of file +#endif // _SHADERCOMP_GLSL_H_ diff --git a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp index 0e0c1ac46..c8942f454 100644 --- a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp @@ -41,26 +41,37 @@ LangElement * ShaderFeatureGLSL::setupTexSpaceMat( Vector &, / Var *B = (Var*) LangElement::find( "B" ); Var *T = (Var*) LangElement::find( "T" ); + Var *tangentW = (Var*) LangElement::find( "tangentW" ); + // setup matrix var *texSpaceMat = new Var; - (*texSpaceMat)->setType( "mat3" ); + (*texSpaceMat)->setType( "float3x3" ); (*texSpaceMat)->setName( "objToTangentSpace" ); MultiLine * meta = new MultiLine; + meta->addStatement( new GenOp( " @;\r\n", new DecOp( *texSpaceMat ) ) ); - // Recreate the binormal if we don't have one. - if ( !B ) + // Protect against missing normal and tangent. + if ( !N || !T ) { - B = new Var; - B->setType( "vec3" ); - B->setName( "B" ); - meta->addStatement( new GenOp( " @ = cross( @, normalize(@) );\r\n", new DecOp( B ), T, N ) ); + meta->addStatement( new GenOp( " tSetMatrixRow(@, 0, float3( 1, 0, 0 )); tSetMatrixRow(@, 1,float3( 0, 1, 0 )); tSetMatrixRow(@,2, float3( 0, 0, 1 ));\r\n", + *texSpaceMat, *texSpaceMat, *texSpaceMat ) ); + return meta; } - meta->addStatement( new GenOp( " @;\r\n", new DecOp( *texSpaceMat ) ) ); - meta->addStatement( new GenOp( " @[0] = vec3(@.x, @.x, normalize(@).x);\r\n", *texSpaceMat, T, B, N ) ); - meta->addStatement( new GenOp( " @[1] = vec3(@.y, @.y, normalize(@).y);\r\n", *texSpaceMat, T, B, N ) ); - meta->addStatement( new GenOp( " @[2] = vec3(@.z, @.z, normalize(@).z);\r\n", *texSpaceMat, T, B, N ) ); + meta->addStatement( new GenOp( " tSetMatrixRow(@, 0, @);\r\n", *texSpaceMat, T ) ); + if ( B ) + meta->addStatement( new GenOp( " tSetMatrixRow(@, 1, @);\r\n", *texSpaceMat, B ) ); + else + { + if(dStricmp((char*)T->type, "vec4") == 0) + meta->addStatement( new GenOp( " tSetMatrixRow(@, 1, cross( @, normalize(@) ) * @.w);\r\n", *texSpaceMat, T, N, T ) ); + else if(tangentW) + meta->addStatement( new GenOp( " tSetMatrixRow(@, 1, cross( @, normalize(@) ) * @);\r\n", *texSpaceMat, T, N, tangentW ) ); + else + meta->addStatement( new GenOp( " tSetMatrixRow(@, 1, cross( @, normalize(@) ));\r\n", *texSpaceMat, T, N ) ); + } + meta->addStatement( new GenOp( " tSetMatrixRow(@, 2, normalize(@));\r\n", *texSpaceMat, N ) ); return meta; } @@ -107,7 +118,7 @@ LangElement* ShaderFeatureGLSL::assignColor( LangElement *elem, case Material::LerpAlpha: if ( !lerpElem ) lerpElem = elem; - assign = new GenOp( "@.rgb = mix( @.rgb, (@).rgb, (@).a )", color, elem, color, lerpElem ); + assign = new GenOp( "@.rgb = lerp( @.rgb, (@).rgb, (@).a )", color, color, elem, lerpElem ); break; case Material::ToneMap: @@ -136,10 +147,19 @@ LangElement *ShaderFeatureGLSL::expandNormalMap( LangElement *sampleNormalOp, if ( fd.features.hasFeature( MFT_IsDXTnm, getProcessIndex() ) ) { + if ( fd.features[MFT_ImposterVert] ) + { + // The imposter system uses object space normals and + // encodes them with the z axis in the alpha component. + meta->addStatement( new GenOp( " @ = float4( normalize( @.xyw * 2.0 - 1.0 ), 0.0 ); // Obj DXTnm\r\n", normalDecl, sampleNormalOp ) ); + } + else + { // DXT Swizzle trick - meta->addStatement( new GenOp( " @ = vec4( @.ag * 2.0 - 1.0, 0.0, 0.0 ); // DXTnm\r\n", normalDecl, sampleNormalOp ) ); + meta->addStatement( new GenOp( " @ = float4( @.ag * 2.0 - 1.0, 0.0, 0.0 ); // DXTnm\r\n", normalDecl, sampleNormalOp ) ); meta->addStatement( new GenOp( " @.z = sqrt( 1.0 - dot( @.xy, @.xy ) ); // DXTnm\r\n", normalVar, normalVar, normalVar ) ); } + } else { meta->addStatement( new GenOp( " @ = @;\r\n", normalDecl, sampleNormalOp ) ); @@ -165,6 +185,18 @@ Var * ShaderFeatureGLSL::getVertTexCoord( const String &name ) inTex = dynamic_cast( LangElement::elementList[i] ); if ( inTex ) { + // NOTE: This used to do this check... + // + // dStrcmp( (char*)inTex->structName, "IN" ) + // + // ... to ensure that the var was from the input + // vertex structure, but this kept some features + // ( ie. imposter vert ) from decoding their own + // coords for other features to use. + // + // If we run into issues with collisions between + // IN vars and local vars we may need to revise. + break; } } @@ -201,7 +233,7 @@ Var* ShaderFeatureGLSL::getOutWorldToTangent( Vector &compon { // turn obj->tangent into world->tangent worldToTangent = new Var; - worldToTangent->setType( "mat3x3" ); + worldToTangent->setType( "float3x3" ); worldToTangent->setName( "worldToTangent" ); LangElement *worldToTangentDecl = new DecOp( worldToTangent ); @@ -211,16 +243,29 @@ Var* ShaderFeatureGLSL::getOutWorldToTangent( Vector &compon { worldToObj = new Var; worldToObj->setName( "worldToObj" ); - worldToObj->setType( "mat4x4" ); + + if ( fd.features[MFT_UseInstancing] ) + { + // We just use transpose to convert the 3x3 portion of + // the object transform to its inverse. + worldToObj->setType( "float3x3" ); + Var *objTrans = getObjTrans( componentList, true, meta ); + meta->addStatement( new GenOp( " @ = transpose( float3x3(@) ); // Instancing!\r\n", new DecOp( worldToObj ), objTrans ) ); + } + else + { + worldToObj->setType( "float4x4" ); worldToObj->uniform = true; worldToObj->constSortPos = cspPrimitive; } + } // assign world->tangent transform - meta->addStatement( new GenOp( " @ = @ * mat3x3( @[0].xyz, @[1].xyz, @[2].xyz );\r\n", worldToTangentDecl, texSpaceMat, worldToObj, worldToObj, worldToObj ) ); + meta->addStatement( new GenOp( " @ = tMul( @, float3x3(@) );\r\n", worldToTangentDecl, texSpaceMat, worldToObj ) ); } else { + // Assume particle normal generation has set this up in the proper space worldToTangent = texSpaceMat; } } @@ -230,13 +275,14 @@ Var* ShaderFeatureGLSL::getOutWorldToTangent( Vector &compon outWorldToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 ); outWorldToTangent->setName( "outWorldToTangent" ); - outWorldToTangent->setType( "mat3x3" ); + outWorldToTangent->setStructName( "OUT" ); + outWorldToTangent->setType( "float3x3" ); meta->addStatement( new GenOp( " @ = @;\r\n", outWorldToTangent, worldToTangent ) ); return outWorldToTangent; } -Var* ShaderFeatureGLSL::getOutViewToTangent( Vector &componentList, +Var* ShaderFeatureGLSL::getOutViewToTangent( Vector &componentList, MultiLine *meta, const MaterialFeatureData &fd ) { @@ -247,14 +293,14 @@ Var* ShaderFeatureGLSL::getOutViewToTangent( Vector &compone Var *viewToTangent = (Var*)LangElement::find( "viewToTangent" ); if ( !viewToTangent ) { + Var *texSpaceMat = getOutObjToTangentSpace( componentList, meta, fd ); if(!fd.features[MFT_ParticleNormal]) { - // turn obj->tangent into world->tangent viewToTangent = new Var; - viewToTangent->setType( "mat3" ); + viewToTangent->setType( "float3x3" ); viewToTangent->setName( "viewToTangent" ); LangElement *viewToTangentDecl = new DecOp( viewToTangent ); @@ -262,11 +308,7 @@ Var* ShaderFeatureGLSL::getOutViewToTangent( Vector &compone Var *viewToObj = getInvWorldView( componentList, fd.features[MFT_UseInstancing], meta ); // assign world->tangent transform - meta->addStatement( new GenOp( " mat3 mat3ViewToObj;\r\n" ) ); - meta->addStatement( new GenOp( " mat3ViewToObj[0] = @[0].xyz;\r\n", viewToObj ) ); - meta->addStatement( new GenOp( " mat3ViewToObj[1] = @[1].xyz;\r\n", viewToObj ) ); - meta->addStatement( new GenOp( " mat3ViewToObj[2] = @[2].xyz;\r\n", viewToObj ) ); - meta->addStatement( new GenOp( " @ = @ * mat3ViewToObj;\r\n", viewToTangentDecl, texSpaceMat ) ); + meta->addStatement( new GenOp( " @ = tMul( (@), float3x3(@) );\r\n", viewToTangentDecl, texSpaceMat, viewToObj ) ); } else { @@ -280,7 +322,8 @@ Var* ShaderFeatureGLSL::getOutViewToTangent( Vector &compone outViewToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 ); outViewToTangent->setName( "outViewToTangent" ); - outViewToTangent->setType( "mat3" ); + outViewToTangent->setStructName( "OUT" ); + outViewToTangent->setType( "float3x3" ); meta->addStatement( new GenOp( " @ = @;\r\n", outViewToTangent, viewToTangent ) ); return outViewToTangent; @@ -304,6 +347,7 @@ Var* ShaderFeatureGLSL::getOutTexCoord( const char *name, texCoord = connectComp->getElement( RT_TEXCOORD ); texCoord->setName( outTexName ); + texCoord->setStructName( "OUT" ); texCoord->setType( type ); texCoord->mapsToSampler = mapsToSampler; @@ -313,21 +357,21 @@ Var* ShaderFeatureGLSL::getOutTexCoord( const char *name, // create texture mat var Var *texMat = new Var; - texMat->setType( "mat4" ); + texMat->setType( "float4x4" ); texMat->setName( "texMat" ); texMat->uniform = true; texMat->constSortPos = cspPass; // Statement allows for casting of different types which // eliminates vector truncation problems. - String statement = String::ToString( " @ = %s(@ * @);\r\n", type ); + String statement = String::ToString( " @ = %s(tMul(@, @));\r\n", type ); meta->addStatement( new GenOp( statement , texCoord, texMat, inTex ) ); } else { // Statement allows for casting of different types which // eliminates vector truncation problems. - String statement = String::ToString( " @ = %s(@);\r\n", type ); + String statement = String::ToString( " @ = %s(@);\r\n", type ); meta->addStatement( new GenOp( statement, texCoord, inTex ) ); } } @@ -349,6 +393,7 @@ Var* ShaderFeatureGLSL::getInTexCoord( const char *name, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); texCoord = connectComp->getElement( RT_TEXCOORD ); texCoord->setName( name ); + texCoord->setStructName( "IN" ); texCoord->setType( type ); texCoord->mapsToSampler = mapsToSampler; } @@ -359,15 +404,97 @@ Var* ShaderFeatureGLSL::getInTexCoord( const char *name, return texCoord; } +Var* ShaderFeatureGLSL::getInColor( const char *name, + const char *type, + Vector &componentList ) +{ + Var *inColor = (Var*)LangElement::find( name ); + if ( !inColor ) + { + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + inColor = connectComp->getElement( RT_COLOR ); + inColor->setName( name ); + inColor->setStructName( "IN" ); + inColor->setType( type ); + } + + AssertFatal( dStrcmp( type, (const char*)inColor->type ) == 0, + "ShaderFeatureGLSL::getInColor - Type mismatch!" ); + + return inColor; +} + +Var* ShaderFeatureGLSL::addOutVpos( MultiLine *meta, + Vector &componentList ) +{ + /* + // Nothing to do if we're on SM 3.0... we use the real vpos. + if ( GFX->getPixelShaderVersion() >= 3.0f ) + return NULL; + */ + + // For SM 2.x we need to generate the vpos in the vertex shader + // and pass it as a texture coord to the pixel shader. + + Var *outVpos = (Var*)LangElement::find( "outVpos" ); + if ( !outVpos ) + { + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + + outVpos = connectComp->getElement( RT_TEXCOORD ); + outVpos->setName( "outVpos" ); + outVpos->setStructName( "OUT" ); + outVpos->setType( "vec4" ); + outVpos->mapsToSampler = false; + + Var *outPosition = (Var*) LangElement::find( "gl_Position" ); + AssertFatal( outPosition, "ShaderFeatureGLSL::addOutVpos - Didn't find the output position." ); + + meta->addStatement( new GenOp( " @ = @;\r\n", outVpos, outPosition ) ); + } + + return outVpos; +} + +Var* ShaderFeatureGLSL::getInVpos( MultiLine *meta, + Vector &componentList ) +{ + Var *inVpos = (Var*)LangElement::find( "vpos" ); + if ( inVpos ) + return inVpos; + + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + /* + if ( GFX->getPixelShaderVersion() >= 3.0f ) + { + inVpos = connectComp->getElement( RT_VPOS ); + inVpos->setName( "vpos" ); + inVpos->setStructName( "IN" ); + inVpos->setType( "vec2" ); + return inVpos; + } + */ + inVpos = connectComp->getElement( RT_TEXCOORD ); + inVpos->setName( "inVpos" ); + inVpos->setStructName( "IN" ); + inVpos->setType( "vec4" ); + + Var *vpos = new Var( "vpos", "vec2" ); + meta->addStatement( new GenOp( " @ = @.xy / @.w;\r\n", new DecOp( vpos ), inVpos, inVpos ) ); + + return vpos; +} + Var* ShaderFeatureGLSL::getInWorldToTangent( Vector &componentList ) { - Var *worldToTangent = (Var*)LangElement::find( "outWorldToTangent" ); + Var *worldToTangent = (Var*)LangElement::find( "worldToTangent" ); if ( !worldToTangent ) { ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); worldToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 ); - worldToTangent->setName( "outWorldToTangent" ); - worldToTangent->setType( "mat3x3" ); + worldToTangent->setName( "worldToTangent" ); + worldToTangent->setStructName( "IN" ); + worldToTangent->setType( "float3x3" ); } return worldToTangent; @@ -375,13 +502,14 @@ Var* ShaderFeatureGLSL::getInWorldToTangent( Vector &component Var* ShaderFeatureGLSL::getInViewToTangent( Vector &componentList ) { - Var *viewToTangent = (Var*)LangElement::find( "outViewToTangent" ); + Var *viewToTangent = (Var*)LangElement::find( "viewToTangent" ); if ( !viewToTangent ) { ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); viewToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 ); - viewToTangent->setName( "outViewToTangent" ); - viewToTangent->setType( "mat3" ); + viewToTangent->setName( "viewToTangent" ); + viewToTangent->setStructName( "IN" ); + viewToTangent->setType( "float3x3" ); } return viewToTangent; @@ -403,16 +531,43 @@ Var* ShaderFeatureGLSL::getNormalMapTex() return normalMap; } -Var* ShaderFeatureGLSL::getObjTrans( Vector &componentList, +Var* ShaderFeatureGLSL::getObjTrans( Vector &componentList, bool useInstancing, MultiLine *meta ) { - Var *objTrans = (Var*) LangElement::find( "objTrans" ); if ( objTrans ) + Var *objTrans = (Var*)LangElement::find( "objTrans" ); + if ( objTrans ) return objTrans; - objTrans = new Var; objTrans->setType( "mat4x4" ); + + if ( useInstancing ) + { + ShaderConnector *vertStruct = dynamic_cast( componentList[C_VERT_STRUCT] ); + Var *instObjTrans = vertStruct->getElement( RT_TEXCOORD, 4, 4 ); + instObjTrans->setStructName( "IN" ); + instObjTrans->setName( "inst_objectTrans" ); + + mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+0 ); + mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+1 ); + mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+2 ); + mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+3 ); + + objTrans = new Var; + objTrans->setType( "mat4x4" ); + objTrans->setName( "objTrans" ); + meta->addStatement( new GenOp( " @ = mat4x4( // Instancing!\r\n", new DecOp( objTrans ), instObjTrans ) ); + meta->addStatement( new GenOp( " @[0],\r\n", instObjTrans ) ); + meta->addStatement( new GenOp( " @[1],\r\n", instObjTrans ) ); + meta->addStatement( new GenOp( " @[2],\r\n",instObjTrans ) ); + meta->addStatement( new GenOp( " @[3] );\r\n", instObjTrans ) ); + } + else + { + objTrans = new Var; + objTrans->setType( "float4x4" ); objTrans->setName( "objTrans" ); objTrans->uniform = true; objTrans->constSortPos = cspPrimitive; + } return objTrans; } @@ -425,12 +580,33 @@ Var* ShaderFeatureGLSL::getModelView( Vector &componentList, if ( modelview ) return modelview; - // create modelview variable + if ( useInstancing ) + { + Var *objTrans = getObjTrans( componentList, useInstancing, meta ); + + Var *viewProj = (Var*)LangElement::find( "viewProj" ); + if ( !viewProj ) + { + viewProj = new Var; + viewProj->setType( "float4x4" ); + viewProj->setName( "viewProj" ); + viewProj->uniform = true; + viewProj->constSortPos = cspPass; + } + modelview = new Var; - modelview->setType( "mat4" ); + modelview->setType( "float4x4" ); + modelview->setName( "modelview" ); + meta->addStatement( new GenOp( " @ = tMul( @, @ ); // Instancing!\r\n", new DecOp( modelview ), viewProj, objTrans ) ); + } + else + { + modelview = new Var; + modelview->setType( "float4x4" ); modelview->setName( "modelview" ); modelview->uniform = true; modelview->constSortPos = cspPrimitive; + } return modelview; } @@ -443,15 +619,39 @@ Var* ShaderFeatureGLSL::getWorldView( Vector &componentList, if ( worldView ) return worldView; + if ( useInstancing ) + { + Var *objTrans = getObjTrans( componentList, useInstancing, meta ); + + Var *worldToCamera = (Var*)LangElement::find( "worldToCamera" ); + if ( !worldToCamera ) + { + worldToCamera = new Var; + worldToCamera->setType( "float4x4" ); + worldToCamera->setName( "worldToCamera" ); + worldToCamera->uniform = true; + worldToCamera->constSortPos = cspPass; + } + + worldView = new Var; + worldView->setType( "float4x4" ); + worldView->setName( "worldViewOnly" ); + + meta->addStatement( new GenOp( " @ = tMul( @, @ ); // Instancing!\r\n", new DecOp( worldView ), worldToCamera, objTrans ) ); + } + else + { worldView = new Var; - worldView->setType( "mat4x4" ); + worldView->setType( "float4x4" ); worldView->setName( "worldViewOnly" ); worldView->uniform = true; worldView->constSortPos = cspPrimitive; + } return worldView; } + Var* ShaderFeatureGLSL::getInvWorldView( Vector &componentList, bool useInstancing, MultiLine *meta ) @@ -460,11 +660,27 @@ Var* ShaderFeatureGLSL::getInvWorldView( Vector &componentLis if ( viewToObj ) return viewToObj; + if ( useInstancing ) + { + Var *worldView = getWorldView( componentList, useInstancing, meta ); + + viewToObj = new Var; + viewToObj->setType( "float3x3" ); + viewToObj->setName( "viewToObj" ); + + // We just use transpose to convert the 3x3 portion + // of the world view transform into its inverse. + + meta->addStatement( new GenOp( " @ = transpose( float3x3(@) ); // Instancing!\r\n", new DecOp( viewToObj ), worldView ) ); + } + else + { viewToObj = new Var; - viewToObj->setType( "mat4" ); + viewToObj->setType( "float4x4" ); viewToObj->setName( "viewToObj" ); viewToObj->uniform = true; viewToObj->constSortPos = cspPrimitive; + } return viewToObj; } @@ -491,7 +707,7 @@ void ShaderFeatureGLSL::getWsPosition( Vector &componentList, Var *objTrans = getObjTrans( componentList, useInstancing, meta ); - meta->addStatement( new GenOp( " @ = ( @ * vec4( @.xyz, 1 ) ).xyz;\r\n", + meta->addStatement( new GenOp( " @ = tMul( @, float4( @.xyz, 1 ) ).xyz;\r\n", wsPosition, objTrans, inPosition ) ); } @@ -505,6 +721,7 @@ Var* ShaderFeatureGLSL::addOutWsPosition( Vector &componentLis ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); outWsPosition = connectComp->getElement( RT_TEXCOORD ); outWsPosition->setName( "outWsPosition" ); + outWsPosition->setStructName( "OUT" ); outWsPosition->setType( "vec3" ); outWsPosition->mapsToSampler = false; @@ -516,12 +733,13 @@ Var* ShaderFeatureGLSL::addOutWsPosition( Vector &componentLis Var* ShaderFeatureGLSL::getInWsPosition( Vector &componentList ) { - Var *wsPosition = (Var*)LangElement::find( "outWsPosition" ); + Var *wsPosition = (Var*)LangElement::find( "wsPosition" ); if ( !wsPosition ) { ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); wsPosition = connectComp->getElement( RT_TEXCOORD ); - wsPosition->setName( "outWsPosition" ); + wsPosition->setName( "wsPosition" ); + wsPosition->setStructName( "IN" ); wsPosition->setType( "vec3" ); } @@ -566,7 +784,7 @@ Var* ShaderFeatureGLSL::addOutDetailTexCoord( Vector &compon // create detail variable Var *detScale = new Var; - detScale->setType( "vec2" ); + detScale->setType( "vec2" ); detScale->setName( "detailScale" ); detScale->uniform = true; detScale->constSortPos = cspPotentialPrimitive; @@ -575,25 +793,26 @@ Var* ShaderFeatureGLSL::addOutDetailTexCoord( Vector &compon ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); outTex = connectComp->getElement( RT_TEXCOORD ); outTex->setName( "detCoord" ); - outTex->setType( "vec2" ); + outTex->setStructName( "OUT" ); + outTex->setType( "vec2" ); outTex->mapsToSampler = true; if ( useTexAnim ) { - inTex->setType( "vec4" ); + inTex->setType( "vec4" ); // Find or create the texture matrix. Var *texMat = (Var*)LangElement::find( "texMat" ); if ( !texMat ) { texMat = new Var; - texMat->setType( "mat4x4" ); + texMat->setType( "float4x4" ); texMat->setName( "texMat" ); texMat->uniform = true; texMat->constSortPos = cspPass; } - meta->addStatement( new GenOp( " @ = (@ * @) * @;\r\n", outTex, texMat, inTex, detScale ) ); + meta->addStatement( new GenOp( " @ = tMul(@, @) * @;\r\n", outTex, texMat, inTex, detScale ) ); } else { @@ -608,7 +827,7 @@ Var* ShaderFeatureGLSL::addOutDetailTexCoord( Vector &compon // Base Texture //**************************************************************************** -void DiffuseMapFeatGLSL::processVert( Vector &componentList, +void DiffuseMapFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { MultiLine *meta = new MultiLine; @@ -625,7 +844,7 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { // grab connector texcoord register - Var *inTex = getInTexCoord( "out_texCoord", "vec2", true, componentList ); + Var *inTex = getInTexCoord( "texCoord", "vec2", true, componentList ); // create texture var Var *diffuseMap = new Var; @@ -645,7 +864,7 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, diffColor->setName( "diffuseColor" ); LangElement *colorDecl = new DecOp( diffColor ); - meta->addStatement( new GenOp( " @ = texture2D(@, @);\r\n", + meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n", colorDecl, diffuseMap, inTex ) ); @@ -662,19 +881,19 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, Var *atlasedTex = new Var; atlasedTex->setName("atlasedTexCoord"); - atlasedTex->setType("float2"); + atlasedTex->setType("vec2"); LangElement *atDecl = new DecOp(atlasedTex); // Parameters of the texture atlas Var *atParams = new Var; - atParams->setType("float4"); + atParams->setType("vec4"); atParams->setName("diffuseAtlasParams"); atParams->uniform = true; atParams->constSortPos = cspPotentialPrimitive; // Parameters of the texture (tile) this object is using in the atlas Var *tileParams = new Var; - tileParams->setType("float4"); + tileParams->setType("vec4"); tileParams->setName("diffuseAtlasTileParams"); tileParams->uniform = true; tileParams->constSortPos = cspPotentialPrimitive; @@ -683,24 +902,24 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, if(is_sm3) { // Figure out the mip level - meta->addStatement(new GenOp(" vec2 _dx = ddx(@ * @.z);\r\n", inTex, atParams)); - meta->addStatement(new GenOp(" vec2 _dy = ddy(@ * @.z);\r\n", inTex, atParams)); + meta->addStatement(new GenOp(" float2 _dx = ddx(@ * @.z);\r\n", inTex, atParams)); + meta->addStatement(new GenOp(" float2 _dy = ddy(@ * @.z);\r\n", inTex, atParams)); meta->addStatement(new GenOp(" float mipLod = 0.5 * log2(max(dot(_dx, _dx), dot(_dy, _dy)));\r\n")); meta->addStatement(new GenOp(" mipLod = clamp(mipLod, 0.0, @.w);\r\n", atParams)); // And the size of the mip level meta->addStatement(new GenOp(" float mipPixSz = pow(2.0, @.w - mipLod);\r\n", atParams)); - meta->addStatement(new GenOp(" vec2 mipSz = mipPixSz / @.xy;\r\n", atParams)); + meta->addStatement(new GenOp(" float2 mipSz = mipPixSz / @.xy;\r\n", atParams)); } else { - meta->addStatement(new GenOp(" vec2 mipSz = float2(1.0, 1.0);\r\n")); + meta->addStatement(new GenOp(" float2 mipSz = float2(1.0, 1.0);\r\n")); } // Tiling mode // TODO: Select wrap or clamp somehow if( true ) // Wrap - meta->addStatement(new GenOp(" @ = fract(@);\r\n", atDecl, inTex)); + meta->addStatement(new GenOp(" @ = frac(@);\r\n", atDecl, inTex)); else // Clamp meta->addStatement(new GenOp(" @ = saturate(@);\r\n", atDecl, inTex)); @@ -724,7 +943,7 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, #ifdef DEBUG_ATLASED_UV_COORDS if(!fd.features[MFT_PrePassConditioner]) { - meta->addStatement(new GenOp(" @ = vec4(@.xy, mipLod / @.w, 1.0);\r\n", new DecOp(diffColor), inTex, atParams)); + meta->addStatement(new GenOp(" @ = float4(@.xy, mipLod / @.w, 1.0);\r\n", new DecOp(diffColor), inTex, atParams)); meta->addStatement(new GenOp(" @; return OUT;\r\n", assignColor(diffColor, Material::Mul))); return; } @@ -732,12 +951,12 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, if(is_sm3) { - meta->addStatement(new GenOp( " @ = texture2Dlod(@, float4(@, 0.0, mipLod));\r\n", + meta->addStatement(new GenOp( " @ = tex2Dlod(@, float4(@, 0.0, mipLod));\r\n", new DecOp(diffColor), diffuseMap, inTex)); } else { - meta->addStatement(new GenOp( " @ = texture2D(@, @);\r\n", + meta->addStatement(new GenOp( " @ = tex2D(@, @);\r\n", new DecOp(diffColor), diffuseMap, inTex)); } @@ -745,7 +964,7 @@ void DiffuseMapFeatGLSL::processPix( Vector &componentList, } else { - LangElement *statement = new GenOp( "texture2D(@, @)", diffuseMap, inTex ); + LangElement *statement = new GenOp( "tex2D(@, @)", diffuseMap, inTex ); output = new GenOp( " @;\r\n", assignColor( statement, Material::Mul ) ); } @@ -767,7 +986,10 @@ void DiffuseMapFeatGLSL::setTexData( Material::StageData &stageDat, { GFXTextureObject *tex = stageDat.getTex( MFT_DiffuseMap ); if ( tex ) + { + passData.mSamplerNames[ texIndex ] = "diffuseMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; + } } @@ -785,6 +1007,7 @@ void OverlayTexFeatGLSL::processVert( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *outTex = connectComp->getElement( RT_TEXCOORD ); outTex->setName( "outTexCoord2" ); + outTex->setStructName( "OUT" ); outTex->setType( "vec2" ); outTex->mapsToSampler = true; @@ -797,13 +1020,13 @@ void OverlayTexFeatGLSL::processVert( Vector &componentList, if ( !texMat ) { texMat = new Var; - texMat->setType( "mat4x4" ); + texMat->setType( "float4x4" ); texMat->setName( "texMat" ); texMat->uniform = true; texMat->constSortPos = cspPass; } - output = new GenOp( " @ = @ * @;\r\n", outTex, texMat, inTex ); + output = new GenOp( " @ = tMul(@, @);\r\n", outTex, texMat, inTex ); return; } @@ -818,7 +1041,8 @@ void OverlayTexFeatGLSL::processPix( Vector &componentList, // grab connector texcoord register ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *inTex = connectComp->getElement( RT_TEXCOORD ); - inTex->setName( "outTexCoord2" ); + inTex->setName( "texCoord2" ); + inTex->setStructName( "IN" ); inTex->setType( "vec2" ); inTex->mapsToSampler = true; @@ -830,7 +1054,7 @@ void OverlayTexFeatGLSL::processPix( Vector &componentList, diffuseMap->sampler = true; diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here - LangElement *statement = new GenOp( "texture2D(@, @)", diffuseMap, inTex ); + LangElement *statement = new GenOp( "tex2D(@, @)", diffuseMap, inTex ); output = new GenOp( " @;\r\n", assignColor( statement, Material::LerpAlpha ) ); } @@ -899,6 +1123,7 @@ void DiffuseVertColorFeatureGLSL::processVert( Vector< ShaderComponent* >& comp AssertFatal( connectComp, "DiffuseVertColorFeatureGLSL::processVert - C_CONNECTOR is not a ShaderConnector" ); Var* outColor = connectComp->getElement( RT_COLOR ); outColor->setName( "vertColor" ); + outColor->setStructName( "OUT" ); outColor->setType( "vec4" ); output = new GenOp( " @ = @;\r\n", outColor, inColor ); @@ -917,6 +1142,7 @@ void DiffuseVertColorFeatureGLSL::processPix( Vector &compon AssertFatal( connectComp, "DiffuseVertColorFeatureGLSL::processVert - C_CONNECTOR is not a ShaderConnector" ); vertColor = connectComp->getElement( RT_COLOR ); vertColor->setName( "vertColor" ); + vertColor->setStructName( "IN" ); vertColor->setType( "vec4" ); } @@ -934,12 +1160,13 @@ void LightmapFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { // grab tex register from incoming vert - Var *inTex = (Var*) LangElement::find( "texCoord2" ); + Var *inTex = getVertTexCoord( "texCoord2" ); // grab connector texcoord register ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *outTex = connectComp->getElement( RT_TEXCOORD ); - outTex->setName( "outTexCoord2" ); + outTex->setName( "texCoord2" ); + outTex->setStructName( "OUT" ); outTex->setType( "vec2" ); outTex->mapsToSampler = true; @@ -953,7 +1180,8 @@ void LightmapFeatGLSL::processPix( Vector &componentList, // grab connector texcoord register ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *inTex = connectComp->getElement( RT_TEXCOORD ); - inTex->setName( "outTexCoord2" ); + inTex->setName( "texCoord2" ); + inTex->setStructName( "IN" ); inTex->setType( "vec2" ); inTex->mapsToSampler = true; @@ -974,7 +1202,7 @@ void LightmapFeatGLSL::processPix( Vector &componentList, lmColor->setType( "vec4" ); LangElement *lmColorDecl = new DecOp( lmColor ); - output = new GenOp( " @ = texture2D(@, @);\r\n", lmColorDecl, lightMap, inTex ); + output = new GenOp( " @ = tex2D(@, @);\r\n", lmColorDecl, lightMap, inTex ); return; } @@ -995,21 +1223,27 @@ void LightmapFeatGLSL::processPix( Vector &componentList, // Lightmap has already been included in the advanced light bin, so // no need to do any sampling or anything if(bPreProcessedLighting) - statement = new GenOp( "vec4(@, 1.0)", inColor ); + statement = new GenOp( "float4(@, 1.0)", inColor ); else - statement = new GenOp( "texture2D(@, @) + vec4(@.rgb, 0.0)", lightMap, inTex, inColor ); + statement = new GenOp( "tex2D(@, @) + float4(@.rgb, 0.0)", lightMap, inTex, inColor ); } } - else - { - statement = new GenOp( "texture2D(@, @)", lightMap, inTex ); - } + + // If we still don't have it... then just sample the lightmap. + if ( !statement ) + statement = new GenOp( "tex2D(@, @)", lightMap, inTex ); // Assign to proper render target + MultiLine *meta = new MultiLine; if( fd.features[MFT_LightbufferMRT] ) - output = new GenOp( " @;\r\n", assignColor( statement, Material::None, NULL, ShaderFeature::RenderTarget1 ) ); + { + meta->addStatement( new GenOp( " @;\r\n", assignColor( statement, Material::None, NULL, ShaderFeature::RenderTarget1 ) ) ); + meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) ) ) ); + } else - output = new GenOp( " @;\r\n", assignColor( statement, Material::Mul ) ); + meta->addStatement( new GenOp( " @;\r\n", assignColor( statement, Material::Mul ) ) ); + + output = meta; } ShaderFeature::Resources LightmapFeatGLSL::getResources( const MaterialFeatureData &fd ) @@ -1027,6 +1261,7 @@ void LightmapFeatGLSL::setTexData( Material::StageData &stageDat, U32 &texIndex ) { GFXTextureObject *tex = stageDat.getTex( MFT_LightMap ); + passData.mSamplerNames[ texIndex ] = "lightMap"; if ( tex ) passData.mTexSlot[ texIndex++ ].texObject = tex; else @@ -1054,7 +1289,8 @@ void TonemapFeatGLSL::processVert( Vector &componentList, if ( inTex2 ) { Var *outTex2 = connectComp->getElement( RT_TEXCOORD ); - outTex2->setName( "toneMapCoord" ); + outTex2->setName( "texCoord2" ); + outTex2->setStructName( "OUT" ); outTex2->setType( "vec2" ); outTex2->mapsToSampler = true; @@ -1069,7 +1305,8 @@ void TonemapFeatGLSL::processPix( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *inTex2 = connectComp->getElement( RT_TEXCOORD ); - inTex2->setName( "toneMapCoord" ); + inTex2->setName( "texCoord2" ); + inTex2->setStructName( "IN" ); inTex2->setType( "vec2" ); inTex2->mapsToSampler = true; @@ -1089,14 +1326,14 @@ void TonemapFeatGLSL::processPix( Vector &componentList, toneMapColor->setName( "toneMapColor" ); LangElement *toneMapColorDecl = new DecOp( toneMapColor ); - meta->addStatement( new GenOp( " @ = texture2D(@, @);\r\n", toneMapColorDecl, toneMap, inTex2 ) ); + meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n", toneMapColorDecl, toneMap, inTex2 ) ); // We do a different calculation if there is a diffuse map or not Material::BlendOp blendOp = Material::Mul; if ( fd.features[MFT_DiffuseMap] ) { // Reverse the tonemap - meta->addStatement( new GenOp( " @ = -1.0 * log(1.0 - @);\r\n", toneMapColor, toneMapColor ) ); + meta->addStatement( new GenOp( " @ = -1.0f * log(1.0f - @);\r\n", toneMapColor, toneMapColor ) ); // Re-tonemap with the current color factored in blendOp = Material::ToneMap; @@ -1126,7 +1363,10 @@ void TonemapFeatGLSL::processPix( Vector &componentList, // Assign to proper render target if( fd.features[MFT_LightbufferMRT] ) + { meta->addStatement( new GenOp( " @;\r\n", assignColor( toneMapColor, Material::None, NULL, ShaderFeature::RenderTarget1 ) ) ); + meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) ) ) ); + } else meta->addStatement( new GenOp( " @;\r\n", assignColor( toneMapColor, blendOp ) ) ); @@ -1151,6 +1391,7 @@ void TonemapFeatGLSL::setTexData( Material::StageData &stageDat, if ( tex ) { passData.mTexType[ texIndex ] = Material::ToneMapTex; + passData.mSamplerNames[ texIndex ] = "toneMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; } } @@ -1194,6 +1435,7 @@ void VertLitGLSL::processVert( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *outColor = connectComp->getElement( RT_COLOR ); outColor->setName( "vertColor" ); + outColor->setStructName( "OUT" ); outColor->setType( "vec4" ); output = new GenOp( " @ = @;\r\n", outColor, inColor ); @@ -1221,6 +1463,7 @@ void VertLitGLSL::processPix( Vector &componentList, AssertFatal( connectComp, "VertLitGLSL::processVert - C_CONNECTOR is not a ShaderConnector" ); vertColor = connectComp->getElement( RT_COLOR ); vertColor->setName( "vertColor" ); + vertColor->setStructName( "IN" ); vertColor->setType( "vec4" ); } @@ -1239,12 +1482,11 @@ void VertLitGLSL::processPix( Vector &componentList, LangElement *finalVertColorDecl = new DecOp( finalVertColor ); // Reverse the tonemap - meta->addStatement( new GenOp( " @ = -1.0 * log(1.0 - @);\r\n", finalVertColorDecl, vertColor ) ); + meta->addStatement( new GenOp( " @ = -1.0f * log(1.0f - @);\r\n", finalVertColorDecl, vertColor ) ); // Set the blend op to tonemap blendOp = Material::ToneMap; outColor = finalVertColor; - } // Add in the realtime lighting contribution, if applicable @@ -1253,7 +1495,6 @@ void VertLitGLSL::processPix( Vector &componentList, Var *rtLightingColor = (Var*) LangElement::find( "d_lightcolor" ); if(rtLightingColor != NULL) { - // Find out if RTLighting should be added or substituted bool bPreProcessedLighting = false; AdvancedLightBinManager *lightBin; if ( Sim::findObject( "AL_LightBinMgr", lightBin ) ) @@ -1263,15 +1504,18 @@ void VertLitGLSL::processPix( Vector &componentList, // the dynamic light buffer, and it already has the baked-vertex-color // included in it if(bPreProcessedLighting) - outColor = new GenOp( "vec4(@.rgb, 1.0)", rtLightingColor ); + outColor = new GenOp( "float4(@.rgb, 1.0)", rtLightingColor ); else - outColor = new GenOp( "vec4(@.rgb, 0.0) + @", rtLightingColor, outColor ); + outColor = new GenOp( "float4(@.rgb + @.rgb, 1.0)", rtLightingColor, outColor ); } } // Output the color if ( fd.features[MFT_LightbufferMRT] ) + { meta->addStatement( new GenOp( " @;\r\n", assignColor( outColor, Material::None, NULL, ShaderFeature::RenderTarget1 ) ) ); + meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) ) ) ); + } else meta->addStatement( new GenOp( " @;\r\n", assignColor( outColor, blendOp ) ) ); @@ -1283,7 +1527,6 @@ U32 VertLitGLSL::getOutputTargets( const MaterialFeatureData &fd ) const return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; } - //**************************************************************************** // Detail map //**************************************************************************** @@ -1319,7 +1562,7 @@ void DetailFeatGLSL::processPix( Vector &componentList, // TODO: We could add a feature to toggle between this // and a simple multiplication with the detail map. - LangElement *statement = new GenOp( "( texture2D(@, @) * 2.0 ) - 1.0", detailMap, inTex ); + LangElement *statement = new GenOp( "( tex2D(@, @) * 2.0 ) - 1.0", detailMap, inTex ); output = new GenOp( " @;\r\n", assignColor( statement, Material::Add ) ); } @@ -1339,7 +1582,10 @@ void DetailFeatGLSL::setTexData( Material::StageData &stageDat, { GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap ); if ( tex ) + { + passData.mSamplerNames[texIndex] = "detailMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; + } } @@ -1347,6 +1593,17 @@ void DetailFeatGLSL::setTexData( Material::StageData &stageDat, // Vertex position //**************************************************************************** +void VertPositionGLSL::determineFeature( Material *material, + const GFXVertexFormat *vertexFormat, + U32 stageNum, + const FeatureType &type, + const FeatureSet &features, + MaterialFeatureData *outFeatureData ) +{ + // This feature is always on! + outFeatureData->features.addFeature( type ); +} + void VertPositionGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { @@ -1365,7 +1622,8 @@ void VertPositionGLSL::processVert( Vector &componentList, Var *modelview = getModelView( componentList, fd.features[MFT_UseInstancing], meta ); - meta->addStatement( new GenOp( " @ = @ * vec4(@.xyz,1);\r\n", outPosition, modelview, inPosition ) ); + meta->addStatement( new GenOp( " @ = tMul(@, float4(@.xyz,1));\r\n", + outPosition, modelview, inPosition ) ); output = meta; } @@ -1378,6 +1636,11 @@ void VertPositionGLSL::processVert( Vector &componentList, void ReflectCubeFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { + // search for vert normal + Var *inNormal = (Var*) LangElement::find( "normal" ); + if ( !inNormal ) + return; + MultiLine * meta = new MultiLine; // If a base or bump tex is present in the material, but not in the @@ -1395,7 +1658,8 @@ void ReflectCubeFeatGLSL::processVert( Vector &componentList, // grab connector texcoord register ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *outTex = connectComp->getElement( RT_TEXCOORD ); - outTex->setName( "outTexCoord" ); + outTex->setName( "texCoord" ); + outTex->setStructName( "OUT" ); outTex->setType( "vec2" ); outTex->mapsToSampler = true; @@ -1405,54 +1669,60 @@ void ReflectCubeFeatGLSL::processVert( Vector &componentList, } // create cubeTrans - Var *cubeTrans = new Var; - cubeTrans->setType( "mat3" ); - cubeTrans->setName( "cubeTrans" ); - cubeTrans->uniform = true; - cubeTrans->constSortPos = cspPrimitive; - - // create cubeEye position - Var *cubeEyePos = new Var; - cubeEyePos->setType( "vec3" ); - cubeEyePos->setName( "cubeEyePos" ); - cubeEyePos->uniform = true; - cubeEyePos->constSortPos = cspPrimitive; - - // search for vert normal - Var *inNormal = (Var*) LangElement::find( "normal" ); + bool useInstancing = fd.features[MFT_UseInstancing]; + Var *cubeTrans = getObjTrans( componentList, useInstancing, meta ); // cube vert position Var * cubeVertPos = new Var; cubeVertPos->setName( "cubeVertPos" ); - cubeVertPos->setType( "vec3" ); + cubeVertPos->setType( "vec3" ); LangElement *cubeVertPosDecl = new DecOp( cubeVertPos ); - meta->addStatement( new GenOp( " @ = @ * @.xyz;\r\n", + meta->addStatement( new GenOp( " @ = tMul(mat3( @ ), @).xyz;\r\n", cubeVertPosDecl, cubeTrans, LangElement::find( "position" ) ) ); // cube normal Var * cubeNormal = new Var; cubeNormal->setName( "cubeNormal" ); - cubeNormal->setType( "vec3" ); + cubeNormal->setType( "vec3" ); LangElement *cubeNormDecl = new DecOp( cubeNormal ); - meta->addStatement( new GenOp( " @ = normalize( @ * normalize(@).xyz );\r\n", + meta->addStatement( new GenOp( " @ = ( tMul( (@), vec4(@, 0) ) ).xyz;\r\n", cubeNormDecl, cubeTrans, inNormal ) ); + // grab the eye position + Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); + if ( !eyePos ) + { + eyePos = new Var( "eyePosWorld", "vec3" ); + eyePos->uniform = true; + eyePos->constSortPos = cspPass; + } + + // cube position + Var * cubePos = new Var; + cubePos->setName( "cubePos" ); + cubePos->setType( "vec3" ); + LangElement *cubePosDecl = new DecOp( cubePos ); + + meta->addStatement( new GenOp( " @ = vec3( @[3][0], @[3][1], @[3][2] );\r\n", + cubePosDecl, cubeTrans, cubeTrans, cubeTrans ) ); + // eye to vert Var * eyeToVert = new Var; eyeToVert->setName( "eyeToVert" ); - eyeToVert->setType( "vec3" ); + eyeToVert->setType( "vec3" ); LangElement *e2vDecl = new DecOp( eyeToVert ); - meta->addStatement( new GenOp( " @ = @ - @;\r\n", - e2vDecl, cubeVertPos, cubeEyePos ) ); + meta->addStatement( new GenOp( " @ = @ - ( @ - @ );\r\n", + e2vDecl, cubeVertPos, eyePos, cubePos ) ); // grab connector texcoord register ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *reflectVec = connectComp->getElement( RT_TEXCOORD ); reflectVec->setName( "reflectVec" ); - reflectVec->setType( "vec3" ); + reflectVec->setStructName( "OUT" ); + reflectVec->setType( "vec3" ); reflectVec->mapsToSampler = true; meta->addStatement( new GenOp( " @ = reflect(@, @);\r\n", reflectVec, eyeToVert, cubeNormal ) ); @@ -1476,7 +1746,7 @@ void ReflectCubeFeatGLSL::processPix( Vector &componentList, fd.materialFeatures[MFT_NormalMap] ) { // grab connector texcoord register - Var *inTex = getInTexCoord( "outTexCoord", "vec2", true, componentList ); + Var *inTex = getInTexCoord( "texCoord", "vec2", true, componentList ); // create texture var Var *newMap = new Var; @@ -1494,7 +1764,7 @@ void ReflectCubeFeatGLSL::processPix( Vector &componentList, glossColor = color; - meta->addStatement( new GenOp( " @ = texture2D( @, @ );\r\n", colorDecl, newMap, inTex ) ); + meta->addStatement( new GenOp( " @ = tex2D( @, @ );\r\n", colorDecl, newMap, inTex ) ); } } else @@ -1508,12 +1778,13 @@ void ReflectCubeFeatGLSL::processPix( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *reflectVec = connectComp->getElement( RT_TEXCOORD ); reflectVec->setName( "reflectVec" ); + reflectVec->setStructName( "IN" ); reflectVec->setType( "vec3" ); reflectVec->mapsToSampler = true; // create cubemap var Var *cubeMap = new Var; - cubeMap->setType( "samplerCube" ); + cubeMap->setType( "samplerCUBE" ); cubeMap->setName( "cubeMap" ); cubeMap->uniform = true; cubeMap->sampler = true; @@ -1527,7 +1798,7 @@ void ReflectCubeFeatGLSL::processPix( Vector &componentList, if ( fd.materialFeatures[MFT_RTLighting] ) attn =(Var*)LangElement::find("d_NL_Att"); - LangElement *texCube = new GenOp( "textureCube( @, @ )", cubeMap, reflectVec ); + LangElement *texCube = new GenOp( "texCUBE( @, @ )", cubeMap, reflectVec ); LangElement *lerpVal = NULL; Material::BlendOp blendOp = Material::LerpAlpha; @@ -1583,22 +1854,27 @@ void ReflectCubeFeatGLSL::setTexData( Material::StageData &stageDat, !passData.mFeatureData.features[MFT_NormalMap] ) { GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap ); - if ( tex && - stageFeatures.features[MFT_DiffuseMap] ) + if ( tex && stageFeatures.features[MFT_DiffuseMap] ) + { + passData.mSamplerNames[ texIndex ] = "diffuseMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; + } else { tex = stageDat.getTex( MFT_NormalMap ); - if ( tex && - stageFeatures.features[ MFT_NormalMap ] ) + if ( tex && stageFeatures.features[ MFT_NormalMap ] ) + { + passData.mSamplerNames[ texIndex ] = "bumpMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; + } } } if( stageDat.getCubemap() ) { passData.mCubeMap = stageDat.getCubemap(); + passData.mSamplerNames[texIndex] = "cubeMap"; passData.mTexType[texIndex++] = Material::Cube; } else @@ -1606,6 +1882,7 @@ void ReflectCubeFeatGLSL::setTexData( Material::StageData &stageDat, if( stageFeatures.features[MFT_CubeMap] ) { // assuming here that it is a scenegraph cubemap + passData.mSamplerNames[texIndex] = "cubeMap"; passData.mTexType[texIndex++] = Material::SGCube; } } @@ -1639,18 +1916,17 @@ void RTLightingFeatGLSL::processVert( Vector &componentList, Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); if ( !eyePos ) { - eyePos = new Var( "eyePosWorld", "float3" ); + eyePos = new Var( "eyePosWorld", "vec3" ); eyePos->uniform = true; eyePos->constSortPos = cspPass; } - //TODO: should this be the same as "Find the incoming vertex normal" below? Var *inPosition = (Var*)LangElement::find( "position" ); Var *outNormal = connectComp->getElement( RT_TEXCOORD ); outNormal->setName( "wsNormal" ); outNormal->setStructName( "OUT" ); - outNormal->setType( "float3" ); + outNormal->setType( "vec3" ); outNormal->mapsToSampler = false; // Transform the normal to world space. @@ -1665,9 +1941,7 @@ void RTLightingFeatGLSL::processVert( Vector &componentList, } // Find the incoming vertex normal. - Var *inNormal = (Var*)LangElement::find( "inNormal" ); - if ( !inNormal ) - inNormal = (Var*)LangElement::find( "normal" ); + Var *inNormal = (Var*)LangElement::find( "normal" ); // Skip out on realtime lighting if we don't have a normal // or we're doing some sort of baked lighting. @@ -1675,29 +1949,25 @@ void RTLightingFeatGLSL::processVert( Vector &componentList, fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] || fd.features[MFT_VertLit] ) - return; - - // Get the transform to world space. - Var *objTrans = getObjTrans( componentList, fd.features[MFT_UseInstancing], meta ); + return; // If there isn't a normal map then we need to pass // the world space normal to the pixel shader ourselves. if ( !fd.features[MFT_NormalMap] ) { Var *outNormal = connectComp->getElement( RT_TEXCOORD ); - outNormal->setName( "outWsNormal" ); + outNormal->setName( "wsNormal" ); + outNormal->setStructName( "OUT" ); outNormal->setType( "vec3" ); outNormal->mapsToSampler = false; + + // Get the transform to world space. + Var *objTrans = getObjTrans( componentList, fd.features[MFT_UseInstancing], meta ); // Transform the normal to world space. - meta->addStatement( new GenOp( " @ = ( @ * vec4( normalize( @ ), 0.0 ) ).xyz;\r\n", outNormal, objTrans, inNormal ) ); + meta->addStatement( new GenOp( " @ = tMul( @, float4( normalize( @ ), 0.0 ) ).xyz;\r\n", outNormal, objTrans, inNormal ) ); } - // Get the input position. - Var *inPosition = (Var*)LangElement::find( "inPosition" ); - if ( !inPosition ) - inPosition = (Var*)LangElement::find( "position" ); - addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta ); output = meta; @@ -1723,41 +1993,25 @@ void RTLightingFeatGLSL::processPix( Vector &componentList, Var *wsNormal = (Var*)LangElement::find( "wsNormal" ); if ( !wsNormal ) { - Var *outWsNormal = connectComp->getElement( RT_TEXCOORD ); - outWsNormal->setName( "outWsNormal" ); - outWsNormal->setType( "vec3" ); + wsNormal = connectComp->getElement( RT_TEXCOORD ); + wsNormal->setName( "wsNormal" ); + wsNormal->setStructName( "IN" ); + wsNormal->setType( "vec3" ); - wsNormal = new Var( "wsNormal", "vec3" ); - - // If we loaded the normal its our resposibility + // If we loaded the normal its our responsibility // to normalize it... the interpolators won't. - meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", - new DecOp( wsNormal ), outWsNormal ) ); + // + // Note we cast to half here to get partial precision + // optimized code which is an acceptable loss of + // precision for normals and performs much better + // on older Geforce cards. + // + meta->addStatement( new GenOp( " @ = normalize( half3( @ ) );\r\n", wsNormal, wsNormal ) ); } - Var *wsPosition = getInWsPosition( componentList ); - - // If we have a specular feature then we need to - // get the world space view vector to pass to the - // lighting calculation. - Var *wsView = new Var( "wsView", "vec3" ); - if ( fd.features[MFT_PixSpecular] ) - { - Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); - if ( !eyePos ) - { - eyePos = new Var; - eyePos->setType( "vec3" ); - eyePos->setName( "eyePosWorld" ); - eyePos->uniform = true; - eyePos->constSortPos = cspPass; - } - - meta->addStatement( new GenOp( " @ = normalize( @ - @ );\r\n", - new DecOp( wsView ), eyePos, wsPosition ) ); - } - else - meta->addStatement( new GenOp( " @ = vec3( 0 );\r\n", new DecOp( wsView ) ) ); + // Now the wsPosition and wsView. + Var *wsPosition = getInWsPosition( componentList ); + Var *wsView = getWsView( wsPosition, meta ); // Create temporaries to hold results of lighting. Var *rtShading = new Var( "rtShading", "vec4" ); @@ -1765,18 +2019,66 @@ void RTLightingFeatGLSL::processPix( Vector &componentList, meta->addStatement( new GenOp( " @; @;\r\n", new DecOp( rtShading ), new DecOp( specular ) ) ); - // Calculate the diffuse shading and specular powers. - meta->addStatement( new GenOp( " compute4Lights( @, @, @, @, @ );\r\n", - wsView, wsPosition, wsNormal, rtShading, specular ) ); - // Look for a light mask generated from a previous // feature (this is done for BL terrain lightmaps). - Var *lightMask = (Var*)LangElement::find( "lightMask" ); - if ( lightMask ) - meta->addStatement( new GenOp( " @.rgb *= @;\r\n", rtShading, lightMask ) ); + LangElement *lightMask = LangElement::find( "lightMask" ); + if ( !lightMask ) + lightMask = new GenOp( "float4( 1, 1, 1, 1 )" ); + + // Get all the light constants. + Var *inLightPos = new Var( "inLightPos", "vec4" ); + inLightPos->uniform = true; + inLightPos->arraySize = 3; + inLightPos->constSortPos = cspPotentialPrimitive; + + Var *inLightInvRadiusSq = new Var( "inLightInvRadiusSq", "vec4" ); + inLightInvRadiusSq->uniform = true; + inLightInvRadiusSq->constSortPos = cspPotentialPrimitive; + + Var *inLightColor = new Var( "inLightColor", "vec4" ); + inLightColor->uniform = true; + inLightColor->arraySize = 4; + inLightColor->constSortPos = cspPotentialPrimitive; + + Var *inLightSpotDir = new Var( "inLightSpotDir", "vec4" ); + inLightSpotDir->uniform = true; + inLightSpotDir->arraySize = 3; + inLightSpotDir->constSortPos = cspPotentialPrimitive; + + Var *inLightSpotAngle = new Var( "inLightSpotAngle", "vec4" ); + inLightSpotAngle->uniform = true; + inLightSpotAngle->constSortPos = cspPotentialPrimitive; + + Var *lightSpotFalloff = new Var( "inLightSpotFalloff", "vec4" ); + lightSpotFalloff->uniform = true; + lightSpotFalloff->constSortPos = cspPotentialPrimitive; + + Var *specularPower = new Var( "specularPower", "float" ); + specularPower->uniform = true; + specularPower->constSortPos = cspPotentialPrimitive; + + Var *specularColor = (Var*)LangElement::find( "specularColor" ); + if ( !specularColor ) + { + specularColor = new Var( "specularColor", "vec4" ); + specularColor->uniform = true; + specularColor->constSortPos = cspPotentialPrimitive; + } + + Var *ambient = new Var( "ambient", "vec4" ); + ambient->uniform = true; + ambient->constSortPos = cspPass; + + // Calculate the diffuse shading and specular powers. + meta->addStatement( new GenOp( " compute4Lights( @, @, @, @,\r\n" + " @, @, @, @, @, @, @, @,\r\n" + " @, @ );\r\n", + wsView, wsPosition, wsNormal, lightMask, + inLightPos, inLightInvRadiusSq, inLightColor, inLightSpotDir, inLightSpotAngle, lightSpotFalloff, specularPower, specularColor, + rtShading, specular ) ); // Apply the lighting to the diffuse color. - LangElement *lighting = new GenOp( "vec4( @.rgb + ambient.rgb, 1 )", rtShading ); + LangElement *lighting = new GenOp( "float4( @.rgb + @.rgb, 1 )", rtShading, ambient ); meta->addStatement( new GenOp( " @;\r\n", assignColor( lighting, Material::Mul ) ) ); output = meta; } @@ -1844,6 +2146,7 @@ void FogFeatGLSL::processVert( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *fogAmount = connectComp->getElement( RT_TEXCOORD ); fogAmount->setName( "fogAmount" ); + fogAmount->setStructName( "OUT" ); fogAmount->setType( "float" ); fogAmount->mapsToSampler = false; @@ -1891,6 +2194,7 @@ void FogFeatGLSL::processPix( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); fogAmount = connectComp->getElement( RT_TEXCOORD ); fogAmount->setName( "fogAmount" ); + fogAmount->setStructName( "IN" ); fogAmount->setType( "float" ); } else @@ -1917,7 +2221,7 @@ void FogFeatGLSL::processPix( Vector &componentList, } // Lerp between the fog color and diffuse color. - LangElement *fogLerp = new GenOp( "mix( @.rgb, @.rgb, @ )", fogColor, color, fogAmount ); + LangElement *fogLerp = new GenOp( "lerp( @.rgb, @.rgb, @ )", fogColor, color, fogAmount ); meta->addStatement( new GenOp( " @.rgb = @;\r\n", color, fogLerp ) ); output = meta; @@ -1935,42 +2239,59 @@ ShaderFeature::Resources FogFeatGLSL::getResources( const MaterialFeatureData &f // Visibility //**************************************************************************** +VisibilityFeatGLSL::VisibilityFeatGLSL() + : mTorqueDep( "shaders/common/gl/torque.glsl" ) +{ + addDependency( &mTorqueDep ); +} + void VisibilityFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - // Pass screen space position to pixel shader to compute a full screen buffer uv - Var* ssPos = ( Var* ) LangElement::find( "screenspacePos" ); - if( !ssPos ) + MultiLine *meta = new MultiLine; + output = meta; + + if ( fd.features[ MFT_UseInstancing ] ) { - ShaderConnector* connectComp = dynamic_cast< ShaderConnector* >( componentList[C_CONNECTOR] ); - AssertFatal( connectComp, "VisibilityFeatGLSL::processVert - invalid ShaderConnector" ); + // We pass the visibility to the pixel shader via + // another output register. + // + // TODO: We should see if we can share this register + // with some other common instanced data. + // + ShaderConnector *conn = dynamic_cast( componentList[C_CONNECTOR] ); + Var *outVisibility = conn->getElement( RT_TEXCOORD ); + outVisibility->setStructName( "OUT" ); + outVisibility->setName( "visibility" ); + outVisibility->setType( "float" ); + + ShaderConnector *vertStruct = dynamic_cast( componentList[C_VERT_STRUCT] ); + Var *instVisibility = vertStruct->getElement( RT_TEXCOORD, 1 ); + instVisibility->setStructName( "IN" ); + instVisibility->setName( "inst_visibility" ); + instVisibility->setType( "float" ); + mInstancingFormat->addElement( "visibility", GFXDeclType_Float, instVisibility->constNum ); - Var* ssPos = connectComp->getElement( RT_TEXCOORD ); - ssPos->setName( "screenspacePos" ); - ssPos->setType( "vec4" ); - - Var* outPosition = ( Var* ) LangElement::find( "gl_Position" ); - AssertFatal( outPosition, "VisibilityFeatGLSL::processVert - No gl_Position" ); - - output = new GenOp( " @ = @;\r\n", ssPos, outPosition ); + meta->addStatement( new GenOp( " @ = @; // Instancing!\r\n", outVisibility, instVisibility ) ); } + + if ( fd.features[ MFT_IsTranslucent ] ) + return; + + addOutVpos( meta, componentList ); } void VisibilityFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) -{ - // Look up output color. - - Var* color = ( Var* ) LangElement::find( "col" ); - if( !color ) +{ + // Get the visibility constant. + Var *visibility = NULL; + if ( fd.features[ MFT_UseInstancing ] ) + visibility = getInTexCoord( "visibility", "float", false, componentList ); + else { - output = NULL; - return; - } + visibility = (Var*)LangElement::find( "visibility" ); - Var* visibility = (Var*)LangElement::find( "visibility" ); - - // Create visibility var. if ( !visibility ) { visibility = new Var(); @@ -1979,94 +2300,36 @@ void VisibilityFeatGLSL::processPix( Vector &componentList, visibility->uniform = true; visibility->constSortPos = cspPotentialPrimitive; } - - Var* ssPos = ( Var* ) LangElement::find( "screenspacePos" ); - if( !ssPos ) - { - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - AssertFatal( connectComp, "VisibilityFeatGLSL::processPix - invalid ShaderConnector" ); - - ssPos = connectComp->getElement( RT_TEXCOORD ); - ssPos->setName( "screenspacePos" ); - ssPos->setType( "vec4" ); } MultiLine* meta = new MultiLine; output = meta; - //Compute final visibility from incoming visibility and strength of fade effects - Var *finalVisibility = new Var( "finalVisibility", "float" ); - meta->addStatement(new GenOp( " @ = @;\r\n", new DecOp( finalVisibility ), visibility ) ); - Var *imposterFade = (Var*) LangElement::find( "imposterFade" ); - if ( imposterFade ) - meta->addStatement( new GenOp( " @ *= @;\r\n", finalVisibility, imposterFade ) ); - Var *foliageFade = (Var*) LangElement::find( "foliageFade" ); - if ( foliageFade ) - meta->addStatement( new GenOp( " @ *= @;\r\n", finalVisibility, foliageFade ) ); - - if( !fd.features[ MFT_IsTranslucent ] ) + // Translucent objects do a simple alpha fade. + if ( fd.features[ MFT_IsTranslucent ] ) { - // Create fizzMap sampler. - - Var* fizzMap = ( Var* ) LangElement::find( "fizzMap" ); - if( !fizzMap ) - { - fizzMap = new Var; - fizzMap->setType( "sampler2D" ); - fizzMap->setName( "fizzMap" ); - fizzMap->uniform = true; - fizzMap->sampler = true; - fizzMap->constNum = Var::getTexUnitNum(); + Var *color = (Var*) LangElement::find( "col" ); + meta->addStatement( new GenOp( " @.a *= @;\r\n", color, visibility ) ); + return; } - // Create fizzScale uniform. - - Var* fizzScale = new Var; - fizzScale->setType( "float2" ); - fizzScale->setName( "fizzScale" ); - fizzScale->uniform = true; - fizzScale->constSortPos = cspPass; - - meta->addStatement( new GenOp( " float fizz = tex2D( @, (@.xy / @.w) * fizzScale ).r + 0.15;\r\n", fizzMap, ssPos, ssPos ) ); - meta->addStatement( new GenOp( " if( ( fizz * @ - 0.329 ) < 0.0 )\r\n" - " discard\r\n;", finalVisibility ) ); - } - else if( color ) - { - meta->addStatement( new GenOp( " @.w *= @;\r\n", color, finalVisibility ) ); - } + // Everything else does a fizzle. + Var *vPos = getInVpos( meta, componentList ); + meta->addStatement( new GenOp( " fizzle( @, @ );\r\n", vPos, visibility ) ); } ShaderFeature::Resources VisibilityFeatGLSL::getResources( const MaterialFeatureData &fd ) { Resources res; + // TODO: Fix for instancing. + if ( !fd.features[ MFT_IsTranslucent ] ) - { - res.numTex = 1; res.numTexReg = 1; - } return res; } -void VisibilityFeatGLSL::setTexData( Material::StageData &stageDat, - const MaterialFeatureData &fd, - RenderPassData &passData, - U32 &texIndex ) -{ - if ( !fd.features[ MFT_IsTranslucent ] ) - { - GFXTexHandle texHandle( "core/art/fizz_noise.dds", &GFXDefaultStaticDiffuseProfile, "VisibilityFeatHLSL_fizz_noise" ); - stageDat.setTex( MFT_Visibility, texHandle ); - - GFXTextureObject *tex = stageDat.getTex( MFT_Visibility ); - if ( tex ) - passData.mTexSlot[ texIndex++ ].texObject = tex; - } -} - - //**************************************************************************** // AlphaTest //**************************************************************************** @@ -2100,7 +2363,7 @@ void AlphaTestGLSL::processPix( Vector &componentList, alphaTestVal->constSortPos = cspPotentialPrimitive; // Do the clip. - output = new GenOp( " if ( ( @.a - @ ) < 0 ) discard;\r\n", color, alphaTestVal ); + output = new GenOp( " clip( @.a - @ );\r\n", color, alphaTestVal ); } @@ -2123,6 +2386,7 @@ void GlowMaskGLSL::processPix( Vector &componentList, output = new GenOp( " @.rgb = 0;\r\n", color ); } + //**************************************************************************** // RenderTargetZero //**************************************************************************** @@ -2140,10 +2404,11 @@ void RenderTargetZeroGLSL::processPix( Vector &componentList, //**************************************************************************** HDROutGLSL::HDROutGLSL() -: mTorqueDep( "shaders/common/gl/torque.glsl" ) + : mTorqueDep( "shaders/common/gl/torque.glsl" ) { addDependency( &mTorqueDep ); } + void HDROutGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { @@ -2153,7 +2418,6 @@ void HDROutGLSL::processPix( Vector &componentList, output = new GenOp( " @ = hdrEncode( @ );\r\n", color, color ); } - //**************************************************************************** // FoliageFeatureGLSL //**************************************************************************** @@ -2169,42 +2433,23 @@ FoliageFeatureGLSL::FoliageFeatureGLSL() void FoliageFeatureGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { - - MultiLine *meta = new MultiLine; - // Get the input variables we need. Var *inPosition = (Var*)LangElement::find( "inPosition" ); - if ( !inPosition ) { - // inPosition = (Var*)LangElement::find( "position" ); - inPosition = new Var( "inPosition", "vec3" ); - meta->addStatement( new GenOp( " @ = @;\n", new DecOp( inPosition ), (Var*)LangElement::find( "position" ) ) ); - } + if ( !inPosition ) + inPosition = (Var*)LangElement::find( "position" ); Var *inColor = (Var*)LangElement::find( "diffuse" ); - Var *outColor = new Var( "inDiffuse", "vec4" ); - meta->addStatement( new GenOp( " @ = @;\n", new DecOp( outColor ), inColor ) ); Var *inParams = (Var*)LangElement::find( "texCoord" ); - Var *outParams = getOutTexCoord( "texCoord", - "vec2", - true, - fd.features[MFT_TexAnim], - meta, - componentList ); - + MultiLine *meta = new MultiLine; // Declare the normal and tangent variables since they do not exist // in this vert type, but we do need to set them up for others. - Var *inNormal = (Var*)LangElement::find( "inNormal" ); - if ( !inNormal ) { - inNormal = new Var( "inNormal", "vec3" ); - meta->addStatement( new GenOp( " @ = @;\n", new DecOp( inNormal ), (Var*)LangElement::find( "normal" ) ) ); - } - //Var *normal = (Var*)LangElement::find( "normal" ); - AssertFatal( inNormal, "FoliageFeatureHLSL requires vert normal!" ); + Var *normal = (Var*)LangElement::find( "normal" ); + AssertFatal( normal, "FoliageFeatureGLSL requires vert normal!" ); Var *tangent = new Var; tangent->setType( "vec3" ); @@ -2216,6 +2461,7 @@ void FoliageFeatureGLSL::processVert( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *fade = connectComp->getElement( RT_TEXCOORD ); fade->setName( "foliageFade" ); + fade->setStructName( "OUT" ); fade->setType( "float" ); // grab the eye position @@ -2227,12 +2473,11 @@ void FoliageFeatureGLSL::processVert( Vector &componentList, eyePos->constSortPos = cspPass; } - // All actual work is offloaded to this method. - meta->addStatement( new GenOp( " foliageProcessVert( @, @, @, @, @, @, @ );\r\n", inPosition, outColor, inParams, outParams, inNormal, tangent, eyePos ) ); + meta->addStatement( new GenOp( " foliageProcessVert( @, @, @, @, @, @ );\r\n", inPosition, inColor, inParams, normal, tangent, eyePos ) ); // Assign to foliageFade. InColor.a was set to the correct value inside foliageProcessVert. - meta->addStatement( new GenOp( " @ = @.a;\r\n", fade, outColor ) ); + meta->addStatement( new GenOp( " @ = @.a;\r\n", fade, inColor ) ); output = meta; } @@ -2244,7 +2489,26 @@ void FoliageFeatureGLSL::processPix( Vector &componentList, ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *fade = connectComp->getElement( RT_TEXCOORD ); fade->setName( "foliageFade" ); + fade->setStructName( "IN" ); fade->setType( "float" ); + + // Find / create visibility + Var *visibility = (Var*) LangElement::find( "visibility" ); + if ( !visibility ) + { + visibility = new Var(); + visibility->setType( "float" ); + visibility->setName( "visibility" ); + visibility->uniform = true; + visibility->constSortPos = cspPotentialPrimitive; + } + + MultiLine *meta = new MultiLine; + + // Multiply foliageFade into visibility. + meta->addStatement( new GenOp( " @ *= @;\r\n", visibility, fade ) ); + + output = meta; } void FoliageFeatureGLSL::determineFeature( Material *material, const GFXVertexFormat *vertexFormat, U32 stageNum, const FeatureType &type, const FeatureSet &features, MaterialFeatureData *outFeatureData ) @@ -2255,6 +2519,7 @@ void FoliageFeatureGLSL::determineFeature( Material *material, const GFXVertexFo outFeatureData->features.addFeature( type ); } + ShaderFeatureConstHandles* FoliageFeatureGLSL::createConstHandles( GFXShader *shader, SimObject *userObject ) { GroundCover *gcover = dynamic_cast< GroundCover* >( userObject ); @@ -2269,10 +2534,6 @@ ShaderFeatureConstHandles* FoliageFeatureGLSL::createConstHandles( GFXShader *sh } -//**************************************************************************** -// ParticleNormal -//**************************************************************************** - void ParticleNormalFeatureGLSL::processVert(Vector &componentList, const MaterialFeatureData &fd) { MultiLine *meta = new MultiLine; @@ -2292,7 +2553,7 @@ void ParticleNormalFeatureGLSL::processVert(Vector &componentL // screen because there is a discontinuity at (0, 1, 0) for gbuffer encoding. Do not // cause this value to be (0, -1, 0) or interlaced normals will be discontinuous. // [11/23/2009 Pat] - meta->addStatement(new GenOp(" @ = vec3(0.0, -0.97, 0.14);\r\n", new DecOp(normal))); + meta->addStatement(new GenOp(" @ = float3(0.0, -0.97, 0.14);\r\n", new DecOp(normal))); } Var *T = (Var*) LangElement::find( "T" ); @@ -2301,17 +2562,16 @@ void ParticleNormalFeatureGLSL::processVert(Vector &componentL T = new Var; T->setType( "vec3" ); T->setName( "T" ); - meta->addStatement(new GenOp(" @ = vec3(0.0, 0.0, -1.0);\r\n", new DecOp(T))); + meta->addStatement(new GenOp(" @ = float3(0.0, 0.0, -1.0);\r\n", new DecOp(T))); } } - //**************************************************************************** // ImposterVertFeatureGLSL //**************************************************************************** ImposterVertFeatureGLSL::ImposterVertFeatureGLSL() -: mDep( "shaders/common/gl/imposter.glsl" ) + : mDep( "shaders/common/gl/imposter.glsl" ) { addDependency( &mDep ); } @@ -2338,7 +2598,7 @@ void ImposterVertFeatureGLSL::processVert( Vector &component Var *imposterUVs = new Var; imposterUVs->setType( "vec4" ); imposterUVs->setName( "imposterUVs" ); - imposterUVs->arraySize = 64; // See imposter.hlsl + imposterUVs->arraySize = 64; // See imposter.glsl imposterUVs->uniform = true; imposterUVs->constSortPos = cspPotentialPrimitive; @@ -2362,15 +2622,15 @@ void ImposterVertFeatureGLSL::processVert( Vector &component meta->addStatement( new GenOp( " @;\r\n", new DecOp( outTexCoord ) ) ); Var *outWorldToTangent = new Var; - outWorldToTangent->setType( "mat3" ); + outWorldToTangent->setType( "float3x3" ); outWorldToTangent->setName( "worldToTangent" ); meta->addStatement( new GenOp( " @;\r\n", new DecOp( outWorldToTangent ) ) ); - //Var *outWorldToTangent = getOutWorldToTangent( componentList, meta, fd ); // Add imposterFade to the OUT structure. ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *outFade = connectComp->getElement( RT_TEXCOORD ); outFade->setName( "imposterFade" ); + outFade->setStructName( "OUT" ); outFade->setType( "float" ); // Assign OUT.imposterFade @@ -2410,7 +2670,7 @@ void ImposterVertFeatureGLSL::processVert( Vector &component // If we new viewToTangent... its the same as the // world to tangent for an imposter. Var *viewToTangent = new Var; - viewToTangent->setType( "mat3" ); + viewToTangent->setType( "float3x3" ); viewToTangent->setName( "viewToTangent" ); meta->addStatement( new GenOp( " @ = @;\r\n", new DecOp( viewToTangent ), outWorldToTangent ) ); } @@ -2418,14 +2678,13 @@ void ImposterVertFeatureGLSL::processVert( Vector &component void ImposterVertFeatureGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { - // Find / create IN.imposterFade ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *fade = connectComp->getElement( RT_TEXCOORD ); fade->setName( "imposterFade" ); + fade->setStructName( "IN" ); fade->setType( "float" ); - /* // Find / create visibility Var *visibility = (Var*) LangElement::find( "visibility" ); if ( !visibility ) @@ -2440,10 +2699,9 @@ void ImposterVertFeatureGLSL::processPix( Vector &componentLis MultiLine *meta = new MultiLine; // Multiply foliageFade into visibility. - //meta->addStatement( new GenOp( " @ *= @;\r\n", visibility, fade ) ); + meta->addStatement( new GenOp( " @ *= @;\r\n", visibility, fade ) ); output = meta; - */ } void ImposterVertFeatureGLSL::determineFeature( Material *material, @@ -2455,4 +2713,5 @@ void ImposterVertFeatureGLSL::determineFeature( Material *material, { if ( features.hasFeature( MFT_ImposterVert ) ) outFeatureData->features.addFeature( MFT_ImposterVert ); -} \ No newline at end of file +} + diff --git a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h index 14af0300f..a0e831e93 100644 --- a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h +++ b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h @@ -25,9 +25,6 @@ #ifndef _SHADERFEATURE_H_ #include "shaderGen/shaderFeature.h" #endif -#ifndef _MATERIALFEATUREDATA_H_ - #include "materials/materialFeatureData.h" -#endif struct LangElement; struct MaterialFeatureData; @@ -54,13 +51,25 @@ public: bool mapsToSampler, Vector &componentList ); + static Var* getInColor( const char *name, + const char *type, + Vector &componentList ); + + /// + static Var* addOutVpos( MultiLine *meta, + Vector &componentList ); + + /// Returns the VPOS input register for the pixel shader. + static Var* getInVpos( MultiLine *meta, + Vector &componentList ); + /// Returns the "objToTangentSpace" transform or creates one if this /// is the first feature to need it. Var* getOutObjToTangentSpace( Vector &componentList, MultiLine *meta, const MaterialFeatureData &fd ); - /// Returns the existing output "worldToTangent" transform or + /// Returns the existing output "outWorldToTangent" transform or /// creates one if this is the first feature to need it. Var* getOutWorldToTangent( Vector &componentList, MultiLine *meta, @@ -70,7 +79,7 @@ public: /// adding it to the input connector if it doesn't exist. static Var* getInWorldToTangent( Vector &componentList ); - /// Returns the existing output "viewToTangent" transform or + /// Returns the existing output "outViewToTangent" transform or /// creates one if this is the first feature to need it. Var* getOutViewToTangent( Vector &componentList, MultiLine *meta, @@ -81,17 +90,16 @@ public: static Var* getInViewToTangent( Vector &componentList ); /// Calculates the world space position in the vertex shader and - /// assigns it to the passed language element. It does not pass /// it across the connector to the pixel shader. + /// assigns it to the passed language element. It does not pass + /// it across the connector to the pixel shader. /// @see addOutWsPosition void getWsPosition( Vector &componentList, - bool useInstancing, MultiLine *meta, LangElement *wsPosition ); /// Adds the "wsPosition" to the input connector if it doesn't exist. Var* addOutWsPosition( Vector &componentList, - bool useInstancing, MultiLine *meta ); @@ -129,7 +137,6 @@ public: bool useInstancing, MultiLine *meta ); - // ShaderFeature Var* getVertTexCoord( const String &name ); LangElement* setupTexSpaceMat( Vector &componentList, Var **texSpaceMat ); @@ -151,25 +158,27 @@ public: virtual String getName() { return mName; } }; - class RenderTargetZeroGLSL : public ShaderFeatureGLSL { -protected: ShaderFeature::OutputTarget mOutputTargetMask; +protected: + ShaderFeature::OutputTarget mOutputTargetMask; String mFeatureName; public: RenderTargetZeroGLSL( const ShaderFeature::OutputTarget target ) : mOutputTargetMask( target ) { - char buffer[256]; dSprintf(buffer, sizeof(buffer), "Render Target Output = 0.0, output mask %04b", mOutputTargetMask); - mFeatureName = buffer; } + char buffer[256]; + dSprintf(buffer, sizeof(buffer), "Render Target Output = 0.0, output mask %04b", mOutputTargetMask); + mFeatureName = buffer; + } virtual String getName() { return mFeatureName; } virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ); - virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return - mOutputTargetMask; } + + virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return mOutputTargetMask; } }; @@ -190,11 +199,7 @@ public: U32 stageNum, const FeatureType &type, const FeatureSet &features, - MaterialFeatureData *outFeatureData ) - { - // This feature is always on! - outFeatureData->features.addFeature( type ); - } + MaterialFeatureData *outFeatureData ); }; @@ -297,7 +302,6 @@ public: } }; - /// Diffuse vertex color class DiffuseVertColorFeatureGLSL : public ShaderFeatureGLSL { @@ -316,7 +320,6 @@ public: } }; - /// Lightmap class LightmapFeatGLSL : public ShaderFeatureGLSL { @@ -491,7 +494,14 @@ public: /// Visibility class VisibilityFeatGLSL : public ShaderFeatureGLSL { +protected: + + ShaderIncludeDependency mTorqueDep; + public: + + VisibilityFeatGLSL(); + virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); @@ -500,11 +510,6 @@ public: virtual Resources getResources( const MaterialFeatureData &fd ); - virtual void setTexData( Material::StageData &stageDat, - const MaterialFeatureData &fd, - RenderPassData &passData, - U32 &texIndex ); - virtual Material::BlendOp getBlendOp() { return Material::None; } virtual String getName() @@ -547,10 +552,10 @@ public: } }; - /// This should be the final feature on most pixel shaders which /// encodes the color for the current HDR target format. -/// @see HDRPostFx/// @see LightManager +/// @see HDRPostFx +/// @see LightManager /// @see torque.glsl class HDROutGLSL : public ShaderFeatureGLSL { @@ -570,9 +575,9 @@ public: virtual String getName() { return "HDR Output"; } }; - /// -class FoliageFeatureGLSL : public ShaderFeatureGLSL{ +class FoliageFeatureGLSL : public ShaderFeatureGLSL +{ protected: ShaderIncludeDependency mDep; @@ -583,6 +588,7 @@ public: virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); + virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ); @@ -597,11 +603,10 @@ public: const FeatureType &type, const FeatureSet &features, MaterialFeatureData *outFeatureData ); + virtual ShaderFeatureConstHandles* createConstHandles( GFXShader *shader, SimObject *userObject ); }; - -/// class ParticleNormalFeatureGLSL : public ShaderFeatureGLSL { public: @@ -616,6 +621,9 @@ public: }; + +/// Special feature for unpacking imposter verts. +/// @see RenderImposterMgr class ImposterVertFeatureGLSL : public ShaderFeatureGLSL { protected: @@ -623,9 +631,12 @@ protected: ShaderIncludeDependency mDep; public: - ImposterVertFeatureGLSL(); + + ImposterVertFeatureGLSL(); + virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); + virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ); diff --git a/Engine/source/shaderGen/GLSL/shaderGenGLSL.cpp b/Engine/source/shaderGen/GLSL/shaderGenGLSL.cpp index ebbf2b3d8..f694b11e3 100644 --- a/Engine/source/shaderGen/GLSL/shaderGenGLSL.cpp +++ b/Engine/source/shaderGen/GLSL/shaderGenGLSL.cpp @@ -56,7 +56,9 @@ void ShaderGenPrinterGLSL::printMainComment( Stream& stream ) void ShaderGenPrinterGLSL::printVertexShaderCloser( Stream& stream ) { - const char *closer = "}\r\n"; + // We are render OpenGL upside down for use DX9 texture coords. + // Must be the last vertex feature. + const char *closer = " gl_Position.y *= -1;\r\n}\r\n"; stream.write( dStrlen(closer), closer ); } @@ -67,7 +69,7 @@ void ShaderGenPrinterGLSL::printPixelShaderOutputStruct( Stream& stream, const M void ShaderGenPrinterGLSL::printPixelShaderCloser( Stream& stream ) { - const char *closer = " gl_FragColor = col;\r\n}\r\n"; + const char *closer = " OUT_FragColor0 = col;\r\n}\r\n"; stream.write( dStrlen(closer), closer ); } @@ -124,6 +126,11 @@ ShaderComponent* ShaderGenComponentFactoryGLSL::createVertexInputConnector( cons var = vertComp->getElement( RT_TANGENT ); var->setName( "T" ); } + else if ( element.isSemantic( GFXSemantic::TANGENTW ) ) + { + var = vertComp->getElement( RT_TANGENTW ); + var->setName( "tangentW" ); + } else if ( element.isSemantic( GFXSemantic::BINORMAL ) ) { var = vertComp->getElement( RT_BINORMAL ); @@ -152,7 +159,7 @@ ShaderComponent* ShaderGenComponentFactoryGLSL::createVertexInputConnector( cons if ( !var ) continue; - var->setStructName( "" ); + var->setStructName( "IN" ); var->setType( typeToString( element.getType() ) ); } diff --git a/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp b/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp index 1318137bb..03634fa50 100644 --- a/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp +++ b/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp @@ -76,6 +76,8 @@ void _initShaderGenGLSL( ShaderGen *shaderGen ) FEATUREMGR->registerFeature( MFT_ParaboloidVertTransform, new ParaboloidVertTransformGLSL ); FEATUREMGR->registerFeature( MFT_IsSinglePassParaboloid, new NamedFeatureGLSL( "Single Pass Paraboloid" ) ); + FEATUREMGR->registerFeature( MFT_UseInstancing, new NamedFeatureGLSL( "Hardware Instancing" ) ); + FEATUREMGR->registerFeature( MFT_RenderTarget1_Zero, new RenderTargetZeroGLSL ( ShaderFeature::RenderTarget1 ) ); @@ -89,6 +91,10 @@ void _initShaderGenGLSL( ShaderGen *shaderGen ) FEATUREMGR->registerFeature( MFT_ImposterVert, new ImposterVertFeatureGLSL ); + //FEATUREMGR->registerFeature( MFT_LightbufferMRT, new NamedFeatureGLSL( "Lightbuffer MRT" ) ); + //FEATUREMGR->registerFeature( MFT_IsTranslucentZWrite, new NamedFeatureGLSL( "Translucent ZWrite" ) ); + //FEATUREMGR->registerFeature( MFT_InterlacedPrePass, new NamedFeatureGLSL( "Interlaced Pre Pass" ) ); + } MODULE_BEGIN( ShaderGenGLSL ) diff --git a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp index 01a2af3f0..586978eec 100644 --- a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp @@ -1679,7 +1679,7 @@ void ReflectCubeFeatHLSL::processVert( Vector &componentList, cubeNormal->setType( "float3" ); LangElement *cubeNormDecl = new DecOp( cubeNormal ); - meta->addStatement( new GenOp( " @ = normalize( mul(@, normalize(@)).xyz );\r\n", + meta->addStatement( new GenOp( " @ = normalize( mul(@, float4(normalize(@),0.0)).xyz );\r\n", cubeNormDecl, cubeTrans, inNormal ) ); // grab the eye position diff --git a/Engine/source/shaderGen/shaderFeature.h b/Engine/source/shaderGen/shaderFeature.h index a5f0a7d89..f18fae7f9 100644 --- a/Engine/source/shaderGen/shaderFeature.h +++ b/Engine/source/shaderGen/shaderFeature.h @@ -48,6 +48,8 @@ class ShaderFeatureConstHandles { public: + virtual ~ShaderFeatureConstHandles() { } + virtual void init( GFXShader *shader ) = 0; virtual void setConsts( SceneRenderState *state, diff --git a/Engine/source/shaderGen/shaderGen.cpp b/Engine/source/shaderGen/shaderGen.cpp index 6c7775353..5cd18f10c 100644 --- a/Engine/source/shaderGen/shaderGen.cpp +++ b/Engine/source/shaderGen/shaderGen.cpp @@ -389,7 +389,7 @@ void ShaderGen::_printDependencies(Stream &stream) { mPrinter->printLine(stream, "// Dependencies:"); - for( int i = 0; i < dependencies.size(); i++ ) + for( S32 i = 0; i < dependencies.size(); i++ ) dependencies[i]->print( stream ); mPrinter->printLine(stream, ""); diff --git a/Engine/source/sim/netConnection.cpp b/Engine/source/sim/netConnection.cpp index ee1815e82..9bfdce3ee 100644 --- a/Engine/source/sim/netConnection.cpp +++ b/Engine/source/sim/netConnection.cpp @@ -1116,7 +1116,6 @@ void NetConnection::validateSendString(const char *str) void NetConnection::packString(BitStream *stream, const char *str) { - char buf[16]; if(!*str) { stream->writeInt(NullString, 2); @@ -1130,6 +1129,7 @@ void NetConnection::packString(BitStream *stream, const char *str) } if(str[0] == '-' || (str[0] >= '0' && str[0] <= '9')) { + char buf[16]; S32 num = dAtoi(str); dSprintf(buf, sizeof(buf), "%d", num); if(!dStrcmp(buf, str)) diff --git a/Engine/source/sim/netInterface.cpp b/Engine/source/sim/netInterface.cpp index 226bd0ca3..e839d6e64 100644 --- a/Engine/source/sim/netInterface.cpp +++ b/Engine/source/sim/netInterface.cpp @@ -531,7 +531,7 @@ void NetInterface::checkTimeouts() #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) -inline U32 rotlFixed(U32 x, unsigned int y) +inline U32 rotlFixed(U32 x, U32 y) { return (x >> y) | (x << (32 - y)); } diff --git a/Engine/source/terrain/glsl/terrFeatureGLSL.cpp b/Engine/source/terrain/glsl/terrFeatureGLSL.cpp index c23d4d85d..63bc8cb60 100644 --- a/Engine/source/terrain/glsl/terrFeatureGLSL.cpp +++ b/Engine/source/terrain/glsl/terrFeatureGLSL.cpp @@ -30,22 +30,35 @@ #include "shaderGen/langElement.h" #include "shaderGen/shaderOp.h" #include "shaderGen/featureMgr.h" +#include "shaderGen/shaderGen.h" #include "core/module.h" +namespace +{ + void register_glsl_shader_features_for_terrain(GFXAdapterType type) + { + if(type != OpenGL) + return; + + FEATUREMGR->registerFeature( MFT_TerrainBaseMap, new TerrainBaseMapFeatGLSL ); + FEATUREMGR->registerFeature( MFT_TerrainParallaxMap, new NamedFeatureGLSL( "Terrain Parallax Texture" ) ); + FEATUREMGR->registerFeature( MFT_TerrainDetailMap, new TerrainDetailMapFeatGLSL ); + FEATUREMGR->registerFeature( MFT_TerrainNormalMap, new TerrainNormalMapFeatGLSL ); + FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new TerrainMacroMapFeatGLSL ); + FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatGLSL ); + FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureGLSL( "Terrain Side Projection" ) ); + FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatGLSL ); + } + +}; MODULE_BEGIN( TerrainFeatGLSL ) - MODULE_INIT_AFTER( ShaderGenFeatureMgr ) + MODULE_INIT_AFTER( ShaderGen ) MODULE_INIT - { - FEATUREMGR->registerFeature( MFT_TerrainBaseMap, new TerrainBaseMapFeatGLSL ); - FEATUREMGR->registerFeature( MFT_TerrainParallaxMap, new TerrainParallaxMapFeatGLSL ); - FEATUREMGR->registerFeature( MFT_TerrainDetailMap, new TerrainDetailMapFeatGLSL ); - FEATUREMGR->registerFeature( MFT_TerrainNormalMap, new TerrainNormalMapFeatGLSL ); - FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatGLSL ); - FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureGLSL( "Terrain Side Projection" ) ); - FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatGLSL ); + { + SHADERGEN->getFeatureInitSignal().notify(®ister_glsl_shader_features_for_terrain); } MODULE_END; @@ -68,7 +81,7 @@ Var* TerrainFeatGLSL::_getUniformVar( const char *name, const char *type, Consta Var* TerrainFeatGLSL::_getInDetailCoord( Vector &componentList ) { - String name( String::ToString( "outDetCoord%d", getProcessIndex() ) ); + String name( String::ToString( "detCoord%d", getProcessIndex() ) ); Var *inDet = (Var*)LangElement::find( name ); if ( !inDet ) @@ -77,6 +90,7 @@ Var* TerrainFeatGLSL::_getInDetailCoord( Vector &componentList inDet = connectComp->getElement( RT_TEXCOORD ); inDet->setName( name ); + inDet->setStructName( "IN" ); inDet->setType( "vec4" ); inDet->mapsToSampler = true; } @@ -84,6 +98,25 @@ Var* TerrainFeatGLSL::_getInDetailCoord( Vector &componentList return inDet; } +Var* TerrainFeatGLSL::_getInMacroCoord( Vector &componentList ) +{ + String name( String::ToString( "macroCoord%d", getProcessIndex() ) ); + Var *inDet = (Var*)LangElement::find( name ); + + if ( !inDet ) + { + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + + inDet = connectComp->getElement( RT_TEXCOORD ); + inDet->setName( name ); + inDet->setStructName( "IN" ); + inDet->setType( "vec4" ); + inDet->mapsToSampler = true; + } + + return inDet; +} + Var* TerrainFeatGLSL::_getNormalMapTex() { String name( String::ToString( "normalMap%d", getProcessIndex() ) ); @@ -119,6 +152,24 @@ Var* TerrainFeatGLSL::_getDetailIdStrengthParallax() return detailInfo; } +Var* TerrainFeatGLSL::_getMacroIdStrengthParallax() +{ + String name( String::ToString( "macroIdStrengthParallax%d", getProcessIndex() ) ); + + Var *detailInfo = (Var*)LangElement::find( name ); + if ( !detailInfo ) + { + detailInfo = new Var; + detailInfo->setType( "vec3" ); + detailInfo->setName( name ); + detailInfo->uniform = true; + detailInfo->constSortPos = cspPotentialPrimitive; + } + + return detailInfo; +} + + void TerrainBaseMapFeatGLSL::processVert( Vector &componentList, const MaterialFeatureData &fd ) { @@ -146,7 +197,7 @@ void TerrainBaseMapFeatGLSL::processVert( Vector &componentLis // So instead i fixed this by flipping the base and detail // coord y scale to compensate when rendering. // - meta->addStatement( new GenOp( " @ = @.xyz * vec3( @, @, -@ );\r\n", + meta->addStatement( new GenOp( " @ = @.xyz * float3( @, @, -@ );\r\n", new DecOp( inTex ), inPos, oneOverTerrainSize, oneOverTerrainSize, oneOverTerrainSize ) ); } @@ -155,6 +206,7 @@ void TerrainBaseMapFeatGLSL::processVert( Vector &componentLis // Pass the texture coord to the pixel shader. Var *outTex = connectComp->getElement( RT_TEXCOORD ); outTex->setName( "outTexCoord" ); + outTex->setStructName( "OUT" ); outTex->setType( "vec3" ); outTex->mapsToSampler = true; meta->addStatement( new GenOp( " @.xy = @.xy;\r\n", outTex, inTex ) ); @@ -166,7 +218,7 @@ void TerrainBaseMapFeatGLSL::processVert( Vector &componentLis { Var *inNormal = (Var*)LangElement::find( "normal" ); meta->addStatement( - new GenOp( " @.z = pow( abs( dot( normalize( vec3( @.x, @.y, 0.0 ) ), vec3( 0, 1, 0 ) ) ), 10.0 );\r\n", + new GenOp( " @.z = pow( abs( dot( normalize( float3( @.x, @.y, 0 ) ), float3( 0, 1, 0 ) ) ), 10.0 );\r\n", outTex, inNormal, inNormal ) ); } else @@ -182,7 +234,7 @@ void TerrainBaseMapFeatGLSL::processVert( Vector &componentLis Var *inTangentZ = getVertTexCoord( "tcTangentZ" ); Var *inTanget = new Var( "T", "vec3" ); Var *squareSize = _getUniformVar( "squareSize", "float", cspPass ); - meta->addStatement( new GenOp( " @ = normalize( vec3( @, 0.0, @ ) );\r\n", + meta->addStatement( new GenOp( " @ = normalize( float3( @, 0, @ ) );\r\n", new DecOp( inTanget ), squareSize, inTangentZ ) ); } @@ -190,7 +242,7 @@ void TerrainBaseMapFeatGLSL::processPix( Vector &componentLis const MaterialFeatureData &fd ) { // grab connector texcoord register - Var *texCoord = getInTexCoord( "outTexCoord", "vec3", true, componentList ); + Var *texCoord = getInTexCoord( "texCoord", "vec3", true, componentList ); // We do nothing more if this is a prepass. if ( fd.features.hasFeature( MFT_PrePassConditioner ) ) @@ -209,7 +261,7 @@ void TerrainBaseMapFeatGLSL::processPix( Vector &componentLis Var *baseColor = new Var; baseColor->setType( "vec4" ); baseColor->setName( "baseColor" ); - meta->addStatement( new GenOp( " @ = texture2D( @, @.xy );\r\n", new DecOp( baseColor ), diffuseMap, texCoord ) ); + meta->addStatement( new GenOp( " @ = tex2D( @, @.xy );\r\n", new DecOp( baseColor ), diffuseMap, texCoord ) ); meta->addStatement( new GenOp( " @;\r\n", assignColor( baseColor, Material::Mul ) ) ); output = meta; @@ -228,8 +280,11 @@ ShaderFeature::Resources TerrainBaseMapFeatGLSL::getResources( const MaterialFea } TerrainDetailMapFeatGLSL::TerrainDetailMapFeatGLSL() - : mTerrainDep( "shaders/common/terrain/terrain.glsl" ) + : mTorqueDep( "shaders/common/gl/torque.glsl" ), + mTerrainDep( "shaders/common/terrain/terrain.glsl" ) + { + addDependency( &mTorqueDep ); addDependency( &mTerrainDep ); } @@ -238,13 +293,6 @@ void TerrainDetailMapFeatGLSL::processVert( Vector &component { const U32 detailIndex = getProcessIndex(); - - // If this is a prepass and we don't have a - // matching normal map... we have nothing to do. - if ( fd.features.hasFeature( MFT_PrePassConditioner ) && - !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) ) - return; - // Grab incoming texture coords... the base map feature // made sure this was created. Var *inTex = (Var*)LangElement::find( "texCoord" ); @@ -260,6 +308,26 @@ void TerrainDetailMapFeatGLSL::processVert( Vector &component MultiLine *meta = new MultiLine; + // If we have parallax mapping then make sure we've sent + // the negative view vector to the pixel shader. + if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) && + !LangElement::find( "outNegViewTS" ) ) + { + // Get the object to tangent transform which + // will consume 3 output registers. + Var *objToTangentSpace = getOutObjToTangentSpace( componentList, meta, fd ); + + // Now use a single output register to send the negative + // view vector in tangent space to the pixel shader. + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + Var *outNegViewTS = connectComp->getElement( RT_TEXCOORD ); + outNegViewTS->setName( "outNegViewTS" ); + outNegViewTS->setStructName( "OUT" ); + outNegViewTS->setType( "vec3" ); + meta->addStatement( new GenOp( " @ = tMul( @, float3( @ - @.xyz ) );\r\n", + outNegViewTS, objToTangentSpace, eyePos, inPos ) ); + } + // Get the distance from the eye to this vertex. Var *dist = (Var*)LangElement::find( "dist" ); if ( !dist ) @@ -275,7 +343,8 @@ void TerrainDetailMapFeatGLSL::processVert( Vector &component // grab connector texcoord register ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); Var *outTex = connectComp->getElement( RT_TEXCOORD ); - outTex->setName( String::ToString( "outDetCoord%d", detailIndex ) ); + outTex->setName( String::ToString( "detCoord%d", detailIndex ) ); + outTex->setStructName( "OUT" ); outTex->setType( "vec4" ); outTex->mapsToSampler = true; @@ -293,7 +362,7 @@ void TerrainDetailMapFeatGLSL::processVert( Vector &component // its scale is flipped to correct for the non negative y // in texCoord. // - // See TerrainBaseMapFeatHLSL::processVert(). + // See TerrainBaseMapFeatGLSL::processVert(). // meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) ); @@ -308,17 +377,30 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component const MaterialFeatureData &fd ) { const U32 detailIndex = getProcessIndex(); + Var *inTex = getVertTexCoord( "texCoord" ); - // If this is a prepass and we don't have a - // matching normal map... we have nothing to do. - if ( fd.features.hasFeature( MFT_PrePassConditioner ) && - !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) ) - return; - - Var *inTex = getVertTexCoord( "outTexCoord" ); - MultiLine *meta = new MultiLine; + // We need the negative tangent space view vector + // as in parallax mapping we step towards the camera. + Var *negViewTS = (Var*)LangElement::find( "negViewTS" ); + if ( !negViewTS && + fd.features.hasFeature( MFT_TerrainParallaxMap ) ) + { + Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" ); + if ( !inNegViewTS ) + { + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + inNegViewTS = connectComp->getElement( RT_TEXCOORD ); + inNegViewTS->setName( "outNegViewTS" ); + inNegViewTS->setStructName( "IN" ); + inNegViewTS->setType( "vec3" ); + } + + negViewTS = new Var( "negViewTS", "vec3" ); + meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) ); + } + // Get the layer samples. Var *layerSample = (Var*)LangElement::find( "layerSample" ); if ( !layerSample ) @@ -336,7 +418,7 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component layerTex->constNum = Var::getTexUnitNum(); // Read the layer texture to get the samples. - meta->addStatement( new GenOp( " @ = round( texture2D( @, @.xy ) * 255.0f );\r\n", + meta->addStatement( new GenOp( " @ = round( tex2D( @, @.xy ) * 255.0f );\r\n", new DecOp( layerSample ), layerTex, inTex ) ); } @@ -372,17 +454,43 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component blendTotal = new Var; blendTotal->setName( "blendTotal" ); blendTotal->setType( "float" ); - meta->addStatement( new GenOp( " @ = 0.0;\r\n", new DecOp( blendTotal ) ) ); + meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) ); } // Add to the blend total. - meta->addStatement( new GenOp( " @ += @;\r\n", blendTotal, detailBlend ) ); - //meta->addStatement( new GenOp( " @ += @ * @.y * @.w;\r\n", - //blendTotal, detailBlend, detailInfo, inDet ) ); + meta->addStatement( new GenOp( " @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend ) ); - // Nothing more to do for a detail texture in prepass. + // If we had a parallax feature... then factor in the parallax + // amount so that it fades out with the layer blending. + if ( fd.features.hasFeature( MFT_TerrainParallaxMap, detailIndex ) ) + { + // Get the rest of our inputs. + Var *normalMap = _getNormalMapTex(); + + // Call the library function to do the rest. + meta->addStatement( new GenOp( " @.xy += parallaxOffset( @, @.xy, @, @.z * @ );\r\n", + inDet, normalMap, inDet, negViewTS, detailInfo, detailBlend ) ); + } + + // If this is a prepass then we skip color. if ( fd.features.hasFeature( MFT_PrePassConditioner ) ) { + // Check to see if we have a gbuffer normal. + Var *gbNormal = (Var*)LangElement::find( "gbNormal" ); + + // If we have a gbuffer normal and we don't have a + // normal map feature then we need to lerp in a + // default normal else the normals below this layer + // will show thru. + if ( gbNormal && + !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) ) + { + Var *viewToTangent = getInViewToTangent( componentList ); + + meta->addStatement( new GenOp( " @ = lerp( @, tGetMatrix3Row(@, 2), min( @, @.w ) );\r\n", + gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) ); + } + output = meta; return; } @@ -407,6 +515,7 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component // If we're using SM 3.0 then take advantage of // dynamic branching to skip layers per-pixel. + if ( GFX->getPixelShaderVersion() >= 3.0f ) meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) ); @@ -421,12 +530,12 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component // if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) ) { - meta->addStatement( new GenOp( " @ = ( mix( texture2D( @, @.yz ), texture2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n", + meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n", detailColor, detailMap, inDet, detailMap, inDet, inTex ) ); } else { - meta->addStatement( new GenOp( " @ = ( texture2D( @, @.xy ) * 2.0 ) - 1.0;\r\n", + meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n", detailColor, detailMap, inDet ) ); } @@ -436,7 +545,7 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component Var *baseColor = (Var*)LangElement::find( "baseColor" ); Var *outColor = (Var*)LangElement::find( "col" ); - meta->addStatement( new GenOp( " @ = mix( @, @ + @, @ );\r\n", + meta->addStatement( new GenOp( " @ = lerp( @, @ + @, @ );\r\n", outColor, outColor, baseColor, detailColor, detailBlend ) ); meta->addStatement( new GenOp( " }\r\n" ) ); @@ -448,28 +557,293 @@ ShaderFeature::Resources TerrainDetailMapFeatGLSL::getResources( const MaterialF { Resources res; + if ( getProcessIndex() == 0 ) + { + // If this is the first detail pass then we + // samples from the layer tex. + res.numTex += 1; + + // If this material also does parallax then it + // will generate the negative view vector and the + // worldToTanget transform. + if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) ) + res.numTexReg += 4; + } + + // If this isn't the prepass then we sample + // from the detail texture for diffuse coloring. + if ( !fd.features.hasFeature( MFT_PrePassConditioner ) ) + res.numTex += 1; + + // If we have parallax for this layer then we'll also + // be sampling the normal map for the parallax heightmap. + if ( fd.features.hasFeature( MFT_TerrainParallaxMap, getProcessIndex() ) ) + res.numTex += 1; + + // Finally we always send the detail texture + // coord to the pixel shader. + res.numTexReg += 1; + + return res; +} + + +TerrainMacroMapFeatGLSL::TerrainMacroMapFeatGLSL() + : mTorqueDep( "shaders/common/gl/torque.glsl" ), + mTerrainDep( "shaders/common/terrain/terrain.glsl" ) + +{ + addDependency( &mTorqueDep ); + addDependency( &mTerrainDep ); +} + + +void TerrainMacroMapFeatGLSL::processVert( Vector &componentList, + const MaterialFeatureData &fd ) +{ + const U32 detailIndex = getProcessIndex(); + + // Grab incoming texture coords... the base map feature + // made sure this was created. + Var *inTex = (Var*)LangElement::find( "texCoord" ); + AssertFatal( inTex, "The texture coord is missing!" ); + + // Grab the input position. + Var *inPos = (Var*)LangElement::find( "inPosition" ); + if ( !inPos ) + inPos = (Var*)LangElement::find( "position" ); + + // Get the object space eye position. + Var *eyePos = _getUniformVar( "eyePos", "vec3", cspPotentialPrimitive ); + + MultiLine *meta = new MultiLine; + + // Get the distance from the eye to this vertex. + Var *dist = (Var*)LangElement::find( "macroDist" ); + if ( !dist ) + { + dist = new Var; + dist->setType( "float" ); + dist->setName( "macroDist" ); + + meta->addStatement( new GenOp( " @ = distance( @.xyz, @ );\r\n", + new DecOp( dist ), inPos, eyePos ) ); + } + + // grab connector texcoord register + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + Var *outTex = connectComp->getElement( RT_TEXCOORD ); + outTex->setName( String::ToString( "macroCoord%d", detailIndex ) ); + outTex->setStructName( "OUT" ); + outTex->setType( "vec4" ); + outTex->mapsToSampler = true; + + // Get the detail scale and fade info. + Var *detScaleAndFade = new Var; + detScaleAndFade->setType( "vec4" ); + detScaleAndFade->setName( String::ToString( "macroScaleAndFade%d", detailIndex ) ); + detScaleAndFade->uniform = true; + detScaleAndFade->constSortPos = cspPotentialPrimitive; + + // Setup the detail coord. + meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) ); + + // And sneak the detail fade thru the w detailCoord. + meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n", + outTex, detScaleAndFade, dist, detScaleAndFade ) ); + + output = meta; +} + + +void TerrainMacroMapFeatGLSL::processPix( Vector &componentList, + const MaterialFeatureData &fd ) +{ + const U32 detailIndex = getProcessIndex(); + Var *inTex = getVertTexCoord( "texCoord" ); + + MultiLine *meta = new MultiLine; + + // We need the negative tangent space view vector + // as in parallax mapping we step towards the camera. + Var *negViewTS = (Var*)LangElement::find( "negViewTS" ); + if ( !negViewTS && + fd.features.hasFeature( MFT_TerrainParallaxMap ) ) + { + Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" ); + if ( !inNegViewTS ) + { + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + inNegViewTS = connectComp->getElement( RT_TEXCOORD ); + inNegViewTS->setName( "outNegViewTS" ); + inNegViewTS->setStructName( "IN" ); + inNegViewTS->setType( "vec3" ); + } + + negViewTS = new Var( "negViewTS", "vec3" ); + meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) ); + } + + // Get the layer samples. + Var *layerSample = (Var*)LangElement::find( "layerSample" ); + if ( !layerSample ) + { + layerSample = new Var; + layerSample->setType( "vec4" ); + layerSample->setName( "layerSample" ); + + // Get the layer texture var + Var *layerTex = new Var; + layerTex->setType( "sampler2D" ); + layerTex->setName( "macrolayerTex" ); + layerTex->uniform = true; + layerTex->sampler = true; + layerTex->constNum = Var::getTexUnitNum(); + + // Read the layer texture to get the samples. + meta->addStatement( new GenOp( " @ = round( tex2D( @, @.xy ) * 255.0f );\r\n", + new DecOp( layerSample ), layerTex, inTex ) ); + } + + Var *layerSize = (Var*)LangElement::find( "layerSize" ); + if ( !layerSize ) + { + layerSize = new Var; + layerSize->setType( "float" ); + layerSize->setName( "layerSize" ); + layerSize->uniform = true; + layerSize->constSortPos = cspPass; + } + + // Grab the incoming detail coord. + Var *inDet = _getInMacroCoord( componentList ); + + // Get the detail id. + Var *detailInfo = _getMacroIdStrengthParallax(); + + // Create the detail blend var. + Var *detailBlend = new Var; + detailBlend->setType( "float" ); + detailBlend->setName( String::ToString( "macroBlend%d", detailIndex ) ); + + // Calculate the blend for this detail texture. + meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n", + new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) ); + + // Get a var and accumulate the blend amount. + Var *blendTotal = (Var*)LangElement::find( "blendTotal" ); + if ( !blendTotal ) + { + blendTotal = new Var; + //blendTotal->setName( "blendTotal" ); + blendTotal->setName( "blendTotal" ); + blendTotal->setType( "float" ); + meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) ); + } + + // Add to the blend total. + meta->addStatement( new GenOp( " @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend ) ); + + // If this is a prepass then we skip color. if ( fd.features.hasFeature( MFT_PrePassConditioner ) ) { - // If this is a prepass and we don't have a - // matching normal map... we use no resources. - if ( !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() ) ) - return res; + // Check to see if we have a gbuffer normal. + Var *gbNormal = (Var*)LangElement::find( "gbNormal" ); - // If this is the first matching normal map then - // it also samples from the layer tex. - if ( !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() - 1 ) ) - res.numTex += 1; + // If we have a gbuffer normal and we don't have a + // normal map feature then we need to lerp in a + // default normal else the normals below this layer + // will show thru. + if ( gbNormal && + !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) ) + { + Var *viewToTangent = getInViewToTangent( componentList ); + + meta->addStatement( new GenOp( " @ = lerp( @, tGetMatrix3Row(@, 2), min( @, @.w ) );\r\n", + gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) ); + } + + output = meta; + return; + } + + Var *detailColor = (Var*)LangElement::find( "macroColor" ); + if ( !detailColor ) + { + detailColor = new Var; + detailColor->setType( "vec4" ); + detailColor->setName( "macroColor" ); + meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) ); + } + + // Get the detail texture. + Var *detailMap = new Var; + detailMap->setType( "sampler2D" ); + detailMap->setName( String::ToString( "macroMap%d", detailIndex ) ); + detailMap->uniform = true; + detailMap->sampler = true; + detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here + + // If we're using SM 3.0 then take advantage of + // dynamic branching to skip layers per-pixel. + if ( GFX->getPixelShaderVersion() >= 3.0f ) + meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) ); + + meta->addStatement( new GenOp( " {\r\n" ) ); + + // Note that we're doing the standard greyscale detail + // map technique here which can darken and lighten the + // diffuse texture. + // + // We take two color samples and lerp between them for + // side projection layers... else a single sample. + // + if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) ) + { + meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n", + detailColor, detailMap, inDet, detailMap, inDet, inTex ) ); } else { - // If this is the first detail pass then it - // also samples from the layer tex. - if ( !fd.features.hasFeature( MFT_TerrainDetailMap, getProcessIndex() - 1 ) ) - res.numTex += 1; - - res.numTex += 1; + meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n", + detailColor, detailMap, inDet ) ); } + meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n", + detailColor, detailInfo, inDet ) ); + + Var *baseColor = (Var*)LangElement::find( "baseColor" ); + Var *outColor = (Var*)LangElement::find( "col" ); + + meta->addStatement( new GenOp( " @ = lerp( @, @ + @, @ );\r\n", + outColor, outColor, outColor, detailColor, detailBlend ) ); + //outColor, outColor, baseColor, detailColor, detailBlend ) ); + + meta->addStatement( new GenOp( " }\r\n" ) ); + + output = meta; +} + + + +ShaderFeature::Resources TerrainMacroMapFeatGLSL::getResources( const MaterialFeatureData &fd ) +{ + Resources res; + + if ( getProcessIndex() == 0 ) + { + // If this is the first detail pass then we + // samples from the layer tex. + res.numTex += 1; + } + + // If this isn't the prepass then we sample + // from the detail texture for diffuse coloring. + if ( !fd.features.hasFeature( MFT_PrePassConditioner ) ) + res.numTex += 1; + + // Finally we always send the detail texture + // coord to the pixel shader. res.numTexReg += 1; return res; @@ -510,7 +884,7 @@ void TerrainNormalMapFeatGLSL::processPix( Vector &component gbNormal = new Var; gbNormal->setName( "gbNormal" ); gbNormal->setType( "vec3" ); - meta->addStatement( new GenOp( " @ = @[2];\r\n", new DecOp( gbNormal ), viewToTangent ) ); + meta->addStatement( new GenOp( " @ = tGetMatrix3Row(@, 2);\r\n", new DecOp( gbNormal ), viewToTangent ) ); } const U32 normalIndex = getProcessIndex(); @@ -520,7 +894,6 @@ void TerrainNormalMapFeatGLSL::processPix( Vector &component // If we're using SM 3.0 then take advantage of // dynamic branching to skip layers per-pixel. - if ( GFX->getPixelShaderVersion() >= 3.0f ) meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) ); @@ -531,7 +904,7 @@ void TerrainNormalMapFeatGLSL::processPix( Vector &component /// Get the texture coord. Var *inDet = _getInDetailCoord( componentList ); - Var *inTex = getVertTexCoord( "outTexCoord" ); + Var *inTex = getVertTexCoord( "texCoord" ); // Sample the normal map. // @@ -540,11 +913,11 @@ void TerrainNormalMapFeatGLSL::processPix( Vector &component LangElement *texOp; if ( fd.features.hasFeature( MFT_TerrainSideProject, normalIndex ) ) { - texOp = new GenOp( "mix( texture2D( @, @.yz ), texture2D( @, @.xz ), @.z )", + texOp = new GenOp( "lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )", normalMap, inDet, normalMap, inDet, inTex ); } else - texOp = new GenOp( "texture2D(@, @.xy)", normalMap, inDet ); + texOp = new GenOp( "tex2D(@, @.xy)", normalMap, inDet ); // create bump normal Var *bumpNorm = new Var; @@ -556,7 +929,7 @@ void TerrainNormalMapFeatGLSL::processPix( Vector &component // Normalize is done later... // Note: The reverse mul order is intentional. Affine matrix. - meta->addStatement( new GenOp( " @ = mix( @, @.xyz * @, min( @, @.w ) );\r\n", + meta->addStatement( new GenOp( " @ = lerp( @, tMul( @.xyz, @ ), min( @, @.w ) );\r\n", gbNormal, gbNormal, bumpNorm, viewToTangent, detailBlend, inDet ) ); // End the conditional block. @@ -578,9 +951,11 @@ ShaderFeature::Resources TerrainNormalMapFeatGLSL::getResources( const MaterialF // We only need to process normals during the prepass. if ( fd.features.hasFeature( MFT_PrePassConditioner ) ) { - // If this is the first normal map then it - // will generate the worldToTanget transform. - if ( !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() - 1 ) ) + // If this is the first normal map and there + // are no parallax features then we will + // generate the worldToTanget transform. + if ( !fd.features.hasFeature( MFT_TerrainParallaxMap ) && + ( getProcessIndex() == 0 || !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() - 1 ) ) ) res.numTexReg = 3; res.numTex = 1; @@ -589,100 +964,11 @@ ShaderFeature::Resources TerrainNormalMapFeatGLSL::getResources( const MaterialF return res; } -TerrainParallaxMapFeatGLSL::TerrainParallaxMapFeatGLSL() - : mIncludeDep( "shaders/common/gl/torque.glsl" ) -{ - addDependency( &mIncludeDep ); -} - -void TerrainParallaxMapFeatGLSL::processVert( Vector &componentList, - const MaterialFeatureData &fd ) -{ - if ( LangElement::find( "outNegViewTS" ) ) - return; - - MultiLine *meta = new MultiLine; - - // Grab the input position. - Var *inPos = (Var*)LangElement::find( "inPosition" ); - if ( !inPos ) - inPos = (Var*)LangElement::find( "position" ); - - // Get the object space eye position and the - // object to tangent transform. - Var *eyePos = _getUniformVar( "eyePos", "vec3" , cspPotentialPrimitive ); - Var *objToTangentSpace = getOutObjToTangentSpace( componentList, meta,fd ); - - // Now send the negative view vector in tangent space to the pixel shader. - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - Var *outNegViewTS = connectComp->getElement( RT_TEXCOORD ); - outNegViewTS->setName( "outNegViewTS" ); - outNegViewTS->setType( "vec3" ); - meta->addStatement( new GenOp( " @ = @ * vec3( @ - @.xyz );\r\n", - outNegViewTS, objToTangentSpace, eyePos, inPos ) ); - - output = meta; -} - -void TerrainParallaxMapFeatGLSL::processPix( Vector &componentList, - const MaterialFeatureData &fd ) -{ - MultiLine *meta = new MultiLine; - - ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); - - // We need the negative tangent space view vector - // as in parallax mapping we step towards the camera. - Var *negViewTS = (Var*)LangElement::find( "negViewTS" ); - if ( !negViewTS ) - { - Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" ); - if ( !inNegViewTS ) - { - inNegViewTS = connectComp->getElement( RT_TEXCOORD ); - inNegViewTS->setName( "outNegViewTS" ); - inNegViewTS->setType( "vec3" ); - } - - negViewTS = new Var( "negViewTS", "vec3" ); - meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) ); - } - - // Get the rest of our inputs. - Var *detailInfo = _getDetailIdStrengthParallax(); - Var *normalMap = _getNormalMapTex(); - Var *texCoord = _getInDetailCoord( componentList ); - - // Call the library function to do the rest. - meta->addStatement( new GenOp( " @.xy += parallaxOffset( @, @.xy, @, @.z );\r\n", - texCoord, normalMap, texCoord, negViewTS, detailInfo ) ); - - output = meta; -} - -ShaderFeature::Resources TerrainParallaxMapFeatGLSL::getResources( const MaterialFeatureData &fd ) -{ - Resources res; - - // If this is the first parallax feature then - // it will generate the tangetEye vector and - // the worldToTanget transform. - if ( getProcessIndex() == 0 || !fd.features.hasFeature( MFT_TerrainParallaxMap, getProcessIndex() - 1 ) ) - res.numTexReg = 4; - - // If this isn't the prepass then we will - // be adding a normal map. - if ( !fd.features.hasFeature( MFT_PrePassConditioner ) ) - res.numTex = 1; - - return res; -} - void TerrainLightMapFeatGLSL::processPix( Vector &componentList, const MaterialFeatureData &fd ) { // grab connector texcoord register - Var *inTex = (Var*)LangElement::find( "outTexCoord" ); + Var *inTex = (Var*)LangElement::find( "texCoord" ); if ( !inTex ) return; @@ -694,13 +980,23 @@ void TerrainLightMapFeatGLSL::processPix( Vector &componentLis lightMap->sampler = true; lightMap->constNum = Var::getTexUnitNum(); - // Create a 'lightMask' value which is read by - // RTLighting to mask out the directional lighting. - Var *lightMask = new Var; - lightMask->setType( "vec3" ); - lightMask->setName( "lightMask" ); + MultiLine *meta = new MultiLine; - output = new GenOp( " @ = texture2D( @, @.xy ).rgb;\r\n", new DecOp( lightMask ), lightMap, inTex ); + // Find or create the lightMask value which is read by + // RTLighting to mask out the lights. + // + // The first light is always the sunlight so we apply + // the shadow mask to only the first channel. + // + Var *lightMask = (Var*)LangElement::find( "lightMask" ); + if ( !lightMask ) + { + lightMask = new Var( "lightMask", "vec4" ); + meta->addStatement( new GenOp( " @ = vec4(1);\r\n", new DecOp( lightMask ) ) ); + } + + meta->addStatement( new GenOp( " @[0] = tex2D( @, @.xy ).r;\r\n", lightMask, lightMap, inTex ) ); + output = meta; } ShaderFeature::Resources TerrainLightMapFeatGLSL::getResources( const MaterialFeatureData &fd ) @@ -721,7 +1017,7 @@ void TerrainAdditiveFeatGLSL::processPix( Vector &componentLis MultiLine *meta = new MultiLine; - meta->addStatement( new GenOp( " if ( @ - 0.0001 < 0.0 ) discard;\r\n", blendTotal ) ); + meta->addStatement( new GenOp( " clip( @ - 0.0001 );\r\n", blendTotal ) ); meta->addStatement( new GenOp( " @.a = @;\r\n", color, blendTotal ) ); output = meta; diff --git a/Engine/source/terrain/glsl/terrFeatureGLSL.h b/Engine/source/terrain/glsl/terrFeatureGLSL.h index c181ef493..790a8a342 100644 --- a/Engine/source/terrain/glsl/terrFeatureGLSL.h +++ b/Engine/source/terrain/glsl/terrFeatureGLSL.h @@ -30,6 +30,7 @@ #include "shaderGen/langElement.h" #endif + /// A shared base class for terrain features which /// includes some helper functions. class TerrainFeatGLSL : public ShaderFeatureGLSL @@ -38,14 +39,18 @@ protected: Var* _getInDetailCoord(Vector &componentList ); + Var* _getInMacroCoord(Vector &componentList ); + Var* _getNormalMapTex(); static Var* _getUniformVar( const char *name, const char *type, ConstantSortPosition csp ); Var* _getDetailIdStrengthParallax(); + Var* _getMacroIdStrengthParallax(); }; + class TerrainBaseMapFeatGLSL : public TerrainFeatGLSL { public: @@ -61,10 +66,12 @@ public: virtual String getName() { return "Terrain Base Texture"; } }; + class TerrainDetailMapFeatGLSL : public TerrainFeatGLSL { protected: + ShaderIncludeDependency mTorqueDep; ShaderIncludeDependency mTerrainDep; public: @@ -83,10 +90,17 @@ public: }; -class TerrainNormalMapFeatGLSL : public TerrainFeatGLSL +class TerrainMacroMapFeatGLSL : public TerrainFeatGLSL { +protected: + + ShaderIncludeDependency mTorqueDep; + ShaderIncludeDependency mTerrainDep; + public: + TerrainMacroMapFeatGLSL(); + virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); @@ -95,19 +109,14 @@ public: virtual Resources getResources( const MaterialFeatureData &fd ); - virtual String getName() { return "Terrain Normal Texture"; } + virtual String getName() { return "Terrain Macro Texture"; } }; -class TerrainParallaxMapFeatGLSL : public TerrainFeatGLSL + +class TerrainNormalMapFeatGLSL : public TerrainFeatGLSL { -protected: - - ShaderIncludeDependency mIncludeDep; - public: - TerrainParallaxMapFeatGLSL(); - virtual void processVert( Vector &componentList, const MaterialFeatureData &fd ); @@ -116,7 +125,7 @@ public: virtual Resources getResources( const MaterialFeatureData &fd ); - virtual String getName() { return "Terrain Parallax Texture"; } + virtual String getName() { return "Terrain Normal Texture"; } }; class TerrainLightMapFeatGLSL : public TerrainFeatGLSL diff --git a/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp b/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp index f7d2c740a..6c94e0743 100644 --- a/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp +++ b/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp @@ -800,7 +800,7 @@ void TerrainMacroMapFeatHLSL::processPix( Vector &componentL meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n", detailColor, detailInfo, inDet ) ); - Var *baseColor = (Var*)LangElement::find( "baseColor" ); + //Var *baseColor = (Var*)LangElement::find( "baseColor" ); Var *outColor = (Var*)LangElement::find( "col" ); meta->addStatement( new GenOp( " @ = lerp( @, @ + @, @ );\r\n", diff --git a/Engine/source/terrain/terrCell.cpp b/Engine/source/terrain/terrCell.cpp index dac6c910a..a0478ed77 100644 --- a/Engine/source/terrain/terrCell.cpp +++ b/Engine/source/terrain/terrCell.cpp @@ -849,7 +849,7 @@ void TerrCell::_updateMaterials() if ( index == U8_MAX || index > 63 ) continue; - mMaterials |= (U64)(1<point; - for (int i = 0; i < 4 ; i++,pos++) { + for (S32 i = 0; i < 4 ; i++,pos++) { S32 dx = i >> 1; S32 dy = dx ^ (i & 1); pos->x = (F32)((x + dx) * mSquareSize); @@ -562,7 +562,7 @@ bool TerrainBlock::buildPolyList(PolyListContext context, AbstractPolyList* poly // Add the missing points U32 vi[5]; - for (int i = 0; i < 4 ; i++) + for (S32 i = 0; i < 4 ; i++) { S32 dx = i >> 1; S32 dy = dx ^ (i & 1); @@ -669,10 +669,10 @@ bool TerrainBlock::castRayI(const Point3F &start, const Point3F &end, RayInfo *i Point3F pStart(start.x * invBlockWorldSize, start.y * invBlockWorldSize, start.z); Point3F pEnd(end.x * invBlockWorldSize, end.y * invBlockWorldSize, end.z); - int blockX = (S32)mFloor(pStart.x); - int blockY = (S32)mFloor(pStart.y); + S32 blockX = (S32)mFloor(pStart.x); + S32 blockY = (S32)mFloor(pStart.y); - int dx, dy; + S32 dx, dy; F32 invDeltaX; if(pEnd.x == pStart.x) @@ -904,7 +904,7 @@ bool TerrainBlock::castRayBlock( const Point3F &pStart, } continue; } - int subSqWidth = 1 << (level - 1); + S32 subSqWidth = 1 << (level - 1); F32 xIntercept = (blockPos.x + subSqWidth) * invBlockSize; F32 xInt = calcInterceptX(pStart.x, invDeltaX, xIntercept); F32 yIntercept = (blockPos.y + subSqWidth) * invBlockSize; diff --git a/Engine/source/terrain/terrRender.cpp b/Engine/source/terrain/terrRender.cpp index 5d7146fec..4b03ac812 100644 --- a/Engine/source/terrain/terrRender.cpp +++ b/Engine/source/terrain/terrRender.cpp @@ -62,7 +62,7 @@ GFX_ImplementTextureProfile( TerrainLayerTexProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::PreserveSize | GFXTextureProfile::Dynamic, - GFXTextureProfile::None ); + GFXTextureProfile::NONE ); void TerrainBlock::_onFlushMaterials() diff --git a/Engine/source/core/util/test/testFixedSizeDeque.cpp b/Engine/source/testing/memoryTester.h similarity index 55% rename from Engine/source/core/util/test/testFixedSizeDeque.cpp rename to Engine/source/testing/memoryTester.h index e9b3f76f5..72d19e8d8 100644 --- a/Engine/source/core/util/test/testFixedSizeDeque.cpp +++ b/Engine/source/testing/memoryTester.h @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC +// Copyright (c) 2013 Stephan Brenner https://github.com/ymx/gtest_mem // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to @@ -20,35 +20,45 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "unit/test.h" -#include "core/util/tFixedSizeDeque.h" +#include +#include +#if defined(TORQUE_OS_WIN) +#define _CRTDBG_MAP_ALLOC +#include +#endif -using namespace UnitTesting; - -#define TEST( x ) test( ( x ), "FAIL: " #x ) - -CreateUnitTest( TestFixedSizeDeque, "Util/FixedSizeDeque" ) +namespace testing { - void run() + class MemoryLeakDetector : public EmptyTestEventListener { - enum { DEQUE_SIZE = 3 }; - FixedSizeDeque< U32 > deque( DEQUE_SIZE ); + public: + virtual void OnTestStart(const TestInfo&) + { +#if defined(TORQUE_OS_WIN) + _CrtMemCheckpoint(&memState_); +#endif + } - TEST( deque.capacity() == DEQUE_SIZE ); - TEST( deque.size() == 0 ); + virtual void OnTestEnd(const TestInfo& test_info) + { + if(test_info.result()->Passed()) + { +#if defined(TORQUE_OS_WIN) + _CrtMemState stateNow, stateDiff; + _CrtMemCheckpoint(&stateNow); + int diffResult = _CrtMemDifference(&stateDiff, &memState_, &stateNow); + if (diffResult) + { + FAIL() << "Memory leak of " << stateDiff.lSizes[1] << " byte(s) detected."; + } +#endif + } + } - deque.pushFront( 1 ); - TEST( deque.capacity() == ( DEQUE_SIZE - 1 ) ); - TEST( deque.size() == 1 ); - TEST( !deque.isEmpty() ); - - deque.pushBack( 2 ); - TEST( deque.capacity() == ( DEQUE_SIZE - 2 ) ); - TEST( deque.size() == 2 ); - - TEST( deque.popFront() == 1 ); - TEST( deque.popFront() == 2 ); - TEST( deque.isEmpty() ); - } -}; + private: +#if defined(TORQUE_OS_WIN) + _CrtMemState memState_; +#endif + }; +} \ No newline at end of file diff --git a/Engine/source/testing/unitTesting.cpp b/Engine/source/testing/unitTesting.cpp new file mode 100644 index 000000000..2724bf637 --- /dev/null +++ b/Engine/source/testing/unitTesting.cpp @@ -0,0 +1,134 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED + +#include "console/engineAPI.h" +#include "console/consoleInternal.h" +#include "unitTesting.h" +#include "memoryTester.h" + +#include + +//----------------------------------------------------------------------------- + +class TorqueUnitTestListener : public ::testing::EmptyTestEventListener +{ + // Called before a test starts. + virtual void OnTestStart( const ::testing::TestInfo& testInfo ) + { + if( mVerbose ) + Con::printf("> Starting Test '%s.%s'", + testInfo.test_case_name(), testInfo.name()); + } + + // Called after a failed assertion or a SUCCEED() invocation. + virtual void OnTestPartResult( const ::testing::TestPartResult& testPartResult ) + { + if ( testPartResult.failed() ) + { + Con::warnf(">> Failed with '%s' in '%s' at (line:%d)\n", + testPartResult.summary(), + testPartResult.file_name(), + testPartResult.line_number() + ); + } + else if( mVerbose ) + { + Con::printf(">> Passed with '%s' in '%s' at (line:%d)", + testPartResult.summary(), + testPartResult.file_name(), + testPartResult.line_number() + ); + } + } + + // Called after a test ends. + virtual void OnTestEnd( const ::testing::TestInfo& testInfo ) + { + if( mVerbose ) + Con::printf("> Ending Test '%s.%s'\n", + testInfo.test_case_name(), testInfo.name()); + } + + bool mVerbose; + +public: + TorqueUnitTestListener( bool verbose ) : mVerbose( verbose ) {} +}; + +DefineConsoleFunction( runAllUnitTests, int, (const char* testSpecs), (""), + "Runs engine unit tests. Some tests are marked as 'stress' tests which do not " + "necessarily check correctness, just performance or possible nondeterministic " + "glitches. There may also be interactive or networking tests which may be " + "excluded by using the testSpecs argument.\n" + "This function should only be called once per executable run, because of " + "googletest's design.\n\n" + + "@param testSpecs A space-sepatated list of filters for test cases. " + "See https://code.google.com/p/googletest/wiki/AdvancedGuide#Running_a_Subset_of_the_Tests " + "and http://stackoverflow.com/a/14021997/945863 " + "for a description of the flag format.") +{ + S32 testArgc = 0; + char** testArgv = NULL; + if ( dStrlen( testSpecs ) > 0 ) + { + String specs(testSpecs); + specs.replace(' ', ':'); + specs.insert(0, "--gtest_filter="); + testArgc = 2; + testArgv = new char*[2]; + testArgv[0] = NULL; // Program name is unused by googletest. + testArgv[1] = new char[specs.length()+1]; + dStrcpy(testArgv[1], specs); + } + + // Initialize Google Test. + testing::InitGoogleTest( &testArgc, testArgv ); + + // Fetch the unit test instance. + testing::UnitTest& unitTest = *testing::UnitTest::GetInstance(); + + // Fetch the unit test event listeners. + testing::TestEventListeners& listeners = unitTest.listeners(); + + // Release the default listener. + delete listeners.Release( listeners.default_result_printer() ); + + if ( Con::getBoolVariable( "$Testing::CheckMemoryLeaks", false ) ) { + // Add the memory leak tester. + listeners.Append( new testing::MemoryLeakDetector ); + } + + // Add the Torque unit test listener. + listeners.Append( new TorqueUnitTestListener(false) ); + + // Perform googletest run. + Con::printf( "\nUnit Tests Starting...\n" ); + const S32 result = RUN_ALL_TESTS(); + Con::printf( "... Unit Tests Ended.\n" ); + + return result; +} + +#endif // TORQUE_TESTS_ENABLED diff --git a/Engine/source/testing/unitTesting.h b/Engine/source/testing/unitTesting.h new file mode 100644 index 000000000..158c3e034 --- /dev/null +++ b/Engine/source/testing/unitTesting.h @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _UNIT_TESTING_H_ +#define _UNIT_TESTING_H_ + +#ifdef TORQUE_TESTS_ENABLED + +#include + +/// Convenience to define a test fixture with a Fixture suffix for use with +/// TEST_FIX. +#define FIXTURE(test_fixture)\ + class test_fixture##Fixture : public ::testing::Test + +/// Allow test fixtures named with a Fixture suffix, so that we can name tests +/// after a class name rather than having to call them XXTest. +#define TEST_FIX(test_fixture, test_name)\ + GTEST_TEST_(test_fixture, test_name, test_fixture##Fixture, \ + ::testing::internal::GetTypeId()) + +#endif // TORQUE_TESTS_ENABLED + +#endif // _UNIT_TESTING_H_ diff --git a/Engine/source/ts/arch/tsMeshIntrinsics.sse.cpp b/Engine/source/ts/arch/tsMeshIntrinsics.sse.cpp index c83add0a1..1e343ac23 100644 --- a/Engine/source/ts/arch/tsMeshIntrinsics.sse.cpp +++ b/Engine/source/ts/arch/tsMeshIntrinsics.sse.cpp @@ -38,10 +38,10 @@ void zero_vert_normal_bulk_SSE(const dsize_t count, U8 * __restrict const outPtr vMask = _mm_load_ps((const F32*)&_point3f_zero_mask); // pre-populate cache - for(int i = 0; i < 8; i++) + for(S32 i = 0; i < 8; i++) _mm_prefetch(reinterpret_cast(outData + outStride * i), _MM_HINT_T0); - for(int i = 0; i < count; i++) + for(S32 i = 0; i < count; i++) { TSMesh::__TSMeshVertexBase *curElem = reinterpret_cast(outData); @@ -102,13 +102,13 @@ void m_matF_x_BatchedVertWeightList_SSE(const MatrixF &mat, // pre-populate cache const TSSkinMesh::BatchData::BatchedVertWeight &firstElem = batch[0]; - for(int i = 0; i < 8; i++) + for(S32 i = 0; i < 8; i++) { _mm_prefetch(reinterpret_cast(iPtr + inStride * i), _MM_HINT_T0); _mm_prefetch(reinterpret_cast(outPtr + outStride * (i + firstElem.vidx)), _MM_HINT_T0); } - for(register int i = 0; i < count; i++) + for(register S32 i = 0; i < count; i++) { const TSSkinMesh::BatchData::BatchedVertWeight &inElem = batch[i]; TSMesh::__TSMeshVertexBase *outElem = reinterpret_cast(outPtr + inElem.vidx * outStride); diff --git a/Engine/source/ts/arch/tsMeshIntrinsics.sse4.cpp b/Engine/source/ts/arch/tsMeshIntrinsics.sse4.cpp index 8dba501c5..9aba0f027 100644 --- a/Engine/source/ts/arch/tsMeshIntrinsics.sse4.cpp +++ b/Engine/source/ts/arch/tsMeshIntrinsics.sse4.cpp @@ -46,13 +46,13 @@ void m_matF_x_BatchedVertWeightList_SSE4(const MatrixF &mat, // pre-populate cache const TSSkinMesh::BatchData::BatchedVertWeight &firstElem = batch[0]; - for(int i = 0; i < 8; i++) + for(S32 i = 0; i < 8; i++) { _mm_prefetch(reinterpret_cast(iPtr + inStride * i), _MM_HINT_T0); _mm_prefetch(reinterpret_cast(outPtr + outStride * (i + firstElem.vidx)), _MM_HINT_T0); } - for(int i = 0; i < count; i++) + for(S32 i = 0; i < count; i++) { const TSSkinMesh::BatchData::BatchedVertWeight &inElem = batch[i]; TSMesh::__TSMeshVertexBase *outElem = reinterpret_cast(outPtr + inElem.vidx * outStride); diff --git a/Engine/source/ts/collada/colladaAppMesh.cpp b/Engine/source/ts/collada/colladaAppMesh.cpp index 1b58140e5..83c0f207c 100644 --- a/Engine/source/ts/collada/colladaAppMesh.cpp +++ b/Engine/source/ts/collada/colladaAppMesh.cpp @@ -179,7 +179,7 @@ private: const domVertices* vertices = daeSafeCast(element); // Search for the input with the desired semantic const char* semantic = SourceTypeToSemantic( type ); - for (int iInput = 0; iInput < vertices->getInput_array().getCount(); iInput++) + for (S32 iInput = 0; iInput < vertices->getInput_array().getCount(); iInput++) { domInputLocal* input = vertices->getInput_array().get(iInput); if (dStrEqual(input->getSemantic(), semantic)) @@ -230,12 +230,12 @@ public: *maxOffset = 0; // Clear output array - for (int i = 0; i < NumStreams; i++) + for (S32 i = 0; i < NumStreams; i++) sortedInputs[i] = 0; // Separate inputs by type, and sort by set (ie. lowest TEXCOORD set becomes UV, // next TEXCOORD set becomes UV2 etc) - for (int iInput = 0; iInput < inputs.getCount(); iInput++) { + for (S32 iInput = 0; iInput < inputs.getCount(); iInput++) { const T& input = inputs[iInput]; const daeString semantic = input->getSemantic(); @@ -247,7 +247,7 @@ public: // The element may contain multiple inputs (eg. POSITION, NORMAL etc) domInputLocalRef verticesInputs[NumStreams]; classifyInputs(vertices->getInput_array(), verticesInputs); - for (int iStream = 0; iStream < NumStreams; iStream++) + for (S32 iStream = 0; iStream < NumStreams; iStream++) { if (verticesInputs[iStream] != 0) sortedInputs[iStream] = input; @@ -367,7 +367,7 @@ bool ColladaAppMesh::animatesMatFrame(const AppSequence* appSeq) // - by animating the morph weights for morph targets with different UVs // Check if the MAYA profile texture transform is animated - for (int iMat = 0; iMat < appMaterials.size(); iMat++) { + for (S32 iMat = 0; iMat < appMaterials.size(); iMat++) { ColladaAppMaterial* appMat = static_cast(appMaterials[iMat]); if (appMat->effectExt && appMat->effectExt->animatesTextureTransform(appSeq->getStart(), appSeq->getEnd())) @@ -379,7 +379,7 @@ bool ColladaAppMesh::animatesMatFrame(const AppSequence* appSeq) bool animated = false; bool differentUVs = false; if (const domMorph* morph = getMorph()) { - for (int iInput = 0; iInput < morph->getTargets()->getInput_array().getCount(); iInput++) { + for (S32 iInput = 0; iInput < morph->getTargets()->getInput_array().getCount(); iInput++) { const domInputLocal* input = morph->getTargets()->getInput_array()[iInput]; if (dStrEqual(input->getSemantic(), "MORPH_TARGET")) { // @todo: Check if morph targets have different UVs to base geometry @@ -402,7 +402,7 @@ bool ColladaAppMesh::animatesFrame(const AppSequence* appSeq) // the morph weights are animated within the sequence interval bool animated = false; if (const domMorph* morph = getMorph()) { - for (int iInput = 0; iInput < morph->getTargets()->getInput_array().getCount(); iInput++) { + for (S32 iInput = 0; iInput < morph->getTargets()->getInput_array().getCount(); iInput++) { const domInputLocal* input = morph->getTargets()->getInput_array()[iInput]; if (dStrEqual(input->getSemantic(), "MORPH_WEIGHT")) { const domSource* source = daeSafeCast(findInputSource(input)); @@ -441,7 +441,7 @@ S32 ColladaAppMesh::addMaterial(const char* symbol) instanceCtrl->getBind_material(); if (binds) { const domInstance_material_Array& matArray = binds->getTechnique_common()->getInstance_material_array(); - for (int iBind = 0; iBind < matArray.getCount(); iBind++) { + for (S32 iBind = 0; iBind < matArray.getCount(); iBind++) { if (dStrEqual(matArray[iBind]->getSymbol(), symbol)) { // Find the index of the bound material in the shape global list @@ -488,7 +488,7 @@ void ColladaAppMesh::getPrimitives(const domGeometry* geometry) // about unsupported elements Vector meshPrims; const daeElementRefArray& contents = geometry->getMesh()->getContents(); - for (int iElem = 0; iElem < contents.getCount(); iElem++) { + for (S32 iElem = 0; iElem < contents.getCount(); iElem++) { if (BasePrimitive::isPrimitive(contents[iElem])) { if (BasePrimitive::isSupportedPrimitive(contents[iElem])) @@ -505,7 +505,7 @@ void ColladaAppMesh::getPrimitives(const domGeometry* geometry) VertTupleMap tupleMap; // Create Torque primitives - for (int iPrim = 0; iPrim < meshPrims.size(); iPrim++) { + for (S32 iPrim = 0; iPrim < meshPrims.size(); iPrim++) { // Primitive element must have at least 1 triangle const domListOfUInts* pTriData = meshPrims[iPrim]->getTriangleData(); @@ -619,11 +619,11 @@ void ColladaAppMesh::getPrimitives(const domGeometry* geometry) } } - for (int iPrim = 0; iPrim < meshPrims.size(); iPrim++) + for (S32 iPrim = 0; iPrim < meshPrims.size(); iPrim++) delete meshPrims[iPrim]; } -void ColladaAppMesh::getVertexData(const domGeometry* geometry, F32 time, const MatrixF& objectOffset, +void ColladaAppMesh::getVertexData(const domGeometry* geometry, F32 time, const MatrixF& objOffset, Vector& v_points, Vector& v_norms, Vector& v_colors, @@ -641,7 +641,7 @@ void ColladaAppMesh::getVertexData(const domGeometry* geometry, F32 time, const // Get the supported primitive elements for this geometry Vector meshPrims; const daeElementRefArray& contents = geometry->getMesh()->getContents(); - for (int iElem = 0; iElem < contents.getCount(); iElem++) { + for (S32 iElem = 0; iElem < contents.getCount(); iElem++) { if (BasePrimitive::isSupportedPrimitive(contents[iElem])) meshPrims.push_back(BasePrimitive::get(contents[iElem])); } @@ -659,7 +659,7 @@ void ColladaAppMesh::getVertexData(const domGeometry* geometry, F32 time, const ColorI* colors_array = NULL; Point2F* uv2s_array = NULL; - for (int iVert = 0; iVert < vertTuples.size(); iVert++) { + for (S32 iVert = 0; iVert < vertTuples.size(); iVert++) { const VertTuple& tuple = vertTuples[iVert]; @@ -693,7 +693,7 @@ void ColladaAppMesh::getVertexData(const domGeometry* geometry, F32 time, const if (appNode->invertMeshes) points_array[iVert].z = -points_array[iVert].z; - objectOffset.mulP(points_array[iVert]); + objOffset.mulP(points_array[iVert]); } if (appendValues || ((tuple.uv >= 0) && (tuple.uv < streams.uvs.size()))) { @@ -751,11 +751,11 @@ void ColladaAppMesh::getVertexData(const domGeometry* geometry, F32 time, const } } - for (int iPrim = 0; iPrim < meshPrims.size(); iPrim++) + for (S32 iPrim = 0; iPrim < meshPrims.size(); iPrim++) delete meshPrims[iPrim]; } -void ColladaAppMesh::getMorphVertexData(const domMorph* morph, F32 time, const MatrixF& objectOffset, +void ColladaAppMesh::getMorphVertexData(const domMorph* morph, F32 time, const MatrixF& objOffset, Vector& v_points, Vector& v_norms, Vector& v_colors, @@ -768,7 +768,7 @@ void ColladaAppMesh::getMorphVertexData(const domMorph* morph, F32 time, const M Vector targetGeoms; domListOfFloats targetWeights; - for (int iInput = 0; iInput < morph->getTargets()->getInput_array().getCount(); iInput++) { + for (S32 iInput = 0; iInput < morph->getTargets()->getInput_array().getCount(); iInput++) { const domInputLocal* input = morph->getTargets()->getInput_array()[iInput]; const domSource* source = daeSafeCast(findInputSource(input)); @@ -777,7 +777,7 @@ void ColladaAppMesh::getMorphVertexData(const domMorph* morph, F32 time, const M _SourceReader srcTargets; srcTargets.initFromSource(source); - for (int iTarget = 0; iTarget < srcTargets.size(); iTarget++) { + for (S32 iTarget = 0; iTarget < srcTargets.size(); iTarget++) { // Lookup the element and add to the targets list daeIDRef idref(srcTargets.getStringValue(iTarget)); idref.setContainer(morph->getDocument()->getDomRoot()); @@ -807,7 +807,7 @@ void ColladaAppMesh::getMorphVertexData(const domMorph* morph, F32 time, const M return; getPrimitives(baseGeometry); - getVertexData(baseGeometry, time, objectOffset, v_points, v_norms, v_colors, v_uvs, v_uv2s, true); + getVertexData(baseGeometry, time, objOffset, v_points, v_norms, v_colors, v_uvs, v_uv2s, true); // Get pointers to the arrays of base geometry data Point3F* points_array = &v_points[v_points.size() - vertTuples.size()]; @@ -820,27 +820,27 @@ void ColladaAppMesh::getMorphVertexData(const domMorph* morph, F32 time, const M if (morph->getMethod() == MORPHMETHODTYPE_NORMALIZED) { F32 weightSum = 0.0f; - for (int iWeight = 0; iWeight < targetWeights.getCount(); iWeight++) { + for (S32 iWeight = 0; iWeight < targetWeights.getCount(); iWeight++) { weightSum += targetWeights[iWeight]; } // Result = Base*(1.0-w1-w2 ... -wN) + w1*Target1 + w2*Target2 ... + wN*TargetN weightSum = mClampF(1.0f - weightSum, 0.0f, 1.0f); - for (int iVert = 0; iVert < vertTuples.size(); iVert++) { + for (S32 iVert = 0; iVert < vertTuples.size(); iVert++) { points_array[iVert] *= weightSum; norms_array[iVert] *= weightSum; uvs_array[iVert] *= weightSum; } if (uv2s_array) { - for (int iVert = 0; iVert < vertTuples.size(); iVert++) + for (S32 iVert = 0; iVert < vertTuples.size(); iVert++) uv2s_array[iVert] *= weightSum; } } // Interpolate using the target geometry and weights - for (int iTarget = 0; iTarget < targetGeoms.size(); iTarget++) { + for (S32 iTarget = 0; iTarget < targetGeoms.size(); iTarget++) { // Ignore empty weights if (targetWeights[iTarget] == 0.0f) @@ -863,27 +863,27 @@ void ColladaAppMesh::getMorphVertexData(const domMorph* morph, F32 time, const M if (uv2s_array) targetUv2s.set(uv2s_array, vertTuples.size()); - getVertexData(targetGeoms[iTarget], time, objectOffset, targetPoints, targetNorms, targetColors, targetUvs, targetUv2s, false); + getVertexData(targetGeoms[iTarget], time, objOffset, targetPoints, targetNorms, targetColors, targetUvs, targetUv2s, false); // Combine with base geometry - for (int iVert = 0; iVert < vertTuples.size(); iVert++) { + for (S32 iVert = 0; iVert < vertTuples.size(); iVert++) { points_array[iVert] += targetPoints[iVert] * targetWeights[iTarget]; norms_array[iVert] += targetNorms[iVert] * targetWeights[iTarget]; uvs_array[iVert] += targetUvs[iVert] * targetWeights[iTarget]; } if (uv2s_array) { - for (int iVert = 0; iVert < vertTuples.size(); iVert++) + for (S32 iVert = 0; iVert < vertTuples.size(); iVert++) uv2s_array[iVert] += targetUv2s[iVert] * targetWeights[iTarget]; } if (colors_array) { - for (int iVert = 0; iVert < vertTuples.size(); iVert++) + for (S32 iVert = 0; iVert < vertTuples.size(); iVert++) colors_array[iVert] += targetColors[iVert] * (F32)targetWeights[iTarget]; } } } -void ColladaAppMesh::lockMesh(F32 t, const MatrixF& objectOffset) +void ColladaAppMesh::lockMesh(F32 t, const MatrixF& objOffset) { // Find the geometry element for this mesh. Could be one of 3 things: // 1) a simple static mesh (Collada element) @@ -923,10 +923,10 @@ void ColladaAppMesh::lockMesh(F32 t, const MatrixF& objectOffset) // Now get the vertex data at the specified time if (geometry->getElementType() == COLLADA_TYPE::GEOMETRY) { getPrimitives(daeSafeCast(geometry)); - getVertexData(daeSafeCast(geometry), t, objectOffset, points, normals, colors, uvs, uv2s, true); + getVertexData(daeSafeCast(geometry), t, objOffset, points, normals, colors, uvs, uv2s, true); } else if (geometry->getElementType() == COLLADA_TYPE::MORPH) { - getMorphVertexData(daeSafeCast(geometry), t, objectOffset, points, normals, colors, uvs, uv2s); + getMorphVertexData(daeSafeCast(geometry), t, objOffset, points, normals, colors, uvs, uv2s); } else { daeErrorHandler::get()->handleWarning(avar("Unsupported geometry type " @@ -963,7 +963,7 @@ void ColladaAppMesh::lookupSkinData() // vertex may have multiple [bone, weight] pairs in the array) Vector vindicesOffset; const domInt* vindices = (domInt*)weights_v.getRaw(0); - for (int iWeight = 0; iWeight < weights_vcount.getCount(); iWeight++) { + for (S32 iWeight = 0; iWeight < weights_vcount.getCount(); iWeight++) { // Store the offset into the vindices array for this vertex vindicesOffset.push_back(vindices - (domInt*)weights_v.getRaw(0)); vindices += (weights_vcount[iWeight]*2); // 2 indices [bone, weight] per vert @@ -971,14 +971,14 @@ void ColladaAppMesh::lookupSkinData() // Set vertex weights bool tooManyWeightsWarning = false; - for (int iVert = 0; iVert < vertsPerFrame; iVert++) { + for (S32 iVert = 0; iVert < vertsPerFrame; iVert++) { const domUint* vcount = (domUint*)weights_vcount.getRaw(0); const domInt* vindices = (domInt*)weights_v.getRaw(0); vindices += vindicesOffset[vertTuples[iVert].vertex]; S32 nonZeroWeightCount = 0; - for (int iWeight = 0; iWeight < vcount[vertTuples[iVert].vertex]; iWeight++) { + for (S32 iWeight = 0; iWeight < vcount[vertTuples[iVert].vertex]; iWeight++) { S32 bIndex = vindices[iWeight*2]; F32 bWeight = streams.weights.getFloatValue( vindices[iWeight*2 + 1] ); @@ -1027,12 +1027,12 @@ void ColladaAppMesh::lookupSkinData() } // Normalize vertex weights (force weights for each vert to sum to 1) - int iWeight = 0; + S32 iWeight = 0; while (iWeight < weight.size()) { // Find the last weight with the same vertex number, and sum all weights for // that vertex F32 invTotalWeight = 0; - int iLast; + S32 iLast; for (iLast = iWeight; iLast < weight.size(); iLast++) { if (vertexIndex[iLast] != vertexIndex[iWeight]) break; @@ -1048,7 +1048,7 @@ void ColladaAppMesh::lookupSkinData() // Add dummy AppNodes to allow Collada joints to be mapped to 3space nodes bones.setSize(streams.joints.size()); initialTransforms.setSize(streams.joints.size()); - for (int iJoint = 0; iJoint < streams.joints.size(); iJoint++) + for (S32 iJoint = 0; iJoint < streams.joints.size(); iJoint++) { const char* jointName = streams.joints.getStringValue(iJoint); @@ -1056,7 +1056,7 @@ void ColladaAppMesh::lookupSkinData() const domNode* joint = 0; if (instanceCtrl->getSkeleton_array().getCount()) { // Search for the node using the as the base element - for (int iSkel = 0; iSkel < instanceCtrl->getSkeleton_array().getCount(); iSkel++) { + for (S32 iSkel = 0; iSkel < instanceCtrl->getSkeleton_array().getCount(); iSkel++) { xsAnyURI skeleton = instanceCtrl->getSkeleton_array()[iSkel]->getValue(); daeSIDResolver resolver(skeleton.getElement(), jointName); joint = daeSafeCast(resolver.getElement()); diff --git a/Engine/source/ts/collada/colladaAppMesh.h b/Engine/source/ts/collada/colladaAppMesh.h index e7d07c376..17ac1cad1 100644 --- a/Engine/source/ts/collada/colladaAppMesh.h +++ b/Engine/source/ts/collada/colladaAppMesh.h @@ -109,11 +109,11 @@ protected: bool checkGeometryType(const daeElement* element); void getPrimitives(const domGeometry* geometry); - void getVertexData( const domGeometry* geometry, F32 time, const MatrixF& objectOffset, + void getVertexData( const domGeometry* geometry, F32 time, const MatrixF& objOffset, Vector& points, Vector& norms, Vector& colors, Vector& uvs, Vector& uv2s, bool appendValues); - void getMorphVertexData( const domMorph* morph, F32 time, const MatrixF& objectOffset, + void getMorphVertexData( const domMorph* morph, F32 time, const MatrixF& objOffset, Vector& points, Vector& norms, Vector& colors, Vector& uvs, Vector& uv2s ); @@ -211,8 +211,8 @@ public: /// Generate the vertex, normal and triangle data for the mesh. /// /// @param time Time at which to generate the mesh data - /// @param objectOffset Transform to apply to the generated data (bounds transform) - void lockMesh(F32 time, const MatrixF& objectOffset); + /// @param objOffset Transform to apply to the generated data (bounds transform) + void lockMesh(F32 time, const MatrixF& objOffset); /// Get the transform of this mesh at a certain time /// diff --git a/Engine/source/ts/collada/colladaAppNode.cpp b/Engine/source/ts/collada/colladaAppNode.cpp index 8a0dcacab..fdf56c775 100644 --- a/Engine/source/ts/collada/colladaAppNode.cpp +++ b/Engine/source/ts/collada/colladaAppNode.cpp @@ -90,7 +90,7 @@ ColladaAppNode::ColladaAppNode(const domNode* node, ColladaAppNode* parent) dFree( properties ); // Create vector of transform elements - for (int iChild = 0; iChild < node->getContents().getCount(); iChild++) { + for (S32 iChild = 0; iChild < node->getContents().getCount(); iChild++) { switch (node->getContents()[iChild]->getElementType()) { case COLLADA_TYPE::TRANSLATE: case COLLADA_TYPE::ROTATE: @@ -109,7 +109,7 @@ ColladaAppNode::ColladaAppNode(const domNode* node, ColladaAppNode* parent) void ColladaAppNode::buildChildList() { // Process children: collect and elements - for (int iChild = 0; iChild < p_domNode->getContents().getCount(); iChild++) { + for (S32 iChild = 0; iChild < p_domNode->getContents().getCount(); iChild++) { daeElement* child = p_domNode->getContents()[iChild]; switch (child->getElementType()) { @@ -139,7 +139,7 @@ void ColladaAppNode::buildChildList() void ColladaAppNode::buildMeshList() { // Process children: collect and elements - for (int iChild = 0; iChild < p_domNode->getContents().getCount(); iChild++) { + for (S32 iChild = 0; iChild < p_domNode->getContents().getCount(); iChild++) { daeElement* child = p_domNode->getContents()[iChild]; switch (child->getElementType()) { @@ -167,7 +167,7 @@ bool ColladaAppNode::animatesTransform(const AppSequence* appSeq) { // Check if any of this node's transform elements are animated during the // sequence interval - for (int iTxfm = 0; iTxfm < nodeTransforms.size(); iTxfm++) { + for (S32 iTxfm = 0; iTxfm < nodeTransforms.size(); iTxfm++) { if (nodeTransforms[iTxfm].isAnimated(appSeq->getStart(), appSeq->getEnd())) return true; } @@ -227,7 +227,7 @@ MatrixF ColladaAppNode::getTransform(F32 time) } // Multiply by local node transform elements - for (int iTxfm = 0; iTxfm < nodeTransforms.size(); iTxfm++) { + for (S32 iTxfm = 0; iTxfm < nodeTransforms.size(); iTxfm++) { MatrixF mat(true); diff --git a/Engine/source/ts/collada/colladaAppSequence.cpp b/Engine/source/ts/collada/colladaAppSequence.cpp index 3422fe029..6f65a01bf 100644 --- a/Engine/source/ts/collada/colladaAppSequence.cpp +++ b/Engine/source/ts/collada/colladaAppSequence.cpp @@ -74,7 +74,7 @@ F32 ColladaAppSequence::getBlendRefTime() void ColladaAppSequence::setActive(bool active) { - for (int iAnim = 0; iAnim < getClip()->getInstance_animation_array().getCount(); iAnim++) { + for (S32 iAnim = 0; iAnim < getClip()->getInstance_animation_array().getCount(); iAnim++) { domAnimation* anim = daeSafeCast(getClip()->getInstance_animation_array()[iAnim]->getUrl().getElement()); if (anim) setAnimationActive(anim, active); @@ -84,7 +84,7 @@ void ColladaAppSequence::setActive(bool active) void ColladaAppSequence::setAnimationActive(const domAnimation* anim, bool active) { // Enabled/disable data channels for this animation - for (int iChannel = 0; iChannel < anim->getChannel_array().getCount(); iChannel++) { + for (S32 iChannel = 0; iChannel < anim->getChannel_array().getCount(); iChannel++) { domChannel* channel = anim->getChannel_array()[iChannel]; AnimData* animData = reinterpret_cast(channel->getUserData()); if (animData) @@ -92,6 +92,6 @@ void ColladaAppSequence::setAnimationActive(const domAnimation* anim, bool activ } // Recurse into child animations - for (int iAnim = 0; iAnim < anim->getAnimation_array().getCount(); iAnim++) + for (S32 iAnim = 0; iAnim < anim->getAnimation_array().getCount(); iAnim++) setAnimationActive(anim->getAnimation_array()[iAnim], active); } diff --git a/Engine/source/ts/collada/colladaExtensions.h b/Engine/source/ts/collada/colladaExtensions.h index ab6d69289..40e490267 100644 --- a/Engine/source/ts/collada/colladaExtensions.h +++ b/Engine/source/ts/collada/colladaExtensions.h @@ -59,8 +59,8 @@ protected: template const domTechnique* findExtraTechnique(const T* element, const char* name) const { if (element) { - for (int iExt = 0; iExt < element->getExtra_array().getCount(); iExt++) { - for (int iTech = 0; iTech < element->getExtra_array()[iExt]->getTechnique_array().getCount(); iTech++) { + for (S32 iExt = 0; iExt < element->getExtra_array().getCount(); iExt++) { + for (S32 iTech = 0; iTech < element->getExtra_array()[iExt]->getTechnique_array().getCount(); iTech++) { if (dStrEqual(element->getExtra_array()[iExt]->getTechnique_array()[iTech]->getProfile(), name)) return element->getExtra_array()[iExt]->getTechnique_array()[iTech]; } @@ -75,7 +75,7 @@ protected: const domCommon_color_or_texture_type_complexType::domTexture* element, const char* name) const { if (element && element->getExtra()) { - for (int iTech = 0; iTech < element->getExtra()->getTechnique_array().getCount(); iTech++) { + for (S32 iTech = 0; iTech < element->getExtra()->getTechnique_array().getCount(); iTech++) { if (dStrEqual(element->getExtra()->getTechnique_array()[iTech]->getProfile(), name)) return element->getExtra()->getTechnique_array()[iTech]; } @@ -88,7 +88,7 @@ protected: { if (pTechnique) { // search the technique contents for the desired parameter - for (int iParam = 0; iParam < pTechnique->getContents().getCount(); iParam++) { + for (S32 iParam = 0; iParam < pTechnique->getContents().getCount(); iParam++) { const domAny* param = daeSafeCast(pTechnique->getContents()[iParam]); if (param && !dStrcmp(param->getElementName(), name)) return param; @@ -290,7 +290,7 @@ public: // Torque profile pTechnique = findExtraTechnique(clip, "Torque"); GET_EXTRA_PARAM(num_triggers, 0); - for (int iTrigger = 0; iTrigger < num_triggers; iTrigger++) { + for (S32 iTrigger = 0; iTrigger < num_triggers; iTrigger++) { triggers.increment(); get(avar("trigger_time%d", iTrigger), triggers.last().time, 0.0f); get(avar("trigger_state%d", iTrigger), triggers.last().state, 0); diff --git a/Engine/source/ts/collada/colladaImport.cpp b/Engine/source/ts/collada/colladaImport.cpp index 7692dcc77..1657d22c4 100644 --- a/Engine/source/ts/collada/colladaImport.cpp +++ b/Engine/source/ts/collada/colladaImport.cpp @@ -50,7 +50,7 @@ static void processNode(GuiTreeViewCtrl* tree, domNode* node, S32 parentID, Scen S32 nodeID = tree->insertItem(parentID, _GetNameOrId(node), "node", "", 0, 0); // Update mesh and poly counts - for (int i = 0; i < node->getContents().getCount(); i++) + for (S32 i = 0; i < node->getContents().getCount(); i++) { domGeometry* geom = 0; const char* elemName = ""; @@ -178,13 +178,13 @@ ConsoleFunction( enumColladaForImport, bool, 3, 3, SceneStats stats; // Query DOM for shape summary details - for (int i = 0; i < root->getLibrary_visual_scenes_array().getCount(); i++) + for (S32 i = 0; i < root->getLibrary_visual_scenes_array().getCount(); i++) { const domLibrary_visual_scenes* libScenes = root->getLibrary_visual_scenes_array()[i]; - for (int j = 0; j < libScenes->getVisual_scene_array().getCount(); j++) + for (S32 j = 0; j < libScenes->getVisual_scene_array().getCount(); j++) { const domVisual_scene* visualScene = libScenes->getVisual_scene_array()[j]; - for (int k = 0; k < visualScene->getNode_array().getCount(); k++) + for (S32 k = 0; k < visualScene->getNode_array().getCount(); k++) processNode(tree, visualScene->getNode_array()[k], nodesID, stats); } } diff --git a/Engine/source/ts/collada/colladaLights.cpp b/Engine/source/ts/collada/colladaLights.cpp index 1388278d0..71d2c33df 100644 --- a/Engine/source/ts/collada/colladaLights.cpp +++ b/Engine/source/ts/collada/colladaLights.cpp @@ -215,11 +215,11 @@ ConsoleFunction( loadColladaLights, bool, 2, 4, // First grab all of the top-level nodes Vector sceneNodes; - for (int iSceneLib = 0; iSceneLib < root->getLibrary_visual_scenes_array().getCount(); iSceneLib++) { + for (S32 iSceneLib = 0; iSceneLib < root->getLibrary_visual_scenes_array().getCount(); iSceneLib++) { const domLibrary_visual_scenes* libScenes = root->getLibrary_visual_scenes_array()[iSceneLib]; - for (int iScene = 0; iScene < libScenes->getVisual_scene_array().getCount(); iScene++) { + for (S32 iScene = 0; iScene < libScenes->getVisual_scene_array().getCount(); iScene++) { const domVisual_scene* visualScene = libScenes->getVisual_scene_array()[iScene]; - for (int iNode = 0; iNode < visualScene->getNode_array().getCount(); iNode++) + for (S32 iNode = 0; iNode < visualScene->getNode_array().getCount(); iNode++) sceneNodes.push_back(new ColladaAppNode(visualScene->getNode_array()[iNode])); } } diff --git a/Engine/source/ts/collada/colladaShapeLoader.cpp b/Engine/source/ts/collada/colladaShapeLoader.cpp index 3822e9e01..f376b78da 100644 --- a/Engine/source/ts/collada/colladaShapeLoader.cpp +++ b/Engine/source/ts/collada/colladaShapeLoader.cpp @@ -50,6 +50,15 @@ #include "core/util/zip/zipVolume.h" #include "gfx/bitmap/gBitmap.h" +MODULE_BEGIN( ColladaShapeLoader ) + MODULE_INIT_AFTER( ShapeLoader ) + MODULE_INIT + { + TSShapeLoader::addFormat("Collada", "dae"); + TSShapeLoader::addFormat("Google Earth", "kmz"); + } +MODULE_END; + // static DAE sDAE; // Collada model database (holds the last loaded file) static Torque::Path sLastPath; // Path of the last loaded Collada file @@ -96,8 +105,8 @@ ColladaShapeLoader::ColladaShapeLoader(domCOLLADA* _root) ColladaShapeLoader::~ColladaShapeLoader() { // Delete all of the animation channels - for (int iAnim = 0; iAnim < animations.size(); iAnim++) { - for (int iChannel = 0; iChannel < animations[iAnim]->size(); iChannel++) + for (S32 iAnim = 0; iAnim < animations.size(); iAnim++) { + for (S32 iChannel = 0; iChannel < animations[iAnim]->size(); iChannel++) delete (*animations[iAnim])[iChannel]; delete animations[iAnim]; } @@ -113,7 +122,7 @@ void ColladaShapeLoader::processAnimation(const domAnimation* anim, F32& maxEndT const char* sSKEWNames[] = { ".ROTATEX", ".ROTATEY", ".ROTATEZ", ".AROUNDX", ".AROUNDY", ".AROUNDZ", ".ANGLE", "" }; const char* sNullNames[] = { "" }; - for (int iChannel = 0; iChannel < anim->getChannel_array().getCount(); iChannel++) { + for (S32 iChannel = 0; iChannel < anim->getChannel_array().getCount(); iChannel++) { // Get the animation elements: , domChannel* channel = anim->getChannel_array()[iChannel]; @@ -150,7 +159,7 @@ void ColladaShapeLoader::processAnimation(const domAnimation* anim, F32& maxEndT channel->setUserData(targetChannels->last()); AnimData& data = *targetChannels->last(); - for (int iInput = 0; iInput < sampler->getInput_array().getCount(); iInput++) { + for (S32 iInput = 0; iInput < sampler->getInput_array().getCount(); iInput++) { const domInputLocal* input = sampler->getInput_array()[iInput]; const domSource* source = daeSafeCast(input->getSource().getElement()); @@ -219,7 +228,7 @@ void ColladaShapeLoader::processAnimation(const domAnimation* anim, F32& maxEndT } // Process child animations - for (int iAnim = 0; iAnim < anim->getAnimation_array().getCount(); iAnim++) + for (S32 iAnim = 0; iAnim < anim->getAnimation_array().getCount(); iAnim++) processAnimation(anim->getAnimation_array()[iAnim], maxEndTime, minFrameTime); } @@ -227,20 +236,20 @@ void ColladaShapeLoader::enumerateScene() { // Get animation clips Vector animationClips; - for (int iClipLib = 0; iClipLib < root->getLibrary_animation_clips_array().getCount(); iClipLib++) { + for (S32 iClipLib = 0; iClipLib < root->getLibrary_animation_clips_array().getCount(); iClipLib++) { const domLibrary_animation_clips* libraryClips = root->getLibrary_animation_clips_array()[iClipLib]; - for (int iClip = 0; iClip < libraryClips->getAnimation_clip_array().getCount(); iClip++) + for (S32 iClip = 0; iClip < libraryClips->getAnimation_clip_array().getCount(); iClip++) appSequences.push_back(new ColladaAppSequence(libraryClips->getAnimation_clip_array()[iClip])); } // Process all animations => this attaches animation channels to the targeted // Collada elements, and determines the length of the sequence if it is not // already specified in the Collada element - for (int iSeq = 0; iSeq < appSequences.size(); iSeq++) { + for (S32 iSeq = 0; iSeq < appSequences.size(); iSeq++) { ColladaAppSequence* appSeq = dynamic_cast(appSequences[iSeq]); F32 maxEndTime = 0; F32 minFrameTime = 1000.0f; - for (int iAnim = 0; iAnim < appSeq->getClip()->getInstance_animation_array().getCount(); iAnim++) { + for (S32 iAnim = 0; iAnim < appSeq->getClip()->getInstance_animation_array().getCount(); iAnim++) { domAnimation* anim = daeSafeCast(appSeq->getClip()->getInstance_animation_array()[iAnim]->getUrl().getElement()); if (anim) processAnimation(anim, maxEndTime, minFrameTime); @@ -256,11 +265,11 @@ void ColladaShapeLoader::enumerateScene() // First grab all of the top-level nodes Vector sceneNodes; - for (int iSceneLib = 0; iSceneLib < root->getLibrary_visual_scenes_array().getCount(); iSceneLib++) { + for (S32 iSceneLib = 0; iSceneLib < root->getLibrary_visual_scenes_array().getCount(); iSceneLib++) { const domLibrary_visual_scenes* libScenes = root->getLibrary_visual_scenes_array()[iSceneLib]; - for (int iScene = 0; iScene < libScenes->getVisual_scene_array().getCount(); iScene++) { + for (S32 iScene = 0; iScene < libScenes->getVisual_scene_array().getCount(); iScene++) { const domVisual_scene* visualScene = libScenes->getVisual_scene_array()[iScene]; - for (int iNode = 0; iNode < visualScene->getNode_array().getCount(); iNode++) + for (S32 iNode = 0; iNode < visualScene->getNode_array().getCount(); iNode++) sceneNodes.push_back(visualScene->getNode_array()[iNode]); } } @@ -272,10 +281,10 @@ void ColladaShapeLoader::enumerateScene() case ColladaUtils::ImportOptions::DetectDTS: // Check for a baseXX->startXX hierarchy at the top-level, if we find // one, use trailing numbers for LOD, otherwise use a single size - for (int iNode = 0; singleDetail && (iNode < sceneNodes.size()); iNode++) { + for (S32 iNode = 0; singleDetail && (iNode < sceneNodes.size()); iNode++) { domNode* node = sceneNodes[iNode]; if (dStrStartsWith(_GetNameOrId(node), "base")) { - for (int iChild = 0; iChild < node->getNode_array().getCount(); iChild++) { + for (S32 iChild = 0; iChild < node->getNode_array().getCount(); iChild++) { domNode* child = node->getNode_array()[iChild]; if (dStrStartsWith(_GetNameOrId(child), "start")) { singleDetail = false; @@ -484,7 +493,7 @@ void updateMaterialsScript(const Torque::Path &path, bool copyTextures = false) // If importing a sketchup file, the paths will point inside the KMZ so we need to cache them. if (copyTextures) { - for (int iMat = 0; iMat < persistMgr.getDirtyList().size(); iMat++) + for (S32 iMat = 0; iMat < persistMgr.getDirtyList().size(); iMat++) { Material *mat = dynamic_cast( persistMgr.getDirtyList()[iMat].getObject() ); diff --git a/Engine/source/ts/collada/colladaUtils.cpp b/Engine/source/ts/collada/colladaUtils.cpp index 7bd5b2e9d..0c409fc95 100644 --- a/Engine/source/ts/collada/colladaUtils.cpp +++ b/Engine/source/ts/collada/colladaUtils.cpp @@ -84,7 +84,7 @@ const domProfile_COMMON* ColladaUtils::findEffectCommonProfile(const domEffect* if (effect) { // Find the COMMON profile const domFx_profile_abstract_Array& profiles = effect->getFx_profile_abstract_array(); - for (int iProfile = 0; iProfile < profiles.getCount(); iProfile++) { + for (S32 iProfile = 0; iProfile < profiles.getCount(); iProfile++) { if (profiles[iProfile]->getElementType() == COLLADA_TYPE::PROFILE_COMMON) return daeSafeCast(profiles[iProfile]); } @@ -245,7 +245,7 @@ BasePrimitive* BasePrimitive::get(const daeElement* element) // Collada animation curves /// Determine which elements are being targeted -void AnimData::parseTargetString(const char* target, int fullCount, const char* elements[]) +void AnimData::parseTargetString(const char* target, S32 fullCount, const char* elements[]) { // Assume targeting all elements at offset 0 targetValueCount = fullCount; @@ -253,7 +253,7 @@ void AnimData::parseTargetString(const char* target, int fullCount, const char* // Check for array syntax: (n) or (n)(m) if (const char* p = dStrchr(target, '(')) { - int indN, indM; + S32 indN, indM; if (dSscanf(p, "(%d)(%d)", &indN, &indM) == 2) { targetValueOffset = (indN * 4) + indM; // @todo: 4x4 matrix only targetValueCount = 1; @@ -265,7 +265,7 @@ void AnimData::parseTargetString(const char* target, int fullCount, const char* } else if (const char* p = dStrrchr(target, '.')) { // Check for named elements - for (int iElem = 0; elements[iElem][0] != 0; iElem++) { + for (S32 iElem = 0; elements[iElem][0] != 0; iElem++) { if (!dStrcmp(p, elements[iElem])) { targetValueOffset = iElem; targetValueCount = 1; @@ -278,9 +278,9 @@ void AnimData::parseTargetString(const char* target, int fullCount, const char* /// Solve the cubic spline B(s) = param for s F32 AnimData::invertParamCubic(F32 param, F32 x0, F32 x1, F32 x2, F32 x3) const { - const double INVERTPARAMCUBIC_TOL = 1.0e-09; - const double INVERTPARAMCUBIC_SMALLERTOL = 1.0e-20; - const double INVERTPARAMCUBIC_MAXIT = 100; + const F64 INVERTPARAMCUBIC_TOL = 1.0e-09; + const F64 INVERTPARAMCUBIC_SMALLERTOL = 1.0e-20; + const F64 INVERTPARAMCUBIC_MAXIT = 100; // check input value for outside range if ((param - x0) < INVERTPARAMCUBIC_SMALLERTOL) @@ -295,12 +295,12 @@ F32 AnimData::invertParamCubic(F32 param, F32 x0, F32 x1, F32 x2, F32 x3) const F32 v = 1.0f; while (iterations < INVERTPARAMCUBIC_MAXIT) { - double a = (x0 + x1)*0.5f; - double b = (x1 + x2)*0.5f; - double c = (x2 + x3)*0.5f; - double d = (a + b)*0.5f; - double e = (b + c)*0.5f; - double f = (d + e)*0.5f; + F64 a = (x0 + x1)*0.5f; + F64 b = (x1 + x2)*0.5f; + F64 c = (x2 + x3)*0.5f; + F64 d = (a + b)*0.5f; + F64 e = (b + c)*0.5f; + F64 f = (d + e)*0.5f; if (mFabs(f - param) < INVERTPARAMCUBIC_TOL) break; @@ -344,7 +344,7 @@ void AnimData::interpValue(F32 t, U32 offset, double* value) const t = mClampF(t, curveStart, curveEnd); // find the index of the input keyframe BEFORE 't' - int index; + S32 index; for (index = 0; index < input.size()-2; index++) { if (input.getFloatValue(index + 1) > t) break; @@ -470,7 +470,7 @@ void AnimData::interpValue(F32 t, U32 offset, const char** value) const t = mClampF(t, curveStart, curveEnd); // find the index of the input keyframe BEFORE 't' - int index; + S32 index; for (index = 0; index < input.size()-2; index++) { if (input.getFloatValue(index + 1) > t) break; @@ -487,9 +487,9 @@ void AnimData::interpValue(F32 t, U32 offset, const char** value) const static void conditioner_fixupTextureSIDs(domCOLLADA* root) { - for (int iLib = 0; iLib < root->getLibrary_effects_array().getCount(); iLib++) { + for (S32 iLib = 0; iLib < root->getLibrary_effects_array().getCount(); iLib++) { domLibrary_effects* lib = root->getLibrary_effects_array()[iLib]; - for (int iEffect = 0; iEffect < lib->getEffect_array().getCount(); iEffect++) { + for (S32 iEffect = 0; iEffect < lib->getEffect_array().getCount(); iEffect++) { domEffect* effect = lib->getEffect_array()[iEffect]; const domCommon_color_or_texture_type_complexType* diffuse = findEffectDiffuse(effect); if (!diffuse || !diffuse->getTexture()) @@ -542,9 +542,9 @@ static void conditioner_fixupTextureSIDs(domCOLLADA* root) static void conditioner_fixupImageURIs(domCOLLADA* root) { - for (int iLib = 0; iLib < root->getLibrary_images_array().getCount(); iLib++) { + for (S32 iLib = 0; iLib < root->getLibrary_images_array().getCount(); iLib++) { domLibrary_images* lib = root->getLibrary_images_array()[iLib]; - for (int iImage = 0; iImage < lib->getImage_array().getCount(); iImage++) { + for (S32 iImage = 0; iImage < lib->getImage_array().getCount(); iImage++) { domImage* image = lib->getImage_array()[iImage]; if (image->getInit_from()) { xsAnyURI& uri = image->getInit_from()->getValue(); @@ -595,7 +595,7 @@ static void conditioner_fixupTransparency(domCOLLADA* root) // Get the string const char *authoringTool = ""; if (const domAsset* asset = root->getAsset()) { - for (int iContrib = 0; iContrib < asset->getContributor_array().getCount(); iContrib++) { + for (S32 iContrib = 0; iContrib < asset->getContributor_array().getCount(); iContrib++) { const domAsset::domContributor* contrib = asset->getContributor_array()[iContrib]; if (contrib->getAuthoring_tool()) { authoringTool = contrib->getAuthoring_tool()->getValue(); @@ -608,7 +608,7 @@ static void conditioner_fixupTransparency(domCOLLADA* root) bool invertTransparency = false; const char *toolNames[] = { "FBX COLLADA exporter", "Google SketchUp", "Illusoft Collada Exporter", "FCollada" }; - for (int iName = 0; iName < (sizeof(toolNames)/sizeof(toolNames[0])); iName++) { + for (S32 iName = 0; iName < (sizeof(toolNames)/sizeof(toolNames[0])); iName++) { if (dStrstr(authoringTool, toolNames[iName])) { invertTransparency = true; break; @@ -619,9 +619,9 @@ static void conditioner_fixupTransparency(domCOLLADA* root) return; // Invert transparency as required for each effect - for (int iLib = 0; iLib < root->getLibrary_effects_array().getCount(); iLib++) { + for (S32 iLib = 0; iLib < root->getLibrary_effects_array().getCount(); iLib++) { domLibrary_effects* lib = root->getLibrary_effects_array()[iLib]; - for (int iEffect = 0; iEffect < lib->getEffect_array().getCount(); iEffect++) { + for (S32 iEffect = 0; iEffect < lib->getEffect_array().getCount(); iEffect++) { domEffect* effect = lib->getEffect_array()[iEffect]; // Find the common profile @@ -658,9 +658,9 @@ static void conditioner_fixupTransparency(domCOLLADA* root) static void conditioner_checkBindShapeMatrix(domCOLLADA* root) { - for (int iLib = 0; iLib < root->getLibrary_controllers_array().getCount(); iLib++) { + for (S32 iLib = 0; iLib < root->getLibrary_controllers_array().getCount(); iLib++) { domLibrary_controllers* lib = root->getLibrary_controllers_array().get(iLib); - for (int iCon = 0; iCon < lib->getController_array().getCount(); iCon++) { + for (S32 iCon = 0; iCon < lib->getController_array().getCount(); iCon++) { domController* con = lib->getController_array().get(iCon); if (con->getSkin() && con->getSkin()->getBind_shape_matrix()) { @@ -677,14 +677,14 @@ static void conditioner_checkBindShapeMatrix(domCOLLADA* root) static void conditioner_fixupVertexWeightJoints(domCOLLADA* root) { - for (int iLib = 0; iLib < root->getLibrary_controllers_array().getCount(); iLib++) { + for (S32 iLib = 0; iLib < root->getLibrary_controllers_array().getCount(); iLib++) { domLibrary_controllers* lib = root->getLibrary_controllers_array().get(iLib); - for (int iCon = 0; iCon < lib->getController_array().getCount(); iCon++) { + for (S32 iCon = 0; iCon < lib->getController_array().getCount(); iCon++) { domController* con = lib->getController_array().get(iCon); if (con->getSkin() && con->getSkin()->getVertex_weights()) { domInputLocalOffset_Array& vw_inputs = con->getSkin()->getVertex_weights()->getInput_array(); - for (int vInput = 0; vInput < vw_inputs.getCount(); vInput++) { + for (S32 vInput = 0; vInput < vw_inputs.getCount(); vInput++) { domInputLocalOffset *vw_input = vw_inputs.get(vInput); if (dStrEqual(vw_input->getSemantic(), "JOINT")) { @@ -695,7 +695,7 @@ static void conditioner_fixupVertexWeightJoints(domCOLLADA* root) // Copy the value from the JOINTS input instead domInputLocal_Array& joint_inputs = con->getSkin()->getJoints()->getInput_array(); - for (int jInput = 0; jInput < joint_inputs.getCount(); jInput++) { + for (S32 jInput = 0; jInput < joint_inputs.getCount(); jInput++) { domInputLocal *joint_input = joint_inputs.get(jInput); if (dStrEqual(joint_input->getSemantic(), "JOINT")) { @@ -714,16 +714,16 @@ static void conditioner_fixupVertexWeightJoints(domCOLLADA* root) static void conditioner_createDefaultClip(domCOLLADA* root) { // Check if the document has any s - for (int iLib = 0; iLib < root->getLibrary_animation_clips_array().getCount(); iLib++) { + for (S32 iLib = 0; iLib < root->getLibrary_animation_clips_array().getCount(); iLib++) { if (root->getLibrary_animation_clips_array()[iLib]->getAnimation_clip_array().getCount()) return; } // Get all top-level s into an array domAnimation_Array animations; - for (int iAnimLib = 0; iAnimLib < root->getLibrary_animations_array().getCount(); iAnimLib++) { + for (S32 iAnimLib = 0; iAnimLib < root->getLibrary_animations_array().getCount(); iAnimLib++) { const domLibrary_animations* libraryAnims = root->getLibrary_animations_array()[iAnimLib]; - for (int iAnim = 0; iAnim < libraryAnims->getAnimation_array().getCount(); iAnim++) + for (S32 iAnim = 0; iAnim < libraryAnims->getAnimation_array().getCount(); iAnim++) animations.append(libraryAnims->getAnimation_array()[iAnim]); } @@ -748,7 +748,7 @@ static void conditioner_createDefaultClip(domCOLLADA* root) // Add all top_level animations to the clip (sub-animations will be included // when the clip is procesed) - for (int iAnim = 0; iAnim < animations.getCount(); iAnim++) { + for (S32 iAnim = 0; iAnim < animations.getCount(); iAnim++) { if (!animations[iAnim]->getId()) animations[iAnim]->setId(avar("dummy-animation-id%d", iAnim)); CREATE_ELEMENT(animation_clip, instance_animation, domInstanceWithExtra) @@ -767,7 +767,7 @@ static void conditioner_createDefaultClip(domCOLLADA* root) static void conditioner_fixupAnimation(domAnimation* anim) { - for (int iChannel = 0; iChannel < anim->getChannel_array().getCount(); iChannel++) { + for (S32 iChannel = 0; iChannel < anim->getChannel_array().getCount(); iChannel++) { // Get the animation elements: , domChannel* channel = anim->getChannel_array()[iChannel]; @@ -848,7 +848,7 @@ static void conditioner_fixupAnimation(domAnimation* anim) } // Process child animations - for (int iAnim = 0; iAnim < anim->getAnimation_array().getCount(); iAnim++) + for (S32 iAnim = 0; iAnim < anim->getAnimation_array().getCount(); iAnim++) conditioner_fixupAnimation(anim->getAnimation_array()[iAnim]); } @@ -893,9 +893,9 @@ void ColladaUtils::applyConditioners(domCOLLADA* root) // 2) Some exporters generate visibility animations but don't add the FCOLLADA // extension, so the target doesn't actually exist! Detect this situation // and add the extension manually so the animation still works. - for (int iLib = 0; iLib < root->getLibrary_animations_array().getCount(); iLib++) { + for (S32 iLib = 0; iLib < root->getLibrary_animations_array().getCount(); iLib++) { const domLibrary_animations* lib = root->getLibrary_animations_array()[iLib]; - for (int iAnim = 0; iAnim < lib->getAnimation_array().getCount(); iAnim++) + for (S32 iAnim = 0; iAnim < lib->getAnimation_array().getCount(); iAnim++) conditioner_fixupAnimation(lib->getAnimation_array()[iAnim]); } } diff --git a/Engine/source/ts/collada/colladaUtils.h b/Engine/source/ts/collada/colladaUtils.h index e2ee4b377..04592126e 100644 --- a/Engine/source/ts/collada/colladaUtils.h +++ b/Engine/source/ts/collada/colladaUtils.h @@ -185,7 +185,7 @@ template<> inline MatrixF vecToMatrixF(const domListOfFloats& vec) template<> inline MatrixF vecToMatrixF(const domListOfFloats& vec) { MatrixF mat; - for (int i = 0; i < 16; i++) + for (S32 i = 0; i < 16; i++) mat[i] = vec[i]; return mat; } @@ -332,7 +332,7 @@ public: // If no input params were specified, just map the source params directly if (!offsets.size()) { - for (int iParam = 0; iParam < accessor->getParam_array().getCount(); iParam++) + for (S32 iParam = 0; iParam < accessor->getParam_array().getCount(); iParam++) offsets.push_back(iParam); } @@ -348,9 +348,9 @@ public: //------------------------------------------------------ // Get a pointer to the start of a group of values (index advances by stride) - //template T getArrayData(int index) const { return 0; } + //template T getArrayData(S32 index) const { return 0; } - const double* getStringArrayData(int index) const + const double* getStringArrayData(S32 index) const { if ((index >= 0) && (index < size())) { if (source->getFloat_array()) @@ -361,9 +361,9 @@ public: //------------------------------------------------------ // Read a single value from the source array - //template T getValue(int index) const { return T; } + //template T getValue(S32 index) const { return T; } - const char* getStringValue(int index) const + const char* getStringValue(S32 index) const { if ((index >= 0) && (index < size())) { // could be plain strings or IDREFs @@ -375,7 +375,7 @@ public: return ""; } - F32 getFloatValue(int index) const + F32 getFloatValue(S32 index) const { F32 value(0); if (const double* data = getStringArrayData(index)) @@ -383,7 +383,7 @@ public: return value; } - Point2F getPoint2FValue(int index) const + Point2F getPoint2FValue(S32 index) const { Point2F value(0, 0); if (const double* data = getStringArrayData(index)) @@ -391,7 +391,7 @@ public: return value; } - Point3F getPoint3FValue(int index) const + Point3F getPoint3FValue(S32 index) const { Point3F value(1, 0, 0); if (const double* data = getStringArrayData(index)) @@ -399,7 +399,7 @@ public: return value; } - ColorI getColorIValue(int index) const + ColorI getColorIValue(S32 index) const { ColorI value(255, 255, 255, 255); if (const double* data = getStringArrayData(index)) @@ -413,11 +413,11 @@ public: return value; } - MatrixF getMatrixFValue(int index) const + MatrixF getMatrixFValue(S32 index) const { MatrixF value(true); if (const double* data = getStringArrayData(index)) { - for (int i = 0; i < 16; i++) + for (S32 i = 0; i < 16; i++) value[i] = data[i]; } return value; @@ -430,6 +430,8 @@ public: class BasePrimitive { public: + virtual ~BasePrimitive() { } + /// Return true if the element is a geometric primitive type static bool isPrimitive(const daeElement* element) { @@ -486,7 +488,7 @@ public: // Determine stride stride = 0; - for (int iInput = 0; iInput < getInputs().getCount(); iInput++) { + for (S32 iInput = 0; iInput < getInputs().getCount(); iInput++) { if (getInputs()[iInput]->getOffset() >= stride) stride = getInputs()[iInput]->getOffset() + 1; } @@ -524,7 +526,7 @@ template<> inline const domListOfUInts *ColladaPrimitive::getTrian // Convert strips to triangles pTriangleData = new domListOfUInts(); - for (int iStrip = 0; iStrip < primitive->getCount(); iStrip++) { + for (S32 iStrip = 0; iStrip < primitive->getCount(); iStrip++) { domP* P = primitive->getP_array()[iStrip]; @@ -537,7 +539,7 @@ template<> inline const domListOfUInts *ColladaPrimitive::getTrian // Convert the strip back to a triangle list domUint* v0 = pSrcData; - for (int iTri = 0; iTri < numTriangles; iTri++, v0 += stride) { + for (S32 iTri = 0; iTri < numTriangles; iTri++, v0 += stride) { if (iTri & 0x1) { // CW triangle @@ -565,7 +567,7 @@ template<> inline const domListOfUInts *ColladaPrimitive::getTriangl // Convert strips to triangles pTriangleData = new domListOfUInts(); - for (int iStrip = 0; iStrip < primitive->getCount(); iStrip++) { + for (S32 iStrip = 0; iStrip < primitive->getCount(); iStrip++) { domP* P = primitive->getP_array()[iStrip]; @@ -578,7 +580,7 @@ template<> inline const domListOfUInts *ColladaPrimitive::getTriangl // Convert the fan back to a triangle list domUint* v0 = pSrcData + stride; - for (int iTri = 0; iTri < numTriangles; iTri++, v0 += stride) { + for (S32 iTri = 0; iTri < numTriangles; iTri++, v0 += stride) { pTriangleData->appendArray(stride, pSrcData); // shared vertex pTriangleData->appendArray(stride, v0); // previous vertex pTriangleData->appendArray(stride, v0+stride); // current vertex @@ -597,7 +599,7 @@ template<> inline const domListOfUInts *ColladaPrimitive::getTriang // Convert polygons to triangles pTriangleData = new domListOfUInts(); - for (int iPoly = 0; iPoly < primitive->getCount(); iPoly++) { + for (S32 iPoly = 0; iPoly < primitive->getCount(); iPoly++) { domP* P = primitive->getP_array()[iPoly]; @@ -612,7 +614,7 @@ template<> inline const domListOfUInts *ColladaPrimitive::getTriang // converting the polygon to triangles. domUint* v0 = pSrcData; pSrcData += stride; - for (int iTri = 0; iTri < numPoints-2; iTri++) { + for (S32 iTri = 0; iTri < numPoints-2; iTri++) { pTriangleData->appendArray(stride, v0); pTriangleData->appendArray(stride*2, pSrcData); pSrcData += stride; @@ -636,7 +638,7 @@ template<> inline const domListOfUInts *ColladaPrimitive::getTriang const domListOfUInts& vcount = primitive->getVcount()->getValue(); U32 expectedCount = 0; - for (int iPoly = 0; iPoly < vcount.getCount(); iPoly++) + for (S32 iPoly = 0; iPoly < vcount.getCount(); iPoly++) expectedCount += vcount[iPoly]; expectedCount *= stride; @@ -648,13 +650,13 @@ template<> inline const domListOfUInts *ColladaPrimitive::getTriang } domUint* pSrcData = &(primitive->getP()->getValue()[0]); - for (int iPoly = 0; iPoly < vcount.getCount(); iPoly++) { + for (S32 iPoly = 0; iPoly < vcount.getCount(); iPoly++) { // Use a simple tri-fan (centered at the first point) method of // converting the polygon to triangles. domUint* v0 = pSrcData; pSrcData += stride; - for (int iTri = 0; iTri < vcount[iPoly]-2; iTri++) { + for (S32 iTri = 0; iTri < vcount[iPoly]-2; iTri++) { pTriangleData->appendArray(stride, v0); pTriangleData->appendArray(stride*2, pSrcData); pSrcData += stride; @@ -671,7 +673,7 @@ template<> inline const domListOfUInts *ColladaPrimitive::getTriang template inline T convert(const char* value) { return value; } template<> inline bool convert(const char* value) { return dAtob(value); } template<> inline S32 convert(const char* value) { return dAtoi(value); } -template<> inline double convert(const char* value) { return dAtof(value); } +template<> inline F64 convert(const char* value) { return dAtof(value); } template<> inline F32 convert(const char* value) { return convert(value); } //----------------------------------------------------------------------------- @@ -713,7 +715,7 @@ struct AnimData AnimData() : enabled(false) { } - void parseTargetString(const char* target, int fullCount, const char* elements[]); + void parseTargetString(const char* target, S32 fullCount, const char* elements[]); F32 invertParamCubic(F32 param, F32 x0, F32 x1, F32 x2, F32 x3) const; void interpValue(F32 t, U32 offset, double* value) const; @@ -757,7 +759,7 @@ struct AnimatedElement // Animate the value const AnimChannels* channels = AnimData::getAnimChannels(element); if (channels && (time >= 0)) { - for (int iChannel = 0; iChannel < channels->size(); iChannel++) { + for (S32 iChannel = 0; iChannel < channels->size(); iChannel++) { const AnimData* animData = (*channels)[iChannel]; if (animData->enabled) animData->interpValue(time, 0, &value); @@ -787,10 +789,10 @@ template struct AnimatedElementList : public AnimatedElement // Animate the vector const AnimChannels* channels = AnimData::getAnimChannels(this->element); if (channels && (time >= 0)) { - for (int iChannel = 0; iChannel < channels->size(); iChannel++) { + for (S32 iChannel = 0; iChannel < channels->size(); iChannel++) { const AnimData* animData = (*channels)[iChannel]; if (animData->enabled) { - for (int iValue = 0; iValue < animData->targetValueCount; iValue++) + for (S32 iValue = 0; iValue < animData->targetValueCount; iValue++) animData->interpValue(time, iValue, &vec[animData->targetValueOffset + iValue]); } } diff --git a/Engine/source/ts/loader/tsShapeLoader.cpp b/Engine/source/ts/loader/tsShapeLoader.cpp index 5170867df..573ae1ee1 100644 --- a/Engine/source/ts/loader/tsShapeLoader.cpp +++ b/Engine/source/ts/loader/tsShapeLoader.cpp @@ -21,6 +21,7 @@ //----------------------------------------------------------------------------- #include "platform/platform.h" +#include "console/engineAPI.h" #include "ts/loader/tsShapeLoader.h" #include "core/volume.h" @@ -30,13 +31,23 @@ #include "ts/tsShapeInstance.h" #include "ts/tsMaterialList.h" +MODULE_BEGIN( ShapeLoader ) + MODULE_INIT_AFTER( GFX ) + MODULE_INIT + { + TSShapeLoader::addFormat("Torque DTS", "dts"); + TSShapeLoader::addFormat("Torque DSQ", "dsq"); + } +MODULE_END; const F32 TSShapeLoader::DefaultTime = -1.0f; -const double TSShapeLoader::MinFrameRate = 15.0f; -const double TSShapeLoader::MaxFrameRate = 60.0f; -const double TSShapeLoader::AppGroundFrameRate = 10.0f; +const F64 TSShapeLoader::MinFrameRate = 15.0f; +const F64 TSShapeLoader::MaxFrameRate = 60.0f; +const F64 TSShapeLoader::AppGroundFrameRate = 10.0f; Torque::Path TSShapeLoader::shapePath; +Vector TSShapeLoader::smFormats; + //------------------------------------------------------------------------------ // Utility functions @@ -102,7 +113,7 @@ void TSShapeLoader::generateNodeTransform(AppNode* node, F32 t, bool blend, F32 //----------------------------------------------------------------------------- -void TSShapeLoader::updateProgress(int major, const char* msg, int numMinor, int minor) +void TSShapeLoader::updateProgress(S32 major, const char* msg, S32 numMinor, S32 minor) { // Calculate progress value F32 progress = (F32)major / NumLoadPhases; @@ -229,7 +240,7 @@ bool cmpShapeName(const String& key, const Vector& names, void* arg1, vo String getUniqueName(const char* name, NameCmpFunc isNameUnique, const Vector& names, void* arg1=0, void* arg2=0) { - const int MAX_ITERATIONS = 0x10000; // maximum of 4 characters (A-P) will be appended + const S32 MAX_ITERATIONS = 0x10000; // maximum of 4 characters (A-P) will be appended String suffix; for (S32 i = 0; i < MAX_ITERATIONS; i++) @@ -336,7 +347,7 @@ void TSShapeLoader::recurseSubshape(AppNode* appNode, S32 parentIndex, bool recu // Create children if (recurseChildren) { - for (int iChild = 0; iChild < appNode->getNumChildNodes(); iChild++) + for (S32 iChild = 0; iChild < appNode->getNumChildNodes(); iChild++) recurseSubshape(appNode->getChildNode(iChild), myIndex, true); } } @@ -500,9 +511,9 @@ void TSShapeLoader::generateObjects() void TSShapeLoader::generateSkins() { Vector skins; - for (int iObject = 0; iObject < shape->objects.size(); iObject++) + for (S32 iObject = 0; iObject < shape->objects.size(); iObject++) { - for (int iMesh = 0; iMesh < shape->objects[iObject].numMeshes; iMesh++) + for (S32 iMesh = 0; iMesh < shape->objects[iObject].numMeshes; iMesh++) { AppMesh* mesh = appMeshes[shape->objects[iObject].startMeshIndex + iMesh]; if (mesh->isSkin()) @@ -510,7 +521,7 @@ void TSShapeLoader::generateSkins() } } - for (int iSkin = 0; iSkin < skins.size(); iSkin++) + for (S32 iSkin = 0; iSkin < skins.size(); iSkin++) { updateProgress(Load_GenerateSkins, "Generating skins...", skins.size(), iSkin); @@ -524,11 +535,11 @@ void TSShapeLoader::generateSkins() // Map bones to nodes skin->nodeIndex.setSize(skin->bones.size()); - for (int iBone = 0; iBone < skin->bones.size(); iBone++) + for (S32 iBone = 0; iBone < skin->bones.size(); iBone++) { // Find the node that matches this bone skin->nodeIndex[iBone] = -1; - for (int iNode = 0; iNode < appNodes.size(); iNode++) + for (S32 iNode = 0; iNode < appNodes.size(); iNode++) { if (appNodes[iNode]->isEqual(skin->bones[iBone])) { @@ -551,7 +562,7 @@ void TSShapeLoader::generateSkins() void TSShapeLoader::generateDefaultStates() { // Generate default object states (includes initial geometry) - for (int iObject = 0; iObject < shape->objects.size(); iObject++) + for (S32 iObject = 0; iObject < shape->objects.size(); iObject++) { updateProgress(Load_GenerateDefaultStates, "Generating initial mesh and node states...", shape->objects.size(), iObject); @@ -559,7 +570,7 @@ void TSShapeLoader::generateDefaultStates() TSShape::Object& obj = shape->objects[iObject]; // Calculate the objectOffset for each mesh at T=0 - for (int iMesh = 0; iMesh < obj.numMeshes; iMesh++) + for (S32 iMesh = 0; iMesh < obj.numMeshes; iMesh++) { AppMesh* appMesh = appMeshes[obj.startMeshIndex + iMesh]; AppNode* appNode = obj.nodeIndex >= 0 ? appNodes[obj.nodeIndex] : boundsNode; @@ -576,7 +587,7 @@ void TSShapeLoader::generateDefaultStates() } // Generate default node transforms - for (int iNode = 0; iNode < appNodes.size(); iNode++) + for (S32 iNode = 0; iNode < appNodes.size(); iNode++) { // Determine the default translation and rotation for the node QuatF rot, srot; @@ -610,7 +621,7 @@ void TSShapeLoader::generateObjectState(TSShape::Object& obj, F32 t, bool addFra void TSShapeLoader::generateFrame(TSShape::Object& obj, F32 t, bool addFrame, bool addMatFrame) { - for (int iMesh = 0; iMesh < obj.numMeshes; iMesh++) + for (S32 iMesh = 0; iMesh < obj.numMeshes; iMesh++) { AppMesh* appMesh = appMeshes[obj.startMeshIndex + iMesh]; @@ -690,7 +701,7 @@ void TSShapeLoader::generateMaterialList() { // Install the materials into the material list shape->materialList = new TSMaterialList; - for (int iMat = 0; iMat < AppMesh::appMaterials.size(); iMat++) + for (S32 iMat = 0; iMat < AppMesh::appMaterials.size(); iMat++) { updateProgress(Load_GenerateMaterials, "Generating materials...", AppMesh::appMaterials.size(), iMat); @@ -705,7 +716,7 @@ void TSShapeLoader::generateMaterialList() void TSShapeLoader::generateSequences() { - for (int iSeq = 0; iSeq < appSequences.size(); iSeq++) + for (S32 iSeq = 0; iSeq < appSequences.size(); iSeq++) { updateProgress(Load_GenerateSequences, "Generating sequences...", appSequences.size(), iSeq); @@ -783,14 +794,14 @@ void TSShapeLoader::setNodeMembership(TSShape::Sequence& seq, const AppSequence* void TSShapeLoader::setRotationMembership(TSShape::Sequence& seq) { - for (int iNode = 0; iNode < appNodes.size(); iNode++) + for (S32 iNode = 0; iNode < appNodes.size(); iNode++) { // Check if any of the node rotations are different to // the default rotation QuatF defaultRot; shape->defaultRotations[iNode].getQuatF(&defaultRot); - for (int iFrame = 0; iFrame < seq.numKeyframes; iFrame++) + for (S32 iFrame = 0; iFrame < seq.numKeyframes; iFrame++) { if (nodeRotCache[iNode][iFrame] != defaultRot) { @@ -803,13 +814,13 @@ void TSShapeLoader::setRotationMembership(TSShape::Sequence& seq) void TSShapeLoader::setTranslationMembership(TSShape::Sequence& seq) { - for (int iNode = 0; iNode < appNodes.size(); iNode++) + for (S32 iNode = 0; iNode < appNodes.size(); iNode++) { // Check if any of the node translations are different to // the default translation Point3F& defaultTrans = shape->defaultTranslations[iNode]; - for (int iFrame = 0; iFrame < seq.numKeyframes; iFrame++) + for (S32 iFrame = 0; iFrame < seq.numKeyframes; iFrame++) { if (!nodeTransCache[iNode][iFrame].equal(defaultTrans)) { @@ -828,10 +839,10 @@ void TSShapeLoader::setScaleMembership(TSShape::Sequence& seq) U32 alignedScaleCount = 0; U32 uniformScaleCount = 0; - for (int iNode = 0; iNode < appNodes.size(); iNode++) + for (S32 iNode = 0; iNode < appNodes.size(); iNode++) { // Check if any of the node scales are not the unit scale - for (int iFrame = 0; iFrame < seq.numKeyframes; iFrame++) + for (S32 iFrame = 0; iFrame < seq.numKeyframes; iFrame++) { Point3F& scale = nodeScaleCache[iNode][iFrame]; if (!unitScale.equal(scale)) @@ -865,7 +876,7 @@ void TSShapeLoader::setObjectMembership(TSShape::Sequence& seq, const AppSequenc seq.frameMatters.clearAll(); // vert animation (morph) (size = objects.size()) seq.matFrameMatters.clearAll(); // UV animation (size = objects.size()) - for (int iObject = 0; iObject < shape->objects.size(); iObject++) + for (S32 iObject = 0; iObject < shape->objects.size(); iObject++) { if (!appMeshes[shape->objects[iObject].startMeshIndex]) continue; @@ -883,16 +894,16 @@ void TSShapeLoader::setObjectMembership(TSShape::Sequence& seq, const AppSequenc void TSShapeLoader::clearNodeTransformCache() { // clear out the transform caches - for (int i = 0; i < nodeRotCache.size(); i++) + for (S32 i = 0; i < nodeRotCache.size(); i++) delete [] nodeRotCache[i]; nodeRotCache.clear(); - for (int i = 0; i < nodeTransCache.size(); i++) + for (S32 i = 0; i < nodeTransCache.size(); i++) delete [] nodeTransCache[i]; nodeTransCache.clear(); - for (int i = 0; i < nodeScaleRotCache.size(); i++) + for (S32 i = 0; i < nodeScaleRotCache.size(); i++) delete [] nodeScaleRotCache[i]; nodeScaleRotCache.clear(); - for (int i = 0; i < nodeScaleCache.size(); i++) + for (S32 i = 0; i < nodeScaleCache.size(); i++) delete [] nodeScaleCache[i]; nodeScaleCache.clear(); } @@ -903,23 +914,23 @@ void TSShapeLoader::fillNodeTransformCache(TSShape::Sequence& seq, const AppSequ clearNodeTransformCache(); nodeRotCache.setSize(appNodes.size()); - for (int i = 0; i < nodeRotCache.size(); i++) + for (S32 i = 0; i < nodeRotCache.size(); i++) nodeRotCache[i] = new QuatF[seq.numKeyframes]; nodeTransCache.setSize(appNodes.size()); - for (int i = 0; i < nodeTransCache.size(); i++) + for (S32 i = 0; i < nodeTransCache.size(); i++) nodeTransCache[i] = new Point3F[seq.numKeyframes]; nodeScaleRotCache.setSize(appNodes.size()); - for (int i = 0; i < nodeScaleRotCache.size(); i++) + for (S32 i = 0; i < nodeScaleRotCache.size(); i++) nodeScaleRotCache[i] = new QuatF[seq.numKeyframes]; nodeScaleCache.setSize(appNodes.size()); - for (int i = 0; i < nodeScaleCache.size(); i++) + for (S32 i = 0; i < nodeScaleCache.size(); i++) nodeScaleCache[i] = new Point3F[seq.numKeyframes]; // get the node transforms for every frame - for (int iFrame = 0; iFrame < seq.numKeyframes; iFrame++) + for (S32 iFrame = 0; iFrame < seq.numKeyframes; iFrame++) { F32 time = appSeq->getStart() + seq.duration * iFrame / getMax(1, seq.numKeyframes - 1); - for (int iNode = 0; iNode < appNodes.size(); iNode++) + for (S32 iNode = 0; iNode < appNodes.size(); iNode++) { generateNodeTransform(appNodes[iNode], time, seq.isBlend(), appSeq->getBlendRefTime(), nodeRotCache[iNode][iFrame], nodeTransCache[iNode][iFrame], @@ -973,9 +984,9 @@ void TSShapeLoader::generateNodeAnimation(TSShape::Sequence& seq) (seq.flags & TSShape::AlignedScale) ? shape->nodeAlignedScales.size() : shape->nodeUniformScales.size(); - for (int iNode = 0; iNode < appNodes.size(); iNode++) + for (S32 iNode = 0; iNode < appNodes.size(); iNode++) { - for (int iFrame = 0; iFrame < seq.numKeyframes; iFrame++) + for (S32 iFrame = 0; iFrame < seq.numKeyframes; iFrame++) { if (seq.rotationMatters.test(iNode)) addNodeRotation(nodeRotCache[iNode][iFrame], false); @@ -1001,7 +1012,7 @@ void TSShapeLoader::generateObjectAnimation(TSShape::Sequence& seq, const AppSeq { seq.baseObjectState = shape->objectStates.size(); - for (int iObject = 0; iObject < shape->objects.size(); iObject++) + for (S32 iObject = 0; iObject < shape->objects.size(); iObject++) { bool visMatters = seq.visMatters.test(iObject); bool frameMatters = seq.frameMatters.test(iObject); @@ -1009,7 +1020,7 @@ void TSShapeLoader::generateObjectAnimation(TSShape::Sequence& seq, const AppSeq if (visMatters || frameMatters || matFrameMatters) { - for (int iFrame = 0; iFrame < seq.numKeyframes; iFrame++) + for (S32 iFrame = 0; iFrame < seq.numKeyframes; iFrame++) { F32 time = appSeq->getStart() + seq.duration * iFrame / getMax(1, seq.numKeyframes - 1); generateObjectState(shape->objects[iObject], time, frameMatters, matFrameMatters); @@ -1036,7 +1047,7 @@ void TSShapeLoader::generateGroundAnimation(TSShape::Sequence& seq, const AppSeq zapScale(invStartMat); invStartMat.inverse(); - for (int iFrame = 0; iFrame < seq.numGroundFrames; iFrame++) + for (S32 iFrame = 0; iFrame < seq.numGroundFrames; iFrame++) { F32 time = appSeq->getStart() + seq.duration * iFrame / getMax(1, seq.numGroundFrames - 1); @@ -1064,7 +1075,7 @@ void TSShapeLoader::generateFrameTriggers(TSShape::Sequence& seq, const AppSeque seq.flags |= TSShape::MakePath; // Add triggers - for (int iTrigger = 0; iTrigger < seq.numTriggers; iTrigger++) + for (S32 iTrigger = 0; iTrigger < seq.numTriggers; iTrigger++) { shape->triggers.increment(); appSeq->getTrigger(iTrigger, shape->triggers.last()); @@ -1075,7 +1086,7 @@ void TSShapeLoader::generateFrameTriggers(TSShape::Sequence& seq, const AppSeque // need to mark ourselves as such so that on/off can become off/on when sequence // is played in reverse... U32 offTriggers = 0; - for (int iTrigger = 0; iTrigger < seq.numTriggers; iTrigger++) + for (S32 iTrigger = 0; iTrigger < seq.numTriggers; iTrigger++) { U32 state = shape->triggers[seq.firstTrigger+iTrigger].state; if ((state & TSShape::Trigger::StateOn) == 0) @@ -1098,18 +1109,18 @@ void TSShapeLoader::sortDetails() // Insert NULL meshes where required - for (int iSub = 0; iSub < subshapes.size(); iSub++) + for (S32 iSub = 0; iSub < subshapes.size(); iSub++) { Vector validDetails; shape->getSubShapeDetails(iSub, validDetails); - for (int iDet = 0; iDet < validDetails.size(); iDet++) + for (S32 iDet = 0; iDet < validDetails.size(); iDet++) { TSShape::Detail &detail = shape->details[validDetails[iDet]]; if (detail.subShapeNum >= 0) detail.objectDetailNum = iDet; - for (int iObj = shape->subShapeFirstObject[iSub]; + for (S32 iObj = shape->subShapeFirstObject[iSub]; iObj < (shape->subShapeFirstObject[iSub] + shape->subShapeNumObjects[iSub]); iObj++) { @@ -1126,7 +1137,7 @@ void TSShapeLoader::sortDetails() object.numMeshes++; // Fixup the start index for the other objects - for (int k = iObj+1; k < shape->objects.size(); k++) + for (S32 k = iObj+1; k < shape->objects.size(); k++) shape->objects[k].startMeshIndex++; } } @@ -1256,17 +1267,67 @@ TSShapeLoader::~TSShapeLoader() clearNodeTransformCache(); // Clear shared AppMaterial list - for (int iMat = 0; iMat < AppMesh::appMaterials.size(); iMat++) + for (S32 iMat = 0; iMat < AppMesh::appMaterials.size(); iMat++) delete AppMesh::appMaterials[iMat]; AppMesh::appMaterials.clear(); // Delete Subshapes delete boundsNode; - for (int iSub = 0; iSub < subshapes.size(); iSub++) + for (S32 iSub = 0; iSub < subshapes.size(); iSub++) delete subshapes[iSub]; // Delete AppSequences - for (int iSeq = 0; iSeq < appSequences.size(); iSeq++) + for (S32 iSeq = 0; iSeq < appSequences.size(); iSeq++) delete appSequences[iSeq]; appSequences.clear(); } + +// Static functions to handle supported formats for shape loader. +void TSShapeLoader::addFormat(String name, String extension) +{ + ShapeFormat newFormat; + newFormat.mName = name; + newFormat.mExtension = extension; + smFormats.push_back(newFormat); +} + +String TSShapeLoader::getFormatExtensions() +{ + // "*.dsq TAB *.dae TAB + StringBuilder output; + for(U32 n = 0; n < smFormats.size(); ++n) + { + output.append("*."); + output.append(smFormats[n].mExtension); + output.append("\t"); + } + return output.end(); +} + +String TSShapeLoader::getFormatFilters() +{ + // "DSQ Files|*.dsq|COLLADA Files|*.dae|" + StringBuilder output; + for(U32 n = 0; n < smFormats.size(); ++n) + { + output.append(smFormats[n].mName); + output.append("|*."); + output.append(smFormats[n].mExtension); + output.append("|"); + } + return output.end(); +} + +DefineConsoleFunction( getFormatExtensions, const char*, ( ),, + "Returns a list of supported shape format extensions separated by tabs." + "Example output: *.dsq TAB *.dae TAB") +{ + return Con::getReturnBuffer(TSShapeLoader::getFormatExtensions()); +} + +DefineConsoleFunction( getFormatFilters, const char*, ( ),, + "Returns a list of supported shape formats in filter form.\n" + "Example output: DSQ Files|*.dsq|COLLADA Files|*.dae|") +{ + return Con::getReturnBuffer(TSShapeLoader::getFormatFilters()); +} diff --git a/Engine/source/ts/loader/tsShapeLoader.h b/Engine/source/ts/loader/tsShapeLoader.h index 83e9db0ca..32b462e46 100644 --- a/Engine/source/ts/loader/tsShapeLoader.h +++ b/Engine/source/ts/loader/tsShapeLoader.h @@ -45,6 +45,19 @@ class TSShapeLoader { +// Supported Format List +protected: + struct ShapeFormat + { + String mName; + String mExtension; + }; + static Vector smFormats; +public: + static void addFormat(String name, String extension); + static String getFormatExtensions(); + static String getFormatFilters(); + public: enum eLoadPhases { @@ -63,7 +76,7 @@ public: Load_Complete = NumLoadPhases }; - static void updateProgress(int major, const char* msg, int numMinor=0, int minor=0); + static void updateProgress(S32 major, const char* msg, S32 numMinor=0, S32 minor=0); protected: struct Subshape @@ -82,9 +95,9 @@ protected: public: static const F32 DefaultTime; - static const double MinFrameRate; - static const double MaxFrameRate; - static const double AppGroundFrameRate; + static const F64 MinFrameRate; + static const F64 MaxFrameRate; + static const F64 AppGroundFrameRate; protected: // Variables used during loading that must be held until the shape is deleted diff --git a/Engine/source/ts/tsLastDetail.h b/Engine/source/ts/tsLastDetail.h index adfd6b5ac..abfb3bac1 100644 --- a/Engine/source/ts/tsLastDetail.h +++ b/Engine/source/ts/tsLastDetail.h @@ -62,12 +62,12 @@ GFXDeclareVertexFormat( ImposterState ) /// .xyz = imposter center /// .w = billboard corner... damn SM 2.0 Point3F center; - float corner; + F32 corner; /// .x = scaled half size /// .y = alpha fade out - float halfSize; - float alpha; + F32 halfSize; + F32 alpha; /// The rotation encoded as the up /// and right vectors... cross FTW. diff --git a/Engine/source/ts/tsMesh.cpp b/Engine/source/ts/tsMesh.cpp index d857c0547..6648ae931 100644 --- a/Engine/source/ts/tsMesh.cpp +++ b/Engine/source/ts/tsMesh.cpp @@ -1203,7 +1203,7 @@ void TSSkinMesh::updateSkin( const Vector &transforms, TSVertexBufferHa // set up bone transforms PROFILE_START(TSSkinMesh_UpdateTransforms); - for( int i=0; i &transforms, TSVertexBufferHa skinnedVert.zero(); skinnedNorm.zero(); - for( int tOp = 0; tOp < curVert.transformCount; tOp++ ) + for( S32 tOp = 0; tOp < curVert.transformCount; tOp++ ) { const BatchData::TransformOp &transformOp = curVert.transform[tOp]; @@ -1418,7 +1418,7 @@ void TSSkinMesh::createBatchData() itr != batchOperations.end(); itr++ ) { const BatchData::BatchedVertex &curTransform = *itr; - for( int i = 0; i < curTransform.transformCount; i++ ) + for( S32 i = 0; i < curTransform.transformCount; i++ ) { const BatchData::TransformOp &transformOp = curTransform.transform[i]; @@ -1443,8 +1443,8 @@ void TSSkinMesh::createBatchData() // Now iterate the resulting operations and convert the vectors to aligned // memory locations - const int numBatchOps = batchData.transformKeys.size(); - for(int i = 0; i < numBatchOps; i++) + const S32 numBatchOps = batchData.transformKeys.size(); + for(S32 i = 0; i < numBatchOps; i++) { BatchData::BatchedTransform &curTransform = *batchData.transformBatchOperations.retreive(batchData.transformKeys[i]); const S32 numVerts = curTransform._tmpVec->size(); @@ -1462,7 +1462,7 @@ void TSSkinMesh::createBatchData() } // Now sort the batch data so that the skin function writes close to linear output - for(int i = 0; i < numBatchOps; i++) + for(S32 i = 0; i < numBatchOps; i++) { BatchData::BatchedTransform &curTransform = *batchData.transformBatchOperations.retreive(batchData.transformKeys[i]); dQsort(curTransform.alignedMem, curTransform.numElements, sizeof(BatchData::BatchedVertWeight), _sort_BatchedVertWeight); @@ -2558,7 +2558,7 @@ void TSMesh::assemble( bool skip ) // need to copy to temporary arrays deleteInputArrays = true; primIn = new TSDrawPrimitive[szPrimIn]; - for (int i = 0; i < szPrimIn; i++) + for (S32 i = 0; i < szPrimIn; i++) { primIn[i].start = prim16[i*2]; primIn[i].numElements = prim16[i*2+1]; @@ -2917,8 +2917,11 @@ inline void TSMesh::findTangent( U32 index1, F32 denom = (s1 * t2 - s2 * t1); if( mFabs( denom ) < 0.0001f ) - return; // handle degenerate triangles from strips - + { + // handle degenerate triangles from strips + if (denom<0) denom = -0.0001f; + else denom = 0.0001f; + } F32 r = 1.0f / denom; Point3F sdir( (t2 * x1 - t1 * x2) * r, @@ -2946,7 +2949,11 @@ inline void TSMesh::findTangent( U32 index1, void TSMesh::createTangents(const Vector &_verts, const Vector &_norms) { U32 numVerts = _verts.size(); - if ( numVerts == 0 ) + U32 numNorms = _norms.size(); + if ( numVerts <= 0 || numNorms <= 0 ) + return; + + if( numVerts != numNorms) return; Vector tan0; diff --git a/Engine/source/ts/tsMesh.h b/Engine/source/ts/tsMesh.h index 0db76ecc8..d2ac79087 100644 --- a/Engine/source/ts/tsMesh.h +++ b/Engine/source/ts/tsMesh.h @@ -214,7 +214,7 @@ class TSMesh } // Vector-like interface - __TSMeshVertexBase &operator[](int idx) const { AssertFatal(idx < numElements, "Out of bounds access!"); return *reinterpret_cast<__TSMeshVertexBase *>(base + idx * vertSz); } + __TSMeshVertexBase &operator[](S32 idx) const { AssertFatal(idx < numElements, "Out of bounds access!"); return *reinterpret_cast<__TSMeshVertexBase *>(base + idx * vertSz); } __TSMeshVertexBase *address() const { return reinterpret_cast<__TSMeshVertexBase *>(base); } U32 size() const { return numElements; } dsize_t mem_size() const { return numElements * vertSz; } diff --git a/Engine/source/ts/tsMeshIntrinsics.cpp b/Engine/source/ts/tsMeshIntrinsics.cpp index fbc93fbe8..94b9abd22 100644 --- a/Engine/source/ts/tsMeshIntrinsics.cpp +++ b/Engine/source/ts/tsMeshIntrinsics.cpp @@ -38,7 +38,7 @@ void zero_vert_normal_bulk_C(const dsize_t count, U8 * __restrict const outPtr, // TODO: Try prefetch w/ ptr de-reference - for(register int i = 0; i < count; i++) + for(register S32 i = 0; i < count; i++) { TSMesh::__TSMeshVertexBase *outElem = reinterpret_cast(outData); outElem->_vert.zero(); @@ -60,7 +60,7 @@ void m_matF_x_BatchedVertWeightList_C(const MatrixF &mat, register Point3F tempPt; register Point3F tempNrm; - for(register int i = 0; i < count; i++) + for(register S32 i = 0; i < count; i++) { const TSSkinMesh::BatchData::BatchedVertWeight &inElem = batch[i]; diff --git a/Engine/source/ts/tsShape.cpp b/Engine/source/ts/tsShape.cpp index 726efabff..7b160b670 100644 --- a/Engine/source/ts/tsShape.cpp +++ b/Engine/source/ts/tsShape.cpp @@ -1170,7 +1170,10 @@ void TSShape::assembleShape() skip = true; TSMesh * mesh = TSMesh::assembleMesh(meshType,skip); if (ptr32) + { ptr32[i] = skip ? 0 : (S32)mesh; + meshes.push_back(skip ? 0 : mesh); + } // fill in location of verts, tverts, and normals for detail levels if (mesh && meshType!=TSMesh::DecalMeshType) @@ -1198,7 +1201,6 @@ void TSShape::assembleShape() } } } - meshes.set(ptr32,numMeshes); tsalloc.checkGuard(); @@ -1225,7 +1227,7 @@ void TSShape::assembleShape() if (smReadVersion<23) { // get detail information about skins... - S32 * detailFirstSkin = tsalloc.getPointer32(numDetails); + S32 * detFirstSkin = tsalloc.getPointer32(numDetails); S32 * detailNumSkins = tsalloc.getPointer32(numDetails); tsalloc.checkGuard(); @@ -1257,7 +1259,7 @@ void TSShape::assembleShape() ptr32 = tsalloc.allocShape32(numSkins); for (i=0; idetails[objectDetails[index]].size); + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%s %d", name, (S32)mShape->details[objectDetails[index]].size); return returnBuffer; }} @@ -1602,8 +1603,9 @@ DefineTSShapeConstructorMethod( getImposterSettings, const char*, ( S32 index ), // Return information about the detail level const TSShape::Detail& det = mShape->details[index]; - char* returnBuffer = Con::getReturnBuffer(512); - dSprintf(returnBuffer, 512, "%d\t%d\t%d\t%d\t%d\t%d\t%g", + static const U32 bufSize = 512; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%d\t%d\t%d\t%d\t%d\t%d\t%g", (S32)( det.subShapeNum < 0 ), // isImposter det.bbEquatorSteps, det.bbPolarSteps, @@ -1727,8 +1729,9 @@ DefineTSShapeConstructorMethod( getSequenceSource, const char*, ( const char* na GET_SEQUENCE( getSequenceSource, seq, name, "" ); // Return information about the source data for this sequence - char* returnBuffer = Con::getReturnBuffer(512); - dSprintf( returnBuffer, 512, "%s\t%d\t%d\t%d", + static const U32 bufSize = 512; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf( returnBuffer, bufSize, "%s\t%d\t%d\t%d", seq->sourceData.from.c_str(), seq->sourceData.start, seq->sourceData.end, seq->sourceData.total ); return returnBuffer; @@ -1802,8 +1805,9 @@ DefineTSShapeConstructorMethod( getSequenceGroundSpeed, const char*, ( const cha rot = mat.toEuler(); } - char* returnBuffer = Con::getReturnBuffer(256); - dSprintf( returnBuffer, 256, "%g %g %g %g %g %g", + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf( returnBuffer, bufSize, "%g %g %g %g %g %g", trans.x, trans.y, trans.z, rot.x, rot.y, rot.z ); return returnBuffer; }} @@ -1896,8 +1900,9 @@ DefineTSShapeConstructorMethod( getSequenceBlend, const char*, ( const char* nam GET_SEQUENCE( getSequenceBlend, seq, name, "0" ); // Return the blend information (flag reference_sequence reference_frame) - char* returnBuffer = Con::getReturnBuffer(512); - dSprintf( returnBuffer, 512, "%d\t%s\t%d", (int)seq->isBlend(), + static const U32 bufSize = 512; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf( returnBuffer, bufSize, "%d\t%s\t%d", (int)seq->isBlend(), seq->sourceData.blendSeq.c_str(), seq->sourceData.blendFrame ); return returnBuffer; }} @@ -2038,8 +2043,9 @@ DefineTSShapeConstructorMethod( getTrigger, const char*, ( const char* name, S32 if (!(trig.state & TSShape::Trigger::StateOn)) state = -state; - char* returnBuffer = Con::getReturnBuffer(32); - dSprintf(returnBuffer, 32, "%d %d", frame, state); + static const U32 bufSize = 32; + char* returnBuffer = Con::getReturnBuffer(bufSize); + dSprintf(returnBuffer, bufSize, "%d %d", frame, state); return returnBuffer; }} diff --git a/Engine/source/ts/tsShapeConstruct.h b/Engine/source/ts/tsShapeConstruct.h index 52d129837..640c80c91 100644 --- a/Engine/source/ts/tsShapeConstruct.h +++ b/Engine/source/ts/tsShapeConstruct.h @@ -213,7 +213,7 @@ public: void write(TSShape* shape, Stream& stream, const String& savePath); }; - static const int MaxLegacySequences = 127; + static const S32 MaxLegacySequences = 127; protected: FileName mShapePath; diff --git a/Engine/source/ts/tsShapeEdit.cpp b/Engine/source/ts/tsShapeEdit.cpp index bcfb34367..8d585022f 100644 --- a/Engine/source/ts/tsShapeEdit.cpp +++ b/Engine/source/ts/tsShapeEdit.cpp @@ -155,7 +155,7 @@ S32 TSShape::addDetail(const String& dname, S32 size, S32 subShapeNum) alphaOut.increment(); // Fixup objectDetailNum in other detail levels - for (int i = index+1; i < details.size(); i++) + for (S32 i = index+1; i < details.size(); i++) { if ((details[i].subShapeNum >= 0) && ((subShapeNum == -1) || (details[i].subShapeNum == subShapeNum))) @@ -1521,7 +1521,7 @@ bool TSShape::addSequence(const Torque::Path& path, const String& fromSeq, // Check if visibility is animated within the frames to be copied const F32 defaultVis = srcShape->objectStates[i].vis; S32 objNum = srcSeq->visMatters.count(i); - for (int iFrame = startFrame; iFrame <= endFrame; iFrame++) + for (S32 iFrame = startFrame; iFrame <= endFrame; iFrame++) { if (srcShape->getObjectState(*srcSeq, iFrame, objNum).vis != defaultVis) { @@ -1600,7 +1600,7 @@ bool TSShape::addSequence(const Torque::Path& path, const String& fromSeq, // Check if node position is animated within the frames to be copied const Point3F& defaultTrans = srcShape->defaultTranslations[i]; S32 tranNum = srcSeq->translationMatters.count(i); - for (int iFrame = startFrame; iFrame <= endFrame; iFrame++) + for (S32 iFrame = startFrame; iFrame <= endFrame; iFrame++) { if (srcShape->getTranslation(*srcSeq, iFrame, tranNum) != defaultTrans) { @@ -1615,7 +1615,7 @@ bool TSShape::addSequence(const Torque::Path& path, const String& fromSeq, // Check if node rotation is animated within the frames to be copied const QuatF defaultRot = srcShape->defaultRotations[i].getQuatF(); S32 rotNum = srcSeq->rotationMatters.count(i); - for (int iFrame = startFrame; iFrame <= endFrame; iFrame++) + for (S32 iFrame = startFrame; iFrame <= endFrame; iFrame++) { QuatF temp; if (srcShape->getRotation(*srcSeq, iFrame, rotNum, &temp) != defaultRot) @@ -1634,7 +1634,7 @@ bool TSShape::addSequence(const Torque::Path& path, const String& fromSeq, { TSScale defaultScale; defaultScale.identity(); - for (int iFrame = startFrame; iFrame <= endFrame; iFrame++) + for (S32 iFrame = startFrame; iFrame <= endFrame; iFrame++) { TSScale temp; if (!(srcShape->getArbitraryScale(*srcSeq, iFrame, scaleNum, &temp) == defaultScale)) @@ -1647,7 +1647,7 @@ bool TSShape::addSequence(const Torque::Path& path, const String& fromSeq, else if (srcSeq->animatesAlignedScale()) { const Point3F defaultScale(Point3F::One); - for (int iFrame = startFrame; iFrame <= endFrame; iFrame++) + for (S32 iFrame = startFrame; iFrame <= endFrame; iFrame++) { if (srcShape->getAlignedScale(*srcSeq, iFrame, scaleNum) != defaultScale) { @@ -1659,7 +1659,7 @@ bool TSShape::addSequence(const Torque::Path& path, const String& fromSeq, else if (srcSeq->animatesUniformScale()) { const F32 defaultScale = 1.0f; - for (int iFrame = startFrame; iFrame <= endFrame; iFrame++) + for (S32 iFrame = startFrame; iFrame <= endFrame; iFrame++) { if (srcShape->getUniformScale(*srcSeq, iFrame, scaleNum) != defaultScale) { diff --git a/Engine/source/ts/tsShapeInstance.cpp b/Engine/source/ts/tsShapeInstance.cpp index cbe2ffc94..d8722b6f9 100644 --- a/Engine/source/ts/tsShapeInstance.cpp +++ b/Engine/source/ts/tsShapeInstance.cpp @@ -616,6 +616,11 @@ S32 TSShapeInstance::setDetailFromDistance( const SceneRenderState *state, F32 s F32 pixelRadius = ( mShape->radius / scaledDistance ) * state->getWorldToScreenScale().y * pixelScale; F32 pixelSize = pixelRadius * smDetailAdjust; + if ( pixelSize < smSmallestVisiblePixelSize ) { + mCurrentDetailLevel = -1; + return mCurrentDetailLevel; + } + if ( pixelSize > smSmallestVisiblePixelSize && pixelSize <= mShape->mSmallestVisibleSize ) pixelSize = mShape->mSmallestVisibleSize + 0.01f; diff --git a/Engine/source/ts/tsShapeInstance.h b/Engine/source/ts/tsShapeInstance.h index f507f7153..7f83851c4 100644 --- a/Engine/source/ts/tsShapeInstance.h +++ b/Engine/source/ts/tsShapeInstance.h @@ -485,8 +485,8 @@ protected: /// @} - virtual void render( const TSRenderState &rdata ); - virtual void render( const TSRenderState &rdata, S32 dl, F32 intraDL = 0.0f ); + void render( const TSRenderState &rdata ); + void render( const TSRenderState &rdata, S32 dl, F32 intraDL = 0.0f ); void animate() { animate( mCurrentDetailLevel ); } void animate(S32 dl); diff --git a/Engine/source/ts/tsShapeOldRead.cpp b/Engine/source/ts/tsShapeOldRead.cpp index e76198de3..d20175a2e 100644 --- a/Engine/source/ts/tsShapeOldRead.cpp +++ b/Engine/source/ts/tsShapeOldRead.cpp @@ -29,7 +29,7 @@ // put old skins into object list //------------------------------------------------- -void TSShape::fixupOldSkins(S32 numMeshes, S32 numSkins, S32 numDetails, S32 * detailFirstSkin, S32 * detailNumSkins) +void TSShape::fixupOldSkins(S32 numMeshes, S32 numSkins, S32 numDetails, S32 * detFirstSkin, S32 * detailNumSkins) { #if !defined(TORQUE_MAX_LIB) // this method not necessary in exporter, and a couple lines won't compile for exporter @@ -63,9 +63,9 @@ void TSShape::fixupOldSkins(S32 numMeshes, S32 numSkins, S32 numDetails, S32 * d // find one mesh per detail to add to this object // don't really need to be versions of the same object i = 0; - while (i -#include - -#include "core/strings/stringFunctions.h" - -#include "console/console.h" - -#include "unit/test.h" - - -namespace UnitTesting -{ - -//----------------------------------------------------------------------------- - -TestRegistry *TestRegistry::_list = 0; - - -//----------------------------------------------------------------------------- - -static const int MaxMarginCount = 32; -static const int MaxMarginValue = 128; -static int _Margin[MaxMarginCount] = { 3 }; -static int* _MarginPtr = _Margin; -static char _MarginString[MaxMarginValue]; - -static void _printMargin() -{ - if (*_MarginPtr) - ::fwrite(_MarginString,1,*_MarginPtr,stdout); -} - -void UnitMargin::Push(int margin) -{ - if (_MarginPtr < _Margin + MaxMarginCount) { - *++_MarginPtr = (margin < MaxMarginValue)? margin: MaxMarginValue; - memset(_MarginString,' ',*_MarginPtr); - } -} - -void UnitMargin::Pop() -{ - if (_MarginPtr > _Margin) { - _MarginPtr--; - memset(_MarginString,' ',*_MarginPtr); - } -} - -int UnitMargin::Current() -{ - return *_MarginPtr; -} - -void UnitPrint(const char* str) -{ - static bool lineStart = true; - Platform::outputDebugString(str); - - // Need to scan for '\n' in order to support margins - const char* ptr = str, *itr = ptr; - for (; *itr != 0; itr++) - if (*itr == '\n') - { - if (lineStart) - _printMargin(); - ::fwrite(ptr,1,itr - ptr + 1,stdout); - ptr = itr + 1; - lineStart = true; - } - - // End the line with a carriage return unless the - // line ends with a line continuation char. - if (ptr != itr) { - if (lineStart) - _printMargin(); - if (itr[-1] == '\\') { - ::fwrite(ptr,1,itr - ptr - 1,stdout); - lineStart = false; - } - else { - ::fwrite(ptr,1,itr - ptr,stdout); - ::fwrite("\n",1,1,stdout); - lineStart = true; - } - } - else { - ::fwrite("\n",1,1,stdout); - lineStart = true; - } - ::fflush(stdout); -} - - -//----------------------------------------------------------------------------- - -UnitTest::UnitTest() { - _testCount = 0; - _failureCount = 0; - _warningCount = 0; - _lastTestResult = true; -} - -void UnitTest::fail(const char* msg) -{ - Con::warnf("** Failed: %s",msg); - dFetchAndAdd( _failureCount, 1 ); -} - -void UnitTest::warn(const char* msg) -{ - Con::warnf("** Warning: %s",msg); - dFetchAndAdd( _warningCount, 1 ); -} - - -//----------------------------------------------------------------------------- - -TestRegistry::TestRegistry(const char* name, bool interactive, const char *className) -{ - // Check that no existing test uses the same class-name; this is guaranteed - // to lead to funkiness. - TestRegistry *walk = _list; - while(walk) - { - if(walk->_className) - { - AssertFatal(dStricmp(className, walk->_className), "TestRegistry::TestRegistry - got two unit tests with identical class names; they must have unique class names!"); - } - - walk = walk->_next; - } - - // Add us to the list. - _next = _list; - _list = this; - - // And fill in our fields. - _name = name; - _className = className; - _isInteractive = interactive; -} - -DynamicTestRegistration::DynamicTestRegistration( const char *name, UnitTest *test ) : TestRegistry( name, false, NULL ), mUnitTest( test ) -{ - -} - -DynamicTestRegistration::~DynamicTestRegistration() -{ - // Un-link ourselves from the test registry - TestRegistry *walk = _list; - - // Easy case! - if( walk == this ) - _list = _next; - else - { - // Search for us and remove - while( ( walk != 0 ) && ( walk->_next != 0 ) && ( walk->_next != this ) ) - walk = walk->_next; - - // When this loop is broken, walk will be the unit test in the list previous to this one - if( walk != 0 && walk->_next != 0 ) - walk->_next = walk->_next->_next; - } -} - - -//----------------------------------------------------------------------------- - -TestRun::TestRun() -{ - _subCount = 0; - _testCount = 0; - _failureCount = 0; - _warningCount = 0; -} - -void TestRun::printStats() -{ - Con::printf("-- %d test%s run (with %d sub-test%s)", - _testCount,(_testCount != 1)? "s": "", - _subCount,(_subCount != 1)? "s": ""); - - if (_testCount) - { - if (_failureCount) - Con::printf("** %d reported failure%s", - _failureCount,(_failureCount != 1)? "s": ""); - else if (_warningCount) - Con::printf("** %d reported warning%s", - _warningCount,(_warningCount != 1)? "s": ""); - else - Con::printf("-- No reported failures"); - } -} - -void TestRun::test(TestRegistry* reg) -{ - Con::printf("-- Testing: %s %s",reg->getName(), reg->isInteractive() ? "(interactive)" : "" ); - - UnitMargin::Push(_Margin[0]); - - // Run the test. - UnitTest* test = reg->newTest(); - test->run(); - - UnitMargin::Pop(); - - // Update stats. - _failureCount += test->getFailureCount(); - _subCount += test->getTestCount(); - _warningCount += test->getWarningCount(); - _testCount++; - - // Don't forget to delete the test! - delete test; -} - -// [tom, 2/5/2007] To provide a predictable environment for the tests, this -// now changes the current directory to the executable's directory before -// running the tests. The previous current directory is restored on exit. - -bool TestRun::test(const char* module, bool skipInteractive) -{ - StringTableEntry cwdSave = Platform::getCurrentDirectory(); - - int len = strlen(module); - - const char *skipMsg = skipInteractive ? "(skipping interactive tests)" : ""; - - // Indicate to the user what we're up to. - if (!len) - Con::printf("-- Running all unit tests %s", skipMsg); - else - Con::printf("-- Running %s tests %s",module, skipMsg); - - for (TestRegistry* itr = TestRegistry::getFirst(); itr; itr = itr->getNext()) - { - if (!len || !dStrnicmp(module,itr->getName(),len)) - { - // Skip the test if it's interactive and we're in skipinteractive mode. - if(skipInteractive && itr->isInteractive()) - continue; - - // Otherwise, run the test! - Platform::setCurrentDirectory(Platform::getMainDotCsDir()); - test(itr); - } - } - // Print out a nice report on how we did. - printStats(); - - Platform::setCurrentDirectory(cwdSave); - - // And indicate our failure situation in the return value. - return !_failureCount; -} - -} // Namespace - diff --git a/Engine/source/unit/test.h b/Engine/source/unit/test.h deleted file mode 100644 index 3f3f4dc3d..000000000 --- a/Engine/source/unit/test.h +++ /dev/null @@ -1,165 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef UNIT_UNITTESTING_H -#define UNIT_UNITTESTING_H - -#ifndef _PLATFORMINTRINSICS_H_ -# include "platform/platformIntrinsics.h" -#endif - - -namespace UnitTesting { - -//----------------------------------------------------------------------------- - -struct UnitMargin -{ -static void Push(int margin); -static void Pop(); -static int Current(); -}; - -void UnitPrint(const char* msg); - - -//----------------------------------------------------------------------------- - -class UnitTest { - int _testCount; - int _failureCount; - int _warningCount; - - bool _lastTestResult; - -public: - UnitTest(); - virtual ~UnitTest() {}; - - /// Test an assertion and note if it has failed. - bool test(bool a,const char* msg) { - dFetchAndAdd( _testCount, 1 ); - if (!a) - fail(msg); - _lastTestResult = a; - return a; - } - - /// Report a failture condition. - void fail(const char* msg); - - /// Report a warning - void warn(const char* msg); - - int getTestCount() const { return _testCount; } - int getFailureCount() const { return _failureCount; } - int getWarningCount() const { return _warningCount; } - bool lastTestPassed() const { return _lastTestResult; } - - /// Implement this with the specific test. - virtual void run() = 0; -}; - - -//----------------------------------------------------------------------------- - -class TestRegistry -{ - friend class DynamicTestRegistration; // Bless me, Father, for I have sinned, but this is damn cool - - static TestRegistry *_list; - TestRegistry *_next; - - const char *_name; - const char *_className; - bool _isInteractive; - -public: - TestRegistry(const char* name, bool interactive, const char *className); - virtual ~TestRegistry() {} - static TestRegistry* getFirst() { return _list; } - TestRegistry* getNext() { return _next; } - const char* getName() { return _name; } - const bool isInteractive() { return _isInteractive; } - virtual UnitTest* newTest() = 0; -}; - -template -class TestRegistration: public TestRegistry -{ -public: - virtual ~TestRegistration() - { - } - - TestRegistration(const char* name, bool interactive, const char *className) - : TestRegistry(name, interactive, className) - { - } - - virtual UnitTest* newTest() - { - return new T; - } -}; - -class DynamicTestRegistration : public TestRegistry -{ - - UnitTest *mUnitTest; - -public: - DynamicTestRegistration( const char *name, UnitTest *test ); - - virtual ~DynamicTestRegistration(); - - virtual UnitTest *newTest() { return mUnitTest; } -}; - - -//----------------------------------------------------------------------------- - -class TestRun { - int _testCount; - int _subCount; - int _failureCount; - int _warningCount; - void test(TestRegistry* reg); -public: - TestRun(); - void printStats(); - bool test(const char* module, bool skipInteractive = false); -}; - -#define CreateUnitTest(Class,Name) \ - class Class; \ - static UnitTesting::TestRegistration _UnitTester##Class (Name, false, #Class); \ - class Class : public UnitTesting::UnitTest - -#define CreateInteractiveTest(Class,Name) \ - class Class; \ - static UnitTesting::TestRegistration _UnitTester##Class (Name, true, #Class); \ - class Class : public UnitTesting::UnitTest - -} // Namespace - -#endif diff --git a/Engine/source/unit/tests/testDefaultConstruction.cpp b/Engine/source/unit/tests/testDefaultConstruction.cpp deleted file mode 100644 index 0eaac89a7..000000000 --- a/Engine/source/unit/tests/testDefaultConstruction.cpp +++ /dev/null @@ -1,67 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "unit/test.h" -#include "console/simObject.h" - - -using namespace UnitTesting; - - -// Test to ensure that all console classes in the system are default-constructible. - -CreateUnitTest( TestDefaultConstruction, "Console/DefaultConstruction" ) -{ - void run() - { - for( AbstractClassRep* classRep = AbstractClassRep::getClassList(); - classRep != NULL; - classRep = classRep->getNextClass() ) - { - // Create object. - - ConsoleObject* object = classRep->create(); - test( object, avar( "AbstractClassRep::create failed for class '%s'", classRep->getClassName() ) ); - if( !object ) - continue; - - // Make sure it's a SimObject. - - SimObject* simObject = dynamic_cast< SimObject* >( object ); - if( !simObject ) - { - SAFE_DELETE( object ); - continue; - } - - // Register the object. - - bool result = simObject->registerObject(); - test( result, avar( "registerObject failed for object of class '%s'", classRep->getClassName() ) ); - - if( result ) - simObject->deleteObject(); - else - SAFE_DELETE( simObject ); - } - } -}; diff --git a/Engine/source/unit/tests/testMatrixMul.cpp b/Engine/source/unit/tests/testMatrixMul.cpp deleted file mode 100644 index 7eb2cbc4f..000000000 --- a/Engine/source/unit/tests/testMatrixMul.cpp +++ /dev/null @@ -1,116 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "unit/test.h" -#include "math/mMath.h" -#include "math/mRandom.h" - -extern void default_matF_x_matF_C(const F32 *a, const F32 *b, F32 *mresult); -extern void mInstallLibrary_ASM(); - -// If we're x86 and not Mac, then include these. There's probably a better way to do this. -#if defined(TORQUE_CPU_X86) && !defined(TORQUE_OS_MAC) -extern "C" void Athlon_MatrixF_x_MatrixF(const F32 *matA, const F32 *matB, F32 *result); -extern "C" void SSE_MatrixF_x_MatrixF(const F32 *matA, const F32 *matB, F32 *result); -#endif - -#if defined( __VEC__ ) -extern void vec_MatrixF_x_MatrixF(const F32 *matA, const F32 *matB, F32 *result); -#endif - -using namespace UnitTesting; - -CreateUnitTest( TestMatrixMul, "Math/Matrix/Multiply" ) -{ - // The purpose of this test is to verify that the matrix multiplication operation - // always agrees with the different implementations of itself within a reasonable - // epsilon. - void run() - { - F32 m1[16], m2[16], mrC[16]; - - // I am not positive that the best way to do this is to use random numbers - // but I think that using some kind of standard matrix may not always catch - // all problems. - for( int i = 0; i < 16; i++ ) - { - m1[i] = gRandGen.randF(); - m2[i] = gRandGen.randF(); - } - - // C will be the baseline - default_matF_x_matF_C( m1, m2, mrC ); - -#if defined(TORQUE_CPU_X86) && !defined(TORQUE_OS_MAC) - // Check the CPU info - U32 cpuProperties = Platform::SystemInfo.processor.properties; - bool same = true; - // Test 3D NOW! if it is available - F32 mrAMD[16]; - if( cpuProperties & CPU_PROP_3DNOW ) - { - Athlon_MatrixF_x_MatrixF( m1, m2, mrAMD ); - - for( int i = 0; i < 16; i++ ) - same &= mIsEqual( mrC[i], mrAMD[i] ); - - test( same, "Matrix multiplication verification failed. (C vs. 3D NOW!)" ); - } - else - warn( "Could not test 3D NOW! matrix multiplication because CPU does not support 3D NOW!." ); - - same = true; - - // Test SSE if it is available - F32 mrSSE[16]; - if( cpuProperties & CPU_PROP_SSE ) - { - SSE_MatrixF_x_MatrixF( m1, m2, mrSSE ); - - for( int i = 0; i < 16; i++ ) - same &= mIsEqual( mrC[i], mrSSE[i] ); - - test( same, "Matrix multiplication verification failed. (C vs. SSE)" ); - } - else - warn( "Could not test SSE matrix multiplication because CPU does not support SSE." ); - - same = true; -#endif - - // If Altivec exists, test it! -#if defined( __VEC__ ) - bool same = false; - F32 mrVEC[16]; - - vec_MatrixF_x_MatrixF( m1, m2, mrVEC ); - - for( int i = 0; i < 16; i++ ) - same &= isEqual( mrC[i], mrVEC[i] ); - - test( same, "Matrix multiplication verification failed. (C vs. Altivec)" ); -#else - warn( "Could not test Altivec matrix multiplication because CPU does not support Altivec." ); -#endif - } -}; diff --git a/Engine/source/unit/tests/testRuntimeClassRep.cpp b/Engine/source/unit/tests/testRuntimeClassRep.cpp deleted file mode 100644 index 5f4d9ff7d..000000000 --- a/Engine/source/unit/tests/testRuntimeClassRep.cpp +++ /dev/null @@ -1,102 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "console/simBase.h" -#include "console/consoleTypes.h" -#include "console/runtimeClassRep.h" -#include "unit/test.h" - -using namespace UnitTesting; - -//----------------------------------------------------------------------------- - -class RuntimeRegisteredSimObject : public SimObject -{ - typedef SimObject Parent; - -protected: - bool mFoo; - -public: - RuntimeRegisteredSimObject() : mFoo( false ) {}; - - DECLARE_RUNTIME_CONOBJECT(RuntimeRegisteredSimObject); - - static void initPersistFields(); -}; - -IMPLEMENT_RUNTIME_CONOBJECT(RuntimeRegisteredSimObject); - -void RuntimeRegisteredSimObject::initPersistFields() -{ - addField( "fooField", TypeBool, Offset( mFoo, RuntimeRegisteredSimObject ) ); -} - -//----------------------------------------------------------------------------- - -CreateUnitTest( RuntimeClassRepUnitTest, "Console/RuntimeClassRep" ) -{ - void run() - { - // First test to make sure that the test class is not registered (don't know how it could be, but that's programming for you) - test( !RuntimeRegisteredSimObject::dynRTClassRep.isRegistered(), "RuntimeRegisteredSimObject class was already registered with the console" ); - - // This should not be able to find the class, and return null (this may AssertWarn as well) - ConsoleObject *conobj = ConsoleObject::create( "RuntimeRegisteredSimObject" ); - test( conobj == NULL, "AbstractClassRep returned non-NULL value! That is really bad!" ); - - // Register with console system - RuntimeRegisteredSimObject::dynRTClassRep.consoleRegister(); - - // Make sure that the object knows it's registered - test( RuntimeRegisteredSimObject::dynRTClassRep.isRegistered(), "RuntimeRegisteredSimObject class failed console registration" ); - - // Now try again to create the instance - conobj = ConsoleObject::create( "RuntimeRegisteredSimObject" ); - test( conobj != NULL, "AbstractClassRep::create method failed!" ); - - // Cast the instance, and test it - RuntimeRegisteredSimObject *rtinst = dynamic_cast( conobj ); - test( rtinst != NULL, "Casting failed for some reason" ); - - // Register it - rtinst->registerObject( "_utRRTestObject" ); - test( rtinst->isProperlyAdded(), "registerObject failed on test object" ); - - // Now execute some script on it - Con::evaluate( "_utRRTestObject.fooField = true;" ); - - // Test to make sure field worked - test( dAtob( rtinst->getDataField( StringTable->insert( "fooField" ), NULL ) ), "Script test failed!" ); - - // BALETED - rtinst->deleteObject(); - - // Unregister the class - RuntimeRegisteredSimObject::dynRTClassRep.consoleUnRegister(); - - // And make sure we can't create another one - conobj = ConsoleObject::create( "RuntimeRegisteredSimObject" ); - test( conobj == NULL, "Unregistration of type failed" ); - } -}; \ No newline at end of file diff --git a/Engine/source/unit/tests/testSwizzle.cpp b/Engine/source/unit/tests/testSwizzle.cpp deleted file mode 100644 index 1c90394ec..000000000 --- a/Engine/source/unit/tests/testSwizzle.cpp +++ /dev/null @@ -1,126 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "unit/test.h" -#include "unit/memoryTester.h" -#include "core/util/swizzle.h" -#include "math/mRandom.h" - -using namespace UnitTesting; - -class TestStruct -{ -private: - static U32 smIdx; - U32 mIdx; - U32 mData; - -public: - TestStruct( const S32 data = -1 ) : mData( data ), mIdx( smIdx++ ) {}; - - dsize_t Idx() const { return mIdx; } - - U32 Data() const { return mData; } - void Data(U32 val) { mData = val; } -}; - -U32 TestStruct::smIdx = 0; - -CreateUnitTest(TestSwizzle, "Utils/Swizzle") -{ - void run() - { - //------------------------------------------------------------------------ - // Debugger-Observable Functionality Tests - //------------------------------------------------------------------------ - U8 simpleBuffer[] = { 0, 1, 2, 3 }; - U8 simpleTest[] = { 0, 1, 2, 3 }; - -#define RESET_SIMPLE() dMemcpy( simpleTest, simpleBuffer, sizeof( simpleBuffer ) ) - - //------------------------------------------------------------------------ - // No-switch test - dsize_t noSwzl4[] = { 0, 1, 2, 3 }; - Swizzle noSwizzle4( noSwzl4 ); - - noSwizzle4.InPlace( simpleTest, sizeof( simpleTest ) ); - test( dMemcmp( simpleTest, simpleBuffer, sizeof( simpleBuffer ) ) == 0, "No-switch test failed!" ); - RESET_SIMPLE(); - - //------------------------------------------------------------------------ - // No-brainer RGBA->BGRA test - dsize_t bgraSwzl[] = { 2, 1, 0, 3 }; - Swizzle bgraSwizzle( bgraSwzl ); - - U8 bgraTest[] = { 2, 1, 0, 3 }; - bgraSwizzle.InPlace( simpleTest, sizeof( simpleTest ) ); - test( dMemcmp( simpleTest, bgraTest, sizeof( bgraTest ) ) == 0, "U8 RGBA->BGRA test failed" ); - - //------------------------------------------------------------------------ - // Reverse test - bgraSwizzle.InPlace( simpleTest, sizeof( simpleTest ) ); - test( dMemcmp( simpleTest, simpleBuffer, sizeof( simpleBuffer ) ) == 0, "U8 RGBA->BGRA reverse test failed" ); - - RESET_SIMPLE(); - - //------------------------------------------------------------------------ - // Object support test - Swizzle bgraObjSwizzle( bgraSwzl ); - { - U32 objIdx[] = { 0, 1, 2, 3 }; - - FrameTemp objTest( sizeof( objIdx ) / sizeof( U32 ) ); - FrameTemp randData( sizeof( objIdx ) / sizeof( U32 ) ); - - bool same = true; - - for( U32 i = 0; i < sizeof( objIdx ) / sizeof( U32 ); i++ ) - { - // Make random data and assign it - randData[i] = gRandGen.randI(); - objTest[i].Data( randData[i] ); - - // Continue object sanity check - same &= ( objTest[i].Idx() == objIdx[i] ); - } - - test( same, "Test object failed to be competent" ); - - bgraObjSwizzle.InPlace( ~objTest, sizeof( TestStruct ) * ( sizeof( objIdx ) / sizeof( U32 ) ) ); - same = true; - - for( U32 i = 0; i < sizeof( objIdx ) / sizeof( U32 ); i++ ) - same &= ( objTest[i].Idx() == bgraTest[i] ) && ( objTest[i].Data() == randData[ (U32)bgraTest[ i ] ] ); - - test( same, "Object RGBA->BGRA test failed." ); - - bgraObjSwizzle.InPlace( ~objTest, sizeof( TestStruct ) * ( sizeof( objIdx ) / sizeof( U32 ) ) ); - same = true; - - for( U32 i = 0; i < sizeof( objIdx ) / sizeof( U32 ); i++ ) - same &= ( objTest[i].Idx() == objIdx[i] ) && ( objTest[i].Data() == randData[i] ); - - test( same, "Object RGBA->BGRA reverse test failed." ); - } - } -}; \ No newline at end of file diff --git a/Engine/source/unit/tests/testThreadStatic.cpp b/Engine/source/unit/tests/testThreadStatic.cpp deleted file mode 100644 index 52cfa5bdc..000000000 --- a/Engine/source/unit/tests/testThreadStatic.cpp +++ /dev/null @@ -1,101 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "unit/test.h" -#include "core/threadStatic.h" -#include "unit/memoryTester.h" - -using namespace UnitTesting; - -//----------------------------------------------------------------------------- -// This unit test will blow up without thread static support -#ifdef TORQUE_ENABLE_THREAD_STATICS - -// Declare a test thread static -DITTS( U32, gUnitTestFoo, 42 ); -DITTS( F32, gUnitTestF32, 1.0 ); - -CreateUnitTest( TestThreadStatic, "Core/ThreadStatic" ) -{ - void run() - { - MemoryTester m; - m.mark(); - - // ThreadStatic list should be initialized right now, so lets see if it has - // any entries. - test( !_TorqueThreadStaticReg::getStaticList().empty(), "Self-registration has failed, or no statics declared" ); - - // Spawn a new copy. - TorqueThreadStaticListHandle testInstance = _TorqueThreadStaticReg::spawnThreadStaticsInstance(); - - // Test the copy - test( _TorqueThreadStaticReg::getStaticList( 0 ).size() == testInstance->size(), "Spawned static list has a different size from master copy." ); - - // Make sure the size test passed before this is attempted - if( lastTestPassed() ) - { - // Traverse the list and compare it to the initial value copy (index 0) - for( int i = 0; i < _TorqueThreadStaticReg::getStaticList().size(); i++ ) - { - _TorqueThreadStatic *master = _TorqueThreadStaticReg::getStaticList()[i]; - _TorqueThreadStatic *cpy = (*testInstance)[i]; - - // Make sure it is not the same memory - test( master != cpy, "Copy not spawned properly." ); - - // Make sure the sizes are the same - test( master->getMemInstSize() == cpy->getMemInstSize(), "Size mismatch between master and copy" ); - - // Make sure the initialization occurred properly - if( lastTestPassed() ) - test( dMemcmp( master->getMemInstPtr(), cpy->getMemInstPtr(), master->getMemInstSize() ) == 0, "Initial value for spawned list is not correct" ); - } - } - - // Test metrics if enabled -#ifdef TORQUE_ENABLE_THREAD_STATIC_METRICS - U32 fooHitCount = (*testInstance)[_gUnitTestFooTorqueThreadStatic::getListIndex()]->getHitCount(); -#endif - - // Set/get some values (If we test static metrics, this is hit 1) - ATTS_(gUnitTestFoo, 1) = 55; - - // Test to see that the master copy and the spawned copy differ - // (If we test metrics, this is hit 2, for the instance, and hit 1 for the master) - test( ATTS_(gUnitTestFoo, 0) != ATTS_(gUnitTestFoo, 1 ) , "Assignment for spawned instanced memory failed" ); - -#ifdef TORQUE_ENABLE_THREAD_STATIC_METRICS - U32 fooHitCount2 = (*testInstance)[_gUnitTestFooTorqueThreadStatic::getListIndex()]->getHitCount(); - test( fooHitCount2 == ( fooHitCount + 2 ), "Thread static metric hit count failed" ); -#endif - - // Destroy instances - _TorqueThreadStaticReg::destroyInstance( testInstance ); - - // Now test the cleanup - test( m.check(), "Memory leak in dynamic static allocation stuff." ); - } -}; - -#endif // TORQUE_ENABLE_THREAD_STATICS \ No newline at end of file diff --git a/Engine/source/unit/tests/testThreadStaticPerformance.cpp b/Engine/source/unit/tests/testThreadStaticPerformance.cpp deleted file mode 100644 index 62eff7dac..000000000 --- a/Engine/source/unit/tests/testThreadStaticPerformance.cpp +++ /dev/null @@ -1,82 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "unit/test.h" -#include "core/threadStatic.h" -#include "math/mRandom.h" -#include "platform/profiler.h" - -using namespace UnitTesting; - -//----------------------------------------------------------------------------- -// This unit test will blow up without thread static support -#if defined(TORQUE_ENABLE_THREAD_STATICS) && defined(TORQUE_ENABLE_PROFILER) - -// Declare a test thread static -DITTS( U32, gInstancedStaticFoo, 42 ); -static U32 gTrueStaticFoo = 42; - -CreateUnitTest( TestThreadStaticPerformance, "Core/ThreadStaticPerformance" ) -{ - void run() - { - // Bail if the profiler is turned on right now - if( !test( !gProfiler->isEnabled(), "Profiler is currently enabled, test cannot continue" ) ) - return; - - // Spawn an instance - TorqueThreadStaticListHandle testInstance = _TorqueThreadStaticReg::spawnThreadStaticsInstance(); - - static const dsize_t TEST_SIZE = 100000; - - // What we are going to do in this test is to test some U32 static - // performance. The test will be run TEST_SIZE times, and so first create - // an array of values to standardize the tests on. - U32 testValue[TEST_SIZE]; - - for( int i = 0; i < TEST_SIZE; i++ ) - testValue[i] = gRandGen.randI(); - - // Reset the profiler, tell it to dump to console when done - gProfiler->dumpToConsole(); - gProfiler->enable( true ); - - // Value array is initialized, so lets put the foo's through the paces - PROFILE_START(ThreadStaticPerf_TrueStaticAssign); - for( int i = 0; i < TEST_SIZE; i++ ) - gTrueStaticFoo = testValue[i]; - PROFILE_END(); - - PROFILE_START(ThreadStaticPerf_InstanceStaticAssign); - for( int i = 0; i < TEST_SIZE; i++ ) - ATTS_( gInstancedStaticFoo, 1 ) = testValue[i]; - PROFILE_END(); - - gProfiler->enable( false ); - - // Clean up instance - _TorqueThreadStaticReg::destroyInstance( testInstance ); - } -}; - -#endif // TORQUE_ENABLE_THREAD_STATICS \ No newline at end of file diff --git a/Engine/source/unit/unitTestComponentInterface.cpp b/Engine/source/unit/unitTestComponentInterface.cpp deleted file mode 100644 index 14d5653c7..000000000 --- a/Engine/source/unit/unitTestComponentInterface.cpp +++ /dev/null @@ -1,24 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "unit/unitTestComponentInterface.h" - diff --git a/Engine/source/unit/unitTestComponentInterface.h b/Engine/source/unit/unitTestComponentInterface.h deleted file mode 100644 index d829311b8..000000000 --- a/Engine/source/unit/unitTestComponentInterface.h +++ /dev/null @@ -1,91 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _UNITTESTCOMPONENTINTERFACE_H_ -#define _UNITTESTCOMPONENTINTERFACE_H_ - -#include "unit/test.h" -#include "component/simComponent.h" -#include "component/componentInterface.h" - -// This is commented out because I want to keep the explicit namespace referencing -// so that the multiple inheritances from UnitTest doesn't screw anyone up. It will -// also make for more readable code in the derived test-interfaces. -patw -//using namespace UnitTesting; - -/// This is a class that will make it very easy for a component author to provide -/// unit testing functionality from within an instantiated component. -class UnitTestComponentInterface : public ComponentInterface, UnitTesting::UnitTest -{ - typedef ComponentInterface Parent; - -private: - StringTableEntry mName; - UnitTesting::DynamicTestRegistration *mTestReg; - - // Constructors/Destructors -public: - UnitTestComponentInterface( const char *name ) - { - mName = StringTable->insert( name ); - - mTestReg = new UnitTesting::DynamicTestRegistration( name, this ); - } - - virtual ~UnitTestComponentInterface() - { - delete mTestReg; - } - - // ComponentInterface overrides -public: - virtual bool isValid() const - { - return Parent::isValid() && ( mTestReg != NULL ); - } - - // UnitTest overrides -public: - /// This is the only function you need to overwrite to add a unit test interface - /// your component. - virtual void run() = 0; -}; - -// Macros -#ifndef TORQUE_DEBUG -# define DECLARE_UNITTEST_INTERFACE(x) -# define CACHE_UNITTEST_INTERFACE(x) -#else -//----------------------------------------------------------------------------- -# define DECLARE_UNITTEST_INTERFACE(x) \ - class x##_UnitTestInterface : public UnitTestComponentInterface \ - {\ - typedef UnitTestComponentInterface Parent; \ - public: \ - x##_UnitTestInterface() : UnitTestComponentInterface( #x ) {}; \ - virtual void run(); \ - } _##x##UnitTestInterface -//----------------------------------------------------------------------------- -# define CACHE_UNITTEST_INTERFACE(x) registerCachedInterface( "unittest", #x, this, &_##x##UnitTestInterface ) -#endif - -#endif \ No newline at end of file diff --git a/Engine/source/util/fpsTracker.cpp b/Engine/source/util/fpsTracker.cpp index d30c812f5..c62c3fd95 100644 --- a/Engine/source/util/fpsTracker.cpp +++ b/Engine/source/util/fpsTracker.cpp @@ -46,7 +46,7 @@ void FPSTracker::reset() void FPSTracker::update() { - const float alpha = 0.07f; + const F32 alpha = 0.07f; F32 realSeconds = (F32)Platform::getRealMilliseconds()/1000.0f; F32 virtualSeconds = (F32)Platform::getVirtualMilliseconds()/1000.0f; diff --git a/Engine/source/util/messaging/eventManager.h b/Engine/source/util/messaging/eventManager.h index e5ec82032..888e8357c 100644 --- a/Engine/source/util/messaging/eventManager.h +++ b/Engine/source/util/messaging/eventManager.h @@ -58,6 +58,9 @@ class EventManagerListener : public Dispatcher::IMessageListener SimpleHashTable< Vector > mSubscribers; public: + // Ensure that the subscriber map doesn't use case-sensitive string comparisons. + EventManagerListener(): mSubscribers(64, false) {} + /// Called by the EventManager queue when an event is triggered. Calls all listeners subscribed to the triggered event. virtual bool onMessageReceived( StringTableEntry queue, const char* event, const char* data ); virtual bool onMessageObjectReceived( StringTableEntry queue, Message *msg ) { return true; }; diff --git a/Engine/source/util/noise2d.cpp b/Engine/source/util/noise2d.cpp index cee3b6fb6..6c51dfc19 100644 --- a/Engine/source/util/noise2d.cpp +++ b/Engine/source/util/noise2d.cpp @@ -267,7 +267,7 @@ bool Noise2D::erodeHydraulic( Vector *src, Vector *dst, U32 iterations for (S32 k=0; k < (size*size); k++) c[k] = 0.0f; - for (int i=0; i +template< S32 NUM_DIMENSIONS > class ScopeTrackerObject { public: @@ -264,7 +264,7 @@ class ScopeTrackerObject /// /// @param NUM_DIMENSIONS Number of dimensions to track; must be <=4. /// @param Object Value type for objects tracked by the ScopeTracker. Must have pointer behavior. -template< int NUM_DIMENSIONS, typename Object > +template< S32 NUM_DIMENSIONS, typename Object > class ScopeTracker { public: @@ -356,7 +356,7 @@ class ScopeTracker //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > ScopeTracker< NUM_DIMENSIONS, Object >::ScopeTracker() : mReferenceObject( NULL ) { @@ -385,7 +385,7 @@ ScopeTracker< NUM_DIMENSIONS, Object >::ScopeTracker() //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > void ScopeTracker< NUM_DIMENSIONS, Object >::setReferenceObject( Object object ) { AssertFatal( !object || !Deref( object ).isRegistered(), @@ -433,7 +433,7 @@ void ScopeTracker< NUM_DIMENSIONS, Object >::setReferenceObject( Object object ) //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > void ScopeTracker< NUM_DIMENSIONS, Object >::registerObject( Object object ) { PROFILE_SCOPE( ScopeTracker_registerObject ); @@ -469,7 +469,7 @@ void ScopeTracker< NUM_DIMENSIONS, Object >::registerObject( Object object ) //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > void ScopeTracker< NUM_DIMENSIONS, Object >::unregisterObject( Object object ) { PROFILE_SCOPE( ScopeTracker_unregisterObject ); @@ -494,7 +494,7 @@ void ScopeTracker< NUM_DIMENSIONS, Object >::unregisterObject( Object object ) //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > void ScopeTracker< NUM_DIMENSIONS, Object >::updateObject( Object object ) { PROFILE_SCOPE( ScopeTracker_updateObject ); @@ -554,7 +554,7 @@ void ScopeTracker< NUM_DIMENSIONS, Object >::updateObject( Object object ) //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > void ScopeTracker< NUM_DIMENSIONS, Object >::_insertTrackingNode( U32 dimension, NodeType* node ) { //RDTODO: substitute brute-force search with some smarter insertion algorithm @@ -579,7 +579,7 @@ void ScopeTracker< NUM_DIMENSIONS, Object >::_insertTrackingNode( U32 dimension, //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > void ScopeTracker< NUM_DIMENSIONS, Object >::_removeTrackingNode( U32 dimension, NodeType* node ) { NodeType* next = node->getNext(); @@ -597,7 +597,7 @@ void ScopeTracker< NUM_DIMENSIONS, Object >::_removeTrackingNode( U32 dimension, //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > void ScopeTracker< NUM_DIMENSIONS, Object >::_moveTrackingNode( U32 dimension, NodeType* node, F32 newPosition ) { PROFILE_SCOPE( ScopeTracker_moveTrackingNode ); @@ -713,7 +713,7 @@ void ScopeTracker< NUM_DIMENSIONS, Object >::_moveTrackingNode( U32 dimension, N //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > void ScopeTracker< NUM_DIMENSIONS, Object >::_setScope( Object object ) { // If there's no reference object, all objects are out of scope. @@ -756,7 +756,7 @@ void ScopeTracker< NUM_DIMENSIONS, Object >::_setScope( Object object ) //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > void ScopeTracker< NUM_DIMENSIONS, Object >::_initTracking() { PROFILE_SCOPE( ScopeTracker_initTracking ); @@ -813,7 +813,7 @@ void ScopeTracker< NUM_DIMENSIONS, Object >::_initTracking() //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > void ScopeTracker< NUM_DIMENSIONS, Object >::_uninitTracking() { PROFILE_SCOPE( ScopeTracker_uninitTracking ); @@ -842,7 +842,7 @@ void ScopeTracker< NUM_DIMENSIONS, Object >::_uninitTracking() //----------------------------------------------------------------------------- -template< int NUM_DIMENSIONS, class Object > +template< S32 NUM_DIMENSIONS, class Object > void ScopeTracker< NUM_DIMENSIONS, Object >::debugDump() { for( U32 n = 0; n < NUM_DIMENSIONS; ++ n ) diff --git a/Engine/source/util/settings.cpp b/Engine/source/util/settings.cpp index 19de55673..826c26cff 100644 --- a/Engine/source/util/settings.cpp +++ b/Engine/source/util/settings.cpp @@ -288,7 +288,6 @@ void Settings::readLayer(SimXMLDocument *document, String groupStack) { for(S32 i=0; document->pushChildElement(i); i++) { - bool groupCount = 0; const UTF8 *type = document->elementValue(); const UTF8 *name = document->attribute("name"); const UTF8 *value = document->getText(); @@ -302,7 +301,6 @@ void Settings::readLayer(SimXMLDocument *document, String groupStack) newStack += name; readLayer(document, newStack); - groupCount++; } else if(dStrcmp(type, "Setting") == 0) { String nameString = groupStack; @@ -635,13 +633,13 @@ void SettingSaveNode::buildDocument(SimXMLDocument *document, bool skipWrite) document->addText(mValue); } else { - for(int i=0; ibuildDocument(document); } - for(int i=0; ibuildDocument(document); diff --git a/Engine/source/windowManager/platformInterface.cpp b/Engine/source/windowManager/platformInterface.cpp index ff34d37db..b756b988a 100644 --- a/Engine/source/windowManager/platformInterface.cpp +++ b/Engine/source/windowManager/platformInterface.cpp @@ -70,7 +70,7 @@ static struct ModifierBitMap { { IM_LOPT, SI_MAC_LOPT }, { IM_ROPT, SI_MAC_ROPT }, }; -static int _ModifierBitMapCount = sizeof(_ModifierBitMap) / sizeof(ModifierBitMap); +static S32 _ModifierBitMapCount = sizeof(_ModifierBitMap) / sizeof(ModifierBitMap); InputModifiers convertModifierBits(const U32 in) { @@ -121,7 +121,7 @@ void Platform::closeWindow() -#ifdef TORQUE_OS_WIN32 +#ifdef TORQUE_OS_WIN // Hack so we can get the HWND of the global window more easily - replacement // for the HWND that was in the platstate. #include "windowManager/win32/win32Window.h" diff --git a/Engine/source/windowManager/platformWindow.h b/Engine/source/windowManager/platformWindow.h index 11d28d384..680e8b12b 100644 --- a/Engine/source/windowManager/platformWindow.h +++ b/Engine/source/windowManager/platformWindow.h @@ -89,6 +89,10 @@ protected: /// Offscreen Render bool mOffscreenRender; + /// This is set as part of the canvas being shown, and flags that the windows should render as normal from now on. + // Basically a flag that lets the window manager know that we've handled the splash screen, and to operate as normal. + bool mDisplayWindow; + /// Protected constructor so that the win PlatformWindow() { @@ -104,6 +108,7 @@ protected: mSuppressReset = false; mOffscreenRender = false; + mDisplayWindow = false; } public: @@ -180,6 +185,8 @@ public: /// This is called to poll the window as to it's idle state. virtual bool getOffscreenRender() { return mOffscreenRender; }; + /// Set whether this window is should display as normal + virtual void setDisplayWindow(bool val ) { mDisplayWindow = val; }; /// Set Focused State (Foreground) /// diff --git a/Engine/source/windowManager/platformWindowMgr.h b/Engine/source/windowManager/platformWindowMgr.h index b744af56b..41fcd8c9d 100644 --- a/Engine/source/windowManager/platformWindowMgr.h +++ b/Engine/source/windowManager/platformWindowMgr.h @@ -133,6 +133,9 @@ public: /// This method removes the curtain window. virtual void raiseCurtain()=0; + /// This method indicates to created windows to show as normal. + virtual void setDisplayWindow(bool set){} + private: /// Process command line arguments from StandardMainLoop. This is done to /// allow web plugin functionality, where we are passed platform-specific diff --git a/Engine/source/windowManager/test/testWinMgr.cpp b/Engine/source/windowManager/test/testWinMgr.cpp deleted file mode 100644 index efe3ec770..000000000 --- a/Engine/source/windowManager/test/testWinMgr.cpp +++ /dev/null @@ -1,538 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "console/console.h" -#include "windowManager/platformWindowMgr.h" -#include "unit/test.h" -#include "core/util/tVector.h" -#include "gfx/gfxStructs.h" -#include "core/util/journal/process.h" -#include "gfx/gfxInit.h" - -using namespace UnitTesting; - -CreateUnitTest(TestWinMgrQueries, "WindowManager/BasicQueries") -{ - void run() - { - PlatformWindowManager *pwm = CreatePlatformWindowManager(); - - // Check out the primary desktop area... - RectI primary = pwm->getPrimaryDesktopArea(); - - Con::printf("Primary desktop area is (%d,%d) (%d,%d)", - primary.point.x, primary.point.y, primary.extent.x, primary.extent.y); - - test(primary.isValidRect(), "Got some sort of invalid rect from the window manager!"); - - // Now try to get info about all the monitors. - Vector monitorRects; - pwm->getMonitorRegions(monitorRects); - - test(monitorRects.size() > 0, "Should get at least one monitor rect back from getMonitorRegions!"); - - // This test is here just to detect overflow/runaway situations. -- BJG - test(monitorRects.size() < 64, "Either something's wrong, or you have a lot of monitors..."); - - for(S32 i=0; icreateWindow(NULL, vm); - - test(pw, "Didn't get a window back from the window manager, no good."); - if(!pw) - return; - - // Setup our events. - pw->mouseEvent.notify(this, &TestWinMgrCreate::handleMouseEvent); - pw->appEvent.notify(this, &TestWinMgrCreate::handleAppEvent); - - // And, go on our way. - while(Process::processEvents()) - ; - - SAFE_DELETE(pw); - } -}; - -CreateInteractiveTest(TestWinMgrGFXInit, "WindowManager/SimpleGFX") -{ - PlatformWindow *mWindow; - GFXDevice *mDevice; - - void handleDrawEvent(WindowId id) - { - mDevice->beginScene(); - mDevice->setActiveRenderTarget(mWindow->getGFXTarget()); - mDevice->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, ColorI( 255, 255, 0 ), 1.0f, 0 ); - mDevice->endScene(); - mWindow->getGFXTarget()->present(); - } - - void forceDraw() - { - handleDrawEvent(0); - } - - void handleAppEvent(WindowId, S32 event) - { - if(event == WindowClose) - Process::requestShutdown(); - } - - void run() - { - PlatformWindowManager *pwm = CreatePlatformWindowManager(); - - // Create a device. - GFXAdapter a; - a.mType = Direct3D9; - a.mIndex = 0; - - mDevice = GFXInit::createDevice(&a); - test(mDevice, "Unable to create d3d9 device #0."); - - // Initialize the window... - GFXVideoMode vm; - vm.resolution.x = 400; - vm.resolution.y = 400; - - mWindow = pwm->createWindow(mDevice, vm); - - test(mWindow, "Didn't get a window back from the window manager, no good."); - if(!mWindow) - return; - - // Setup our events. - mWindow->displayEvent.notify(this, &TestWinMgrGFXInit::handleDrawEvent); - mWindow->idleEvent.notify(this, &TestWinMgrGFXInit::forceDraw); - mWindow->appEvent.notify(this, &TestWinMgrGFXInit::handleAppEvent); - - // And, go on our way. - while(Process::processEvents()) - ; - - mWindow->displayEvent.remove(this, &TestWinMgrGFXInit::handleDrawEvent); - mWindow->idleEvent.remove(this, &TestWinMgrGFXInit::forceDraw); - mWindow->appEvent.remove(this, &TestWinMgrGFXInit::handleAppEvent); - - // Clean up! - SAFE_DELETE(mDevice); - SAFE_DELETE(mWindow); - } -}; - -CreateInteractiveTest(TestWinMgrGFXInitMultiWindow, "WindowManager/GFXMultiWindow") -{ - enum { - NumWindows = 4, - }; - - PlatformWindowManager *mWindowManager; - PlatformWindow *mWindows[NumWindows]; - GFXDevice *mDevice; - - void handleDrawEvent(WindowId id) - { - // Which window are we getting this event on? - PlatformWindow *w = mWindowManager->getWindowById(id); - - mDevice->beginScene(); - mDevice->setActiveRenderTarget(w->getGFXTarget()); - - // Vary clear color by window to discern which window is which. - mDevice->clear( GFXClearTarget, - ColorI( 255 - (id * 50), 255, id * 100 ), 1.0f, 0 ); - mDevice->endScene(); - - // Call swap on the window's render target. - ((GFXWindowTarget*)w->getGFXTarget())->present(); - } - - void handleAppEvent(WindowId, S32 event) - { - if(event == WindowClose) - Process::requestShutdown(); - } - - void handleIdleEvent() - { - for(S32 i=0; igetWindowId()); - } - - void run() - { - mWindowManager = CreatePlatformWindowManager(); - - // Create a device. - GFXAdapter a; - a.mType = Direct3D9; - a.mIndex = 0; - - mDevice = GFXInit::createDevice(&a); - test(mDevice, "Unable to create d3d9 device #0."); - - // Initialize the windows... - GFXVideoMode vm; - vm.resolution.x = 400; - vm.resolution.y = 400; - - for(S32 i=0; icreateWindow(mDevice, vm); - - test(mWindows[i], "Didn't get a window back from the window manager, no good."); - if(!mWindows[i]) - continue; - - // Setup our events. - mWindows[i]->displayEvent.notify(this, &TestWinMgrGFXInitMultiWindow::handleDrawEvent); - mWindows[i]->appEvent.notify(this, &TestWinMgrGFXInitMultiWindow::handleAppEvent); - mWindows[i]->idleEvent.notify(this, &TestWinMgrGFXInitMultiWindow::handleIdleEvent); - } - - // And, go on our way. - while(Process::processEvents()) - ; - - SAFE_DELETE(mWindowManager); - SAFE_DELETE(mDevice); - } -}; - -CreateInteractiveTest(TestJournaledMultiWindowGFX, "WindowManager/GFXJournaledMultiWindow") -{ - enum { - NumWindows = 2, - }; - - PlatformWindowManager *mWindowManager; - PlatformWindow *mWindows[NumWindows]; - GFXDevice *mDevice; - - S32 mNumDraws; - S32 mNumResize; - - void drawToWindow(PlatformWindow *win) - { - // Do some simple checks to make sure we draw the same number of times - // on both runs. - if(Journal::IsPlaying()) - mNumDraws--; - else - mNumDraws++; - - // Render! - mDevice->beginScene(); - mDevice->setActiveRenderTarget(win->getGFXTarget()); - - // Vary clear color by window to discern which window is which. - static S32 timeVariance = 0; - - mDevice->clear( GFXClearTarget, - ColorI( 0xFF - (++timeVariance * 5), 0xFF, win->getWindowId() * 0x0F ), 1.0f, 0 ); - - mDevice->endScene(); - - // Call swap on the window's render target. - win->getGFXTarget()->present(); - - } - - void handleDrawEvent(WindowId id) - { - // Which window are we getting this event on? - PlatformWindow *w = mWindowManager->getWindowById(id); - - drawToWindow(w); - } - - void handleAppEvent(WindowId, S32 event) - { - if(event == WindowClose) - Process::requestShutdown(); - } - - void handleIdleEvent() - { - for(S32 i=0; igetWindowById(id)->setSize(Point2I(width, height)); - - mNumResize--; - } - else - { - // If we're not playing back, do nothing except note it. - mNumResize++; - } - - // Which window are we getting this event on? - PlatformWindow *w = mWindowManager->getWindowById(id); - - drawToWindow(w); - } - - /// The mainloop of our app - we'll run this twice, once to create - /// a journal and again to play it back. - void mainLoop() - { - mWindowManager = CreatePlatformWindowManager(); - - // Create a device. - GFXAdapter a; - a.mType = Direct3D9; - a.mIndex = 0; - - mDevice = GFXInit::createDevice(&a); - test(mDevice, "Unable to create ogl device #0."); - - // Initialize the windows... - GFXVideoMode vm; - vm.resolution.x = 400; - vm.resolution.y = 400; - - for(S32 i=0; icreateWindow(mDevice, vm); - - test(mWindows[i], "Didn't get a window back from the window manager, no good."); - if(!mWindows[i]) - continue; - - // Setup our events. - mWindows[i]->displayEvent.notify(this, &TestJournaledMultiWindowGFX::handleDrawEvent); - mWindows[i]->appEvent.notify(this, &TestJournaledMultiWindowGFX::handleAppEvent); - mWindows[i]->resizeEvent.notify(this, &TestJournaledMultiWindowGFX::handleResizeEvent); - - // Only subscribe to the first idle event. - if(i==0) - mWindows[i]->idleEvent.notify(this, &TestJournaledMultiWindowGFX::handleIdleEvent); - } - - // And, go on our way. - while(Process::processEvents()) - ; - - // Finally, clean up. - for(S32 i=0; i 0, "No draws occurred!"); - test(mNumResize > 0, "No resizes occurred!"); - - // And play it back. - Journal::Play("multiwindow.jrn"); - mainLoop(); - Journal::Stop(); - - test(mNumDraws == 0, "Failed to play journal back with same number of draws."); - test(mNumResize == 0, "Failed to play journal back with same number of resizes."); -#endif - } -}; - -CreateInteractiveTest(GFXTestFullscreenToggle, "GFX/TestFullscreenToggle") -{ - enum Constants - { - NumWindows = 1, - }; - - PlatformWindowManager *mWindowManager; - PlatformWindow *mWindows[NumWindows]; - GFXDevice *mDevice; - - void drawToWindow(PlatformWindow *win) - { - // Render! - mDevice->beginScene(); - mDevice->setActiveRenderTarget(win->getGFXTarget()); - - // Vary clear color by window to discern which window is which. - static S32 timeVariance = 0; - - mDevice->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, - ColorI( 0xFF - (++timeVariance * 5), 0xFF, win->getWindowId() * 0x40 ), 1.0f, 0 ); - - mDevice->endScene(); - - // Call swap on the window's render target. - win->getGFXTarget()->present(); - } - - void handleDrawEvent(WindowId id) - { - // Which window are we getting this event on? - PlatformWindow *w = mWindowManager->getWindowById(id); - - drawToWindow(w); - } - - void handleAppEvent(WindowId, S32 event) - { - if(event == WindowClose) - Process::requestShutdown(); - } - - void handleIdleEvent() - { - // Redraw everything. - for(S32 i=0; igetWindowById(did); - GFXVideoMode winVm = win->getVideoMode(); - - // If the window is not full screen, make it full screen 800x600x32 - if(winVm.fullScreen == false) - { - winVm.fullScreen = true; - winVm.resolution.set(800,600); - } - else - { - // If the window is full screen, then bump it to 400x400x32 - winVm.fullScreen = false; - winVm.resolution.set(400,400); - } - - win->setVideoMode(winVm); - } - - void run() - { - mWindowManager = CreatePlatformWindowManager(); - - // Create a device. - GFXAdapter a; - a.mType = Direct3D9; - a.mIndex = 0; - - mDevice = GFXInit::createDevice(&a); - test(mDevice, "Unable to create d3d9 device #0."); - - // Initialize the windows... - GFXVideoMode vm; - vm.resolution.x = 400; - vm.resolution.y = 400; - - for(S32 i=0; icreateWindow(mDevice, vm); - - test(mWindows[i], "Didn't get a window back from the window manager, no good."); - if(!mWindows[i]) - continue; - - // Setup our events. - mWindows[i]->appEvent.notify(this, &GFXTestFullscreenToggle::handleAppEvent); - mWindows[i]->buttonEvent.notify(this, &GFXTestFullscreenToggle::handleButtonEvent); - mWindows[i]->displayEvent.notify(this, &GFXTestFullscreenToggle::handleDrawEvent); - - // Only subscribe to the first idle event. - if(i==0) - mWindows[i]->idleEvent.notify(this, &GFXTestFullscreenToggle::handleIdleEvent); - } - - // And, go on our way. - while(Process::processEvents()) - ; - - // Finally, clean up. - for(S32 i=0; ipreDestroy(); - SAFE_DELETE(mDevice); - SAFE_DELETE(mWindowManager); - } -}; \ No newline at end of file diff --git a/Engine/source/windowManager/test/windowManagerTest.cpp b/Engine/source/windowManager/test/windowManagerTest.cpp new file mode 100644 index 000000000..d6179c96b --- /dev/null +++ b/Engine/source/windowManager/test/windowManagerTest.cpp @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2014 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifdef TORQUE_TESTS_ENABLED +#include "testing/unitTesting.h" +#include "windowManager/platformWindowMgr.h" + +// Mysteriously, TEST(WindowManager, BasicAPI) gives an error. Huh. +TEST(WinMgr, BasicAPI) +{ + PlatformWindowManager *pwm = CreatePlatformWindowManager(); + + // Check out the primary desktop area... + RectI primary = pwm->getPrimaryDesktopArea(); + + EXPECT_TRUE(primary.isValidRect()) + << "Got some sort of invalid rect from the window manager!"; + + // Now try to get info about all the monitors. + Vector monitorRects; + pwm->getMonitorRegions(monitorRects); + + EXPECT_GT(monitorRects.size(), 0) + << "Should get at least one monitor rect back from getMonitorRegions!"; + + // This test is here just to detect overflow/runaway situations. -- BJG + EXPECT_LT(monitorRects.size(), 64) + << "Either something's wrong, or you have a lot of monitors..."; + + for(S32 i=0; igetWindowId() : 0; if (window && window->getOffscreenRender()) @@ -708,8 +712,8 @@ LRESULT PASCAL Win32Window::WindowProc( HWND hWnd, UINT message, WPARAM wParam, case WM_CREATE: // CodeReview [tom, 4/30/2007] Why don't we just cast this to a LONG // instead of having a ton of essentially pointless casts ? - SetWindowLong(hWnd, GWL_USERDATA, - (LONG)((PlatformWindow*)((CREATESTRUCT*)lParam)->lpCreateParams)); + SetWindowLongPtr(hWnd, GWLP_USERDATA, + (LONG_PTR)((PlatformWindow*)((CREATESTRUCT*)lParam)->lpCreateParams)); break; case WM_SETFOCUS: @@ -1068,7 +1072,7 @@ bool Win32Window::translateMessage(MSG &msg) if(mAccelHandle == NULL || mWindowHandle == NULL || !mEnableAccelerators) return false; - int ret = TranslateAccelerator(mWindowHandle, mAccelHandle, &msg); + S32 ret = TranslateAccelerator(mWindowHandle, mAccelHandle, &msg); return ret != 0; } diff --git a/Engine/source/windowManager/win32/win32WindowMgr.cpp b/Engine/source/windowManager/win32/win32WindowMgr.cpp index 05e889c9a..ef04c7fe1 100644 --- a/Engine/source/windowManager/win32/win32WindowMgr.cpp +++ b/Engine/source/windowManager/win32/win32WindowMgr.cpp @@ -41,7 +41,8 @@ PlatformWindowManager * CreatePlatformWindowManager() Win32WindowManager::Win32WindowManager() { // Register in the process list. - Process::notify(this, &Win32WindowManager::_process, PROCESS_INPUT_ORDER); + mOnProcessSignalSlot.setDelegate( this, &Win32WindowManager::_process ); + Process::notify( mOnProcessSignalSlot, PROCESS_INPUT_ORDER ); // Init our list of allocated windows. mWindowListHead = NULL; @@ -53,14 +54,13 @@ Win32WindowManager::Win32WindowManager() mOffscreenRender = false; + mDisplayWindow = false; + buildMonitorsList(); } Win32WindowManager::~Win32WindowManager() { - // Get ourselves off the process list. - Process::remove(this, &Win32WindowManager::_process); - // Kill all our windows first. while(mWindowListHead) // The destructors update the list, so this works just fine. @@ -136,7 +136,7 @@ void Win32WindowManager::buildMonitorsList() mMonitors.clear(); // Enumerate all monitors - EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (U32)(void*)&mMonitors); + EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (size_t)(void*)&mMonitors); } S32 Win32WindowManager::findFirstMatchingMonitor(const char* name) @@ -252,7 +252,7 @@ PlatformWindow *Win32WindowManager::createWindow(GFXDevice *device, const GFXVid w32w->setVideoMode(mode); // Associate our window struct with the HWND. - SetWindowLongPtrW(w32w->mWindowHandle, GWLP_USERDATA, (LONG)w32w); + SetWindowLongPtr(w32w->mWindowHandle, GWLP_USERDATA, (LONG_PTR)w32w); // Do some error checking. AssertFatal(w32w->mWindowHandle != NULL, "Win32WindowManager::createWindow - Could not create window!"); @@ -265,11 +265,13 @@ PlatformWindow *Win32WindowManager::createWindow(GFXDevice *device, const GFXVid // If we're not rendering offscreen, make sure our window is shown and drawn to. - if (!mOffscreenRender) - ShowWindow( w32w->mWindowHandle, SW_SHOWDEFAULT ); + w32w->setDisplayWindow(mDisplayWindow); - // Close any splash screen we created - CloseSplashWindow(winState.appInstance); + if (!mOffscreenRender && mDisplayWindow) + { + ShowWindow( w32w->mWindowHandle, SW_SHOWDEFAULT ); + CloseSplashWindow(winState.appInstance); + } // Bind the window to the specified device. if(device) @@ -356,7 +358,7 @@ void Win32WindowManager::_process() // [tom, 4/30/2007] I think this should work, but leaving the above commented // out just in case this is actually fubared with multiple windows. - Win32Window* window = (Win32Window*)(GetWindowLong(msg.hwnd, GWL_USERDATA)); + Win32Window* window = (Win32Window*)(GetWindowLongPtr(msg.hwnd, GWLP_USERDATA)); if(window) translated = window->translateMessage(msg); @@ -452,7 +454,7 @@ void Win32WindowManager::_processCmdLineArgs( const S32 argc, const char **argv { if (argc > 1) { - for (int i = 1; i < argc; i++) + for (S32 i = 1; i < argc; i++) { if ( dStrnicmp( argv[i], "-window", 7 ) == 0 ) { diff --git a/Engine/source/windowManager/win32/win32WindowMgr.h b/Engine/source/windowManager/win32/win32WindowMgr.h index a5c747501..5282d116b 100644 --- a/Engine/source/windowManager/win32/win32WindowMgr.h +++ b/Engine/source/windowManager/win32/win32WindowMgr.h @@ -56,6 +56,10 @@ class Win32WindowManager : public PlatformWindowManager // is intended for offscreen rendering bool mOffscreenRender; + /// This is set as part of the canvas being shown, and flags that the windows should render as normal from now on. + // Basically a flag that lets the window manager know that we've handled the splash screen, and to operate as normal. + bool mDisplayWindow; + /// Internal structure used when enumerating monitors struct MonitorInfo { HMONITOR monitorHandle; @@ -85,6 +89,8 @@ class Win32WindowManager : public PlatformWindowManager /// If a curtain window is present, then its HWND will be stored here. HWND mCurtainWindow; + SignalSlot mOnProcessSignalSlot; + public: Win32WindowManager(); ~Win32WindowManager(); @@ -115,6 +121,8 @@ public: virtual void lowerCurtain(); virtual void raiseCurtain(); + + virtual void setDisplayWindow(bool set) { mDisplayWindow = set; } }; #endif \ No newline at end of file diff --git a/Engine/source/windowManager/win32/winDispatch.cpp b/Engine/source/windowManager/win32/winDispatch.cpp index f49010f0e..0d26def4d 100644 --- a/Engine/source/windowManager/win32/winDispatch.cpp +++ b/Engine/source/windowManager/win32/winDispatch.cpp @@ -176,7 +176,7 @@ static bool _dispatch(HWND hWnd,UINT message,WPARAM wParam,WPARAM lParam) static S32 mouseNCState = -1; // -1 denotes unchanged, // 0 denotes changed but was hidden // 1 denotes changed but was visible - Win32Window* window = hWnd?(Win32Window*)GetWindowLong(hWnd, GWL_USERDATA): 0; + Win32Window* window = hWnd?(Win32Window*)GetWindowLongPtr(hWnd, GWLP_USERDATA): 0; const WindowId devId = window ? window->getWindowId() : 0; // State tracking for focus/lose focus cursor management @@ -283,7 +283,7 @@ static bool _dispatch(HWND hWnd,UINT message,WPARAM wParam,WPARAM lParam) case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: { - int index = (message - WM_LBUTTONDOWN) / 3; + S32 index = (message - WM_LBUTTONDOWN) / 3; button[index] = true; // Capture the mouse on button down to allow dragging outside @@ -299,7 +299,7 @@ static bool _dispatch(HWND hWnd,UINT message,WPARAM wParam,WPARAM lParam) case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: { - int index = (message - WM_LBUTTONUP) / 3; + S32 index = (message - WM_LBUTTONUP) / 3; button[index] = false; // Release mouse capture from button down. @@ -560,7 +560,7 @@ private: static WinMessageQueue _MessageQueue; -void RemoveMessages(HWND hWnd,UINT msgBegin,WPARAM msgEnd ) +void RemoveMessages(HWND hWnd,UINT msgBegin,UINT msgEnd ) { _MessageQueue.remove( hWnd, msgBegin, msgEnd ); } diff --git a/My Projects/readme.txt b/My Projects/readme.txt index 299a8f786..9663bd6e3 100644 --- a/My Projects/readme.txt +++ b/My Projects/readme.txt @@ -1 +1 @@ -The Torque Toolbox places your projects here. +your projects will go in this folder \ No newline at end of file diff --git a/README.md b/README.md index a461b5db0..412e858ff 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Torque 3D v3.5.1 +Torque 3D v3.6 ================ MIT Licensed Open Source version of [Torque 3D](http://www.garagegames.com/products/torque-3d) from [GarageGames](http://www.garagegames.com) @@ -21,7 +21,7 @@ Pre-compiled Version In addition to GitHub we also have a couple of pre-packaged files for you to download if you would prefer to not compile the code yourself: -* [Complete Torque 3D 3.5.1 zip package](http://mit.garagegames.com/Torque3D-3-5-1.zip) with updated TorqueScript documentation, the *Project Manager*, and compiled versions of the templates. +* [Complete Torque 3D 3.6 zip package](http://mit.garagegames.com/Torque3D-3-6.zip) with updated TorqueScript documentation, the *Project Manager*, and compiled versions of the templates. * [Torque 3D Project Manager v2.1](http://mit.garagegames.com/T3DProjectManager-2-1.zip) on its own for use in your T3D forks. If you're looking for an older release see the [Torque 3D Archive](https://github.com/GarageGames/Torque3D/wiki/Torque-3D-Archive) diff --git a/Templates/Empty/buildFiles/config/torque3D_dedicated.conf b/Templates/Empty/buildFiles/config/torque3D_dedicated.conf index eecf2fc4f..ec0b6281d 100644 --- a/Templates/Empty/buildFiles/config/torque3D_dedicated.conf +++ b/Templates/Empty/buildFiles/config/torque3D_dedicated.conf @@ -60,14 +60,14 @@ addProjectDependency( 'libbullet' ); } - if ( Generator::$platform == "mac" ) + if ( T3D_Generator::$platform == "mac" ) { addProjectDefine( '__MACOSX__' ); addProjectDefine( 'LTM_DESC' ); } - if (Generator::$platform == "win32") + if (T3D_Generator::$platform == "win32") { setProjectModuleDefinitionFile('../../' . getLibSrcDir() . 'Torque3D/msvc/torque3d.def'); diff --git a/Templates/Empty/game/core/scripts/gui/messageBoxes/messageBox.ed.cs b/Templates/Empty/game/core/scripts/gui/messageBoxes/messageBox.ed.cs index d778ae7ee..7c970c341 100644 --- a/Templates/Empty/game/core/scripts/gui/messageBoxes/messageBox.ed.cs +++ b/Templates/Empty/game/core/scripts/gui/messageBoxes/messageBox.ed.cs @@ -42,8 +42,8 @@ if( isObject( IODropdownDlg ) ) exec("./messageBoxOk.ed.gui"); exec("./messageBoxYesNo.ed.gui"); exec("./messageBoxYesNoCancel.ed.gui"); -exec("./messageBoxOKCancel.ed.gui"); -exec("./messageBoxOKCancelDetailsDlg.ed.gui"); +exec("./messageBoxOkCancel.ed.gui"); +exec("./MessageBoxOKCancelDetailsDlg.ed.gui"); exec("./messagePopup.ed.gui"); exec("./IODropdownDlg.ed.gui"); diff --git a/Templates/Empty/game/main.cs b/Templates/Empty/game/main.cs index bd1333e6a..5d26b7fca 100644 --- a/Templates/Empty/game/main.cs +++ b/Templates/Empty/game/main.cs @@ -38,7 +38,10 @@ function createCanvas(%windowTitle) } // Create the Canvas - %foo = new GuiCanvas(Canvas); + %foo = new GuiCanvas(Canvas) + { + displayWindow = false; + }; // Set the window title if (isObject(Canvas)) @@ -246,6 +249,15 @@ if ($displayHelp) { else { onStart(); echo("Engine initialized..."); + + if( !$isDedicated ) + { + // As we know at this point that the initial load is complete, + // we can hide any splash screen we have, and show the canvas. + // This keeps things looking nice, instead of having a blank window + closeSplashWindow(); + Canvas.showWindow(); + } // Auto-load on the 360 if( $platform $= "xenon" ) diff --git a/Templates/Empty/game/main.cs.in b/Templates/Empty/game/main.cs.in new file mode 100644 index 000000000..d3b5791ef --- /dev/null +++ b/Templates/Empty/game/main.cs.in @@ -0,0 +1,292 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Set the name of our application +$appName = "@TORQUE_APP_NAME@"; + +// The directory it is run from +$defaultGame = "scripts"; + +// Set profile directory +$Pref::Video::ProfilePath = "core/profile"; + +function createCanvas(%windowTitle) +{ + if ($isDedicated) + { + GFXInit::createNullDevice(); + return true; + } + + // Create the Canvas + %foo = new GuiCanvas(Canvas) + { + displayWindow = false; + }; + + // Set the window title + if (isObject(Canvas)) + Canvas.setWindowTitle(getEngineName() @ " - " @ $appName); + + return true; +} + +// Display the optional commandline arguements +$displayHelp = false; + +// Use these to record and play back crashes +//saveJournal("editorOnFileQuitCrash.jrn"); +//playJournal("editorOnFileQuitCrash.jrn", false); + +//------------------------------------------------------------------------------ +// Check if a script file exists, compiled or not. +function isScriptFile(%path) +{ + if( isFile(%path @ ".dso") || isFile(%path) ) + return true; + + return false; +} + +//------------------------------------------------------------------------------ +// Process command line arguments +exec("core/parseArgs.cs"); + +$isDedicated = false; +$dirCount = 2; +$userDirs = $defaultGame @ ";art;levels"; + +// load tools scripts if we're a tool build +if (isToolBuild()) + $userDirs = "tools;" @ $userDirs; + + +// Parse the executable arguments with the standard +// function from core/main.cs +defaultParseArgs(); + + +if($dirCount == 0) { + $userDirs = $defaultGame; + $dirCount = 1; +} + +//----------------------------------------------------------------------------- +// Display a splash window immediately to improve app responsiveness before +// engine is initialized and main window created +if (!$isDedicated) + displaySplashWindow(); + + +//----------------------------------------------------------------------------- +// The displayHelp, onStart, onExit and parseArgs function are overriden +// by mod packages to get hooked into initialization and cleanup. + +function onStart() +{ + // Default startup function +} + +function onExit() +{ + // OnExit is called directly from C++ code, whereas onStart is + // invoked at the end of this file. +} + +function parseArgs() +{ + // Here for mod override, the arguments have already + // been parsed. +} + +function compileFiles(%pattern) +{ + %path = filePath(%pattern); + + %saveDSO = $Scripts::OverrideDSOPath; + %saveIgnore = $Scripts::ignoreDSOs; + + $Scripts::OverrideDSOPath = %path; + $Scripts::ignoreDSOs = false; + %mainCsFile = makeFullPath("main.cs"); + + for (%file = findFirstFileMultiExpr(%pattern); %file !$= ""; %file = findNextFileMultiExpr(%pattern)) + { + // we don't want to try and compile the primary main.cs + if(%mainCsFile !$= %file) + compile(%file, true); + } + + $Scripts::OverrideDSOPath = %saveDSO; + $Scripts::ignoreDSOs = %saveIgnore; + +} + +if($compileAll) +{ + echo(" --- Compiling all files ---"); + compileFiles("*.cs"); + compileFiles("*.gui"); + compileFiles("*.ts"); + echo(" --- Exiting after compile ---"); + quit(); +} + +if($compileTools) +{ + echo(" --- Compiling tools scritps ---"); + compileFiles("tools/*.cs"); + compileFiles("tools/*.gui"); + compileFiles("tools/*.ts"); + echo(" --- Exiting after compile ---"); + quit(); +} + +package Help { + function onExit() { + // Override onExit when displaying help + } +}; + +function displayHelp() { + activatePackage(Help); + + // Notes on logmode: console logging is written to console.log. + // -log 0 disables console logging. + // -log 1 appends to existing logfile; it also closes the file + // (flushing the write buffer) after every write. + // -log 2 overwrites any existing logfile; it also only closes + // the logfile when the application shuts down. (default) + + error( + "Torque Demo command line options:\n"@ + " -log Logging behavior; see main.cs comments for details\n"@ + " -game Reset list of mods to only contain \n"@ + " Works like the -game argument\n"@ + " -dir Add to list of directories\n"@ + " -console Open a separate console\n"@ + " -show Deprecated\n"@ + " -jSave Record a journal\n"@ + " -jPlay Play back a journal\n"@ + " -jDebug Play back a journal and issue an int3 at the end\n"@ + " -help Display this help message\n" + ); +} + + +//-------------------------------------------------------------------------- + +// Default to a new logfile each session. +if( !$logModeSpecified ) +{ + if( $platform !$= "xbox" && $platform !$= "xenon" ) + setLogMode(6); +} + +// Get the first dir on the list, which will be the last to be applied... this +// does not modify the list. +nextToken($userDirs, currentMod, ";"); + +// Execute startup scripts for each mod, starting at base and working up +function loadDir(%dir) +{ + pushback($userDirs, %dir, ";"); + + if (isScriptFile(%dir @ "/main.cs")) + exec(%dir @ "/main.cs"); +} + +echo("--------- Loading DIRS ---------"); +function loadDirs(%dirPath) +{ + %dirPath = nextToken(%dirPath, token, ";"); + if (%dirPath !$= "") + loadDirs(%dirPath); + + if(exec(%token @ "/main.cs") != true) + { + error("Error: Unable to find specified directory: " @ %token ); + $dirCount--; + } +} +loadDirs($userDirs); +echo(""); + +if($dirCount == 0) { + enableWinConsole(true); + error("Error: Unable to load any specified directories"); + quit(); +} +// Parse the command line arguments +echo("--------- Parsing Arguments ---------"); +parseArgs(); + +// Either display the help message or startup the app. +if ($displayHelp) { + enableWinConsole(true); + displayHelp(); + quit(); +} +else { + onStart(); + echo("Engine initialized..."); + + if( !$isDedicated ) + { + // As we know at this point that the initial load is complete, + // we can hide any splash screen we have, and show the canvas. + // This keeps things looking nice, instead of having a blank window + closeSplashWindow(); + Canvas.showWindow(); + } + + // Auto-load on the 360 + if( $platform $= "xenon" ) + { + %mission = "levels/Empty Terrain.mis"; + + echo("Xbox360 Autoloading level: '" @ %mission @ "'"); + + + if ($pref::HostMultiPlayer) + %serverType = "MultiPlayer"; + else + %serverType = "SinglePlayer"; + + createAndConnectToLocalServer( %serverType, %mission ); + } +} + +// Display an error message for unused arguments +for ($i = 1; $i < $Game::argc; $i++) { + if (!$argUsed[$i]) + error("Error: Unknown command line argument: " @ $Game::argv[$i]); +} + +// Automatically start up the appropriate eidtor, if any +if ($startWorldEditor) { + Canvas.setCursor("DefaultCursor"); + Canvas.setContent(EditorChooseLevelGui); +} else if ($startGUIEditor) { + Canvas.setCursor("DefaultCursor"); + Canvas.setContent(EditorChooseGUI); +} diff --git a/Templates/Empty/game/runTests.cs b/Templates/Empty/game/runTests.cs new file mode 100644 index 000000000..b6d903ff0 --- /dev/null +++ b/Templates/Empty/game/runTests.cs @@ -0,0 +1,5 @@ +setLogMode(2); +$Con::LogBufferEnabled = false; +$Testing::CheckMemoryLeaks = false; +runAllUnitTests("-*.Stress*"); +quit(); diff --git a/Templates/Empty/game/shaders/common/gl/blurP.glsl b/Templates/Empty/game/shaders/common/gl/blurP.glsl index bc05b992f..5c37ebc6b 100644 --- a/Templates/Empty/game/shaders/common/gl/blurP.glsl +++ b/Templates/Empty/game/shaders/common/gl/blurP.glsl @@ -26,12 +26,12 @@ uniform vec4 kernel; uniform sampler2D diffuseMap; -varying vec2 texc0, texc1, texc2, texc3; +in vec2 texc0, texc1, texc2, texc3; void main() { - gl_FragColor = texture2D(diffuseMap, texc0) * kernel.x; - gl_FragColor += texture2D(diffuseMap, texc1) * kernel.y; - gl_FragColor += texture2D(diffuseMap, texc2) * kernel.z; - gl_FragColor += texture2D(diffuseMap, texc3) * kernel.w; + OUT_FragColor0 = texture(diffuseMap, texc0) * kernel.x; + OUT_FragColor0 += texture(diffuseMap, texc1) * kernel.y; + OUT_FragColor0 += texture(diffuseMap, texc2) * kernel.z; + OUT_FragColor0 += texture(diffuseMap, texc3) * kernel.w; } diff --git a/Templates/Empty/game/shaders/common/gl/blurV.glsl b/Templates/Empty/game/shaders/common/gl/blurV.glsl index d5d615fb9..1bfb0cd1b 100644 --- a/Templates/Empty/game/shaders/common/gl/blurV.glsl +++ b/Templates/Empty/game/shaders/common/gl/blurV.glsl @@ -24,20 +24,25 @@ // Glow shader //***************************************************************************** +in vec4 vPosition; +in vec4 vColor; +in vec2 vTexCoord0; + uniform mat4 modelview; uniform vec2 offset0, offset1, offset2, offset3; -varying vec2 texc0, texc1, texc2, texc3; +out vec2 texc0, texc1, texc2, texc3; void main() { - gl_Position = modelview * gl_Vertex; + gl_Position = modelview * vPosition; - vec2 tc = gl_MultiTexCoord0.st; + vec2 tc = vTexCoord0.st; tc.y = 1.0 - tc.y; texc0 = tc + offset0; texc1 = tc + offset1; texc2 = tc + offset2; texc3 = tc + offset3; + gl_Position.y *= -1; } \ No newline at end of file diff --git a/Templates/Empty/game/shaders/common/gl/cloudLayerP.glsl b/Templates/Empty/game/shaders/common/gl/cloudLayerP.glsl index 326f2d3c6..da3996d58 100644 --- a/Templates/Empty/game/shaders/common/gl/cloudLayerP.glsl +++ b/Templates/Empty/game/shaders/common/gl/cloudLayerP.glsl @@ -22,12 +22,20 @@ #include "hlslCompat.glsl" -varying vec4 texCoord12; -varying vec4 texCoord34; -varying vec3 vLightTS; // light vector in tangent space, denormalized -varying vec3 vViewTS; // view vector in tangent space, denormalized -varying vec3 vNormalWS; // Normal vector in world space -varying float worldDist; +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- +//ConnectData +in vec4 texCoord12; +#define IN_texCoord12 texCoord12 +in vec4 texCoord34; +#define IN_texCoord34 texCoord34 +in vec3 vLightTS; // light vector in tangent space, denormalized +#define IN_vLightTS vLightTS +in vec3 vViewTS; // view vector in tangent space, denormalized +#define IN_vViewTS vViewTS +in float worldDist; +#define IN_worldDist worldDist //----------------------------------------------------------------------------- // Uniforms @@ -37,6 +45,7 @@ uniform vec3 ambientColor; uniform vec3 sunColor; uniform float cloudCoverage; uniform vec3 cloudBaseColor; +uniform float cloudExposure; //----------------------------------------------------------------------------- // Globals @@ -97,26 +106,25 @@ void main() // Normalize the interpolated vectors: vec3 vViewTS = normalize( vViewTS ); vec3 vLightTS = normalize( vLightTS ); - vec3 vNormalWS = normalize( vNormalWS ); - vec4 cResultColor = float4( 0, 0, 0, 1 ); + vec4 cResultColor = vec4( 0, 0, 0, 1 ); - vec2 texSample = texCoord12.xy; + vec2 texSample = IN_texCoord12.xy; - vec4 noise1 = texture2D( normalHeightMap, texCoord12.zw ); + vec4 noise1 = texture( normalHeightMap, IN_texCoord12.zw ); noise1 = normalize( ( noise1 - 0.5 ) * 2.0 ); //return noise1; - vec4 noise2 = texture2D( normalHeightMap, texCoord34.xy ); + vec4 noise2 = texture( normalHeightMap, IN_texCoord34.xy ); noise2 = normalize( ( noise2 - 0.5 ) * 2.0 ); //return noise2; vec3 noiseNormal = normalize( noise1 + noise2 ).xyz; - //return float4( noiseNormal, 1.0 ); + //return vec4( noiseNormal, 1.0 ); float noiseHeight = noise1.a * noise2.a * ( cloudCoverage / 2.0 + 0.5 ); - vec3 vNormalTS = normalize( texture2D( normalHeightMap, texSample ).xyz * 2.0 - 1.0 ); + vec3 vNormalTS = normalize( texture( normalHeightMap, texSample ).xyz * 2.0 - 1.0 ); vNormalTS += noiseNormal; vNormalTS = normalize( vNormalTS ); @@ -124,16 +132,14 @@ void main() cResultColor.rgb = ComputeIllumination( texSample, vLightTS, vViewTS, vNormalTS ); float coverage = ( cloudCoverage - 0.5 ) * 2.0; - cResultColor.a = texture2D( normalHeightMap, texSample ).a + coverage + noiseHeight; + cResultColor.a = texture( normalHeightMap, texSample ).a + coverage + noiseHeight; if ( cloudCoverage > -1.0 ) cResultColor.a /= 1.0 + coverage; - cResultColor.a = saturate( cResultColor.a * pow( saturate(cloudCoverage), 0.25 ) ); + cResultColor.a = clamp( cResultColor.a * pow( saturate(cloudCoverage), 0.25 ), 0.0, 1.0 ); - cResultColor.a = mix( cResultColor.a, 0.0, 1.0 - pow(worldDist,2.0) ); + cResultColor.a = mix( cResultColor.a, 0.0, 1.0 - pow(IN_worldDist,2.0) ); - // If using HDR rendering, make sure to tonemap the resuld color prior to outputting it. - // But since this example isn't doing that, we just output the computed result color here: - gl_FragColor = cResultColor; + OUT_FragColor0 = cResultColor; } diff --git a/Templates/Empty/game/shaders/common/gl/cloudLayerV.glsl b/Templates/Empty/game/shaders/common/gl/cloudLayerV.glsl index 39a6f4ba8..395c6f286 100644 --- a/Templates/Empty/game/shaders/common/gl/cloudLayerV.glsl +++ b/Templates/Empty/game/shaders/common/gl/cloudLayerV.glsl @@ -20,12 +20,24 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -varying vec4 texCoord12; -varying vec4 texCoord34; -varying vec3 vLightTS; // light vector in tangent space, denormalized -varying vec3 vViewTS; // view vector in tangent space, denormalized -varying vec3 vNormalWS; // Normal vector in world space -varying float worldDist; +#include "hlslCompat.glsl" + +in vec4 vPosition; +in vec3 vNormal; +in vec3 vBinormal; +in vec3 vTangent; +in vec2 vTexCoord0; + +out vec4 texCoord12; +#define OUT_texCoord12 texCoord12 +out vec4 texCoord34; +#define OUT_texCoord34 texCoord34 +out vec3 vLightTS; // light vector in tangent space, denormalized +#define OUT_vLightTS vLightTS +out vec3 vViewTS; // view vector in tangent space, denormalized +#define OUT_vViewTS vViewTS +out float worldDist; +#define OUT_worldDist worldDist //----------------------------------------------------------------------------- // Uniforms @@ -43,37 +55,37 @@ uniform vec3 texScale; //----------------------------------------------------------------------------- void main() { - vec4 pos = gl_Vertex; - vec3 normal = gl_Normal; - vec3 binormal = gl_MultiTexCoord0.xyz; - vec3 tangent = gl_MultiTexCoord1.xyz; - vec2 uv0 = gl_MultiTexCoord2.st; + vec4 IN_pos = vPosition; + vec3 IN_normal = vNormal; + vec3 IN_binormal = vBinormal; + vec3 IN_tangent = vTangent; + vec2 IN_uv0 = vTexCoord0.st; - gl_Position = modelview * pos; + gl_Position = modelview * IN_pos; // Offset the uv so we don't have a seam directly over our head. - vec2 uv = uv0 + vec2( 0.5, 0.5 ); + vec2 uv = IN_uv0 + vec2( 0.5, 0.5 ); - texCoord12.xy = uv * texScale.x; - texCoord12.xy += texOffset0; + OUT_texCoord12.xy = uv * texScale.x; + OUT_texCoord12.xy += texOffset0; - texCoord12.zw = uv * texScale.y; - texCoord12.zw += texOffset1; + OUT_texCoord12.zw = uv * texScale.y; + OUT_texCoord12.zw += texOffset1; - texCoord34.xy = uv * texScale.z; - texCoord34.xy += texOffset2; + OUT_texCoord34.xy = uv * texScale.z; + OUT_texCoord34.xy += texOffset2; - texCoord34.z = pos.z; - texCoord34.w = 0.0; + OUT_texCoord34.z = IN_pos.z; + OUT_texCoord34.w = 0.0; // Transform the normal, tangent and binormal vectors from object space to // homogeneous projection space: - vNormalWS = -normal; - vec3 vTangentWS = -tangent; - vec3 vBinormalWS = -binormal; + vec3 vNormalWS = -IN_normal; + vec3 vTangentWS = -IN_tangent; + vec3 vBinormalWS = -IN_binormal; // Compute position in world space: - vec4 vPositionWS = pos + vec4( eyePosWorld, 1 ); //mul( pos, objTrans ); + vec4 vPositionWS = IN_pos + vec4( eyePosWorld, 1 ); //tMul( IN_pos, objTrans ); // Compute and output the world view vector (unnormalized): vec3 vViewWS = eyePosWorld - vPositionWS.xyz; @@ -81,12 +93,14 @@ void main() // Compute denormalized light vector in world space: vec3 vLightWS = -sunVec; - // Normalize the light and view vectors and transform it to the tangent space: + // Normalize the light and view vectors and transform it to the IN_tangent space: mat3 mWorldToTangent = mat3( vTangentWS, vBinormalWS, vNormalWS ); // Propagate the view and the light vectors (in tangent space): - vLightTS = mWorldToTangent * vLightWS; - vViewTS = vViewWS * mWorldToTangent; - - worldDist = clamp( pow( pos.z, 2.0 ), 0.0, 1.0 ); + OUT_vLightTS = vLightWS * mWorldToTangent; + OUT_vViewTS = mWorldToTangent * vViewWS; + + OUT_worldDist = clamp( pow( max( IN_pos.z, 0 ), 2 ), 0.0, 1.0 ); + + correctSSP(gl_Position); } diff --git a/Templates/Empty/game/shaders/common/gl/foliage.glsl b/Templates/Empty/game/shaders/common/gl/foliage.glsl index 2fee902e3..38b66e767 100644 --- a/Templates/Empty/game/shaders/common/gl/foliage.glsl +++ b/Templates/Empty/game/shaders/common/gl/foliage.glsl @@ -46,7 +46,19 @@ uniform vec3 gc_gustInfo; uniform vec2 gc_turbInfo; -//static float sMovableCorner[4] = { 0.0, 0.0, 1.0, 1.0 }; +const float sCornerRight[4] = float[]( -0.5, 0.5, 0.5, -0.5 ); + +const float sCornerUp[4] = float[]( 0, 0, 1, 1 ); + +const float sMovableCorner[4] = float[]( 0, 0, 1, 1 ); + +const vec2 sUVCornerExtent[4] = vec2[] +( + vec2( 0, 1 ), + vec2( 1, 1 ), + vec2( 1, 0 ), + vec2( 0, 0 ) +); /////////////////////////////////////////////////////////////////////////////// @@ -106,34 +118,13 @@ vec2 windEffect( float bbPhase, void foliageProcessVert( inout vec3 position, inout vec4 diffuse, - in vec4 texCoord, - out vec2 outTexCoord, + inout vec4 texCoord, inout vec3 normal, inout vec3 T, in vec3 eyePos ) { - - float sCornerRight[4]; - sCornerRight[0] = -0.5; - sCornerRight[1] = 0.5; - sCornerRight[2] = 0.5; - sCornerRight[3] = -0.5; - - float sCornerUp[4]; - sCornerUp[0] = 0.0; - sCornerUp[1] = 0.0; - sCornerUp[2] = 1.0; - sCornerUp[3] = 1.0; - - vec2 sUVCornerExtent[4]; - sUVCornerExtent[0] = vec2( 0.0, 1.0 ); - sUVCornerExtent[1] = vec2( 1.0, 1.0 ); - sUVCornerExtent[2] = vec2( 1.0, 0.0 ); - sUVCornerExtent[3] = vec2( 0.0, 0.0 ); - - // Assign the normal and tagent values. - //normal = cross( gc_camUp, gc_camRight ); + //normal = vec3( 0, 0, 1 );//cross( gc_camUp, gc_camRight ); T = gc_camRight; // Pull out local vars we need for work. @@ -172,8 +163,8 @@ void foliageProcessVert( inout vec3 position, // Grab the uv set and setup the texture coord. vec4 uvSet = gc_typeRects[type]; - outTexCoord.x = uvSet.x + ( uvSet.z * sUVCornerExtent[corner].x ); - outTexCoord.y = uvSet.y + ( uvSet.w * sUVCornerExtent[corner].y ); + texCoord.x = uvSet.x + ( uvSet.z * sUVCornerExtent[corner].x ); + texCoord.y = uvSet.y + ( uvSet.w * sUVCornerExtent[corner].y ); // Animate the normal to get lighting changes // across the the wind swept foliage. @@ -184,7 +175,6 @@ void foliageProcessVert( inout vec3 position, normal.xy += wind.xy * ( 10.0 * texCoord.w ); normal = normalize( normal ); - // Get the alpha fade value. float fadeStart = gc_fadeParams.x; diff --git a/Templates/Empty/game/shaders/common/gl/fxFoliageReplicatorP.glsl b/Templates/Empty/game/shaders/common/gl/fxFoliageReplicatorP.glsl index 9e5b34caa..fb5abb91e 100644 --- a/Templates/Empty/game/shaders/common/gl/fxFoliageReplicatorP.glsl +++ b/Templates/Empty/game/shaders/common/gl/fxFoliageReplicatorP.glsl @@ -26,15 +26,15 @@ uniform sampler2D diffuseMap, alphaMap; uniform vec4 groundAlpha; -varying vec4 color, groundAlphaCoeff; -varying vec2 outTexCoord, alphaLookup; +in vec4 color, groundAlphaCoeff; +in vec2 outTexCoord, alphaLookup; //----------------------------------------------------------------------------- // Main //----------------------------------------------------------------------------- void main() { - vec4 alpha = texture2D(alphaMap, alphaLookup); - gl_FragColor = color * texture2D(diffuseMap, outTexCoord); - gl_FragColor.a = gl_FragColor.a * min(alpha, groundAlpha + groundAlphaCoeff.x).x; + vec4 alpha = texture(alphaMap, alphaLookup); + OUT_FragColor0 = color * texture(diffuseMap, outTexCoord); + OUT_FragColor0.a = OUT_FragColor0.a * min(alpha, groundAlpha + groundAlphaCoeff.x).x; } diff --git a/Templates/Empty/game/shaders/common/gl/fxFoliageReplicatorV.glsl b/Templates/Empty/game/shaders/common/gl/fxFoliageReplicatorV.glsl index 94a7af2b0..c8dcf1ddb 100644 --- a/Templates/Empty/game/shaders/common/gl/fxFoliageReplicatorV.glsl +++ b/Templates/Empty/game/shaders/common/gl/fxFoliageReplicatorV.glsl @@ -23,13 +23,20 @@ //----------------------------------------------------------------------------- // Data //----------------------------------------------------------------------------- +in vec4 vPosition; +in vec3 vNormal; +in vec4 vColor; +in vec2 vTexCoord0; +in vec2 vTexCoord1; +in vec2 vTexCoord2; + uniform mat4 projection, world; uniform vec3 CameraPos; uniform float GlobalSwayPhase, SwayMagnitudeSide, SwayMagnitudeFront, GlobalLightPhase, LuminanceMagnitude, LuminanceMidpoint, DistanceRange; -varying vec4 color, groundAlphaCoeff; -varying vec2 outTexCoord, alphaLookup; +out vec4 color, groundAlphaCoeff; +out vec2 outTexCoord, alphaLookup; //----------------------------------------------------------------------------- // Main @@ -42,9 +49,9 @@ void main() trans[1][1] = 1.0; trans[2][2] = 1.0; trans[3][3] = 1.0; - trans[3][0] = gl_Vertex.x; - trans[3][1] = gl_Vertex.y; - trans[3][2] = gl_Vertex.z; + trans[3][0] = vPosition.x; + trans[3][1] = vPosition.y; + trans[3][2] = vPosition.z; // Billboard transform * world matrix mat4 o = world; @@ -64,28 +71,29 @@ void main() // Handle sway. Sway is stored in a texture coord. The x coordinate is the sway phase multiplier, // the y coordinate determines if this vertex actually sways or not. float xSway, ySway; - float wavePhase = GlobalSwayPhase * gl_MultiTexCoord1.x; + float wavePhase = GlobalSwayPhase * vTexCoord1.x; ySway = sin(wavePhase); xSway = cos(wavePhase); - xSway = xSway * gl_MultiTexCoord1.y * SwayMagnitudeSide; - ySway = ySway * gl_MultiTexCoord1.y * SwayMagnitudeFront; + xSway = xSway * vTexCoord1.y * SwayMagnitudeSide; + ySway = ySway * vTexCoord1.y * SwayMagnitudeFront; vec4 p; - p = o * vec4(gl_Normal.x + xSway, ySway, gl_Normal.z, 1.0); + p = o * vec4(vNormal.x + xSway, ySway, vNormal.z, 1.0); // Project the point gl_Position = projection * p; // Lighting - float Luminance = LuminanceMidpoint + LuminanceMagnitude * cos(GlobalLightPhase + gl_Normal.y); + float Luminance = LuminanceMidpoint + LuminanceMagnitude * cos(GlobalLightPhase + vNormal.y); // Alpha - vec3 worldPos = vec3(gl_Vertex.x, gl_Vertex.y, gl_Vertex.z); + vec3 worldPos = vec3(vPosition.x, vPosition.y, vPosition.z); float alpha = abs(distance(worldPos, CameraPos)) / DistanceRange; alpha = clamp(alpha, 0.0, 1.0); //pass it through alphaLookup = vec2(alpha, 0.0); - bool alphaCoeff = bool(gl_Normal.z); + bool alphaCoeff = bool(vNormal.z); groundAlphaCoeff = vec4(float(alphaCoeff)); - outTexCoord = gl_MultiTexCoord0.st; + outTexCoord = vTexCoord0.st; color = vec4(Luminance, Luminance, Luminance, 1.0); + gl_Position.y *= -1; } \ No newline at end of file diff --git a/Templates/Empty/game/shaders/common/gl/guiMaterialV.glsl b/Templates/Empty/game/shaders/common/gl/guiMaterialV.glsl index cd44de2f2..de3845ee7 100644 --- a/Templates/Empty/game/shaders/common/gl/guiMaterialV.glsl +++ b/Templates/Empty/game/shaders/common/gl/guiMaterialV.glsl @@ -20,16 +20,20 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +in vec4 vPosition; +in vec2 vTexCoord0; + uniform mat4x4 modelview; -varying vec4 hpos; -varying vec2 uv0; +out vec4 hpos; +out vec2 uv0; void main() { - hpos = vec4( modelview * gl_Vertex ); + hpos = vec4( modelview * vPosition ); gl_Position = hpos; - uv0 = gl_MultiTexCoord0.st; + uv0 = vTexCoord0.st; + gl_Position.y *= -1; } diff --git a/Templates/Empty/game/shaders/common/gl/hlslCompat.glsl b/Templates/Empty/game/shaders/common/gl/hlslCompat.glsl index be5c63340..0815df51f 100644 --- a/Templates/Empty/game/shaders/common/gl/hlslCompat.glsl +++ b/Templates/Empty/game/shaders/common/gl/hlslCompat.glsl @@ -27,17 +27,79 @@ #define float3 vec3 #define float2 vec2 -#define texCUBE textureCube -#define tex2D texture2D +#define half float +#define half2 vec2 +#define half3 vec3 +#define half4 vec4 + +#define float4x4 mat4 +#define float3x3 mat3 +#define float2x2 mat2 + +#define texCUBE texture +#define tex2D texture +#define tex1D texture +#define tex2Dproj textureProj +#define tex2Dlod( sampler, texCoord ) textureLod(sampler, texCoord.xy, texCoord.w) + +#define samplerCUBE samplerCube + +#define frac fract #define lerp mix -float saturate( float val ) { return clamp( val, 0.0, 1.0 ); } -vec2 saturate( vec2 val ) { return clamp( val, 0.0, 1.0 ); } -vec3 saturate( vec3 val ) { return clamp( val, 0.0, 1.0 ); } -vec4 saturate( vec4 val ) { return clamp( val, 0.0, 1.0 ); } +void tSetMatrixRow(out float3x3 m, int row, float3 value) +{ + m[0][row] = value.x; + m[1][row] = value.y; + m[2][row] = value.z; +} -float round( float n ) { return sign( n ) * floor( abs( n ) + 0.5 ); } -vec2 round( vec2 n ) { return sign( n ) * floor( abs( n ) + 0.5 ); } -vec3 round( vec3 n ) { return sign( n ) * floor( abs( n ) + 0.5 ); } -vec4 round( vec4 n ) { return sign( n ) * floor( abs( n ) + 0.5 ); } +void tSetMatrixRow(out float4x4 m, int row, float4 value) +{ + m[0][row] = value.x; + m[1][row] = value.y; + m[2][row] = value.z; + m[3][row] = value.w; +} + +#define tGetMatrix3Row(matrix, row) float3(matrix[0][row], matrix[1][row], matrix[2][row]) +#define tGetMatrix4Row(matrix, row) float4(matrix[0][row], matrix[1][row], matrix[2][row], matrix[3][row]) + +float3x3 float4x4to3x3(float4x4 m) +{ + return float3x3( vec3(m[0]).xyz, m[1].xyz, m[2].xyz); +} + +float3x3 float4x4to3x3_(float4x4 m) +{ + return float3x3( vec3(m[0]), m[1].xyz, m[2].xyz); +} + +mat4 mat4FromRow( float r0c0, float r0c1, float r0c2, float r0c3, + float r1c0, float r1c1, float r1c2, float r1c3, + float r2c0, float r2c1, float r2c2, float r2c3, + float r3c0, float r3c1, float r3c2, float r3c3 ) +{ + return mat4( r0c0, r1c0, r2c0, r3c0, + r0c1, r1c1, r2c1, r3c1, + r0c2, r1c2, r2c2, r3c2, + r0c3, r1c3, r2c3, r3c3 ); +} + + +#define saturate( val ) clamp( val, 0.0, 1.0 ) + +#define round( n ) (sign( n ) * floor( abs( n ) + 0.5 )) + +#define tMul(a, b) (a*b) + +#define inversesqrt( n ) inversesqrt( n ) + +#define correctSSP(vec) vec.y *= -1 + +#ifdef TORQUE_PIXEL_SHADER + void clip(float a) { if(a < 0) discard;} + + out vec4 OUT_FragColor0; +#endif diff --git a/Templates/Empty/game/shaders/common/gl/lighting.glsl b/Templates/Empty/game/shaders/common/gl/lighting.glsl index 3f8867d3b..4483c7526 100644 --- a/Templates/Empty/game/shaders/common/gl/lighting.glsl +++ b/Templates/Empty/game/shaders/common/gl/lighting.glsl @@ -20,73 +20,181 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- + +#ifndef TORQUE_SHADERGEN + // These are the uniforms used by most lighting shaders. -uniform vec3 inLightPos[4]; +uniform vec4 inLightPos[3]; uniform vec4 inLightInvRadiusSq; uniform vec4 inLightColor[4]; + +#ifndef TORQUE_BL_NOSPOTLIGHT + uniform vec4 inLightSpotDir[3]; + uniform vec4 inLightSpotAngle; + uniform vec4 inLightSpotFalloff; +#endif + uniform vec4 ambient; uniform float specularPower; uniform vec4 specularColor; - -// This is used to limit the maximum processed -// lights in the compute4Lights down for really -// low end GPUs. -// -// NOTE: If you want to support 10.5.x, this needs to be changed to 2. -#define C4L_MAX_LIGHTS 4 +#endif // !TORQUE_SHADERGEN void compute4Lights( vec3 wsView, vec3 wsPosition, - vec3 wsNormal, + vec3 wsNormal, + vec4 shadowMask, + + #ifdef TORQUE_SHADERGEN + + vec4 inLightPos[3], + vec4 inLightInvRadiusSq, + vec4 inLightColor[4], + vec4 inLightSpotDir[3], + vec4 inLightSpotAngle, + vec4 inLightSpotFalloff, + float specularPower, + vec4 specularColor, + + #endif // TORQUE_SHADERGEN + out vec4 outDiffuse, out vec4 outSpecular ) { - #ifdef PHONG_SPECULAR - // (R.V)^c - float reflected = reflect( wsView, wsNormal ); - #endif - - vec4 nDotL = vec4( 0.0 ); - vec4 rDotL = vec4( 0.0 ); - vec4 sqDists = vec4( 0.0 ); + // NOTE: The light positions and spotlight directions + // are stored in SoA order, so inLightPos[0] is the + // x coord for all 4 lights... inLightPos[1] is y... etc. + // + // This is the key to fully utilizing the vector units and + // saving a huge amount of instructions. + // + // For example this change saved more than 10 instructions + // over a simple for loop for each light. + int i; - for ( i = 0; i < C4L_MAX_LIGHTS; ++i ) - { - vec3 lightVector = inLightPos[i] - wsPosition; - vec3 lightDirection = normalize( lightVector ); + vec4 lightVectors[3]; + for ( i = 0; i < 3; i++ ) + lightVectors[i] = wsPosition[i] - inLightPos[i]; - nDotL[i] = max( dot( lightDirection, wsNormal ), 0.0 ); + vec4 squareDists = vec4(0); + for ( i = 0; i < 3; i++ ) + squareDists += lightVectors[i] * lightVectors[i]; - #ifdef PHONG_SPECULAR - rDotL[i] = saturate( dot( lightDirection, reflected ) ); - #else - // (N.H)^c [Blinn-Phong, TGEA style, default] - rDotL[i] = dot( wsNormal, normalize( lightDirection + wsView ) ); - #endif + // Accumulate the dot product between the light + // vector and the normal. + // + // The normal is negated because it faces away from + // the surface and the light faces towards the + // surface... this keeps us from needing to flip + // the light vector direction which complicates + // the spot light calculations. + // + // We normalize the result a little later. + // + vec4 nDotL = vec4(0); + for ( i = 0; i < 3; i++ ) + nDotL += lightVectors[i] * -wsNormal[i]; - sqDists[i] = dot( lightVector, lightVector ); - } + vec4 rDotL = vec4(0); + #ifndef TORQUE_BL_NOSPECULAR - // Attenuation - vec4 atten = vec4( 1.0 ) - ( sqDists * inLightInvRadiusSq ); + // We're using the Phong specular reflection model + // here where traditionally Torque has used Blinn-Phong + // which has proven to be more accurate to real materials. + // + // We do so because its cheaper as do not need to + // calculate the half angle for all 4 lights. + // + // Advanced Lighting still uses Blinn-Phong, but the + // specular reconstruction it does looks fairly similar + // to this. + // + vec3 R = reflect( wsView, -wsNormal ); + + for ( i = 0; i < 3; i++ ) + rDotL += lightVectors[i] * R[i]; + + #endif + + // Normalize the dots. + // + // Notice we're using the half type here to get a + // much faster sqrt via the rsq_pp instruction at + // the loss of some precision. + // + // Unless we have some extremely large point lights + // i don't believe the precision loss will matter. + // + half4 correction = half4(inversesqrt( squareDists )); + nDotL = saturate( nDotL * correction ); + rDotL = clamp( rDotL * correction, 0.00001, 1.0 ); + + // First calculate a simple point light linear + // attenuation factor. + // + // If this is a directional light the inverse + // radius should be greater than the distance + // causing the attenuation to have no affect. + // + vec4 atten = saturate( 1.0 - ( squareDists * inLightInvRadiusSq ) ); + + #ifndef TORQUE_BL_NOSPOTLIGHT + + // The spotlight attenuation factor. This is really + // fast for what it does... 6 instructions for 4 spots. + + vec4 spotAtten = vec4(0); + for ( i = 0; i < 3; i++ ) + spotAtten += lightVectors[i] * inLightSpotDir[i]; + + vec4 cosAngle = ( spotAtten * correction ) - inLightSpotAngle; + atten *= saturate( cosAngle * inLightSpotFalloff ); + + #endif + + // Finally apply the shadow masking on the attenuation. + atten *= shadowMask; + + // Get the final light intensity. + vec4 intensity = nDotL * atten; // Combine the light colors for output. - vec4 diffuse = clamp( nDotL * atten, vec4( 0.0 ), vec4( 1.0 ) ); - outDiffuse = vec4( 0.0 ); - for ( i = 0; i < C4L_MAX_LIGHTS; ++i ) - outDiffuse += vec4( diffuse[i] ) * inLightColor[i]; + outDiffuse = vec4(0); + for ( i = 0; i < 4; i++ ) + outDiffuse += intensity[i] * inLightColor[i]; // Output the specular power. - rDotL = max( rDotL, vec4( 0.00001 ) ); - outSpecular = pow( rDotL, vec4( specularPower ) ); + vec4 specularIntensity = pow( rDotL, vec4(specularPower) ) * atten; + + // Apply the per-light specular attenuation. + vec4 specular = vec4(0,0,0,1); + for ( i = 0; i < 4; i++ ) + specular += vec4( inLightColor[i].rgb * inLightColor[i].a * specularIntensity[i], 1 ); + + // Add the final specular intensity values together + // using a single dot product operation then get the + // final specular lighting color. + outSpecular = specularColor * specular; } -/// The standard specular calculation. +// This value is used in AL as a constant power to raise specular values +// to, before storing them into the light info buffer. The per-material +// specular value is then computer by using the integer identity of +// exponentiation: +// +// (a^m)^n = a^(m*n) +// +// or +// +// (specular^constSpecular)^(matSpecular/constSpecular) = specular^(matSpecular*constSpecular) +// +#define AL_ConstantSpecularPower 12.0f + +/// The specular calculation used in Advanced Lighting. /// /// @param toLight Normalized vector representing direction from the pixel /// being lit, to the light source, in world space. @@ -96,11 +204,7 @@ void compute4Lights( vec3 wsView, /// @param toEye The normalized vector representing direction from the pixel /// being lit to the camera. /// -/// @param specPwr The specular exponent. -/// -/// @param specScale A scalar on the specular output used in RGB accumulation. -/// -float calcSpecular( vec3 toLight, vec3 normal, vec3 toEye, float specPwr ) +float AL_CalcSpecular( vec3 toLight, vec3 normal, vec3 toEye ) { #ifdef PHONG_SPECULAR // (R.V)^c @@ -111,5 +215,5 @@ float calcSpecular( vec3 toLight, vec3 normal, vec3 toEye, float specPwr ) #endif // Return the specular factor. - return pow( max( specVal, 0.00001f ), specPwr ); + return pow( max( specVal, 0.00001f ), AL_ConstantSpecularPower ); } diff --git a/Templates/Empty/game/shaders/common/gl/particleCompositeP.glsl b/Templates/Empty/game/shaders/common/gl/particleCompositeP.glsl index 4f2d9b359..6971e1013 100644 --- a/Templates/Empty/game/shaders/common/gl/particleCompositeP.glsl +++ b/Templates/Empty/game/shaders/common/gl/particleCompositeP.glsl @@ -21,6 +21,13 @@ //----------------------------------------------------------------------------- #include "torque.glsl" +#include "hlslCompat.glsl" + +in vec4 offscreenPos; +in vec4 backbufferPos; + +#define IN_offscreenPos offscreenPos +#define IN_backbufferPos backbufferPos uniform sampler2D colorSource; uniform vec4 offscreenTargetParams; @@ -31,8 +38,6 @@ uniform sampler2D edgeSource; uniform vec4 edgeTargetParams; #endif -varying vec4 backbufferPos; -varying vec4 offscreenPos; void main() { @@ -47,11 +52,10 @@ void main() #ifdef REJECT_EDGES // Cut out particles along the edges, this will create the stencil mask uvScene.zw = viewportCoordToRenderTarget(uvScene.zw, edgeTargetParams); - float edge = texture2D( edgeSource, uvScene.zw ).r; - if (-edge < 0.0) - discard; + float edge = texture( edgeSource, uvScene.zw ).r; + clip( -edge ); #endif // Sample offscreen target and return - gl_FragColor = texture2D( colorSource, uvScene.xy ); -} + OUT_FragColor0 = texture( colorSource, uvScene.xy ); +} \ No newline at end of file diff --git a/Templates/Empty/game/shaders/common/gl/particleCompositeV.glsl b/Templates/Empty/game/shaders/common/gl/particleCompositeV.glsl index 88a9431d1..8c8f840d1 100644 --- a/Templates/Empty/game/shaders/common/gl/particleCompositeV.glsl +++ b/Templates/Empty/game/shaders/common/gl/particleCompositeV.glsl @@ -20,16 +20,29 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -uniform mat4 modelViewProj; -uniform mat4 targetModelViewProj; +#include "hlslCompat.glsl" -varying vec4 offscreenPos; -varying vec4 backbufferPos; +in vec2 vTexCoord0; +#define uvCoord vTexCoord0 + +out vec4 offscreenPos; +out vec4 backbufferPos; + +#define OUT_hpos gl_Position +#define OUT_offscreenPos offscreenPos +#define OUT_backbufferPos backbufferPos + +uniform vec4 screenRect; // point, extent void main() { - gl_Position = modelViewProj * gl_Vertex; - backbufferPos = gl_Position; - offscreenPos = targetModelViewProj * gl_Vertex; + OUT_hpos = vec4(uvCoord.xy, 1.0, 1.0); + OUT_hpos.xy *= screenRect.zw; + OUT_hpos.xy += screenRect.xy; + + OUT_backbufferPos = OUT_hpos; + OUT_offscreenPos = OUT_hpos; + + correctSSP(gl_Position); } diff --git a/Templates/Empty/game/shaders/common/gl/particlesP.glsl b/Templates/Empty/game/shaders/common/gl/particlesP.glsl index 66a3fee28..efd930302 100644 --- a/Templates/Empty/game/shaders/common/gl/particlesP.glsl +++ b/Templates/Empty/game/shaders/common/gl/particlesP.glsl @@ -20,63 +20,92 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "hlslCompat.glsl" #include "torque.glsl" - +#include "hlslCompat.glsl" + // With advanced lighting we get soft particles. #ifdef TORQUE_LINEAR_DEPTH #define SOFTPARTICLES #endif -#define CLIP_Z // TODO: Make this a proper macro - -uniform sampler2D diffuseMap; - #ifdef SOFTPARTICLES #include "shadergen:/autogenConditioners.h" uniform float oneOverSoftness; uniform float oneOverFar; - uniform sampler2D prepassTex; + uniform sampler2D prepassTex; //uniform vec3 vEye; uniform vec4 prePassTargetParams; #endif +#define CLIP_Z // TODO: Make this a proper macro + +in vec4 color; +in vec2 uv0; +in vec4 pos; + +#define IN_color color +#define IN_uv0 uv0 +#define IN_pos pos + +uniform sampler2D diffuseMap; + +uniform sampler2D paraboloidLightMap; + +vec4 lmSample( vec3 nrm ) +{ + bool calcBack = (nrm.z < 0.0); + if ( calcBack ) + nrm.z = nrm.z * -1.0; + + vec2 lmCoord; + lmCoord.x = (nrm.x / (2*(1 + nrm.z))) + 0.5; + lmCoord.y = 1-((nrm.y / (2*(1 + nrm.z))) + 0.5); + + + // If this is the back, offset in the atlas + if ( calcBack ) + lmCoord.x += 1.0; + + // Atlasing front and back maps, so scale + lmCoord.x *= 0.5; + + return texture(paraboloidLightMap, lmCoord); +} + + uniform float alphaFactor; uniform float alphaScale; -varying vec4 color; -varying vec2 uv0; -varying vec4 pos; - - void main() { - float softBlend = 1.0; + float softBlend = 1; #ifdef SOFTPARTICLES - float2 tc = pos.xy * vec2(1.0, -1.0 ) / pos.w; + vec2 tc = IN_pos.xy * vec2(1.0, -1.0) / IN_pos.w; tc = viewportCoordToRenderTarget(saturate( ( tc + 1.0 ) * 0.5 ), prePassTargetParams); float sceneDepth = prepassUncondition( prepassTex, tc ).w; - float depth = pos.w * oneOverFar; - float diff = sceneDepth - depth; + float depth = IN_pos.w * oneOverFar; + float diff = sceneDepth - depth; #ifdef CLIP_Z // If drawing offscreen, this acts as the depth test, since we don't line up with the z-buffer // When drawing high-res, though, we want to be able to take advantage of hi-z // so this is #ifdef'd out - if (diff < 0.0) - discard; + //clip(diff); #endif softBlend = saturate( diff * oneOverSoftness ); #endif - - vec4 diffuse = texture2D( diffuseMap, uv0 ); + + vec4 diffuse = texture( diffuseMap, IN_uv0 ); + + //OUT_FragColor0 = vec4( lmSample(vec3(0, 0, -1)).rgb, IN_color.a * diffuse.a * softBlend * alphaScale); // Scale output color by the alpha factor (turn LerpAlpha into pre-multiplied alpha) - vec3 colorScale = ( alphaFactor < 0.0 ? color.rgb * diffuse.rgb : ( alphaFactor > 0.0 ? vec3(color.a * alphaFactor * diffuse.a * softBlend) : vec3(softBlend) ) ); + vec3 colorScale = ( alphaFactor < 0.0 ? IN_color.rgb * diffuse.rgb : vec3( alphaFactor > 0.0 ? IN_color.a * diffuse.a * alphaFactor * softBlend : softBlend ) ); - gl_FragColor = hdrEncode( vec4(color.rgb * diffuse.rgb * colorScale, softBlend * color.a * diffuse.a * alphaScale) ); + OUT_FragColor0 = hdrEncode( vec4( IN_color.rgb * diffuse.rgb * colorScale, + IN_color.a * diffuse.a * softBlend * alphaScale ) ); } diff --git a/Templates/Empty/game/shaders/common/gl/particlesV.glsl b/Templates/Empty/game/shaders/common/gl/particlesV.glsl index da896431f..3d75a6fb6 100644 --- a/Templates/Empty/game/shaders/common/gl/particlesV.glsl +++ b/Templates/Empty/game/shaders/common/gl/particlesV.glsl @@ -20,18 +20,35 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -varying vec4 color; -varying vec2 uv0; -varying vec4 pos; +#include "hlslCompat.glsl" + +in vec4 vPosition; +in vec4 vColor; +in vec2 vTexCoord0; + +#define In_pos vPosition +#define In_color vColor +#define In_uv0 vTexCoord0 + +out vec4 color; +out vec2 uv0; +out vec4 pos; + +#define OUT_hpos gl_Position +#define OUT_color color +#define OUT_uv0 uv0 +#define OUT_pos pos uniform mat4 modelViewProj; uniform mat4 fsModelViewProj; void main() { - gl_Position = modelViewProj * gl_Vertex; - pos = fsModelViewProj * gl_Vertex; - color = gl_Color; - uv0 = gl_MultiTexCoord0.st; + OUT_hpos = tMul( modelViewProj, In_pos ); + OUT_pos = tMul( fsModelViewProj, In_pos ); + OUT_color = In_color; + OUT_uv0 = In_uv0; + + correctSSP(gl_Position); } diff --git a/Templates/Empty/game/shaders/common/gl/planarReflectBumpP.glsl b/Templates/Empty/game/shaders/common/gl/planarReflectBumpP.glsl index 00413aa3b..334c70a70 100644 --- a/Templates/Empty/game/shaders/common/gl/planarReflectBumpP.glsl +++ b/Templates/Empty/game/shaders/common/gl/planarReflectBumpP.glsl @@ -26,8 +26,8 @@ uniform sampler2D diffuseMap, refractMap, bumpMap; uniform vec4 shadeColor; -varying vec2 TEX0; -varying vec4 TEX1; +in vec2 TEX0; +in vec4 TEX1; //----------------------------------------------------------------------------- // Fade edges of axis for texcoord passed in @@ -49,7 +49,7 @@ float fadeAxis( float val ) //----------------------------------------------------------------------------- void main() { - vec3 bumpNorm = texture2D( bumpMap, TEX0 ).rgb * 2.0 - 1.0; + vec3 bumpNorm = texture( bumpMap, TEX0 ).rgb * 2.0 - 1.0; vec2 offset = vec2( bumpNorm.x, bumpNorm.y ); vec4 texIndex = TEX1; @@ -61,8 +61,8 @@ void main() const float distortion = 0.2; texIndex.xy += offset * distortion * fadeVal; - vec4 diffuseColor = texture2D( diffuseMap, TEX0 ); - vec4 reflectColor = texture2DProj( refractMap, texIndex ); + vec4 diffuseColor = texture( diffuseMap, TEX0 ); + vec4 reflectColor = textureProj( refractMap, texIndex ); - gl_FragColor = diffuseColor + reflectColor * diffuseColor.a; + OUT_FragColor0 = diffuseColor + reflectColor * diffuseColor.a; } diff --git a/Templates/Empty/game/shaders/common/gl/planarReflectBumpV.glsl b/Templates/Empty/game/shaders/common/gl/planarReflectBumpV.glsl index 820bdf698..90bcd27d8 100644 --- a/Templates/Empty/game/shaders/common/gl/planarReflectBumpV.glsl +++ b/Templates/Empty/game/shaders/common/gl/planarReflectBumpV.glsl @@ -23,10 +23,13 @@ //----------------------------------------------------------------------------- // Data //----------------------------------------------------------------------------- +in vec4 vPosition; +in vec2 vTexCoord0; + uniform mat4 modelview; -varying vec2 TEX0; -varying vec4 TEX1; +out vec2 TEX0; +out vec4 TEX1; //----------------------------------------------------------------------------- // Main @@ -38,11 +41,11 @@ void main() 0.0, 0.0, 1.0, 0.0, 0.5, 0.5, 0.0, 1.0); - gl_Position = modelview * gl_Vertex; + gl_Position = modelview * vPosition; - TEX0 = gl_MultiTexCoord0.st; + TEX0 = vTexCoord0.st; TEX1 = texGenTest * gl_Position; TEX1.y = -TEX1.y; - + gl_Position.y *= -1; } diff --git a/Templates/Empty/game/shaders/common/gl/planarReflectP.glsl b/Templates/Empty/game/shaders/common/gl/planarReflectP.glsl index b4f4fab39..77914b80e 100644 --- a/Templates/Empty/game/shaders/common/gl/planarReflectP.glsl +++ b/Templates/Empty/game/shaders/common/gl/planarReflectP.glsl @@ -26,16 +26,16 @@ uniform sampler2D diffuseMap, refractMap; uniform vec4 shadeColor; -varying vec2 TEX0; -varying vec4 TEX1; +in vec2 TEX0; +in vec4 TEX1; //----------------------------------------------------------------------------- // Main //----------------------------------------------------------------------------- void main() { - vec4 diffuseColor = texture2D( diffuseMap, TEX0 ); - vec4 reflectColor = texture2DProj( refractMap, TEX1 ); + vec4 diffuseColor = texture( diffuseMap, TEX0 ); + vec4 reflectColor = textureProj( refractMap, TEX1 ); - gl_FragColor = diffuseColor + reflectColor * diffuseColor.a; + OUT_FragColor0 = diffuseColor + reflectColor * diffuseColor.a; } diff --git a/Templates/Empty/game/shaders/common/gl/planarReflectV.glsl b/Templates/Empty/game/shaders/common/gl/planarReflectV.glsl index 820bdf698..ba2484f66 100644 --- a/Templates/Empty/game/shaders/common/gl/planarReflectV.glsl +++ b/Templates/Empty/game/shaders/common/gl/planarReflectV.glsl @@ -23,10 +23,13 @@ //----------------------------------------------------------------------------- // Data //----------------------------------------------------------------------------- +in vec4 vPosition; +in vec2 vTexCoord0; + uniform mat4 modelview; -varying vec2 TEX0; -varying vec4 TEX1; +out vec2 TEX0; +out vec4 TEX1; //----------------------------------------------------------------------------- // Main @@ -38,9 +41,9 @@ void main() 0.0, 0.0, 1.0, 0.0, 0.5, 0.5, 0.0, 1.0); - gl_Position = modelview * gl_Vertex; + gl_Position = modelview * vPosition; - TEX0 = gl_MultiTexCoord0.st; + TEX0 = vTexCoord0; TEX1 = texGenTest * gl_Position; TEX1.y = -TEX1.y; diff --git a/Templates/Empty/game/shaders/common/gl/precipP.glsl b/Templates/Empty/game/shaders/common/gl/precipP.glsl index a04f16e4b..3c669517d 100644 --- a/Templates/Empty/game/shaders/common/gl/precipP.glsl +++ b/Templates/Empty/game/shaders/common/gl/precipP.glsl @@ -25,13 +25,13 @@ //----------------------------------------------------------------------------- uniform sampler2D diffuseMap; -varying vec4 color; -varying vec2 texCoord; +in vec4 color; +in vec2 texCoord; //----------------------------------------------------------------------------- // Main //----------------------------------------------------------------------------- void main() { - gl_FragColor = texture2D(diffuseMap, texCoord) * color; + OUT_FragColor0 = texture(diffuseMap, texCoord) * color; } diff --git a/Templates/Empty/game/shaders/common/gl/precipV.glsl b/Templates/Empty/game/shaders/common/gl/precipV.glsl index 3535f2f38..29f921630 100644 --- a/Templates/Empty/game/shaders/common/gl/precipV.glsl +++ b/Templates/Empty/game/shaders/common/gl/precipV.glsl @@ -23,28 +23,32 @@ //----------------------------------------------------------------------------- // Data //----------------------------------------------------------------------------- +in vec4 vPosition; +in vec2 vTexCoord0; + uniform mat4 modelview; uniform vec3 cameraPos, ambient; uniform vec2 fadeStartEnd; -varying vec4 color; -varying vec2 texCoord; +out vec4 color; +out vec2 texCoord; //----------------------------------------------------------------------------- // Main //----------------------------------------------------------------------------- void main() { - gl_Position = modelview * gl_Vertex; - texCoord = gl_MultiTexCoord0.st; + gl_Position = modelview * vPosition; + texCoord = vTexCoord0.st; color = vec4( ambient.r, ambient.g, ambient.b, 1.0 ); // Do we need to do a distance fade? if ( fadeStartEnd.x < fadeStartEnd.y ) { - float distance = length( cameraPos - gl_Vertex.xyz ); + float distance = length( cameraPos - vPosition.xyz ); color.a = abs( clamp( ( distance - fadeStartEnd.x ) / ( fadeStartEnd.y - fadeStartEnd.x ), 0.0, 1.0 ) - 1.0 ); } + gl_Position.y *= -1; } diff --git a/Templates/Empty/game/shaders/common/gl/projectedShadowP.glsl b/Templates/Empty/game/shaders/common/gl/projectedShadowP.glsl index 1dc963a4f..8ce0fba13 100644 --- a/Templates/Empty/game/shaders/common/gl/projectedShadowP.glsl +++ b/Templates/Empty/game/shaders/common/gl/projectedShadowP.glsl @@ -20,9 +20,11 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -varying vec2 texCoord; -varying vec4 color; -varying float fade; +in vec2 texCoord; +in vec4 color; +in float fade; + +out vec4 OUT_FragColor0; uniform sampler2D inputTex; uniform vec4 ambient; @@ -30,17 +32,6 @@ uniform vec4 ambient; void main() { - vec3 LUMINANCE_VECTOR = vec3(0.2125f, 0.4154f, 0.1721f); - float esmFactor = 200.0; - - float lum = dot( ambient.rgb, LUMINANCE_VECTOR ); - - gl_FragColor.rgb = ambient.rgb * lum; - gl_FragColor.a = 0.0; - float depth = texture2D(inputTex, texCoord).a; - - depth = depth * exp(depth - 10.0); - depth = exp(esmFactor * depth) - 1.0; - - gl_FragColor.a = clamp(depth * 300.0, 0.0, 1.0) * (1.0 - lum) * fade * color.a; + float shadow = texture( inputTex, texCoord ).a * color.a; + OUT_FragColor0 = ( ambient * shadow ) + ( 1 - shadow ); } diff --git a/Templates/Empty/game/shaders/common/gl/projectedShadowV.glsl b/Templates/Empty/game/shaders/common/gl/projectedShadowV.glsl index c8abde742..b5de84181 100644 --- a/Templates/Empty/game/shaders/common/gl/projectedShadowV.glsl +++ b/Templates/Empty/game/shaders/common/gl/projectedShadowV.glsl @@ -20,13 +20,16 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -//***************************************************************************** -// Precipitation vertex shader -//***************************************************************************** +#include "hlslCompat.glsl" -varying vec2 texCoord; -varying vec4 color; -varying float fade; +in vec4 vPosition; +in vec4 vColor; +in vec2 vTexCoord0; +in vec2 vTexCoord1; + +out vec2 texCoord; +out vec4 color; +out float fade; uniform mat4 modelview; uniform float shadowLength; @@ -34,11 +37,13 @@ uniform vec3 shadowCasterPosition; void main() { - gl_Position = modelview * vec4(gl_Vertex.xyz, 1.0); + gl_Position = modelview * vec4(vPosition.xyz, 1.0); - color = gl_Color; - texCoord = gl_MultiTexCoord1.st; + color = vColor; + texCoord = vTexCoord1.st; - float fromCasterDist = length(gl_Vertex.xyz - shadowCasterPosition) - shadowLength; - fade = 1.0 - clamp(fromCasterDist/shadowLength, 0.0, 1.0); + float fromCasterDist = length(vPosition.xyz - shadowCasterPosition) - shadowLength; + fade = 1.0 - clamp( fromCasterDist / shadowLength , 0.0, 1.0 ); + + correctSSP(gl_Position); } diff --git a/Templates/Empty/game/shaders/common/gl/scatterSkyP.glsl b/Templates/Empty/game/shaders/common/gl/scatterSkyP.glsl index 6a6b9b97c..691567a37 100644 --- a/Templates/Empty/game/shaders/common/gl/scatterSkyP.glsl +++ b/Templates/Empty/game/shaders/common/gl/scatterSkyP.glsl @@ -21,36 +21,32 @@ //----------------------------------------------------------------------------- #include "torque.glsl" +#include "hlslCompat.glsl" -// Calculates the Mie phase function -float getMiePhase(float fCos, float fCos2, float g, float g2) -{ - return 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos2) / pow(abs(1.0 + g2 - 2.0*g*fCos), 1.5); -} -// Calculates the Rayleigh phase function -float getRayleighPhase(float fCos2) -{ - //return 1.0; - return 0.75 + 0.75*fCos2; -} +// Conn +in vec4 rayleighColor; +#define IN_rayleighColor rayleighColor +in vec4 mieColor; +#define IN_mieColor mieColor +in vec3 v3Direction; +#define IN_v3Direction v3Direction +in float zPosition; +#define IN_zPosition zPosition +in vec3 pos; +#define IN_pos pos -varying vec4 rayleighColor; -varying vec4 mieColor; -varying vec3 v3Direction; -varying float zPosition; -varying vec3 pos; - -uniform samplerCube nightSky; +uniform samplerCube nightSky ; uniform vec4 nightColor; uniform vec2 nightInterpAndExposure; uniform float useCubemap; uniform vec3 lightDir; uniform vec3 sunDir; -void main() +void main() { - float fCos = dot( lightDir, v3Direction ) / length(v3Direction); + + float fCos = dot( lightDir, IN_v3Direction ) / length(IN_v3Direction); float fCos2 = fCos*fCos; float g = -0.991; @@ -58,15 +54,15 @@ void main() float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos2) / pow(abs(1.0 + g2 - 2.0*g*fCos), 1.5); - vec4 color = rayleighColor + fMiePhase * mieColor; + vec4 color = IN_rayleighColor + fMiePhase * IN_mieColor; color.a = color.b; - vec4 nightSkyColor = textureCube(nightSky, -v3Direction); + vec4 nightSkyColor = texture(nightSky, -v3Direction); nightSkyColor = mix(nightColor, nightSkyColor, useCubemap); float fac = dot( normalize( pos ), sunDir ); fac = max( nightInterpAndExposure.y, pow( clamp( fac, 0.0, 1.0 ), 2 ) ); - gl_FragColor = mix( color, nightSkyColor, nightInterpAndExposure.y ); + OUT_FragColor0 = mix( color, nightSkyColor, nightInterpAndExposure.y ); // Clip based on the camera-relative // z position of the vertex, passed through @@ -74,6 +70,6 @@ void main() if(zPosition < 0.0) discard; - gl_FragColor.a = 1; - gl_FragColor = hdrEncode( gl_FragColor ); + OUT_FragColor0.a = 1; + OUT_FragColor0 = hdrEncode( OUT_FragColor0 ); } diff --git a/Templates/Empty/game/shaders/common/gl/scatterSkyV.glsl b/Templates/Empty/game/shaders/common/gl/scatterSkyV.glsl index 53abd5a6b..61580d785 100644 --- a/Templates/Empty/game/shaders/common/gl/scatterSkyV.glsl +++ b/Templates/Empty/game/shaders/common/gl/scatterSkyV.glsl @@ -20,12 +20,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -const int nSamples = 4; -const float fSamples = 4.0; - -// The scale depth (the altitude at which the average atmospheric density is found) -const float fScaleDepth = 0.25; -const float fInvScaleDepth = 1.0 / 0.25; +#include "hlslCompat.glsl" // The scale equation calculated by Vernier's Graphical Analysis float vernierScale(float fCos) @@ -40,12 +35,27 @@ float vernierScale(float fCos) return 0.25 * outx; } +in vec4 vPosition; +in vec3 vNormal; +in vec4 vColor; +in vec2 vTexCoord0; + +// This is the shader input vertex structure. +#define IN_position vPosition +#define IN_normal vNormal +#define IN_color vColor + // This is the shader output data. -varying vec4 rayleighColor; -varying vec4 mieColor; -varying vec3 v3Direction; -varying float zPosition; -varying vec3 pos; +out vec4 rayleighColor; +#define OUT_rayleighColor rayleighColor +out vec4 mieColor; +#define OUT_mieColor mieColor +out vec3 v3Direction; +#define OUT_v3Direction v3Direction +out float zPosition; +#define OUT_zPosition zPosition +out vec3 pos; +#define OUT_pos pos uniform mat4 modelView; uniform vec4 misc; @@ -54,13 +64,16 @@ uniform vec4 scatteringCoeffs; uniform vec3 camPos; uniform vec3 lightDir; uniform vec4 invWaveLength; - -void main() -{ - vec4 position = gl_Vertex.xyzw; - vec3 normal = gl_Normal.xyz; - vec4 color = gl_MultiTexCoord0.xyzw; +uniform vec4 colorize; +vec3 desaturate(const vec3 color, const float desaturation) +{ + const vec3 gray_conv = vec3 (0.30, 0.59, 0.11); + return mix(color, vec3(dot(gray_conv , color)), desaturation); +} + +void main() +{ // Pull some variables out: float camHeight = misc.x; float camHeightSqr = misc.y; @@ -83,7 +96,7 @@ void main() // Get the ray from the camera to the vertex, // and its length (which is the far point of the ray // passing through the atmosphere). - vec3 v3Pos = position.xyz / 6378000.0;// / outerRadius; + vec3 v3Pos = vec3(IN_position / 6378000.0);// / outerRadius; vec3 newCamPos = vec3( 0, 0, camHeight ); v3Pos.z += innerRadius; vec3 v3Ray = v3Pos.xyz - newCamPos; @@ -97,16 +110,7 @@ void main() float fDepth = exp(scaleOverScaleDepth * (innerRadius - camHeight)); float fStartAngle = dot(v3Ray, v3Start) / fHeight; - float x = 1.0 - fStartAngle; - float x5 = x * 5.25; - float x5p6 = (-6.80 + x5); - float xnew = (3.83 + x * x5p6); - float xfinal = (0.459 + x * xnew); - float xfinal2 = -0.00287 + x * xfinal; - float othx = exp( xfinal2 ); - float vscale1 = 0.25 * othx; - - float fStartOffset = fDepth * vscale1;//vernierScale(fStartAngle); + float fStartOffset = fDepth * vernierScale( fStartAngle ); // Initialize the scattering loop variables. float fSampleLength = fFar / 2.0; @@ -123,24 +127,8 @@ void main() float fLightAngle = dot(lightDir, v3SamplePoint) / fHeight; float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight; - x = 1.0 - fCameraAngle; - x5 = x * 5.25; - x5p6 = (-6.80 + x5); - xnew = (3.83 + x * x5p6); - xfinal = (0.459 + x * xnew); - xfinal2 = -0.00287 + x * xfinal; - othx = exp( xfinal2 ); - float vscale3 = 0.25 * othx; - - - x = 1.0 - fLightAngle; - x5 = x * 5.25; - x5p6 = (-6.80 + x5); - xnew = (3.83 + x * x5p6); - xfinal = (0.459 + x * xnew); - xfinal2 = -0.00287 + x * xfinal; - othx = exp( xfinal2 ); - float vscale2 = 0.25 * othx; + float vscale3 = vernierScale( fCameraAngle ); + float vscale2 = vernierScale( fLightAngle ); float fScatter = (fStartOffset + fDepth*(vscale2 - vscale3)); vec3 v3Attenuate = exp(-fScatter * (invWaveLength.xyz * rayleigh4PI + mie4PI)); @@ -150,16 +138,24 @@ void main() // Finally, scale the Mie and Rayleigh colors // and set up the varying variables for the pixel shader. - gl_Position = modelView * position; - mieColor.rgb = v3FrontColor * mieBrightness; - mieColor.a = 1.0; - rayleighColor.rgb = v3FrontColor * (invWaveLength.xyz * rayleighBrightness); - rayleighColor.a = 1.0; - v3Direction = newCamPos - v3Pos.xyz; + gl_Position = modelView * IN_position; + OUT_mieColor.rgb = v3FrontColor * mieBrightness; + OUT_mieColor.a = 1.0; + OUT_rayleighColor.rgb = v3FrontColor * (invWaveLength.xyz * rayleighBrightness); + OUT_rayleighColor.a = 1.0; + OUT_v3Direction = newCamPos - v3Pos.xyz; + OUT_pos = IN_position.xyz; - // This offset is to get rid of the black line between the atmosky and the waterPlane - // along the horizon. - zPosition = position.z + 4000.0; - pos = position.xyz; +#ifdef USE_COLORIZE + + OUT_rayleighColor.rgb = desaturate(OUT_rayleighColor.rgb, 1) * colorize.a; + + OUT_rayleighColor.r *= colorize.r; + OUT_rayleighColor.g *= colorize.g; + OUT_rayleighColor.b *= colorize.b; + +#endif + + correctSSP(gl_Position); } diff --git a/Templates/Empty/game/shaders/common/gl/torque.glsl b/Templates/Empty/game/shaders/common/gl/torque.glsl index dc73a706f..a98ef859f 100644 --- a/Templates/Empty/game/shaders/common/gl/torque.glsl +++ b/Templates/Empty/game/shaders/common/gl/torque.glsl @@ -117,6 +117,7 @@ mat3x3 quatToMat( vec4 quat ) return mat; } + /// The number of additional substeps we take when refining /// the results of the offset parallax mapping function below. /// @@ -129,19 +130,20 @@ mat3x3 quatToMat( vec4 quat ) /// Performs fast parallax offset mapping using /// multiple refinement steps. -////// @param texMap The texture map whos alpha channel we sample the parallax depth. +/// +/// @param texMap The texture map whos alpha channel we sample the parallax depth. /// @param texCoord The incoming texture coordinate for sampling the parallax depth. /// @param negViewTS The negative view vector in tangent space. /// @param depthScale The parallax factor used to scale the depth result. /// vec2 parallaxOffset( sampler2D texMap, vec2 texCoord, vec3 negViewTS, float depthScale ) { - float depth = texture2D( texMap, texCoord ).a; + float depth = texture( texMap, texCoord ).a; vec2 offset = negViewTS.xy * ( depth * depthScale ); for ( int i=0; i < PARALLAX_REFINE_STEPS; i++ ) { - depth = ( depth + texture2D( texMap, texCoord + offset ).a ) * 0.5; + depth = ( depth + texture( texMap, texCoord + offset ).a ) * 0.5; offset = negViewTS.xy * ( depth * depthScale ); } @@ -151,59 +153,61 @@ vec2 parallaxOffset( sampler2D texMap, vec2 texCoord, vec3 negViewTS, float dept /// The maximum value for 16bit per component integer HDR encoding. const float HDR_RGB16_MAX = 100.0; -/// The maximum value for 10bit per component integer HDR encoding.const float HDR_RGB10_MAX = 4.0; +/// The maximum value for 10bit per component integer HDR encoding. +const float HDR_RGB10_MAX = 4.0; /// Encodes an HDR color for storage into a target. -vec3 hdrEncode( vec3 sample ){ +vec3 hdrEncode( vec3 _sample ) +{ #if defined( TORQUE_HDR_RGB16 ) - return sample / HDR_RGB16_MAX; + return _sample / HDR_RGB16_MAX; #elif defined( TORQUE_HDR_RGB10 ) - return sample / HDR_RGB10_MAX; + return _sample / HDR_RGB10_MAX; #else // No encoding. - return sample; + return _sample; #endif } /// Encodes an HDR color for storage into a target. -vec4 hdrEncode( vec4 sample ) +vec4 hdrEncode( vec4 _sample ) { - return vec4( hdrEncode( sample.rgb ), sample.a ); + return vec4( hdrEncode( _sample.rgb ), _sample.a ); } /// Decodes an HDR color from a target. -vec3 hdrDecode( vec3 sample ) +vec3 hdrDecode( vec3 _sample ) { #if defined( TORQUE_HDR_RGB16 ) - return sample * HDR_RGB16_MAX; + return _sample * HDR_RGB16_MAX; #elif defined( TORQUE_HDR_RGB10 ) - return sample * HDR_RGB10_MAX; + return _sample * HDR_RGB10_MAX; #else // No encoding. - return sample; + return _sample; #endif } /// Decodes an HDR color from a target. -vec4 hdrDecode( vec4 sample ) +vec4 hdrDecode( vec4 _sample ) { - return vec4( hdrDecode( sample.rgb ), sample.a ); + return vec4( hdrDecode( _sample.rgb ), _sample.a ); } /// Returns the luminance for an HDR pixel. -float hdrLuminance( vec3 sample ) +float hdrLuminance( vec3 _sample ) { // There are quite a few different ways to // calculate luminance from an rgb value. @@ -216,7 +220,7 @@ float hdrLuminance( vec3 sample ) // // Max component luminance. // - //float lum = max( sample.r, max( sample.g, sample.b ) ); + //float lum = max( _sample.r, max( _sample.g, _sample.b ) ); //////////////////////////////////////////////////////////////////////////// // The perceptual relative luminance. @@ -224,23 +228,45 @@ float hdrLuminance( vec3 sample ) // See http://en.wikipedia.org/wiki/Luminance_(relative) // const vec3 RELATIVE_LUMINANCE = vec3( 0.2126, 0.7152, 0.0722 ); - float lum = dot( sample, RELATIVE_LUMINANCE ); + float lum = dot( _sample, RELATIVE_LUMINANCE ); //////////////////////////////////////////////////////////////////////////// // // The average component luminance. // //const vec3 AVERAGE_LUMINANCE = vec3( 0.3333, 0.3333, 0.3333 ); - //float lum = dot( sample, AVERAGE_LUMINANCE ); + //float lum = dot( _sample, AVERAGE_LUMINANCE ); return lum; } +#ifdef TORQUE_PIXEL_SHADER +/// Called from the visibility feature to do screen +/// door transparency for fading of objects. +void fizzle(vec2 vpos, float visibility) +{ + // NOTE: The magic values below are what give us + // the nice even pattern during the fizzle. + // + // These values can be changed to get different + // patterns... some better than others. + // + // Horizontal Blinds - { vpos.x, 0.916, vpos.y, 0 } + // Vertical Lines - { vpos.x, 12.9898, vpos.y, 78.233 } + // + // I'm sure there are many more patterns here to + // discover for different effects. + + mat2x2 m = mat2x2( vpos.x, vpos.y, 0.916, 0.350 ); + if( (visibility - fract( determinant( m ) )) < 0 ) //if(a < 0) discard; + discard; +} +#endif //TORQUE_PIXEL_SHADER /// Basic assert macro. If the condition fails, then the shader will output color. /// @param condition This should be a bvec[2-4]. If any items is false, condition is considered to fail. /// @param color The color that should be outputted if the condition fails. /// @note This macro will only work in the void main() method of a pixel shader. -#define assert(condition, color) { if(!any(condition)) { gl_FragColor = color; return; } } +#define assert(condition, color) { if(!any(condition)) { OUT_FragColor0 = color; return; } } #endif // _TORQUE_GLSL_ diff --git a/Templates/Empty/game/shaders/common/gl/wavesP.glsl b/Templates/Empty/game/shaders/common/gl/wavesP.glsl index 24bd8cbb4..ddb683947 100644 --- a/Templates/Empty/game/shaders/common/gl/wavesP.glsl +++ b/Templates/Empty/game/shaders/common/gl/wavesP.glsl @@ -28,10 +28,10 @@ uniform float specularPower; uniform vec4 ambient; uniform float accumTime; -varying vec2 TEX0; -varying vec4 outLightVec; -varying vec3 outPos; -varying vec3 outEyePos; +in vec2 TEX0; +in vec4 outLightVec; +in vec3 outPos; +in vec3 outEyePos; void main() { @@ -42,14 +42,14 @@ void main() texOffset.x = TEX0.x + sinOffset1 + sinOffset2; texOffset.y = TEX0.y + cos( accumTime * 3.0 + TEX0.x * 6.28319 * 2.0 ) * 0.05; - vec4 bumpNorm = texture2D(bumpMap, texOffset) * 2.0 - 1.0; - vec4 diffuse = texture2D(diffMap, texOffset); + vec4 bumpNorm = texture(bumpMap, texOffset) * 2.0 - 1.0; + vec4 diffuse = texture(diffMap, texOffset); - gl_FragColor = diffuse * (clamp(dot(outLightVec.xyz, bumpNorm.xyz), 0.0, 1.0) + ambient); + OUT_FragColor0 = diffuse * (clamp(dot(outLightVec.xyz, bumpNorm.xyz), 0.0, 1.0) + ambient); vec3 eyeVec = normalize(outEyePos - outPos); vec3 halfAng = normalize(eyeVec + outLightVec.xyz); float specular = clamp(dot(bumpNorm.xyz, halfAng), 0.0, 1.0) * outLightVec.w; specular = pow(specular, specularPower); - gl_FragColor += specularColor * specular; + OUT_FragColor0 += specularColor * specular; } diff --git a/Templates/Empty/game/shaders/common/lighting/advanced/gl/convexGeometryV.glsl b/Templates/Empty/game/shaders/common/lighting/advanced/gl/convexGeometryV.glsl index 6d3e36e7e..1807ac43f 100644 --- a/Templates/Empty/game/shaders/common/lighting/advanced/gl/convexGeometryV.glsl +++ b/Templates/Empty/game/shaders/common/lighting/advanced/gl/convexGeometryV.glsl @@ -20,16 +20,33 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -varying vec4 wsEyeDir; -varying vec4 ssPos; +#include "../../../gl/hlslCompat.glsl" + +in vec4 vPosition; + +#define IN_pos vPosition + +out vec4 wsEyeDir; +out vec4 ssPos; +out vec4 vsEyeDir; + +#define OUT_hpos gl_Position +#define OUT_wsEyeDir wsEyeDir +#define OUT_ssPos ssPos +#define OUT_vsEyeDir vsEyeDir uniform mat4 modelview; uniform mat4 objTrans; +uniform mat4 worldViewOnly; uniform vec3 eyePosWorld; void main() { - gl_Position = modelview * gl_Vertex; - wsEyeDir = objTrans * gl_Vertex - vec4( eyePosWorld, 0.0 ); - ssPos = gl_Position; + OUT_hpos = tMul( modelview, IN_pos ); + OUT_wsEyeDir = tMul( objTrans, IN_pos ) - vec4( eyePosWorld, 0.0 ); + OUT_vsEyeDir = tMul( worldViewOnly, IN_pos ); + OUT_ssPos = OUT_hpos; + + correctSSP(gl_Position); } + diff --git a/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgDepthVisualizeP.glsl b/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgDepthVisualizeP.glsl index 4a954ae84..e3ee59c8a 100644 --- a/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgDepthVisualizeP.glsl +++ b/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgDepthVisualizeP.glsl @@ -20,14 +20,15 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../../gl/hlslCompat.glsl" #include "shadergen:/autogenConditioners.h" -varying vec2 uv0; +in vec2 uv0; uniform sampler2D prepassBuffer; uniform sampler1D depthViz; void main() { float depth = prepassUncondition( prepassBuffer, uv0 ).w; - gl_FragColor = vec4( texture1D( depthViz, depth ).rgb, 1 ); + OUT_FragColor0 = vec4( texture( depthViz, depth ).rgb, 1.0 ); } \ No newline at end of file diff --git a/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl b/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl index 580204487..aa17df4d6 100644 --- a/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl +++ b/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl @@ -20,15 +20,16 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../../gl/hlslCompat.glsl" #include "shadergen:/autogenConditioners.h" -varying vec2 uv0; +in vec2 uv0; uniform sampler2D lightInfoBuffer; void main() { - vec3 lightcolor; + vec3 lightcolor; float nl_Att, specular; - lightinfoUncondition( texture2DLod( lightInfoBuffer, uv0 ), lightcolor, nl_Att, specular ); - gl_FragColor = vec4( lightcolor, 1.0 ); + lightinfoUncondition( texture( lightInfoBuffer, uv0 ), lightcolor, nl_Att, specular ); + OUT_FragColor0 = vec4( lightcolor, 1.0 ); } \ No newline at end of file diff --git a/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl b/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl index 6f7c52486..e549922ff 100644 --- a/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl +++ b/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl @@ -20,15 +20,16 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../../gl/hlslCompat.glsl" #include "shadergen:/autogenConditioners.h" -varying vec2 uv0; +in vec2 uv0; uniform sampler2D lightInfoBuffer; void main() { - vec3 lightcolor; + vec3 lightcolor; float nl_Att, specular; - lightinfoUncondition( texture2DLod( lightInfoBuffer, uv0 ), lightcolor, nl_Att, specular ); - gl_FragColor = vec4( specular, specular, specular, 1.0 ); + lightinfoUncondition( texture( lightInfoBuffer, uv0 ), lightcolor, nl_Att, specular ); + OUT_FragColor0 = vec4( specular, specular, specular, 1.0 ); } \ No newline at end of file diff --git a/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgNormalVisualizeP.glsl b/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgNormalVisualizeP.glsl index 96b645524..f61706393 100644 --- a/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgNormalVisualizeP.glsl +++ b/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgNormalVisualizeP.glsl @@ -20,14 +20,14 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../../gl/hlslCompat.glsl" #include "shadergen:/autogenConditioners.h" - -varying vec2 uv0; -uniform sampler2D prepassTex; +in vec2 uv0; +uniform sampler2D prepassBuffer; void main() { - vec3 normal = prepassUncondition( prepassTex, uv0 ).xyz; - gl_FragColor = vec4( ( normal + 1.0 ) * 0.5, 1.0 ); + vec3 normal = prepassUncondition( prepassBuffer, uv0 ).xyz; + OUT_FragColor0 = vec4( ( normal + 1.0 ) * 0.5, 1.0 ); } \ No newline at end of file diff --git a/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgShadowVisualizeP.glsl b/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgShadowVisualizeP.glsl index 51609fc6b..e997950ab 100644 --- a/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgShadowVisualizeP.glsl +++ b/Templates/Empty/game/shaders/common/lighting/advanced/gl/dbgShadowVisualizeP.glsl @@ -19,13 +19,14 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../../gl/hlslCompat.glsl" -varying vec2 uv0; +in vec2 uv0; uniform sampler2D shadowMap; uniform sampler1D depthViz; void main() { - float depth = clamp( texture2DLod( shadowMap, uv0, 0 ).r, 0.0, 1.0 ); - gl_FragColor = vec4( texture1D( depthViz, depth ).rgb, 1.0 ); + float depth = saturate( texture( shadowMap, uv0 ).r ); + OUT_FragColor0 = vec4( texture( depthViz, depth ).rgb, 1 ); } \ No newline at end of file diff --git a/Templates/Empty/game/shaders/common/lighting/advanced/gl/farFrustumQuad.glsl b/Templates/Empty/game/shaders/common/lighting/advanced/gl/farFrustumQuad.glsl index 866a39b0b..76054eb09 100644 --- a/Templates/Empty/game/shaders/common/lighting/advanced/gl/farFrustumQuad.glsl +++ b/Templates/Empty/game/shaders/common/lighting/advanced/gl/farFrustumQuad.glsl @@ -24,7 +24,7 @@ vec2 getUVFromSSPos( vec3 ssPos, vec4 rtParams ) { vec2 outPos = ( ssPos.xy + 1.0 ) / 2.0; + outPos.y = 1.0 - outPos.y; outPos = ( outPos * rtParams.zw ) + rtParams.xy; - //outPos.y = 1.0 - outPos.y; return outPos; } diff --git a/Templates/Empty/game/shaders/common/lighting/advanced/gl/farFrustumQuadV.glsl b/Templates/Empty/game/shaders/common/lighting/advanced/gl/farFrustumQuadV.glsl index ce5c2ad81..a80e856ed 100644 --- a/Templates/Empty/game/shaders/common/lighting/advanced/gl/farFrustumQuadV.glsl +++ b/Templates/Empty/game/shaders/common/lighting/advanced/gl/farFrustumQuadV.glsl @@ -20,24 +20,32 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../../gl/hlslCompat.glsl" #include "farFrustumQuad.glsl" -uniform vec4 renderTargetParams; - -varying vec4 hpos; -varying vec2 uv0; -varying vec3 wsEyeRay; +in vec4 vPosition; +in vec3 vNormal; +in vec3 vTangent; +in vec2 vTexCoord0; +uniform vec4 rtParams0; +out vec4 hpos; +out vec2 uv0; +out vec3 wsEyeRay; +out vec3 vsEyeRay; void main() -{ - // Expand the SS coordinate (stored in uv0) - hpos = vec4( gl_MultiTexCoord0.st * 2.0 - 1.0, 1.0, 1.0 ); - gl_Position = hpos; - +{ + hpos = vec4( vTexCoord0, 0, 1 ); + // Get a RT-corrected UV from the SS coord - uv0 = getUVFromSSPos( hpos.xyz, renderTargetParams ); + uv0 = getUVFromSSPos( hpos.xyz, rtParams0 ); + gl_Position = hpos; - // Interpolators will generate eye ray from far-frustum corners - wsEyeRay = gl_Vertex.xyz; + // Interpolators will generate eye rays the + // from far-frustum corners. + wsEyeRay = vTangent; + vsEyeRay = vNormal; + + correctSSP(gl_Position); } diff --git a/Templates/Empty/game/shaders/common/lighting/advanced/gl/pointLightP.glsl b/Templates/Empty/game/shaders/common/lighting/advanced/gl/pointLightP.glsl index b135f1aa8..c0610508b 100644 --- a/Templates/Empty/game/shaders/common/lighting/advanced/gl/pointLightP.glsl +++ b/Templates/Empty/game/shaders/common/lighting/advanced/gl/pointLightP.glsl @@ -21,34 +21,26 @@ //----------------------------------------------------------------------------- #include "../../../gl/hlslCompat.glsl" -#include "farFrustumQuad.glsl" -#include "lightingUtils.glsl" -#include "../../shadowMap/shadowMapIO_GLSL.h" #include "shadergen:/autogenConditioners.h" +#include "farFrustumQuad.glsl" +#include "lightingUtils.glsl" +#include "../../../gl/lighting.glsl" +#include "../../shadowMap/shadowMapIO_GLSL.h" +#include "softShadow.glsl" -#if TORQUE_SM >= 30 +in vec4 wsEyeDir; +in vec4 ssPos; +in vec4 vsEyeDir; - // Enables high quality soft shadow - // filtering for SM3.0 and above. - #define SOFTSHADOW_SM3 - - #include "softShadow.glsl" - -#else +#ifdef USE_COOKIE_TEX +/// The texture for cookie rendering. +uniform samplerCube cookieMap ; #endif - -// I am not sure if we should do this in a better way -//#define SHADOW_CUBE -//#define SHADOW_PARABOLOID -#define SHADOW_DUALPARABOLOID -#define SHADOW_DUALPARABOLOID_SINGLE_PASS - - #ifdef SHADOW_CUBE vec3 decodeShadowCoord( vec3 shadowCoord ) @@ -56,39 +48,47 @@ return shadowCoord; } - vec4 shadowSample( samplerCUBE shadowMap, vec3 shadowCoord ) + vec4 shadowSample( samplerCube shadowMap, vec3 shadowCoord ) { - return textureCUBE( shadowMap, shadowCoord ); + return texture( shadowMap, shadowCoord ); } - -#elif defined( SHADOW_DUALPARABOLOID ) + +#else vec3 decodeShadowCoord( vec3 paraVec ) { - // Swizzle z and y + // Flip y and z paraVec = paraVec.xzy; - #ifdef SHADOW_DUALPARABOLOID_SINGLE_PASS + #ifndef SHADOW_PARABOLOID bool calcBack = (paraVec.z < 0.0); - if(calcBack) + if ( calcBack ) + { paraVec.z = paraVec.z * -1.0; + + #ifdef SHADOW_DUALPARABOLOID + paraVec.x = -paraVec.x; + #endif + } #endif vec3 shadowCoord; - shadowCoord.x = (paraVec.x / (2.0*(1.0 + paraVec.z))) + 0.5; - shadowCoord.y = ((paraVec.y / (2.0*(1.0 + paraVec.z))) + 0.5); + shadowCoord.x = (paraVec.x / (2*(1 + paraVec.z))) + 0.5; + shadowCoord.y = 1-((paraVec.y / (2*(1 + paraVec.z))) + 0.5); shadowCoord.z = 0; // adjust the co-ordinate slightly if it is near the extent of the paraboloid // this value was found via experementation - shadowCoord.xy *= 0.997; + // NOTE: this is wrong, it only biases in one direction, not towards the uv + // center ( 0.5 0.5 ). + //shadowCoord.xy *= 0.997; - #ifdef SHADOW_DUALPARABOLOID_SINGLE_PASS + #ifndef SHADOW_PARABOLOID // If this is the back, offset in the atlas - if(calcBack) + if ( calcBack ) shadowCoord.x += 1.0; // Atlasing front and back maps, so scale @@ -99,51 +99,35 @@ return shadowCoord; } -#else - - #error Unknown shadow type! - #endif -varying vec4 wsEyeDir; -varying vec4 ssPos; - - uniform sampler2D prePassBuffer; #ifdef SHADOW_CUBE - uniform samplerCube shadowMap; + uniform samplerCube shadowMap; #else - uniform sampler2D shadowMap; -#endif -#ifdef ACCUMULATE_LUV - uniform sampler2D scratchTarget; + uniform sampler2D shadowMap; #endif -uniform vec4 renderTargetParams; +uniform vec4 rtParams0; uniform vec3 lightPosition; uniform vec4 lightColor; -uniform float lightBrightness; -uniform float lightRange; +uniform float lightBrightness; +uniform float lightRange; uniform vec2 lightAttenuation; uniform vec4 lightMapParams; - -uniform vec3 eyePosWorld; -uniform vec4 farPlane; -uniform float negFarPlaneDotEye; -uniform mat3x3 worldToLightProj; - +uniform vec4 vsFarPlane; +uniform mat3 viewToLightProj; uniform vec4 lightParams; uniform float shadowSoftness; -uniform float constantSpecularPower; + - -void main() -{ +void main() +{ // Compute scene UV - vec3 ssPosP = ssPos.xyz / ssPos.w; - vec2 uvScene = getUVFromSSPos( ssPosP, renderTargetParams ); + vec3 ssPos = ssPos.xyz / ssPos.w; + vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); // Sample/unpack the normal/z data vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene ); @@ -151,21 +135,17 @@ void main() float depth = prepassSample.a; // Eye ray - Eye -> Pixel - vec3 eyeRay = getDistanceVectorToPlane( negFarPlaneDotEye, wsEyeDir.xyz / wsEyeDir.w , farPlane ); - - // Get world space pixel position - vec3 worldPos = eyePosWorld + eyeRay * depth; + vec3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane ); + vec3 viewSpacePos = eyeRay * depth; // Build light vec, get length, clip pixel if needed - vec3 lightVec = lightPosition - worldPos; + vec3 lightVec = lightPosition - viewSpacePos; float lenLightV = length( lightVec ); - if ( lightRange - lenLightV < 0.0 ) - discard; - + clip( lightRange - lenLightV ); + // Get the attenuated falloff. float atten = attenuate( lightColor, lightAttenuation, lenLightV ); - if ( atten - 1e-6 < 0.0 ) - discard; + clip( atten - 1e-6 ); // Normalize lightVec lightVec /= lenLightV; @@ -181,61 +161,73 @@ void main() #else - // Convert the light vector into a shadow map - // here once instead of in the filtering loop. - vec4 shadowCoord = vec4(0.0); - #ifdef SHADOW_CUBE - shadowCoord.xy = decodeShadowCoord( -lightVec ); - #else - shadowCoord.xy = decodeShadowCoord( worldToLightProj * -lightVec ).xy; - #endif - // Get a linear depth from the light source. - float distToLight = lenLightV / lightRange; + float distToLight = lenLightV / lightRange; - #ifdef SOFTSHADOW_SM3 + #ifdef SHADOW_CUBE + + // TODO: We need to fix shadow cube to handle soft shadows! + float occ = texture( shadowMap, tMul( viewToLightProj, -lightVec ) ).r; + float shadowed = saturate( exp( lightParams.y * ( occ - distToLight ) ) ); + + #else + vec2 shadowCoord = decodeShadowCoord( tMul( viewToLightProj, -lightVec ) ).xy; + float shadowed = softShadow_filter( shadowMap, - gTapRotationTex, - ssPosP.xy, - shadowCoord.xy, + ssPos.xy, + shadowCoord, shadowSoftness, distToLight, nDotL, lightParams.y ); - - #else // !SOFTSHADOW_SM3 - - // TODO: Implement the SM2 lower quality - // shadow filtering method. #endif #endif // !NO_SHADOW - + + #ifdef USE_COOKIE_TEX + + // Lookup the cookie sample. + vec4 cookie = texture( cookieMap, tMul( viewToLightProj, -lightVec ) ); + + // Multiply the light with the cookie tex. + lightColor.rgb *= cookie.rgb; + + // Use a maximum channel luminance to attenuate + // the lighting else we get specular in the dark + // regions of the cookie texture. + atten *= max( cookie.r, max( cookie.g, cookie.b ) ); + + #endif + // NOTE: Do not clip on fully shadowed pixels as it would // cause the hardware occlusion query to disable the shadow. // Specular term - float specular = calcSpecular( lightVec, - normal, - normalize( -eyeRay ), - constantSpecularPower, - shadowed * atten * lightBrightness ); - - // N.L * Attenuation - float Sat_NL_Att = clamp( nDotL * atten * shadowed, 0.0, 1.0 ); - - // In LUV color mode we need to blend in the - // output from the previous target. - vec4 previousPix = vec4(0.0); - #ifdef ACCUMULATE_LUV - previousPix = texture2DLod( scratchTarget, uvScene, 0 ); - #endif + float specular = AL_CalcSpecular( lightVec, + normal, + normalize( -eyeRay ) ) * lightBrightness * atten * shadowed; - // Output - gl_FragColor = lightinfoCondition( lightColor.rgb * lightBrightness, - Sat_NL_Att, - specular, - previousPix ) * lightMapParams; + float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness; + vec3 lightColorOut = lightMapParams.rgb * lightColor.rgb; + vec4 addToResult = vec4(0.0); + + // TODO: This needs to be removed when lightmapping is disabled + // as its extra work per-pixel on dynamic lit scenes. + // + // Special lightmapping pass. + if ( lightMapParams.a < 0.0 ) + { + // This disables shadows on the backsides of objects. + shadowed = nDotL < 0.0f ? 1.0f : shadowed; + + Sat_NL_Att = 1.0f; + shadowed = mix( 1.0f, shadowed, atten ); + lightColorOut = vec3(shadowed); + specular *= lightBrightness; + addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); + } + + OUT_FragColor0 = lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult ); } diff --git a/Templates/Empty/game/shaders/common/lighting/advanced/gl/softShadow.glsl b/Templates/Empty/game/shaders/common/lighting/advanced/gl/softShadow.glsl index 8ef09ed2f..a14213946 100644 --- a/Templates/Empty/game/shaders/common/lighting/advanced/gl/softShadow.glsl +++ b/Templates/Empty/game/shaders/common/lighting/advanced/gl/softShadow.glsl @@ -19,113 +19,141 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- - - -#define NUM_TAPS 12 - -#define NUM_PRE_TAPS 4 - -/// The non-uniform poisson disk used in the -/// high quality shadow filtering. -vec2 sNonUniformTaps[NUM_TAPS]; -void initNonUniformTaps() + +#if defined( SOFTSHADOW ) && defined( SOFTSHADOW_HIGH_QUALITY ) + +#define NUM_PRE_TAPS 4 +#define NUM_TAPS 12 + +/// The non-uniform poisson disk used in the +/// high quality shadow filtering. +vec2 sNonUniformTaps[NUM_TAPS] = vec2[] +( + // These first 4 taps are located around the edges + // of the disk and are used to predict fully shadowed + // or unshadowed areas. + vec2( 0.992833, 0.979309 ), + vec2( -0.998585, 0.985853 ), + vec2( 0.949299, -0.882562 ), + vec2( -0.941358, -0.893924 ), + + // The rest of the samples. + vec2( 0.545055, -0.589072 ), + vec2( 0.346526, 0.385821 ), + vec2( -0.260183, 0.334412 ), + vec2( 0.248676, -0.679605 ), + vec2( -0.569502, -0.390637 ), + vec2( -0.614096, 0.212577 ), + vec2( -0.259178, 0.876272 ), + vec2( 0.649526, 0.864333 ) +); + +#else + +#define NUM_PRE_TAPS 5 + +/// The non-uniform poisson disk used in the +/// high quality shadow filtering. +vec2 sNonUniformTaps[NUM_PRE_TAPS] = vec2[] +( + vec2( 0.892833, 0.959309 ), + vec2( -0.941358, -0.873924 ), + vec2( -0.260183, 0.334412 ), + vec2( 0.348676, -0.679605 ), + vec2( -0.569502, -0.390637 ) +); + +#endif + + +/// The texture used to do per-pixel pseudorandom +/// rotations of the filter taps. +uniform sampler2D gTapRotationTex ; + + +float softShadow_sampleTaps( sampler2D shadowMap, + vec2 sinCos, + vec2 shadowPos, + float filterRadius, + float distToLight, + float esmFactor, + int startTap, + int endTap ) { - // These first 4 taps are located around the edges - // of the disk and are used to predict fully shadowed - // or unshadowed areas. - sNonUniformTaps[0] = vec2( 0.992833, 0.979309 ); - sNonUniformTaps[1] = vec2( -0.998585, 0.985853 ); - sNonUniformTaps[2] = vec2( 0.949299, -0.882562 ); - sNonUniformTaps[3] = vec2( -0.941358, -0.893924 ); - - // The rest of the samples. - sNonUniformTaps[4] = vec2( 0.545055, -0.589072 ); - sNonUniformTaps[5] = vec2( 0.346526, 0.385821 ); - sNonUniformTaps[6] = vec2( -0.260183, 0.334412 ); - sNonUniformTaps[7] = vec2( 0.248676, -0.679605 ); - sNonUniformTaps[8] = vec2( -0.569502, -0.390637 ); - sNonUniformTaps[9] = vec2( -0.014096, 0.012577 ); - sNonUniformTaps[10] = vec2( -0.259178, 0.876272 ); - sNonUniformTaps[11] = vec2( 0.649526, 0.664333 ); + float shadow = 0; + + vec2 tap = vec2(0); + for ( int t = startTap; t < endTap; t++ ) + { + tap.x = ( sNonUniformTaps[t].x * sinCos.y - sNonUniformTaps[t].y * sinCos.x ) * filterRadius; + tap.y = ( sNonUniformTaps[t].y * sinCos.y + sNonUniformTaps[t].x * sinCos.x ) * filterRadius; + float occluder = tex2Dlod( shadowMap, vec4( shadowPos + tap, 0, 0 ) ).r; + + float esm = saturate( exp( esmFactor * ( occluder - distToLight ) ) ); + shadow += esm / float( endTap - startTap ); + } + + return shadow; } - -/// The texture used to do per-pixel pseudorandom -/// rotations of the filter taps. -uniform sampler2D gTapRotationTex; - - -float softShadow_sampleTaps( sampler2D shadowMap, - vec2 sinCos, - vec2 shadowPos, - float filterRadius, - float distToLight, - float esmFactor, - int startTap, - int endTap ) -{ - initNonUniformTaps(); - float shadow = 0.0; - - vec2 tap = vec2(0.0); - for ( int t = startTap; t < endTap; t++ ) - { - tap.x = ( sNonUniformTaps[t].x * sinCos.y - sNonUniformTaps[t].y * sinCos.x ) * filterRadius; - tap.y = ( sNonUniformTaps[t].y * sinCos.y + sNonUniformTaps[t].x * sinCos.x ) * filterRadius; - float occluder = texture2DLod( shadowMap, shadowPos + tap, 0.0 ).r; - - float esm = clamp( exp( esmFactor * ( occluder - distToLight ) ), 0.0, 1.0 ); - shadow += esm / float( endTap - startTap ); - } - - return shadow; -} - - -// HACK! HACK! HACK! -// We take the noise texture directly as the second parameter to ensure that it -// is the "last used" sampler, and thus doesn't collide with the prepass buffer -// or shadow map. If we use gTapRotationTex directly here, then it is the first -// used sampler and will collide with the prepass buffer. -float softShadow_filter( sampler2D shadowMap, - sampler2D noiseTexture, - vec2 vpos, - vec2 shadowPos, - float filterRadius, - float distToLight, - float dotNL, - float esmFactor ) -{ - // Lookup the random rotation for this screen pixel. - vec2 sinCos = ( texture2DLod( noiseTexture, vpos * 16.0, 0.0 ).rg - 0.5 ) * 2.0; - - // Do the prediction taps first. - float shadow = softShadow_sampleTaps( shadowMap, - sinCos, - shadowPos, - filterRadius, - distToLight, - esmFactor, - 0, - NUM_PRE_TAPS ); - - // Only do the expensive filtering if we're really - // in a partially shadowed area. - if ( shadow * ( 1.0 - shadow ) * max( dotNL, 0.0 ) > 0.06 ) - { - shadow += softShadow_sampleTaps( shadowMap, - sinCos, - shadowPos, - filterRadius, - distToLight, - esmFactor, - NUM_PRE_TAPS, - NUM_TAPS ); - - // This averages the taps above with the results - // of the prediction samples. - shadow *= 0.5; - } - - return shadow; -} \ No newline at end of file + + +float softShadow_filter( sampler2D shadowMap, + vec2 vpos, + vec2 shadowPos, + float filterRadius, + float distToLight, + float dotNL, + float esmFactor ) +{ + #ifndef SOFTSHADOW + + // If softshadow is undefined then we skip any complex + // filtering... just do a single sample ESM. + + float occluder = tex2Dlod( shadowMap, vec4( shadowPos, 0, 0 ) ).r; + float shadow = saturate( exp( esmFactor * ( occluder - distToLight ) ) ); + + #else + + // Lookup the random rotation for this screen pixel. + vec2 sinCos = ( tex2Dlod( gTapRotationTex, vec4( vpos * 16, 0, 0 ) ).rg - 0.5 ) * 2; + + // Do the prediction taps first. + float shadow = softShadow_sampleTaps( shadowMap, + sinCos, + shadowPos, + filterRadius, + distToLight, + esmFactor, + 0, + NUM_PRE_TAPS ); + + // We live with only the pretap results if we don't + // have high quality shadow filtering enabled. + #ifdef SOFTSHADOW_HIGH_QUALITY + + // Only do the expensive filtering if we're really + // in a partially shadowed area. + if ( shadow * ( 1.0 - shadow ) * max( dotNL, 0 ) > 0.06 ) + { + shadow += softShadow_sampleTaps( shadowMap, + sinCos, + shadowPos, + filterRadius, + distToLight, + esmFactor, + NUM_PRE_TAPS, + NUM_TAPS ); + + // This averages the taps above with the results + // of the prediction samples. + shadow *= 0.5; + } + + #endif // SOFTSHADOW_HIGH_QUALITY + + #endif // SOFTSHADOW + + return shadow; +} \ No newline at end of file diff --git a/Templates/Empty/game/shaders/common/lighting/advanced/gl/spotLightP.glsl b/Templates/Empty/game/shaders/common/lighting/advanced/gl/spotLightP.glsl index d29f5edb0..c07be1f34 100644 --- a/Templates/Empty/game/shaders/common/lighting/advanced/gl/spotLightP.glsl +++ b/Templates/Empty/game/shaders/common/lighting/advanced/gl/spotLightP.glsl @@ -25,58 +25,49 @@ #include "lightingUtils.glsl" #include "../../shadowMap/shadowMapIO_GLSL.h" #include "shadergen:/autogenConditioners.h" +#include "softShadow.glsl" +#include "../../../gl/lighting.glsl" +in vec4 wsEyeDir; +in vec4 ssPos; +in vec4 vsEyeDir; -#if TORQUE_SM >= 30 +#define IN_wsEyeDir wsEyeDir +#define IN_ssPos ssPos +#define IN_vsEyeDir vsEyeDir - // Enables high quality soft shadow - // filtering for SM3.0 and above. - #define SOFTSHADOW_SM3 - - #include "softShadow.glsl" - -#else +#ifdef USE_COOKIE_TEX +/// The texture for cookie rendering. +uniform sampler2D cookieMap; #endif - -varying vec4 ssPos; -varying vec4 wsEyeDir; - - uniform sampler2D prePassBuffer; uniform sampler2D shadowMap; -#ifdef ACCUMULATE_LUV - uniform sampler2D scratchTarget; -#endif -uniform vec4 renderTargetParams; +uniform vec4 rtParams0; uniform vec3 lightPosition; uniform vec4 lightColor; -uniform float lightBrightness; -uniform float lightRange; +uniform float lightBrightness; +uniform float lightRange; uniform vec2 lightAttenuation; uniform vec3 lightDirection; uniform vec4 lightSpotParams; uniform vec4 lightMapParams; -uniform vec3 eyePosWorld; -uniform vec4 farPlane; -uniform float negFarPlaneDotEye; -uniform mat4x4 worldToLightProj; +uniform vec4 vsFarPlane; +uniform mat4 viewToLightProj; uniform vec4 lightParams; uniform float shadowSoftness; -uniform float constantSpecularPower; - void main() -{ +{ // Compute scene UV - vec3 ssPosP = ssPos.xyz / ssPos.w; - vec2 uvScene = getUVFromSSPos( ssPosP, renderTargetParams ); + vec3 ssPos = IN_ssPos.xyz / IN_ssPos.w; + vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); // Sample/unpack the normal/z data vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene ); @@ -84,85 +75,92 @@ void main() float depth = prepassSample.a; // Eye ray - Eye -> Pixel - vec3 eyeRay = getDistanceVectorToPlane( negFarPlaneDotEye, wsEyeDir.xyz / wsEyeDir.w , farPlane ); - - // Get world space pixel position - vec3 worldPos = eyePosWorld + eyeRay * depth; + vec3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN_vsEyeDir.xyz, vsFarPlane ); + vec3 viewSpacePos = eyeRay * depth; // Build light vec, get length, clip pixel if needed - vec3 lightToPxlVec = worldPos - lightPosition; + vec3 lightToPxlVec = viewSpacePos - lightPosition; float lenLightV = length( lightToPxlVec ); lightToPxlVec /= lenLightV; - //lightDirection = float3( -lightDirection.xy, lightDirection.z ); //float3( 0, 0, -1 ); + //lightDirection = vec3( -lightDirection.xy, lightDirection.z ); //vec3( 0, 0, -1 ); float cosAlpha = dot( lightDirection, lightToPxlVec ); - if ( cosAlpha - lightSpotParams.x < 0.0 ) discard; - if ( lightRange - lenLightV < 0.0 ) discard; + clip( cosAlpha - lightSpotParams.x ); + clip( lightRange - lenLightV ); float atten = attenuate( lightColor, lightAttenuation, lenLightV ); atten *= ( cosAlpha - lightSpotParams.x ) / lightSpotParams.y; - if ( atten - 1e-6 < 0.0 ) discard; + clip( atten - 1e-6 ); + atten = saturate( atten ); float nDotL = dot( normal, -lightToPxlVec ); + // Get the shadow texture coordinate + vec4 pxlPosLightProj = tMul( viewToLightProj, vec4( viewSpacePos, 1 ) ); + vec2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 ); + shadowCoord.y = 1.0f - shadowCoord.y; + #ifdef NO_SHADOW float shadowed = 1.0; #else - // Find Shadow coordinate - vec4 pxlPosLightProj = vec4( worldToLightProj * vec4( worldPos, 1.0 ) ); - vec2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 ); - // Get a linear depth from the light source. float distToLight = pxlPosLightProj.z / lightRange; - #ifdef SOFTSHADOW_SM3 - - float shadowed = softShadow_filter( shadowMap, - gTapRotationTex, - ssPosP.xy, - shadowCoord, - shadowSoftness, - distToLight, - nDotL, - lightParams.y ); - - #else // !SOFTSHADOW_SM3 - - // Simple exponential shadow map. - float occluder = decodeShadowMap( texture2DLod( shadowMap, shadowCoord, 0.0 ) ); - float esmFactor = lightParams.y; - float shadowed = clamp( exp( esmFactor * ( occluder - distToLight ) ), 0.0, 1.0 ); - - #endif + float shadowed = softShadow_filter( shadowMap, + ssPos.xy, + shadowCoord, + shadowSoftness, + distToLight, + nDotL, + lightParams.y ); #endif // !NO_SHADOW - + + #ifdef USE_COOKIE_TEX + + // Lookup the cookie sample. + vec4 cookie = texture( cookieMap, shadowCoord ); + + // Multiply the light with the cookie tex. + lightColor.rgb *= cookie.rgb; + + // Use a maximum channel luminance to attenuate + // the lighting else we get specular in the dark + // regions of the cookie texture. + atten *= max( cookie.r, max( cookie.g, cookie.b ) ); + + #endif + // NOTE: Do not clip on fully shadowed pixels as it would // cause the hardware occlusion query to disable the shadow. // Specular term - float specular = calcSpecular( -lightToPxlVec, - normal, - normalize( -eyeRay ), - constantSpecularPower, - shadowed * atten * lightBrightness ); - - // N.L * Attenuation - float Sat_NL_Att = clamp( nDotL * atten * shadowed, 0.0, 1.0 ); - - // In LUV color mode we need to blend in the - // output from the previous target. - vec4 previousPix = vec4(0.0); - #ifdef ACCUMULATE_LUV - previousPix = texture2DLod( scratchTarget, uvScene, 0.0 ); - #endif + float specular = AL_CalcSpecular( -lightToPxlVec, + normal, + normalize( -eyeRay ) ) * lightBrightness * atten * shadowed; - // Output - gl_FragColor = lightinfoCondition( lightColor.rgb * lightBrightness, - Sat_NL_Att, - specular, - previousPix ) * lightMapParams; + float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness; + vec3 lightColorOut = lightMapParams.rgb * lightColor.rgb; + vec4 addToResult = vec4(0.0); + + // TODO: This needs to be removed when lightmapping is disabled + // as its extra work per-pixel on dynamic lit scenes. + // + // Special lightmapping pass. + if ( lightMapParams.a < 0.0 ) + { + // This disables shadows on the backsides of objects. + shadowed = nDotL < 0.0f ? 1.0f : shadowed; + + Sat_NL_Att = 1.0f; + shadowed = mix( 1.0f, shadowed, atten ); + lightColorOut = vec3(shadowed); + specular *= lightBrightness; + addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); + } + + OUT_FragColor0 = lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult ); } diff --git a/Templates/Empty/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl b/Templates/Empty/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl index bbd567fd0..0178c35ea 100644 --- a/Templates/Empty/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl +++ b/Templates/Empty/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl @@ -22,40 +22,32 @@ #include "../../../gl/hlslCompat.glsl" #include "shadergen:/autogenConditioners.h" +#include "farFrustumQuad.glsl" +#include "../../../gl/torque.glsl" +#include "../../../gl/lighting.glsl" #include "lightingUtils.glsl" #include "../../shadowMap/shadowMapIO_GLSL.h" +#include "softShadow.glsl" -varying vec2 uv0; -varying vec3 wsEyeRay; +in vec4 hpos; +in vec2 uv0; +in vec3 wsEyeRay; +in vec3 vsEyeRay; -uniform sampler2D prePassBuffer; -uniform sampler2D ShadowMap; +uniform sampler2D ShadowMap ; -#if TORQUE_SM >= 30 - - // Enables high quality soft shadow - // filtering for SM3.0 and above. - #define SOFTSHADOW_SM3 - - #include "softShadow.glsl" - -#else - - - +#ifdef USE_SSAO_MASK +uniform sampler2D ssaoMask ; +uniform vec4 rtParams2; #endif - + +uniform sampler2D prePassBuffer; uniform vec3 lightDirection; uniform vec4 lightColor; -uniform float lightBrightness; -uniform vec4 lightAmbient; -uniform vec4 lightTrilight; - -uniform vec3 eyePosWorld; - -uniform mat4 worldToLightProj; -uniform vec4 splitDistStart; -uniform vec4 splitDistEnd; +uniform float lightBrightness; +uniform vec4 lightAmbient; +uniform vec3 eyePosWorld; +uniform mat4x4 worldToLightProj; uniform vec4 scaleX; uniform vec4 scaleY; uniform vec4 offsetX; @@ -65,16 +57,12 @@ uniform vec4 atlasYOffset; uniform vec2 atlasScale; uniform vec4 zNearFarInvNearFar; uniform vec4 lightMapParams; - -uniform float constantSpecularPower; uniform vec2 fadeStartLength; uniform vec4 farPlaneScalePSSM; -uniform vec4 splitFade; uniform vec4 overDarkPSSM; uniform float shadowSoftness; - -void main() +void main() { // Sample/unpack the normal/z data vec4 prepassSample = prepassUncondition( prePassBuffer, uv0 ); @@ -83,148 +71,162 @@ void main() // Use eye ray to get ws pos vec4 worldPos = vec4(eyePosWorld + wsEyeRay * depth, 1.0f); - + // Get the light attenuation. float dotNL = dot(-lightDirection, normal); + + #ifdef PSSM_DEBUG_RENDER + vec3 debugColor = vec3(0); + #endif #ifdef NO_SHADOW // Fully unshadowed. float shadowed = 1.0; + #ifdef PSSM_DEBUG_RENDER + debugColor = vec3(1.0); + #endif + #else - + // Compute shadow map coordinate - vec4 pxlPosLightProj = worldToLightProj * worldPos; + vec4 pxlPosLightProj = tMul(worldToLightProj, worldPos); vec2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w; - - float distOffset = 0.0; - float shadowed = 0.0; - float fadeAmt = 0.0; - vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth); - - // Calculate things dependant on the shadowmap split - for ( int i = 0; i < 2; i++ ) - { - float zDistSplit = zDist.x + distOffset; - vec4 mask0; - mask0.x = float(zDistSplit >= splitDistStart.x); - mask0.y = float(zDistSplit >= splitDistStart.y); - mask0.z = float(zDistSplit >= splitDistStart.z); - mask0.w = float(zDistSplit >= splitDistStart.w); + + // Distance to light, in shadowmap space + float distToLight = pxlPosLightProj.z / pxlPosLightProj.w; - vec4 mask1; - mask1.x = float(zDistSplit < splitDistEnd.x); - mask1.y = float(zDistSplit < splitDistEnd.y); - mask1.z = float(zDistSplit < splitDistEnd.z); - mask1.w = float(zDistSplit < splitDistEnd.w); + // Figure out which split to sample from. Basically, we compute the shadowmap sample coord + // for all of the splits and then check if its valid. + vec4 shadowCoordX = vec4( baseShadowCoord.x ); + vec4 shadowCoordY = vec4( baseShadowCoord.y ); + vec4 farPlaneDists = vec4( distToLight ); + shadowCoordX *= scaleX; + shadowCoordY *= scaleY; + shadowCoordX += offsetX; + shadowCoordY += offsetY; + farPlaneDists *= farPlaneScalePSSM; + + // If the shadow sample is within -1..1 and the distance + // to the light for this pixel is less than the far plane + // of the split, use it. + vec4 finalMask; + if ( shadowCoordX.x > -0.99 && shadowCoordX.x < 0.99 && + shadowCoordY.x > -0.99 && shadowCoordY.x < 0.99 && + farPlaneDists.x < 1.0 ) + finalMask = vec4(1, 0, 0, 0); + + else if ( shadowCoordX.y > -0.99 && shadowCoordX.y < 0.99 && + shadowCoordY.y > -0.99 && shadowCoordY.y < 0.99 && + farPlaneDists.y < 1.0 ) + finalMask = vec4(0, 1, 0, 0); + + else if ( shadowCoordX.z > -0.99 && shadowCoordX.z < 0.99 && + shadowCoordY.z > -0.99 && shadowCoordY.z < 0.99 && + farPlaneDists.z < 1.0 ) + finalMask = vec4(0, 0, 1, 0); - vec4 finalMask = mask0 * mask1; + else + finalMask = vec4(0, 0, 0, 1); - float splitFadeDist = dot( finalMask, splitFade ); - vec2 finalScale; - finalScale.x = dot(finalMask, scaleX); - finalScale.y = dot(finalMask, scaleY); + #ifdef PSSM_DEBUG_RENDER + if ( finalMask.x > 0 ) + debugColor += vec3( 1, 0, 0 ); + else if ( finalMask.y > 0 ) + debugColor += vec3( 0, 1, 0 ); + else if ( finalMask.z > 0 ) + debugColor += vec3( 0, 0, 1 ); + else if ( finalMask.w > 0 ) + debugColor += vec3( 1, 1, 0 ); + #endif - vec2 finalOffset; - finalOffset.x = dot(finalMask, offsetX); - finalOffset.y = dot(finalMask, offsetY); - - vec2 shadowCoord; - shadowCoord = baseShadowCoord * finalScale; - shadowCoord += finalOffset; + // Here we know what split we're sampling from, so recompute the texcoord location + // Yes, we could just use the result from above, but doing it this way actually saves + // shader instructions. + vec2 finalScale; + finalScale.x = dot(finalMask, scaleX); + finalScale.y = dot(finalMask, scaleY); - // Convert to texcoord space - shadowCoord = 0.5 * shadowCoord + vec2(0.5, 0.5); - //shadowCoord.y = 1.0f - shadowCoord.y; + vec2 finalOffset; + finalOffset.x = dot(finalMask, offsetX); + finalOffset.y = dot(finalMask, offsetY); - // Move around inside of atlas - vec2 aOffset; - aOffset.x = dot(finalMask, atlasXOffset); - aOffset.y = dot(finalMask, atlasYOffset); + vec2 shadowCoord; + shadowCoord = baseShadowCoord * finalScale; + shadowCoord += finalOffset; - shadowCoord *= atlasScale; - shadowCoord += aOffset; - - // Distance to light, in shadowmap space - float distToLight = pxlPosLightProj.z / pxlPosLightProj.w; - - // Each split has a different far plane, take this into account. - float farPlaneScale = dot( farPlaneScalePSSM, finalMask ); - distToLight *= farPlaneScale; - - #ifdef SOFTSHADOW_SM3 + // Convert to texcoord space + shadowCoord = 0.5 * shadowCoord + vec2(0.5, 0.5); + shadowCoord.y = 1.0f - shadowCoord.y; - float esmShadow = softShadow_filter( ShadowMap, - gTapRotationTex, - uv0.xy, - shadowCoord, - farPlaneScale * shadowSoftness, - distToLight, - dotNL, - dot( finalMask, overDarkPSSM ) ); - - #else // !SOFTSHADOW_SM3 + // Move around inside of atlas + vec2 aOffset; + aOffset.x = dot(finalMask, atlasXOffset); + aOffset.y = dot(finalMask, atlasYOffset); - float occluder = decodeShadowMap( texture2DLod( ShadowMap, shadowCoord, 0.0 ) ); - float overDark = dot( finalMask, overDarkPSSM ); - float esmShadow = saturate( exp( esmFactor * ( occluder - distToLight ) ) ); - - #endif - - if ( i == 0 ) - { - float endDist = dot(splitDistEnd, finalMask); - fadeAmt = smoothstep(endDist - splitFadeDist, endDist, zDist).x; - shadowed = esmShadow * ( 1.0 - fadeAmt ); - } - else - shadowed += esmShadow * fadeAmt; - - distOffset += splitFadeDist; - } + shadowCoord *= atlasScale; + shadowCoord += aOffset; + + // Each split has a different far plane, take this into account. + float farPlaneScale = dot( farPlaneScalePSSM, finalMask ); + distToLight *= farPlaneScale; + + float shadowed = softShadow_filter( ShadowMap, + uv0.xy, + shadowCoord, + farPlaneScale * shadowSoftness, + distToLight, + dotNL, + dot( finalMask, overDarkPSSM ) ); // Fade out the shadow at the end of the range. + vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth); float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y; - shadowed = mix( shadowed, 1.0, clamp( fadeOutAmt, 0.0, 1.0 ) ); + shadowed = mix( shadowed, 1.0, saturate( fadeOutAmt ) ); + + #ifdef PSSM_DEBUG_RENDER + if ( fadeOutAmt > 1.0 ) + debugColor = vec3(1.0); + #endif #endif // !NO_SHADOW - - // Calc lighting coefficents - float specular = calcSpecular( -lightDirection, - normal, - normalize(-wsEyeRay), - constantSpecularPower, - shadowed * lightBrightness ); - - float Sat_NL_Att = clamp(dotNL, 0.0, 1.0) * shadowed; - - // Trilight, described by Tom Forsyth - // http://home.comcast.net/~tom_forsyth/papers/trilight/trilight.html -#ifdef ACCUMULATE_LUV - // In LUV multiply in the brightness of the light color (normaly done in the attenuate function) - Sat_NL_Att *= lightColor.a; + // Specular term + float specular = AL_CalcSpecular( -lightDirection, + normal, + normalize(-vsEyeRay) ) * lightBrightness * shadowed; - vec4 ambientBlend = lightAmbient; - ambientBlend.b *= clamp(-dotNL, 0.0, 1.0); - - vec3 trilight = lightTrilight.rgb; - trilight.b *= clamp(1.0 - abs(dotNL), 0.0, 1.0); - - ambientBlend.rg = mix(ambientBlend.rg, trilight.rg, clamp(0.5 * trilight.b / lightAmbient.b, 0.0, 1.0)); - ambientBlend.b += trilight.b; + float Sat_NL_Att = saturate( dotNL * shadowed ) * lightBrightness; + vec3 lightColorOut = lightMapParams.rgb * lightColor.rgb; + vec4 addToResult = lightAmbient; -#else + // TODO: This needs to be removed when lightmapping is disabled + // as its extra work per-pixel on dynamic lit scenes. + // + // Special lightmapping pass. + if ( lightMapParams.a < 0.0 ) + { + // This disables shadows on the backsides of objects. + shadowed = dotNL < 0.0f ? 1.0f : shadowed; - // RGB - // TODO: Trilight seems broken... it does lighting in shadows! - //vec4 ambientBlend = vec4(lightTrilight.rgb * clamp(1.0 - abs(dotNL), 0.0, 1.0) + lightAmbient.rgb * clamp(-dotNL, 0.0, 1.0), 0.0); - vec4 ambientBlend = vec4(lightAmbient.rgb, 0.0); + Sat_NL_Att = 1.0f; + lightColorOut = vec3(shadowed); + specular *= lightBrightness; + addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); + } -#endif + // Sample the AO texture. + #ifdef USE_SSAO_MASK + float ao = 1.0 - texture( ssaoMask, viewportCoordToRenderTarget( uv0.xy, rtParams2 ) ).r; + addToResult *= ao; + #endif + + #ifdef PSSM_DEBUG_RENDER + lightColorOut = debugColor; + #endif + + OUT_FragColor0 = lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult ); - // Output - gl_FragColor = lightinfoCondition( lightColor.rgb * lightBrightness, Sat_NL_Att, specular, ambientBlend) * lightMapParams; } diff --git a/Templates/Empty/game/shaders/common/lighting/basic/gl/shadowFilterP.glsl b/Templates/Empty/game/shaders/common/lighting/basic/gl/shadowFilterP.glsl index 238721e5e..4e97fa347 100644 --- a/Templates/Empty/game/shaders/common/lighting/basic/gl/shadowFilterP.glsl +++ b/Templates/Empty/game/shaders/common/lighting/basic/gl/shadowFilterP.glsl @@ -20,35 +20,27 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../../gl/hlslCompat.glsl" + uniform sampler2D diffuseMap; -varying vec2 uv; +in vec2 uv; uniform vec2 oneOverTargetSize; +const float offset[3] = float[]( 0.0, 1.3846153846, 3.2307692308 ); +const float weight[3] = float[]( 0.2270270270, 0.3162162162, 0.0702702703 ); + void main() { - vec2 sNonUniformTaps[8]; - - sNonUniformTaps[0] = vec2(0.992833, 0.979309); - sNonUniformTaps[1] = vec2(-0.998585, 0.985853); - sNonUniformTaps[2] = vec2(0.949299, -0.882562); - sNonUniformTaps[3] = vec2(-0.941358, -0.893924); - sNonUniformTaps[4] = vec2(0.545055, -0.589072); - sNonUniformTaps[5] = vec2(0.346526, 0.385821); - sNonUniformTaps[6] = vec2(-0.260183, 0.334412); - sNonUniformTaps[7] = vec2(0.248676, -0.679605); + vec4 OUT = texture( diffuseMap, uv ) * weight[0]; - gl_FragColor = vec4(0.0); - - vec2 texScale = vec2(1.0); - - for ( int i=0; i < 4; i++ ) + for ( int i=1; i < 3; i++ ) { - vec2 offset = (oneOverTargetSize * texScale) * sNonUniformTaps[i]; - gl_FragColor += texture2D( diffuseMap, uv + offset ); + vec2 _sample = (BLUR_DIR * offset[i]) * oneOverTargetSize; + OUT += texture( diffuseMap, uv + _sample ) * weight[i]; + OUT += texture( diffuseMap, uv - _sample ) * weight[i]; } - - gl_FragColor /= vec4(4.0); - gl_FragColor.rgb = vec3(0.0); + + OUT_FragColor0 = OUT; } diff --git a/Templates/Empty/game/shaders/common/lighting/basic/gl/shadowFilterV.glsl b/Templates/Empty/game/shaders/common/lighting/basic/gl/shadowFilterV.glsl index cbf3696be..0eeb2e0fd 100644 --- a/Templates/Empty/game/shaders/common/lighting/basic/gl/shadowFilterV.glsl +++ b/Templates/Empty/game/shaders/common/lighting/basic/gl/shadowFilterV.glsl @@ -22,13 +22,16 @@ #include "../../../../../../shaders/common/gl/torque.glsl" -uniform vec2 oneOverTargetSize; +in vec4 vPosition; +in vec2 vTexCoord0; + uniform vec4 rtParams0; -varying vec2 uv; +out vec2 uv; void main() { - gl_Position = gl_Vertex; - uv = viewportCoordToRenderTarget( gl_MultiTexCoord0.st, rtParams0 ); + gl_Position = vPosition; + uv = viewportCoordToRenderTarget( vTexCoord0.st, rtParams0 ); + gl_Position.y *= -1; //correct ssp } diff --git a/Templates/Empty/game/shaders/common/lighting/shadowMap/gl/boxFilterP.glsl b/Templates/Empty/game/shaders/common/lighting/shadowMap/gl/boxFilterP.glsl index 2800a3f17..0f568c716 100644 --- a/Templates/Empty/game/shaders/common/lighting/shadowMap/gl/boxFilterP.glsl +++ b/Templates/Empty/game/shaders/common/lighting/shadowMap/gl/boxFilterP.glsl @@ -26,7 +26,7 @@ uniform sampler2D diffuseMap0; uniform float texSize; uniform vec2 blurDimension; -varying vec2 tex0; +in vec2 tex0; void main() { @@ -40,8 +40,8 @@ void main() vec4 accum = vec4(0.0, 0.0, 0.0, 0.0); for(int i = 0; i < int(blurSamples); i++) { - accum += texture2D(diffuseMap0, BaseTexCoord + float(i) * SampleOffset); + accum += texture(diffuseMap0, BaseTexCoord + float(i) * SampleOffset); } accum /= blurSamples; - gl_FragColor = accum; + OUT_FragColor0 = accum; } \ No newline at end of file diff --git a/Templates/Empty/game/shaders/common/lighting/shadowMap/gl/boxFilterV.glsl b/Templates/Empty/game/shaders/common/lighting/shadowMap/gl/boxFilterV.glsl index 3850f83c7..9fc436f6c 100644 --- a/Templates/Empty/game/shaders/common/lighting/shadowMap/gl/boxFilterV.glsl +++ b/Templates/Empty/game/shaders/common/lighting/shadowMap/gl/boxFilterV.glsl @@ -20,12 +20,15 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +in vec4 vPosition; +in vec2 vTexCoord0; + uniform mat4 modelview; -varying vec2 tex0; +out vec2 tex0; void main() { - gl_Position = modelview * gl_Vertex; - tex0 = gl_MultiTexCoord0.st; + gl_Position = modelview * vPosition; + tex0 = vTexCoord0.st; } \ No newline at end of file diff --git a/Templates/Empty/game/shaders/common/postFx/lightRay/lightRayOccludeP.hlsl b/Templates/Empty/game/shaders/common/postFx/lightRay/lightRayOccludeP.hlsl index 8769905f6..e8870b3c4 100644 --- a/Templates/Empty/game/shaders/common/postFx/lightRay/lightRayOccludeP.hlsl +++ b/Templates/Empty/game/shaders/common/postFx/lightRay/lightRayOccludeP.hlsl @@ -45,7 +45,7 @@ float4 main( PFXVertToPix IN ) : COLOR0 col = tex2D( backBuffer, IN.uv0 ); //col = 1 - exp(-120000 * col); - col += dot( col, LUMINANCE_VECTOR ) + 0.0001f; + col += dot( col.rgb, LUMINANCE_VECTOR ) + 0.0001f; col *= brightScalar; } diff --git a/Templates/Empty/game/shaders/common/postFx/lightRay/lightRayP.hlsl b/Templates/Empty/game/shaders/common/postFx/lightRay/lightRayP.hlsl index 7dd334607..ff44abfae 100644 --- a/Templates/Empty/game/shaders/common/postFx/lightRay/lightRayP.hlsl +++ b/Templates/Empty/game/shaders/common/postFx/lightRay/lightRayP.hlsl @@ -59,7 +59,7 @@ float4 main( PFXVertToPix IN ) : COLOR0 half2 deltaTexCoord = (half2)( texCoord.xy - screenSunPos ); // Divide by number of samples and scale by control factor. - deltaTexCoord *= 1.0 / (half)samples * density; + deltaTexCoord *= (half)(1.0 / samples * density); // Evaluate summation from Equation 3 NUM_SAMPLES iterations. for ( int i = 0; i < samples; i++ ) @@ -71,13 +71,13 @@ float4 main( PFXVertToPix IN ) : COLOR0 half3 sample = (half3)tex2Dlod( frameSampler, texCoord ); // Apply sample attenuation scale/decay factors. - sample *= illuminationDecay * weight; + sample *= half(illuminationDecay * weight); // Accumulate combined color. color += sample; // Update exponential decay factor. - illuminationDecay *= decay; + illuminationDecay *= half(decay); } //return saturate( amount ) * color * Exposure; diff --git a/Templates/Empty/game/shaders/common/postFx/postFxV.glsl b/Templates/Empty/game/shaders/common/postFx/postFxV.glsl index 3aded2e0f..96a5ec819 100644 --- a/Templates/Empty/game/shaders/common/postFx/postFxV.glsl +++ b/Templates/Empty/game/shaders/common/postFx/postFxV.glsl @@ -22,27 +22,30 @@ #include "./../gl/torque.glsl" +in vec4 vPosition; +in vec2 vTexCoord0; +in vec3 vTexCoord1; uniform vec4 rtParams0; uniform vec4 rtParams1; uniform vec4 rtParams2; uniform vec4 rtParams3; -varying vec2 uv0; -varying vec2 uv1; -varying vec2 uv2; -varying vec2 uv3; -varying vec3 wsEyeRay; +out vec2 uv0; +out vec2 uv1; +out vec2 uv2; +out vec2 uv3; +out vec3 wsEyeRay; void main() { - gl_Position = gl_Vertex; + gl_Position = vPosition; - uv0 = viewportCoordToRenderTarget( gl_MultiTexCoord0.st, rtParams0 ); - uv1 = viewportCoordToRenderTarget( gl_MultiTexCoord0.st, rtParams1 ); - uv2 = viewportCoordToRenderTarget( gl_MultiTexCoord0.st, rtParams2 ); - uv3 = viewportCoordToRenderTarget( gl_MultiTexCoord0.st, rtParams3 ); + uv0 = viewportCoordToRenderTarget( vTexCoord0, rtParams0 ); + uv1 = viewportCoordToRenderTarget( vTexCoord0, rtParams1 ); + uv2 = viewportCoordToRenderTarget( vTexCoord0, rtParams2 ); + uv3 = viewportCoordToRenderTarget( vTexCoord0, rtParams3 ); - wsEyeRay = gl_MultiTexCoord1.xyz; + wsEyeRay = vTexCoord1; } diff --git a/Templates/Empty/game/shaders/common/terrain/gl/blendP.glsl b/Templates/Empty/game/shaders/common/terrain/gl/blendP.glsl index 3817e1de2..a2e4af787 100644 --- a/Templates/Empty/game/shaders/common/terrain/gl/blendP.glsl +++ b/Templates/Empty/game/shaders/common/terrain/gl/blendP.glsl @@ -23,8 +23,10 @@ #include "../terrain.glsl" #include "../../gl/hlslCompat.glsl" -varying vec2 layerCoord; -varying vec2 texCoord; +in vec2 layerCoord; +#define IN_layerCoord layerCoord +in vec2 texCoord; +#define IN_texCoord texCoord uniform sampler2D layerTex; uniform sampler2D textureMap; @@ -33,12 +35,12 @@ uniform float layerSize; void main() { - vec4 layerSample = round(texture2D( layerTex, layerCoord ) * 255.0); + vec4 layerSample = round(texture( layerTex, IN_layerCoord ) * 255.0); - float blend = calcBlend( texId, layerCoord, layerSize, layerSample ); + float blend = calcBlend( texId, IN_layerCoord, layerSize, layerSample ); if(blend - 0.0001 < 0.0) discard; - gl_FragColor = vec4( texture2D( textureMap, texCoord ).rgb, blend ); + OUT_FragColor0 = vec4( texture( textureMap, IN_texCoord ).rgb, blend ); } diff --git a/Templates/Empty/game/shaders/common/terrain/gl/blendV.glsl b/Templates/Empty/game/shaders/common/terrain/gl/blendV.glsl index 44362085b..dc7b7befa 100644 --- a/Templates/Empty/game/shaders/common/terrain/gl/blendV.glsl +++ b/Templates/Empty/game/shaders/common/terrain/gl/blendV.glsl @@ -23,14 +23,19 @@ /// The vertex shader used in the generation and caching of the /// base terrain texture. -varying vec2 layerCoord; -varying vec2 texCoord; +in vec4 vPosition; +in vec2 vTexCoord0; + +out vec2 layerCoord; +out vec2 texCoord; uniform vec2 texScale; void main() { - gl_Position = vec4(gl_Vertex.xyz, 1.0); - layerCoord = gl_MultiTexCoord0.st; - texCoord = gl_MultiTexCoord0.st * texScale; + gl_Position = vec4(vPosition.xyz, 1.0); + layerCoord = vTexCoord0.st; + texCoord = vTexCoord0.st * texScale; + + gl_Position.y *= -1; } diff --git a/Templates/Empty/game/shaders/common/water/gl/waterBasicP.glsl b/Templates/Empty/game/shaders/common/water/gl/waterBasicP.glsl index 72232622a..44207dea9 100644 --- a/Templates/Empty/game/shaders/common/water/gl/waterBasicP.glsl +++ b/Templates/Empty/game/shaders/common/water/gl/waterBasicP.glsl @@ -31,7 +31,7 @@ #define FRESNEL_BIAS miscParams[0] #define FRESNEL_POWER miscParams[1] #define CLARITY miscParams[2] -#define ISRIVER miscParams[3] +#define ISRIVER miscParams[3] // reflectParams #define REFLECT_PLANE_Z reflectParams[0] @@ -45,40 +45,49 @@ #define DISTORT_FULL_DEPTH distortionParams[2] // ConnectData.misc -#define LIGHT_VEC misc.xyz -#define WORLD_Z objPos.w +#define LIGHT_VEC IN_misc.xyz +#define WORLD_Z IN_objPos.w // specularParams #define SPEC_POWER specularParams[3] #define SPEC_COLOR specularParams.xyz +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- + // TexCoord 0 and 1 (xy,zw) for ripple texture lookup -varying vec4 rippleTexCoord01; +in vec4 rippleTexCoord01; +#define IN_rippleTexCoord01 rippleTexCoord01 // TexCoord 2 for ripple texture lookup -varying vec2 rippleTexCoord2; +in vec2 rippleTexCoord2; +#define IN_rippleTexCoord2 rippleTexCoord2 // Screenspace vert position BEFORE wave transformation -varying vec4 posPreWave; +in vec4 posPreWave; +#define IN_posPreWave posPreWave // Screenspace vert position AFTER wave transformation -varying vec4 posPostWave; +in vec4 posPostWave; +#define IN_posPostWave posPostWave // Worldspace unit distance/depth of this vertex/pixel -varying float pixelDist; - -// Objectspace vert position BEFORE wave transformation -// w coord is world space z position. -varying vec4 objPos; +in float pixelDist; +#define IN_pixelDist pixelDist -varying vec3 misc; +in vec4 objPos; +#define IN_objPos objPos + +in vec3 misc; +#define IN_misc misc //----------------------------------------------------------------------------- // approximate Fresnel function //----------------------------------------------------------------------------- float fresnel(float NdotV, float bias, float power) { - return bias + (1.0-bias)*pow(abs(1.0 - max(NdotV, 0.0)), power); + return bias + (1.0-bias)*pow(abs(1.0 - max(NdotV, 0)), power); } //----------------------------------------------------------------------------- @@ -89,7 +98,7 @@ uniform sampler2D bumpMap; uniform sampler2D reflectMap; uniform sampler2D refractBuff; uniform samplerCube skyMap; -//uniform sampler foamMap; +//uniform sampler2D foamMap; uniform vec4 baseColor; uniform vec4 miscParams; uniform vec4 reflectParams; @@ -98,8 +107,9 @@ uniform vec3 eyePos; uniform vec3 distortionParams; uniform vec3 fogData; uniform vec4 fogColor; -uniform vec3 rippleMagnitude; +uniform vec4 rippleMagnitude; uniform vec4 specularParams; +uniform mat4 modelMat; //----------------------------------------------------------------------------- // Main @@ -107,31 +117,35 @@ uniform vec4 specularParams; void main() { // Modulate baseColor by the ambientColor. - vec4 waterBaseColor = baseColor * vec4( ambientColor.rgb, 1.0 ); + vec4 waterBaseColor = baseColor * vec4( ambientColor.rgb, 1 ); // Get the bumpNorm... - vec3 bumpNorm = ( texture2D( bumpMap, rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x; - bumpNorm += ( texture2D( bumpMap, rippleTexCoord01.zw ).rgb * 2.0 - 1.0 ) * rippleMagnitude.y; - bumpNorm += ( texture2D( bumpMap, rippleTexCoord2 ).rgb * 2.0 - 1.0 ) * rippleMagnitude.z; - + vec3 bumpNorm = ( texture( bumpMap, IN_rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x; + bumpNorm += ( texture( bumpMap, IN_rippleTexCoord01.zw ).rgb * 2.0 - 1.0 ) * rippleMagnitude.y; + bumpNorm += ( texture( bumpMap, IN_rippleTexCoord2 ).rgb * 2.0 - 1.0 ) * rippleMagnitude.z; + + bumpNorm = normalize( bumpNorm ); + bumpNorm = mix( bumpNorm, vec3(0,0,1), 1.0 - rippleMagnitude.w ); + // We subtract a little from it so that we don't // distort where the water surface intersects the // camera near plane. - float distortAmt = saturate( pixelDist / 1.0 ) * 0.8; + float distortAmt = saturate( IN_pixelDist / 1.0 ) * 0.8; - vec4 distortPos = posPostWave; + vec4 distortPos = IN_posPostWave; distortPos.xy += bumpNorm.xy * distortAmt; #ifdef UNDERWATER - gl_FragColor = texture2DProj( refractBuff, distortPos.xyz ); + OUT_FragColor0 = hdrEncode( textureProj( refractBuff, distortPos ) ); #else - vec3 eyeVec = objPos.xyz - eyePos; - vec3 reflectionVec = reflect( eyeVec, normalize(bumpNorm) ); + vec3 eyeVec = IN_objPos.xyz - eyePos; + eyeVec = tMul( mat3(modelMat), eyeVec ); + vec3 reflectionVec = reflect( eyeVec, bumpNorm ); // Color that replaces the reflection color when we do not // have one that is appropriate. - vec4 fakeColor = vec4(ambientColor,1.0); + vec4 fakeColor = vec4(ambientColor,1); // Use fakeColor for ripple-normals that are angled towards the camera eyeVec = -eyeVec; @@ -140,58 +154,61 @@ void main() float fakeColorAmt = ang; // Get reflection map color - vec4 refMapColor = texture2DProj( reflectMap, distortPos ); + vec4 refMapColor = hdrDecode( textureProj( reflectMap, distortPos ) ); // If we do not have a reflection texture then we use the cubemap. - refMapColor = mix( refMapColor, textureCube( skyMap, -reflectionVec ), NO_REFLECT ); + refMapColor = mix( refMapColor, texture( skyMap, reflectionVec ), NO_REFLECT ); // Combine reflection color and fakeColor. vec4 reflectColor = mix( refMapColor, fakeColor, fakeColorAmt ); //return refMapColor; // Get refract color - vec4 refractColor = texture2DProj( refractBuff, distortPos.xyz ); + vec4 refractColor = hdrDecode( textureProj( refractBuff, distortPos ) ); // calc "diffuse" color by lerping from the water color // to refraction image based on the water clarity. - vec4 diffuseColor = mix( refractColor, waterBaseColor, 1.0 - CLARITY ); + vec4 diffuseColor = mix( refractColor, waterBaseColor, 1.0f - CLARITY ); // fresnel calculation float fresnelTerm = fresnel( ang, FRESNEL_BIAS, FRESNEL_POWER ); + //return vec4( fresnelTerm.rrr, 1 ); // Also scale the frensel by our distance to the // water surface. This removes the hard reflection // when really close to the water surface. - fresnelTerm *= saturate( pixelDist - 0.1 ); + fresnelTerm *= saturate( IN_pixelDist - 0.1 ); // Combine the diffuse color and reflection image via the // fresnel term and set out output color. - gl_FragColor = mix( diffuseColor, reflectColor, fresnelTerm ); - + vec4 OUT = mix( diffuseColor, reflectColor, fresnelTerm ); + #ifdef WATER_SPEC // Get some specular reflection. vec3 newbump = bumpNorm; newbump.xy *= 3.5; newbump = normalize( bumpNorm ); - vec3 halfAng = normalize( eyeVec + -LIGHT_VEC ); + half3 halfAng = normalize( eyeVec + -LIGHT_VEC ); float specular = saturate( dot( newbump, halfAng ) ); specular = pow( specular, SPEC_POWER ); - gl_FragColor.rgb = gl_FragColor.rgb + ( SPEC_COLOR * specular.xxx ); + OUT.rgb = OUT.rgb + ( SPEC_COLOR * specular.xxx ); #else // Disable fogging if spec is on because otherwise we run out of instructions. // Fog it. float factor = computeSceneFog( eyePos, - objPos.xyz, + IN_objPos.xyz, WORLD_Z, fogData.x, fogData.y, fogData.z ); - gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor.rgb, 1.0 - saturate( factor ) ); - - #endif + //OUT.rgb = mix( OUT.rgb, fogColor.rgb, 1.0 - saturate( factor ) ); + #endif + + OUT_FragColor0 = OUT; + #endif } diff --git a/Templates/Empty/game/shaders/common/water/gl/waterBasicV.glsl b/Templates/Empty/game/shaders/common/water/gl/waterBasicV.glsl index bb2a0c954..1634fd2de 100644 --- a/Templates/Empty/game/shaders/common/water/gl/waterBasicV.glsl +++ b/Templates/Empty/game/shaders/common/water/gl/waterBasicV.glsl @@ -27,23 +27,30 @@ //----------------------------------------------------------------------------- // TexCoord 0 and 1 (xy,zw) for ripple texture lookup -varying vec4 rippleTexCoord01; +out vec4 rippleTexCoord01; +#define OUT_rippleTexCoord01 rippleTexCoord01 // TexCoord 2 for ripple texture lookup -varying vec2 rippleTexCoord2; +out vec2 rippleTexCoord2; +#define OUT_rippleTexCoord2 rippleTexCoord2 // Screenspace vert position BEFORE wave transformation -varying vec4 posPreWave; +out vec4 posPreWave; +#define OUT_posPreWave posPreWave // Screenspace vert position AFTER wave transformation -varying vec4 posPostWave; +out vec4 posPostWave; +#define OUT_posPostWave posPostWave // Worldspace unit distance/depth of this vertex/pixel -varying float pixelDist; +out float pixelDist; +#define OUT_pixelDist pixelDist -varying vec4 objPos; +out vec4 objPos; +#define OUT_objPos objPos -varying vec3 misc; +out vec3 misc; +#define OUT_misc misc //----------------------------------------------------------------------------- // Uniforms @@ -63,49 +70,56 @@ uniform float gridElementSize; uniform float elapsedTime; uniform float undulateMaxDist; +in vec4 vPosition; +in vec3 vNormal; +in vec4 vColor; +in vec2 vTexCoord0; +in vec4 vTexCoord1; + //----------------------------------------------------------------------------- // Main //----------------------------------------------------------------------------- void main() { - vec4 position = gl_Vertex; - vec3 normal = gl_Normal; - vec2 undulateData = gl_MultiTexCoord0.st; - vec4 horizonFactor = gl_MultiTexCoord1; + vec4 IN_position = vPosition; + vec3 IN_normal = vNormal; + vec2 IN_undulateData = vTexCoord0; + vec4 IN_horizonFactor = vTexCoord1; + vec4 OUT_hpos = vec4(0); // use projection matrix for reflection / refraction texture coords - mat4 texGen = mat4(0.5, 0.0, 0.0, 0.0, - 0.0, 0.5, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.5, 0.5, 0.0, 1.0); + mat4 texGen = mat4FromRow( 0.5, 0.0, 0.0, 0.5, + 0.0, -0.5, 0.0, 0.5, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 ); // Move the vertex based on the horizonFactor if specified to do so for this vert. - //if ( horizonFactor.z > 0.0 ) - //{ - //vec2 offsetXY = eyePos.xy - mod(eyePos.xy, gridElementSize); - //position.xy += offsetXY; - //undulateData += offsetXY; - //} + // if ( IN_horizonFactor.z > 0 ) + // { + // vec2 offsetXY = eyePos.xy - eyePos.xy % gridElementSize; + // IN_position.xy += offsetXY; + // IN_undulateData += offsetXY; + // } - vec4 worldPos = modelMat * position; - //fogPos = position.xyz; - position.z = mix( position.z, eyePos.z, horizonFactor.x ); - - objPos.xyz = position.xyz; - objPos.w = worldPos.z; + vec4 worldPos = tMul( modelMat, IN_position ); + + IN_position.z = mix( IN_position.z, eyePos.z, IN_horizonFactor.x ); + + //OUT_objPos = worldPos; + OUT_objPos.xyz = IN_position.xyz; + OUT_objPos.w = worldPos.z; // Send pre-undulation screenspace position - posPreWave = modelview * position; - posPreWave = texGen * posPreWave; + OUT_posPreWave = tMul( modelview, IN_position ); + OUT_posPreWave = tMul( texGen, OUT_posPreWave ); // Calculate the undulation amount for this vertex. - vec2 undulatePos = (modelMat * vec4( undulateData.xy, 0, 1 )).xy; - - //if ( undulatePos.x < 0.0 ) - //undulatePos = position.xy; - - float undulateAmt = 0.0; + vec2 undulatePos = tMul( modelMat, vec4( IN_undulateData.xy, 0, 1 ) ).xy; + //if ( undulatePos.x < 0 ) + // undulatePos = IN_position.xy; + float undulateAmt = 0.0; + undulateAmt += waveData[0].y * sin( elapsedTime * waveData[0].x + undulatePos.x * waveDir[0].x + undulatePos.y * waveDir[0].y ); @@ -114,118 +128,84 @@ void main() undulatePos.y * waveDir[1].y ); undulateAmt += waveData[2].y * sin( elapsedTime * waveData[2].x + undulatePos.x * waveDir[2].x + - undulatePos.y * waveDir[2].y ); - - float undulateFade = 1.0; - - // Scale down wave magnitude amount based on distance from the camera. - float dist = length( position.xyz - eyePos ); + undulatePos.y * waveDir[2].y ); + + float undulateFade = 1; + + // Scale down wave magnitude amount based on distance from the camera. + float dist = distance( IN_position.xyz, eyePos ); dist = clamp( dist, 1.0, undulateMaxDist ); - undulateFade *= ( 1.0 - dist / undulateMaxDist ); + undulateFade *= ( 1 - dist / undulateMaxDist ); // Also scale down wave magnitude if the camera is very very close. - undulateFade *= saturate( ( length( position.xyz - eyePos ) - 0.5 ) / 10.0 ); - + undulateFade *= saturate( ( distance( IN_position.xyz, eyePos ) - 0.5 ) / 10.0 ); + undulateAmt *= undulateFade; + //#endif //undulateAmt = 0; // Apply wave undulation to the vertex. - posPostWave = position; - posPostWave.xyz += normal.xyz * undulateAmt; + OUT_posPostWave = IN_position; + OUT_posPostWave.xyz += IN_normal.xyz * undulateAmt; // Save worldSpace position of this pixel/vert - //worldPos = posPostWave.xyz; + //OUT_worldPos = OUT_posPostWave.xyz; + //OUT_worldPos = tMul( modelMat, OUT_posPostWave.xyz ); + //OUT_worldPos.z += objTrans[2][2]; //91.16; - //worldSpaceZ = ( modelMat * vec4(fogPos,1.0) ).z; - //if ( horizonFactor.x > 0.0 ) - //{ - //vec3 awayVec = normalize( fogPos.xyz - eyePos ); - //fogPos.xy += awayVec.xy * 1000.0; - //} + // OUT_misc.w = tMul( modelMat, OUT_fogPos ).z; + // if ( IN_horizonFactor.x > 0 ) + // { + // vec3 awayVec = normalize( OUT_fogPos.xyz - eyePos ); + // OUT_fogPos.xy += awayVec.xy * 1000.0; + // } // Convert to screen - posPostWave = modelview * posPostWave; + OUT_posPostWave = tMul( modelview, OUT_posPostWave ); // tMul( modelview, vec4( OUT_posPostWave.xyz, 1 ) ); // Setup the OUT position symantic variable - gl_Position = posPostWave; - //gl_Position.z = mix(gl_Position.z, gl_Position.w, horizonFactor.x); + OUT_hpos = OUT_posPostWave; // tMul( modelview, vec4( IN_position.xyz, 1 ) ); //vec4( OUT_posPostWave.xyz, 1 ); + //OUT_hpos.z = mix( OUT_hpos.z, OUT_hpos.w, IN_horizonFactor.x ); // Save world space camera dist/depth of the outgoing pixel - pixelDist = gl_Position.z; + OUT_pixelDist = OUT_hpos.z; // Convert to reflection texture space - posPostWave = texGen * posPostWave; + OUT_posPostWave = tMul( texGen, OUT_posPostWave ); vec2 txPos = undulatePos; - if ( horizonFactor.x > 0.0 ) + if ( bool(IN_horizonFactor.x) ) txPos = normalize( txPos ) * 50000.0; - - - // set up tex coordinates for the 3 interacting normal maps - rippleTexCoord01.xy = txPos * rippleTexScale[0]; - rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; + + // set up tex coordinates for the 3 interacting normal maps + OUT_rippleTexCoord01.xy = txPos * rippleTexScale[0]; + OUT_rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; mat2 texMat; texMat[0][0] = rippleMat[0].x; texMat[1][0] = rippleMat[0].y; texMat[0][1] = rippleMat[0].z; texMat[1][1] = rippleMat[0].w; - rippleTexCoord01.xy = texMat * rippleTexCoord01.xy ; + OUT_rippleTexCoord01.xy = tMul( texMat, OUT_rippleTexCoord01.xy ); - rippleTexCoord01.zw = txPos * rippleTexScale[1]; - rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; + OUT_rippleTexCoord01.zw = txPos * rippleTexScale[1]; + OUT_rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; texMat[0][0] = rippleMat[1].x; texMat[1][0] = rippleMat[1].y; texMat[0][1] = rippleMat[1].z; texMat[1][1] = rippleMat[1].w; - rippleTexCoord01.zw = texMat * rippleTexCoord01.zw ; + OUT_rippleTexCoord01.zw = tMul( texMat, OUT_rippleTexCoord01.zw ); - rippleTexCoord2.xy = txPos * rippleTexScale[2]; - rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; + OUT_rippleTexCoord2.xy = txPos * rippleTexScale[2]; + OUT_rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; texMat[0][0] = rippleMat[2].x; texMat[1][0] = rippleMat[2].y; texMat[0][1] = rippleMat[2].z; texMat[1][1] = rippleMat[2].w; - rippleTexCoord2.xy = texMat * rippleTexCoord2.xy ; - - - /*rippleTexCoord01.xy = mix( position.xy * rippleTexScale[0], txPos.xy * rippleTexScale[0], horizonFactor.x ); - rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; - - rippleTexCoord01.zw = mix( position.xy * rippleTexScale[1], txPos.xy * rippleTexScale[1], horizonFactor.x ); - rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; - - rippleTexCoord2.xy = mix( position.xy * rippleTexScale[2], txPos.xy * rippleTexScale[2], horizonFactor.x ); - rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; */ - - - /*rippleTexCoord01.xy = mix( position.xy * rippleTexScale[0], txPos.xy * rippleTexScale[0], horizonFactor.x ); - rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; - mat2 texMat; - texMat[0][0] = rippleMat[0].x; - texMat[1][0] = rippleMat[0].y; - texMat[0][1] = rippleMat[0].z; - texMat[1][1] = rippleMat[0].w; - rippleTexCoord01.xy = texMat * rippleTexCoord01.xy ; - - rippleTexCoord01.zw = mix( position.xy * rippleTexScale[1], txPos.xy * rippleTexScale[1], horizonFactor.x ); - rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; - texMat[0][0] = rippleMat[1].x; - texMat[1][0] = rippleMat[1].y; - texMat[0][1] = rippleMat[1].z; - texMat[1][1] = rippleMat[1].w; - rippleTexCoord01.zw = texMat * rippleTexCoord01.zw ; - - rippleTexCoord2.xy = mix( position.xy * rippleTexScale[2], txPos.xy * rippleTexScale[2], horizonFactor.x ); - rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; - texMat[0][0] = rippleMat[2].x; - texMat[1][0] = rippleMat[2].y; - texMat[0][1] = rippleMat[2].z; - texMat[1][1] = rippleMat[2].w; - rippleTexCoord2.xy = texMat * rippleTexCoord2.xy ;*/ + OUT_rippleTexCoord2.xy = tMul( texMat, OUT_rippleTexCoord2.xy ); #ifdef WATER_SPEC @@ -234,8 +214,8 @@ void main() vec3 normal; for ( int i = 0; i < 3; i++ ) { - binormal.z += undulateFade * waveDir[i].x * waveData[i].y * cos( waveDir[i].x * undulateData.x + waveDir[i].y * undulateData.y + elapsedTime * waveData[i].x ); - tangent.z += undulateFade * waveDir[i].y * waveData[i].y * cos( waveDir[i].x * undulateData.x + waveDir[i].y * undulateData.y + elapsedTime * waveData[i].x ); + binormal.z += undulateFade * waveDir[i].x * waveData[i].y * cos( waveDir[i].x * IN_undulateData.x + waveDir[i].y * IN_undulateData.y + elapsedTime * waveData[i].x ); + tangent.z += undulateFade * waveDir[i].y * waveData[i].y * cos( waveDir[i].x * IN_undulateData.x + waveDir[i].y * IN_undulateData.y + elapsedTime * waveData[i].x ); } binormal = normalize( binormal ); @@ -246,15 +226,19 @@ void main() worldToTangent[0] = binormal; worldToTangent[1] = tangent; worldToTangent[2] = normal; + + worldToTangent = transpose(worldToTangent); - misc.xyz = inLightVec * modelMat; - misc.xyz = worldToTangent * misc.xyz; + OUT_misc.xyz = tMul( inLightVec, modelMat ); + OUT_misc.xyz = tMul( worldToTangent, OUT_misc.xyz ); #else - misc.xyz = inLightVec; - + OUT_misc.xyz = inLightVec; + #endif - + + gl_Position = OUT_hpos; + correctSSP(gl_Position); } diff --git a/Templates/Empty/game/shaders/common/water/gl/waterP.glsl b/Templates/Empty/game/shaders/common/water/gl/waterP.glsl index bf482d724..3e15fe576 100644 --- a/Templates/Empty/game/shaders/common/water/gl/waterP.glsl +++ b/Templates/Empty/game/shaders/common/water/gl/waterP.glsl @@ -20,6 +20,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../gl/hlslCompat.glsl" #include "shadergen:/autogenConditioners.h" #include "../../gl/torque.glsl" @@ -27,10 +28,7 @@ // Defines //----------------------------------------------------------------------------- -#ifdef TORQUE_BASIC_LIGHTING - #define BASIC -#endif - +#define PIXEL_DIST IN_rippleTexCoord2.z // miscParams #define FRESNEL_BIAS miscParams[0] #define FRESNEL_POWER miscParams[1] @@ -57,33 +55,54 @@ #define DISTORT_FULL_DEPTH distortionParams[2] // foamParams -#define FOAM_SCALE foamParams[0] +#define FOAM_OPACITY foamParams[0] #define FOAM_MAX_DEPTH foamParams[1] +#define FOAM_AMBIENT_LERP foamParams[2] +#define FOAM_RIPPLE_INFLUENCE foamParams[3] -// Incoming data -// Worldspace position of this pixel -varying vec3 worldPos; +// specularParams +#define SPEC_POWER specularParams[3] +#define SPEC_COLOR specularParams.xyz + +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- + +//ConnectData IN + +in vec4 hpos; // TexCoord 0 and 1 (xy,zw) for ripple texture lookup -varying vec4 rippleTexCoord01; +in vec4 rippleTexCoord01; -// TexCoord 2 for ripple texture lookup -varying vec2 rippleTexCoord2; +// xy is TexCoord 2 for ripple texture lookup +// z is the Worldspace unit distance/depth of this vertex/pixel +// w is amount of the crestFoam ( more at crest of waves ). +in vec4 rippleTexCoord2; // Screenspace vert position BEFORE wave transformation -varying vec4 posPreWave; +in vec4 posPreWave; // Screenspace vert position AFTER wave transformation -varying vec4 posPostWave; +in vec4 posPostWave; -// Worldspace unit distance/depth of this vertex/pixel -varying float pixelDist; +// Objectspace vert position BEFORE wave transformation +// w coord is world space z position. +in vec4 objPos; -varying vec3 fogPos; +in vec4 foamTexCoords; -varying float worldSpaceZ; +in mat3 tangentMat; -varying vec4 foamTexCoords; + +#define IN_hpos hpos +#define IN_rippleTexCoord01 rippleTexCoord01 +#define IN_rippleTexCoord2 rippleTexCoord2 +#define IN_posPreWave posPreWave +#define IN_posPostWave posPostWave +#define IN_objPos objPos +#define IN_foamTexCoords foamTexCoords +#define IN_tangentMat tangentMat //----------------------------------------------------------------------------- // approximate Fresnel function @@ -100,10 +119,10 @@ uniform sampler2D bumpMap; uniform sampler2D prepassTex; uniform sampler2D reflectMap; uniform sampler2D refractBuff; -uniform samplerCUBE skyMap; +uniform samplerCube skyMap; uniform sampler2D foamMap; -uniform vec4 specularColor; -uniform float specularPower; +uniform sampler1D depthGradMap; +uniform vec4 specularParams; uniform vec4 baseColor; uniform vec4 miscParams; uniform vec2 fogParams; @@ -112,64 +131,45 @@ uniform vec3 reflectNormal; uniform vec2 wetnessParams; uniform float farPlaneDist; uniform vec3 distortionParams; -//uniform vec4 renderTargetParams; -uniform vec2 foamParams; -uniform vec3 foamColorMod; +uniform vec4 foamParams; uniform vec3 ambientColor; -uniform vec3 eyePos; -uniform vec3 inLightVec; +uniform vec3 eyePos; // This is in object space! uniform vec3 fogData; uniform vec4 fogColor; -//uniform vec4 rtParams; -uniform vec2 rtScale; -uniform vec2 rtHalfPixel; -uniform vec4 rtOffset; -uniform vec3 rippleMagnitude; +uniform vec4 rippleMagnitude; +uniform vec4 rtParams1; +uniform float depthGradMax; +uniform vec3 inLightVec; +uniform mat4 modelMat; +uniform vec4 sunColor; +uniform float sunBrightness; +uniform float reflectivity; //----------------------------------------------------------------------------- // Main //----------------------------------------------------------------------------- void main() { - vec4 rtParams = vec4( rtOffset.x / rtOffset.z + rtHalfPixel.x, - rtOffset.y / rtOffset.w + rtHalfPixel.x, - rtScale ); - - // Modulate baseColor by the ambientColor. - vec4 waterBaseColor = baseColor * vec4( ambientColor.rgb, 1 ); - // Get the bumpNorm... - vec3 bumpNorm = ( tex2D( bumpMap, IN.rippleTexCoord01.xy ) * 2.0 - 1.0 ) * rippleMagnitude.x; - bumpNorm += ( tex2D( bumpMap, IN.rippleTexCoord01.zw ) * 2.0 - 1.0 ) * rippleMagnitude.y; - bumpNorm += ( tex2D( bumpMap, IN.rippleTexCoord2 ) * 2.0 - 1.0 ) * rippleMagnitude.z; - - // JCF: this was here, but seems to make the dot product against the bump - // normal we use below for cubeMap fade-in to be less reliable. - //bumpNorm.xy *= 0.75; - //bumpNorm = normalize( bumpNorm ); - //return vec4( bumpNorm, 1 ); + vec3 bumpNorm = ( texture( bumpMap, IN_rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x; + bumpNorm += ( texture( bumpMap, IN_rippleTexCoord01.zw ).rgb * 2.0 - 1.0 ) * rippleMagnitude.y; + bumpNorm += ( texture( bumpMap, IN_rippleTexCoord2.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.z; + + bumpNorm = normalize( bumpNorm ); + bumpNorm = mix( bumpNorm, vec3(0,0,1), 1.0 - rippleMagnitude.w ); + bumpNorm = tMul( bumpNorm, IN_tangentMat ); // Get depth of the water surface (this pixel). // Convert from WorldSpace to EyeSpace. - float pixelDepth = IN.pixelDist / farPlaneDist; + float pixelDepth = PIXEL_DIST / farPlaneDist; - // Get prepass depth at the undistorted pixel. - //vec4 prepassCoord = IN.posPostWave; - //prepassCoord.xy += renderTargetParams.xy; - vec2 prepassCoord = viewportCoordToRenderTarget( IN.posPostWave, rtParams ); - //vec2 prepassCoord = IN.posPostWave.xy; + vec2 prepassCoord = viewportCoordToRenderTarget( IN_posPostWave, rtParams1 ); - float startDepth = prepassUncondition( tex2D( prepassTex, prepassCoord ) ).w; - //return vec4( startDepth.rrr, 1 ); + float startDepth = prepassUncondition( prepassTex, prepassCoord ).w; // The water depth in world units of the undistorted pixel. float startDelta = ( startDepth - pixelDepth ); - if ( startDelta <= 0.0 ) - { - //return vec4( 1, 0, 0, 1 ); - startDelta = 0; - } - + startDelta = max( startDelta, 0.0 ); startDelta *= farPlaneDist; // Calculate the distortion amount for the water surface. @@ -177,23 +177,22 @@ void main() // We subtract a little from it so that we don't // distort where the water surface intersects the // camera near plane. - float distortAmt = saturate( ( IN.pixelDist - DISTORT_START_DIST ) / DISTORT_END_DIST ); + float distortAmt = saturate( ( PIXEL_DIST - DISTORT_START_DIST ) / DISTORT_END_DIST ); // Scale down distortion in shallow water. distortAmt *= saturate( startDelta / DISTORT_FULL_DEPTH ); - //distortAmt = 0; // Do the intial distortion... we might remove it below. vec2 distortDelta = bumpNorm.xy * distortAmt; - vec4 distortPos = IN.posPostWave; + vec4 distortPos = IN_posPostWave; distortPos.xy += distortDelta; - prepassCoord = viewportCoordToRenderTarget( distortPos, rtParams ); - //prepassCoord = distortPos; - //prepassCoord.xy += renderTargetParams.xy; + prepassCoord = viewportCoordToRenderTarget( distortPos, rtParams1 ); // Get prepass depth at the position of this distorted pixel. - float prepassDepth = prepassUncondition( tex2D( prepassTex, prepassCoord ) ).w; + float prepassDepth = prepassUncondition( prepassTex, prepassCoord ).w; + if ( prepassDepth > 0.99 ) + prepassDepth = 5.0; float delta = ( prepassDepth - pixelDepth ) * farPlaneDist; @@ -202,7 +201,7 @@ void main() // If we got a negative delta then the distorted // sample is above the water surface. Mask it out // by removing the distortion. - distortPos = IN.posPostWave; + distortPos = IN_posPostWave; delta = startDelta; distortAmt = 0; } @@ -212,20 +211,20 @@ void main() if ( diff < 0 ) { - distortAmt = saturate( ( IN.pixelDist - DISTORT_START_DIST ) / DISTORT_END_DIST ); + distortAmt = saturate( ( PIXEL_DIST - DISTORT_START_DIST ) / DISTORT_END_DIST ); distortAmt *= saturate( delta / DISTORT_FULL_DEPTH ); distortDelta = bumpNorm.xy * distortAmt; - distortPos = IN.posPostWave; + distortPos = IN_posPostWave; distortPos.xy += distortDelta; - prepassCoord = viewportCoordToRenderTarget( distortPos, rtParams ); - //prepassCoord = distortPos; - //prepassCoord.xy += renderTargetParams.xy; + prepassCoord = viewportCoordToRenderTarget( distortPos, rtParams1 ); // Get prepass depth at the position of this distorted pixel. - prepassDepth = prepassUncondition( tex2D( prepassTex, prepassCoord ) ).w; + prepassDepth = prepassUncondition( prepassTex, prepassCoord ).w; + if ( prepassDepth > 0.99 ) + prepassDepth = 5.0; delta = ( prepassDepth - pixelDepth ) * farPlaneDist; } @@ -234,133 +233,78 @@ void main() // If we got a negative delta then the distorted // sample is above the water surface. Mask it out // by removing the distortion. - distortPos = IN.posPostWave; + distortPos = IN_posPostWave; delta = startDelta; distortAmt = 0; } } - //return vec4( prepassDepth.rrr, 1 ); - - vec4 temp = IN.posPreWave; + vec4 temp = IN_posPreWave; temp.xy += bumpNorm.xy * distortAmt; - vec2 reflectCoord = viewportCoordToRenderTarget( temp, rtParams ); + vec2 reflectCoord = viewportCoordToRenderTarget( temp, rtParams1 ); - vec2 refractCoord = viewportCoordToRenderTarget( distortPos, rtParams ); + vec2 refractCoord = viewportCoordToRenderTarget( distortPos, rtParams1 ); - // Use cubemap colors instead of reflection colors in several cases... - - // First lookup the CubeMap color - // JCF: which do we want to use here, the reflectNormal or the bumpNormal - // neithor of them is exactly right and how can we combine the two together? - //bumpNorm = reflectNormal; - vec3 eyeVec = IN.worldPos - eyePos; + vec4 fakeColor = vec4(ambientColor,1); + vec3 eyeVec = IN_objPos.xyz - eyePos; + eyeVec = tMul( mat3(modelMat), eyeVec ); + eyeVec = tMul( IN_tangentMat, eyeVec ); vec3 reflectionVec = reflect( eyeVec, bumpNorm ); - //vec4 cubeColor = texCUBE( skyMap, reflectionVec ); - //return cubeColor; - // JCF: using ambient color instead of cubeColor for waterPlane, how do we still use the cubemap for rivers? - vec4 cubeColor = vec4(ambientColor,1); - //cubeColor.rgb = vec3( 0, 0, 1 ); - // Use cubeColor for waves that are angled towards camera + // Use fakeColor for ripple-normals that are angled towards the camera eyeVec = -eyeVec; eyeVec = normalize( eyeVec ); float ang = saturate( dot( eyeVec, bumpNorm ) ); - float cubeAmt = ang; + float fakeColorAmt = ang; - //float rplaneDist = (reflectPlane.x * IN.pos.x + reflectPlane.y * IN.pos.y + reflectPlane.z * IN.pos.z) + reflectPlane.w; - //rplaneDist = saturate( abs( rplaneDist ) / 0.5 ); - - -//#ifdef RIVER // for verts far from the reflect plane z position - float rplaneDist = abs( REFLECT_PLANE_Z - IN.worldPos.z ); + float rplaneDist = abs( REFLECT_PLANE_Z - IN_objPos.w ); rplaneDist = saturate( ( rplaneDist - 1.0 ) / 2.0 ); - //rplaneDist = REFLECT_PLANE_Z / eyePos.z; rplaneDist *= ISRIVER; - cubeAmt = max( cubeAmt, rplaneDist ); -//#endif - - //rplaneDist = IN.worldPos.z / eyePos.z; - - //return vec4( rplaneDist.rrr, 1 ); - //return vec4( (reflectParams[REFLECT_PLANE_Z] / 86.0 ).rrr, 1 ); - - // and for verts farther from the camera - //float cubeAmt = ( eyeDist - reflectParams[REFLECT_MIN_DIST] ) / ( reflectParams[REFLECT_MAX_DIST] - reflectParams[REFLECT_MIN_DIST] ); - //cubeAmt = saturate ( cubeAmt ); - - //float temp = ( eyeDist - reflectParams[REFLECT_MIN_DIST] ) / ( reflectParams[REFLECT_MAX_DIST] - reflectParams[REFLECT_MIN_DIST] ); - //temp = saturate ( temp ); - - // If the camera is very very close to the reflect plane. - //float eyeToPlaneDist = eyePos.z - REFLECT_PLANE_Z; // dot( reflectNormal, eyePos ) + REFLECT_PLANE_Z; - //eyeToPlaneDist = abs( eyeToPlaneDist ); - //eyeToPlaneDist = 1.0 - saturate( abs( eyeToPlaneDist ) / 1 ); - - //return vec4( eyeToPlaneDist.rrr, 1 ); - - //cubeAmt = max( cubeAmt, eyeToPlaneDist ); - //cubeAmt = max( cubeAmt, rplaneDist ); - //cubeAmt = max( cubeAmt, ang ); - //cubeAmt = max( cubeAmt, rplaneDist ); - //cubeAmt = max( cubeAmt, IN.depth.w ); - - // All cubemap if fullReflect is specifically user disabled - cubeAmt = max( cubeAmt, NO_REFLECT ); + fakeColorAmt = max( fakeColorAmt, rplaneDist ); #ifndef UNDERWATER - // Get foam color and amount - IN.foamTexCoords.xy += distortDelta * 0.5; - IN.foamTexCoords.zw += distortDelta * 0.5; + vec2 foamRippleOffset = bumpNorm.xy * FOAM_RIPPLE_INFLUENCE; + vec4 IN_foamTexCoords = IN_foamTexCoords; + IN_foamTexCoords.xy += foamRippleOffset; + IN_foamTexCoords.zw += foamRippleOffset; - vec4 foamColor = tex2D( foamMap, IN.foamTexCoords.xy ); - foamColor += tex2D( foamMap, IN.foamTexCoords.zw ); - //foamColor += tex2D( foamMap, IN.rippleTexCoord2 ) * 0.3; + vec4 foamColor = texture( foamMap, IN_foamTexCoords.xy ); + foamColor += texture( foamMap, IN_foamTexCoords.zw ); foamColor = saturate( foamColor ); - // Modulate foam color by ambient color so we don't have glowing white - // foam at night. - foamColor.rgb = lerp( foamColor.rgb, ambientColor.rgb, foamColorMod.rgb ); + + // Modulate foam color by ambient color + // so we don't have glowing white foam at night. + foamColor.rgb = mix( foamColor.rgb, ambientColor.rgb, FOAM_AMBIENT_LERP ); float foamDelta = saturate( delta / FOAM_MAX_DEPTH ); - float foamAmt = 1.0 - foamDelta; + float foamAmt = 1 - pow( foamDelta, 2 ); // Fade out the foam in very very low depth, // this improves the shoreline a lot. float diff = 0.8 - foamAmt; if ( diff < 0.0 ) - { - //return vec4( 1,0,0,1 ); foamAmt -= foamAmt * abs( diff ) / 0.2; - } - //return vec4( foamAmt.rrr, 1 ); - - foamAmt *= FOAM_SCALE * foamColor.a; - //return vec4( foamAmt.rrr, 1 ); - // Get reflection map color - vec4 refMapColor = tex2D( reflectMap, reflectCoord ); + foamAmt *= FOAM_OPACITY * foamColor.a; - //cubeAmt = 0; + foamColor.rgb *= FOAM_OPACITY * foamAmt * foamColor.a; - // Combine cube and foam colors into reflect color - vec4 reflectColor = lerp( refMapColor, cubeColor, cubeAmt ); - //return refMapColor; + // Get reflection map color. + vec4 refMapColor = hdrDecode( texture( reflectMap, reflectCoord ) ); - // This doesn't work because REFLECT_PLANE_Z is in worldSpace - // while eyePos is actually in objectSpace! + // If we do not have a reflection texture then we use the cubemap. + refMapColor = mix( refMapColor, texture( skyMap, reflectionVec ), NO_REFLECT ); - //float eyeToPlaneDist = eyePos.z - REFLECT_PLANE_Z; // dot( reflectNormal, eyePos ) + REFLECT_PLANE_Z; - //float transitionFactor = 1.0 - saturate( ( abs( eyeToPlaneDist ) - 0.5 ) / 5 ); - //reflectColor = lerp( reflectColor, waterBaseColor, transitionFactor ); - - //return reflectColor; + fakeColor = ( texture( skyMap, reflectionVec ) ); + fakeColor.a = 1; + // Combine reflection color and fakeColor. + vec4 reflectColor = mix( refMapColor, fakeColor, fakeColorAmt ); // Get refract color - vec4 refractColor = tex2D( refractBuff, refractCoord ); - //return refractColor; + vec4 refractColor = hdrDecode( texture( refractBuff, refractCoord ) ); // We darken the refraction color a bit to make underwater // elements look wet. We fade out this darkening near the @@ -371,86 +315,80 @@ void main() // Add Water fog/haze. float fogDelta = delta - FOG_DENSITY_OFFSET; - //return vec4( fogDelta.rrr, 1 ); + if ( fogDelta < 0.0 ) fogDelta = 0.0; float fogAmt = 1.0 - saturate( exp( -FOG_DENSITY * fogDelta ) ); - //return vec4( fogAmt.rrr, 1 ); + + // Calculate the water "base" color based on depth. + vec4 waterBaseColor = baseColor * texture( depthGradMap, saturate( delta / depthGradMax ) ); + + // Modulate baseColor by the ambientColor. + waterBaseColor *= vec4( ambientColor.rgb, 1 ); // calc "diffuse" color by lerping from the water color // to refraction image based on the water clarity. - vec4 diffuseColor = lerp( refractColor, waterBaseColor, fogAmt ); + vec4 diffuseColor = mix( refractColor, waterBaseColor, fogAmt ); // fresnel calculation float fresnelTerm = fresnel( ang, FRESNEL_BIAS, FRESNEL_POWER ); - //return vec4( fresnelTerm.rrr, 1 ); // Scale the frensel strength by fog amount // so that parts that are very clear get very little reflection. fresnelTerm *= fogAmt; - //return vec4( fresnelTerm.rrr, 1 ); // Also scale the frensel by our distance to the // water surface. This removes the hard reflection // when really close to the water surface. - fresnelTerm *= saturate( IN.pixelDist - 0.1 ); + fresnelTerm *= saturate( PIXEL_DIST - 0.1 ); + + fresnelTerm *= reflectivity; // Combine the diffuse color and reflection image via the // fresnel term and set out output color. - vec4 gl_FragColor = lerp( diffuseColor, reflectColor, fresnelTerm ); + vec4 OUT = mix( diffuseColor, reflectColor, fresnelTerm ); - //float brightness = saturate( 1.0 - ( waterHeight - eyePosWorld.z - 5.0 ) / 50.0 ); - //gl_FragColor.rgb *= brightness; + vec3 lightVec = inLightVec; + + // Get some specular reflection. + vec3 newbump = bumpNorm; + newbump.xy *= 3.5; + newbump = normalize( bumpNorm ); + vec3 halfAng = normalize( eyeVec + -lightVec ); + float specular = saturate( dot( newbump, halfAng ) ); + specular = pow( specular, SPEC_POWER ); + + // Scale down specularity in very shallow water to improve the transparency of the shoreline. + specular *= saturate( delta / 2 ); + OUT.rgb = OUT.rgb + ( SPEC_COLOR * vec3(specular) ); #else - vec4 refractColor = tex2D( refractBuff, refractCoord ); - vec4 gl_FragColor = refractColor; + + vec4 refractColor = hdrDecode( texture( refractBuff, refractCoord ) ); + vec4 OUT = refractColor; + #endif #ifndef UNDERWATER - gl_FragColor.rgb = lerp( gl_FragColor.rgb, foamColor.rgb, foamAmt ); -#endif - gl_FragColor.a = 1.0; - - // specular experiments - -// 1: -/* - float fDot = dot( bumpNorm, inLightVec ); - vec3 reflect = normalize( 2.0 * bumpNorm * fDot - eyeVec ); - // float specular = saturate(dot( reflect, inLightVec ) ); - float specular = pow( reflect, specularPower ); - gl_FragColor += specularColor * specular; -*/ - - -// 2: This almost looks good -/* - bumpNorm.xy *= 2.0; - bumpNorm = normalize( bumpNorm ); - - vec3 halfAng = normalize( eyeVec + inLightVec ); - float specular = saturate( dot( bumpNorm, halfAng) ); - specular = pow(specular, specularPower); - gl_FragColor += specularColor * specular; -*/ - -#ifndef UNDERWATER + OUT.rgb = OUT.rgb + foamColor.rgb; float factor = computeSceneFog( eyePos, - IN.fogPos, - IN.worldSpaceZ, + IN_objPos.xyz, + IN_objPos.w, fogData.x, fogData.y, fogData.z ); - gl_FragColor.rgb = lerp( gl_FragColor.rgb, fogColor.rgb, 1.0 - saturate( factor ) ); + OUT.rgb = mix( OUT.rgb, fogColor.rgb, 1.0 - saturate( factor ) ); + + //OUT.rgb = fogColor.rgb; #endif - //return vec4( refMapColor.rgb, 1 ); - gl_FragColor.a = 1.0; + OUT.a = 1.0; + + //return OUT; - return gl_FragColor; + OUT_FragColor0 = hdrEncode( OUT ); } diff --git a/Templates/Empty/game/shaders/common/water/gl/waterV.glsl b/Templates/Empty/game/shaders/common/water/gl/waterV.glsl index d4337476f..490af63a7 100644 --- a/Templates/Empty/game/shaders/common/water/gl/waterV.glsl +++ b/Templates/Empty/game/shaders/common/water/gl/waterV.glsl @@ -20,58 +20,86 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../gl/hlslCompat.glsl" #include "shadergen:/autogenConditioners.h" +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- +struct VertData +{ + vec4 position ;// POSITION; + vec3 normal ;// NORMAL; + vec2 undulateData ;// TEXCOORD0; + vec4 horizonFactor ;// TEXCOORD1; +}; + //----------------------------------------------------------------------------- // Defines //----------------------------------------------------------------------------- +//VertData IN +in vec4 vPosition; +in vec3 vNormal; +in vec2 vTexCoord0; +in vec4 vTexCoord1; -// waveData -#define WAVE_SPEED(i) waveData[i].x -#define WAVE_MAGNITUDE(i) waveData[i].y +#define IN_position_ vPosition +#define IN_normal vNormal +#define IN_undulateData vTexCoord0 +#define IN_horizonFactor vTexCoord1 -// Outgoing data -// Worldspace position of this pixel -varying vec3 worldPos; +//ConnectData OUT +// + out vec4 hpos ; // TexCoord 0 and 1 (xy,zw) for ripple texture lookup -varying vec4 rippleTexCoord01; +out vec4 rippleTexCoord01; -// TexCoord 2 for ripple texture lookup -varying vec2 rippleTexCoord2; + // xy is TexCoord 2 for ripple texture lookup + // z is the Worldspace unit distance/depth of this vertex/pixel + // w is amount of the crestFoam ( more at crest of waves ). + out vec4 rippleTexCoord2 ; // Screenspace vert position BEFORE wave transformation -varying vec4 posPreWave; +out vec4 posPreWave; // Screenspace vert position AFTER wave transformation -varying vec4 posPostWave; +out vec4 posPostWave; -// Worldspace unit distance/depth of this vertex/pixel -varying float pixelDist; + // Objectspace vert position BEFORE wave transformation + // w coord is world space z position. + out vec4 objPos ; -varying vec3 fogPos; + out vec4 foamTexCoords ; -varying float worldSpaceZ; + out mat3 tangentMat ; +// -varying vec4 foamTexCoords; +#define OUT_hpos hpos +#define OUT_rippleTexCoord01 rippleTexCoord01 +#define OUT_rippleTexCoord2 rippleTexCoord2 +#define OUT_posPreWave posPreWave +#define OUT_posPostWave posPostWave +#define OUT_objPos objPos +#define OUT_foamTexCoords foamTexCoords +#define OUT_tangentMat tangentMat //----------------------------------------------------------------------------- // Uniforms //----------------------------------------------------------------------------- uniform mat4 modelMat; uniform mat4 modelview; -uniform mat3 cubeTrans; -uniform mat4 objTrans; -uniform vec3 cubeEyePos; +uniform vec4 rippleMat[3]; uniform vec3 eyePos; uniform vec2 waveDir[3]; uniform vec2 waveData[3]; uniform vec2 rippleDir[3]; uniform vec2 rippleTexScale[3]; uniform vec3 rippleSpeed; -uniform vec2 reflectTexSize; +uniform vec4 foamDir; +uniform vec4 foamTexScale; +uniform vec2 foamSpeed; uniform vec3 inLightVec; -uniform vec3 reflectNormal; uniform float gridElementSize; uniform float elapsedTime; uniform float undulateMaxDist; @@ -81,97 +109,133 @@ uniform float undulateMaxDist; //----------------------------------------------------------------------------- void main() { - // Copy incoming attributes into locals so we can modify them in place. - vec4 position = gl_Vertex.xyzw; - vec3 normal = gl_Normal.xyz; - vec2 undulateData = gl_MultiTexCoord0.st; - vec4 horizonFactor = gl_MultiTexCoord1.xyzw; + vec4 IN_position = IN_position_; // use projection matrix for reflection / refraction texture coords - mat4 texGen = { 0.5, 0.0, 0.0, 0.5, //+ 0.5 / reflectTexSize.x, - 0.0, 0.5, 0.0, 0.5, //+ 1.0 / reflectTexSize.y, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0 }; + mat4 texGen = mat4FromRow( 0.5, 0.0, 0.0, 0.5, + 0.0, -0.5, 0.0, 0.5, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 ); - // Move the vertex based on the horizonFactor if specified to do so for this vert. - if ( horizonFactor.z > 0 ) - { - vec2 offsetXY = eyePos.xy - eyePos.xy % gridElementSize; - position.xy += offsetXY; - undulateData += offsetXY; - } + IN_position.z = mix( IN_position.z, eyePos.z, IN_horizonFactor.x ); - fogPos = position; - position.z = mix( position.z, eyePos.z, horizonFactor.x ); + OUT_objPos = IN_position; + OUT_objPos.w = tMul( modelMat, IN_position ).z; // Send pre-undulation screenspace position - posPreWave = modelview * position; - posPreWave = texGen * posPreWave; + OUT_posPreWave = tMul( modelview, IN_position ); + OUT_posPreWave = tMul( texGen, OUT_posPreWave ); // Calculate the undulation amount for this vertex. - vec2 undulatePos = undulateData; - float undulateAmt = 0; + vec2 undulatePos = tMul( modelMat, vec4 ( IN_undulateData.xy, 0, 1 ) ).xy; + float undulateAmt = 0.0; - for ( int i = 0; i < 3; i++ ) - { - undulateAmt += WAVE_MAGNITUDE(i) * sin( elapsedTime * WAVE_SPEED(i) + - undulatePos.x * waveDir[i].x + - undulatePos.y * waveDir[i].y ); - } + undulateAmt += waveData[0].y * sin( elapsedTime * waveData[0].x + + undulatePos.x * waveDir[0].x + + undulatePos.y * waveDir[0].y ); + undulateAmt += waveData[1].y * sin( elapsedTime * waveData[1].x + + undulatePos.x * waveDir[1].x + + undulatePos.y * waveDir[1].y ); + undulateAmt += waveData[2].y * sin( elapsedTime * waveData[2].x + + undulatePos.x * waveDir[2].x + + undulatePos.y * waveDir[2].y ); + + float undulateFade = 1; // Scale down wave magnitude amount based on distance from the camera. - float dist = distance( position, eyePos ); + float dist = distance( IN_position.xyz, eyePos ); dist = clamp( dist, 1.0, undulateMaxDist ); - undulateAmt *= ( 1 - dist / undulateMaxDist ); + undulateFade *= ( 1 - dist / undulateMaxDist ); // Also scale down wave magnitude if the camera is very very close. - undulateAmt *= clamp( ( distance( IN.position, eyePos ) - 0.5 ) / 10.0, 0.0, 1.0 ); + undulateFade *= saturate( ( distance( IN_position.xyz, eyePos ) - 0.5 ) / 10.0 ); + + undulateAmt *= undulateFade; + + OUT_rippleTexCoord2.w = undulateAmt / ( waveData[0].y + waveData[1].y + waveData[2].y ); + OUT_rippleTexCoord2.w = saturate( OUT_rippleTexCoord2.w - 0.2 ) / 0.8; // Apply wave undulation to the vertex. - posPostWave = position; - posPostWave.xyz += normal.xyz * undulateAmt; - - // Save worldSpace position of this pixel/vert - worldPos = posPostWave.xyz; + OUT_posPostWave = IN_position; + OUT_posPostWave.xyz += IN_normal.xyz * undulateAmt; // Convert to screen - posPostWave = modelview * posPostWave; + OUT_posPostWave = tMul( modelview, OUT_posPostWave ); // Setup the OUT position symantic variable - gl_Position = posPostWave; - gl_Position.z = mix(gl_Position.z, gl_Position.w, horizonFactor.x); + OUT_hpos = OUT_posPostWave; + //OUT_hpos.z = mix( OUT_hpos.z, OUT_hpos.w, IN_horizonFactor.x ); - worldSpaceZ = modelMat * vec4(fogPos, 1.0) ).z; - if ( horizonFactor.x > 0.0 ) - { - vec3 awayVec = normalize( fogPos.xyz - eyePos ); - fogPos.xy += awayVec.xy * 1000.0; - } + // if ( IN_horizonFactor.x > 0 ) + // { + // vec3 awayVec = normalize( OUT_objPos.xyz - eyePos ); + // OUT_objPos.xy += awayVec.xy * 1000.0; + // } // Save world space camera dist/depth of the outgoing pixel - pixelDist = gl_Position.z; + OUT_rippleTexCoord2.z = OUT_hpos.z; // Convert to reflection texture space - posPostWave = texGen * posPostWave; + OUT_posPostWave = tMul( texGen, OUT_posPostWave ); - float2 ripplePos = undulateData; - float2 txPos = normalize( ripplePos ); - txPos *= 50000.0; - ripplePos = mix( ripplePos, txPos, IN.horizonFactor.x ); + vec2 txPos = undulatePos; + if ( bool(IN_horizonFactor.x) ) + txPos = normalize( txPos ) * 50000.0; // set up tex coordinates for the 3 interacting normal maps - rippleTexCoord01.xy = mix( ripplePos * rippleTexScale[0], txPos.xy * rippleTexScale[0], IN.horizonFactor.x ); - rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; + OUT_rippleTexCoord01.xy = txPos * rippleTexScale[0]; + OUT_rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; - rippleTexCoord01.zw = mix( ripplePos * rippleTexScale[1], txPos.xy * rippleTexScale[1], IN.horizonFactor.x ); - rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; + mat2 texMat; + texMat[0][0] = rippleMat[0].x; + texMat[1][0] = rippleMat[0].y; + texMat[0][1] = rippleMat[0].z; + texMat[1][1] = rippleMat[0].w; + OUT_rippleTexCoord01.xy = tMul( texMat, OUT_rippleTexCoord01.xy ); - rippleTexCoord2.xy = mix( ripplePos * rippleTexScale[2], txPos.xy * rippleTexScale[2], IN.horizonFactor.x ); - rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; + OUT_rippleTexCoord01.zw = txPos * rippleTexScale[1]; + OUT_rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; + + texMat[0][0] = rippleMat[1].x; + texMat[1][0] = rippleMat[1].y; + texMat[0][1] = rippleMat[1].z; + texMat[1][1] = rippleMat[1].w; + OUT_rippleTexCoord01.zw = tMul( texMat, OUT_rippleTexCoord01.zw ); - foamTexCoords.xy = mix( ripplePos * 0.2, txPos.xy * rippleTexScale[0], IN.horizonFactor.x ); - foamTexCoords.xy += rippleDir[0] * sin( ( elapsedTime + 500.0 ) * -0.4 ) * 0.15; + OUT_rippleTexCoord2.xy = txPos * rippleTexScale[2]; + OUT_rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; - foamTexCoords.zw = mix( ripplePos * 0.3, txPos.xy * rippleTexScale[1], IN.horizonFactor.x ); - foamTexCoords.zw += rippleDir[1] * sin( elapsedTime * 0.4 ) * 0.15; + texMat[0][0] = rippleMat[2].x; + texMat[1][0] = rippleMat[2].y; + texMat[0][1] = rippleMat[2].z; + texMat[1][1] = rippleMat[2].w; + OUT_rippleTexCoord2.xy = tMul( texMat, OUT_rippleTexCoord2.xy ); + + OUT_foamTexCoords.xy = txPos * foamTexScale.xy + foamDir.xy * foamSpeed.x * elapsedTime; + OUT_foamTexCoords.zw = txPos * foamTexScale.zw + foamDir.zw * foamSpeed.y * elapsedTime; + + + vec3 binormal = vec3 ( 1, 0, 0 ); + vec3 tangent = vec3 ( 0, 1, 0 ); + vec3 normal; + for ( int i = 0; i < 3; i++ ) + { + binormal.z += undulateFade * waveDir[i].x * waveData[i].y * cos( waveDir[i].x * undulatePos.x + waveDir[i].y * undulatePos.y + elapsedTime * waveData[i].x ); + tangent.z += undulateFade * waveDir[i].y * waveData[i].y * cos( waveDir[i].x * undulatePos.x + waveDir[i].y * undulatePos.y + elapsedTime * waveData[i].x ); + } + + binormal = binormal; + tangent = tangent; + normal = cross( binormal, tangent ); + + mat3 worldToTangent; + worldToTangent[0] = binormal; + worldToTangent[1] = tangent; + worldToTangent[2] = normal; + + OUT_tangentMat = transpose(worldToTangent); + + gl_Position = OUT_hpos; + correctSSP(gl_Position); } + diff --git a/Templates/Empty/game/tools/gui/openFileDialog.ed.cs b/Templates/Empty/game/tools/gui/openFileDialog.ed.cs index 00a388789..b988d3361 100644 --- a/Templates/Empty/game/tools/gui/openFileDialog.ed.cs +++ b/Templates/Empty/game/tools/gui/openFileDialog.ed.cs @@ -42,3 +42,29 @@ function getLoadFilename(%filespec, %callback, %currentFile) %dlg.delete(); } + +// Opens a choose file dialog with format filters already loaded +// in. This avoids the issue of passing a massive list of format +// filters into a function as an arguement. +function getLoadFormatFilename(%callback, %currentFile) +{ + %dlg = new OpenFileDialog() + { + Filters = getFormatFilters() @ "(All Files (*.*)|*.*|"; + DefaultFile = %currentFile; + ChangePath = false; + MustExist = true; + MultipleFiles = false; + }; + + if ( filePath( %currentFile ) !$= "" ) + %dlg.DefaultPath = filePath(%currentFile); + + if ( %dlg.Execute() ) + { + eval(%callback @ "(\"" @ %dlg.FileName @ "\");"); + $Tools::FileDialogs::LastFilePath = filePath( %dlg.FileName ); + } + + %dlg.delete(); +} diff --git a/Templates/Empty/game/tools/gui/profiles.ed.cs b/Templates/Empty/game/tools/gui/profiles.ed.cs index 8d6718601..b3a5b2295 100644 --- a/Templates/Empty/game/tools/gui/profiles.ed.cs +++ b/Templates/Empty/game/tools/gui/profiles.ed.cs @@ -764,7 +764,7 @@ singleton GuiControlProfile( GuiInspectorGroupProfile ) opaque = false; border = false; - bitmap = "tools/editorclasses/gui/images/rollout"; + bitmap = "tools/editorClasses/gui/images/rollout"; textOffset = "20 0"; diff --git a/Templates/Empty/game/tools/particleEditor/particleEmitterEditor.ed.cs b/Templates/Empty/game/tools/particleEditor/particleEmitterEditor.ed.cs index 11678a053..8d290f0a3 100644 --- a/Templates/Empty/game/tools/particleEditor/particleEmitterEditor.ed.cs +++ b/Templates/Empty/game/tools/particleEditor/particleEmitterEditor.ed.cs @@ -84,6 +84,9 @@ function PE_EmitterEditor::guiSync( %this ) PE_EmitterEditor-->PEE_ejectionOffset_slider.setValue( %data.ejectionOffset ); PE_EmitterEditor-->PEE_ejectionOffset_textEdit.setText( %data.ejectionOffset ); + PE_EmitterEditor-->PEE_ejectionOffsetVariance_slider.setValue( %data.ejectionOffsetVariance ); + PE_EmitterEditor-->PEE_ejectionOffsetVariance_textEdit.setText( %data.ejectionOffsetVariance ); + %blendTypeId = PE_EmitterEditor-->PEE_blendType.findText( %data.blendStyle ); PE_EmitterEditor-->PEE_blendType.setSelected( %blendTypeId, false ); diff --git a/Templates/Empty/game/tools/riverEditor/main.cs b/Templates/Empty/game/tools/riverEditor/main.cs index b51bd5273..eafb3c3c8 100644 --- a/Templates/Empty/game/tools/riverEditor/main.cs +++ b/Templates/Empty/game/tools/riverEditor/main.cs @@ -25,8 +25,8 @@ function initializeRiverEditor() echo(" % - Initializing River Editor"); exec( "./riverEditor.cs" ); - exec( "./riverEditorGui.gui" ); - exec( "./riverEditorToolbar.gui" ); + exec( "./RiverEditorGui.gui" ); + exec( "./RiverEditorToolbar.gui" ); exec( "./riverEditorGui.cs" ); // Add ourselves to EditorGui, where all the other tools reside diff --git a/Templates/Empty/game/tools/roadEditor/main.cs b/Templates/Empty/game/tools/roadEditor/main.cs index cb7ea052c..f45823670 100644 --- a/Templates/Empty/game/tools/roadEditor/main.cs +++ b/Templates/Empty/game/tools/roadEditor/main.cs @@ -25,8 +25,8 @@ function initializeRoadEditor() echo( " - Initializing Road and Path Editor" ); exec( "./roadEditor.cs" ); - exec( "./roadEditorGui.gui" ); - exec( "./roadEditorToolbar.gui"); + exec( "./RoadEditorGui.gui" ); + exec( "./RoadEditorToolbar.gui"); exec( "./roadEditorGui.cs" ); // Add ourselves to EditorGui, where all the other tools reside diff --git a/Templates/Empty/game/tools/shapeEditor/gui/Profiles.ed.cs b/Templates/Empty/game/tools/shapeEditor/gui/Profiles.ed.cs index 0b92a30e2..cb42ef169 100644 --- a/Templates/Empty/game/tools/shapeEditor/gui/Profiles.ed.cs +++ b/Templates/Empty/game/tools/shapeEditor/gui/Profiles.ed.cs @@ -41,7 +41,7 @@ singleton GuiControlProfile(GuiShapeEdTextListProfile : ToolsGuiTextListProfile) singleton GuiControlProfile(GuiShapeEdRolloutProfile : GuiInspectorRolloutProfile0) { - bitmap = "tools/editorclasses/gui/images/rollout"; + bitmap = "tools/editorClasses/gui/images/rollout"; category = "Editor"; }; diff --git a/Templates/Empty/game/tools/shapeEditor/main.cs b/Templates/Empty/game/tools/shapeEditor/main.cs index f033bae86..721313e95 100644 --- a/Templates/Empty/game/tools/shapeEditor/main.cs +++ b/Templates/Empty/game/tools/shapeEditor/main.cs @@ -33,7 +33,7 @@ function initializeShapeEditor() exec("./gui/shapeEdPreviewWindow.ed.gui"); exec("./gui/shapeEdAnimWindow.ed.gui"); exec("./gui/shapeEdAdvancedWindow.ed.gui"); - exec("./gui/shapeEditorToolbar.ed.gui"); + exec("./gui/ShapeEditorToolbar.ed.gui"); exec("./gui/shapeEdSelectWindow.ed.gui"); exec("./gui/shapeEdPropWindow.ed.gui"); diff --git a/Templates/Empty/game/tools/shapeEditor/scripts/shapeEditor.ed.cs b/Templates/Empty/game/tools/shapeEditor/scripts/shapeEditor.ed.cs index 5eb26f3c0..6282f32ce 100644 --- a/Templates/Empty/game/tools/shapeEditor/scripts/shapeEditor.ed.cs +++ b/Templates/Empty/game/tools/shapeEditor/scripts/shapeEditor.ed.cs @@ -366,7 +366,7 @@ function ShapeEdSelectWindow::navigate( %this, %address ) %this-->shapeLibrary.clear(); ShapeEdSelectMenu.clear(); - %filePatterns = "*.dts" TAB "*.dae" TAB "*.kmz"; + %filePatterns = getFormatExtensions(); %fullPath = findFirstFileMultiExpr( %filePatterns ); while ( %fullPath !$= "" ) @@ -1632,7 +1632,7 @@ function ShapeEdSequences::onAddSequence( %this, %name ) if ( %from $= "" ) { // No sequence selected => open dialog to browse for one - getLoadFilename( "DSQ Files|*.dsq|COLLADA Files|*.dae|Google Earth Files|*.kmz", %this @ ".onAddSequenceFromBrowse", ShapeEdFromMenu.lastPath ); + getLoadFormatFilename( %this @ ".onAddSequenceFromBrowse", ShapeEdFromMenu.lastPath ); return; } else @@ -1740,7 +1740,7 @@ function ShapeEdSeqFromMenu::onSelect( %this, %id, %text ) %this.setText( %seqFrom ); // Allow the user to browse for an external source of animation data - getLoadFilename( "DSQ Files|*.dsq|COLLADA Files|*.dae|Google Earth Files|*.kmz", %this @ ".onBrowseSelect", %this.lastPath ); + getLoadFormatFilename( %this @ ".onBrowseSelect", %this.lastPath ); } else { @@ -2862,7 +2862,7 @@ function ShapeEdDetails::onAddMeshFromFile( %this, %path ) { if ( %path $= "" ) { - getLoadFilename( "DTS Files|*.dts|COLLADA Files|*.dae|Google Earth Files|*.kmz", %this @ ".onAddMeshFromFile", %this.lastPath ); + getLoadFormatFilename( %this @ ".onAddMeshFromFile", %this.lastPath ); return; } @@ -3291,7 +3291,7 @@ function ShapeEdMountShapeMenu::onSelect( %this, %id, %text ) if ( %text $= "Browse..." ) { // Allow the user to browse for an external model file - getLoadFilename( "DTS Files|*.dts|COLLADA Files|*.dae|Google Earth Files|*.kmz", %this @ ".onBrowseSelect", %this.lastPath ); + getLoadFormatFilename( %this @ ".onBrowseSelect", %this.lastPath ); } else { diff --git a/Templates/Empty/game/tools/worldEditor/gui/ProceduralTerrainPainterGui.gui b/Templates/Empty/game/tools/worldEditor/gui/ProceduralTerrainPainterGui.gui index d2eccdbb7..d25f848f0 100644 --- a/Templates/Empty/game/tools/worldEditor/gui/ProceduralTerrainPainterGui.gui +++ b/Templates/Empty/game/tools/worldEditor/gui/ProceduralTerrainPainterGui.gui @@ -20,7 +20,7 @@ HorizSizing = "right"; VertSizing = "bottom"; Position = "285 83"; - Extent = "175 209"; + Extent = "175 233"; MinExtent = "8 2"; canSave = "1"; Visible = "1"; @@ -52,7 +52,7 @@ Profile = "ToolsGuiButtonProfile"; HorizSizing = "right"; VertSizing = "bottom"; - Position = "19 164"; + Position = "19 193"; Extent = "140 30"; MinExtent = "8 2"; canSave = "1"; @@ -305,6 +305,83 @@ sinkAllKeyEvents = "0"; passwordMask = "*"; }; + + + new GuiTextCtrl() { + text = "COVERAGE"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "10 165"; + extent = "55 13"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "1"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "97 162"; + extent = "66 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + variable = "$TPPCoverage"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "%"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "77 164"; + extent = "11 14"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; }; }; //--- OBJECT WRITE END --- @@ -313,6 +390,7 @@ $TPPHeightMin = -10000; $TPPHeightMax = 10000; $TPPSlopeMin = 0; $TPPSlopeMax = 90; +$TPPCoverage = 100; function autoLayers() { @@ -322,5 +400,5 @@ function autoLayers() function generateProceduralTerrainMask() { Canvas.popDialog(ProceduralTerrainPainterGui); - ETerrainEditor.autoMaterialLayer($TPPHeightMin, $TPPHeightMax, $TPPSlopeMin, $TPPSlopeMax); + ETerrainEditor.autoMaterialLayer($TPPHeightMin, $TPPHeightMax, $TPPSlopeMin, $TPPSlopeMax, $TPPCoverage); } diff --git a/Templates/Empty/game/tools/worldEditor/main.cs b/Templates/Empty/game/tools/worldEditor/main.cs index 1b20201e0..773dbac17 100644 --- a/Templates/Empty/game/tools/worldEditor/main.cs +++ b/Templates/Empty/game/tools/worldEditor/main.cs @@ -29,7 +29,7 @@ function initializeWorldEditor() exec("./scripts/cursors.ed.cs"); exec("./gui/guiCreateNewTerrainGui.gui" ); - exec("./gui/genericPromptDialog.ed.gui" ); + exec("./gui/GenericPromptDialog.ed.gui" ); exec("./gui/guiTerrainImportGui.gui" ); exec("./gui/guiTerrainExportGui.gui" ); exec("./gui/EditorGui.ed.gui"); diff --git a/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs b/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs index 2e0a3165c..d63542d67 100644 --- a/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs +++ b/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs @@ -324,13 +324,13 @@ function EWCreatorWindow::navigate( %this, %address ) if ( %this.tab $= "Meshes" ) { - %fullPath = findFirstFileMultiExpr( "*.dts" TAB "*.dae" TAB "*.kmz" TAB "*.dif" ); + %fullPath = findFirstFileMultiExpr( getFormatExtensions() ); while ( %fullPath !$= "" ) { if (strstr(%fullPath, "cached.dts") != -1) { - %fullPath = findNextFileMultiExpr( "*.dts" TAB "*.dae" TAB "*.kmz" TAB "*.dif" ); + %fullPath = findNextFileMultiExpr( getFormatExtensions() ); continue; } @@ -338,7 +338,7 @@ function EWCreatorWindow::navigate( %this, %address ) %splitPath = strreplace( %fullPath, "/", " " ); if( getWord(%splitPath, 0) $= "tools" ) { - %fullPath = findNextFileMultiExpr( "*.dts" TAB "*.dae" TAB "*.kmz" TAB "*.dif" ); + %fullPath = findNextFileMultiExpr( getFormatExtensions() ); continue; } @@ -396,7 +396,7 @@ function EWCreatorWindow::navigate( %this, %address ) } } - %fullPath = findNextFileMultiExpr( "*.dts" TAB "*.dae" TAB "*.kmz" TAB "*.dif" ); + %fullPath = findNextFileMultiExpr( getFormatExtensions() ); } } diff --git a/Templates/Full/buildFiles/config/torque3D_dedicated.conf b/Templates/Full/buildFiles/config/torque3D_dedicated.conf index eecf2fc4f..ec0b6281d 100644 --- a/Templates/Full/buildFiles/config/torque3D_dedicated.conf +++ b/Templates/Full/buildFiles/config/torque3D_dedicated.conf @@ -60,14 +60,14 @@ addProjectDependency( 'libbullet' ); } - if ( Generator::$platform == "mac" ) + if ( T3D_Generator::$platform == "mac" ) { addProjectDefine( '__MACOSX__' ); addProjectDefine( 'LTM_DESC' ); } - if (Generator::$platform == "win32") + if (T3D_Generator::$platform == "win32") { setProjectModuleDefinitionFile('../../' . getLibSrcDir() . 'Torque3D/msvc/torque3d.def'); diff --git a/Templates/Full/game/art/datablocks/weapons/grenadefx.cs b/Templates/Full/game/art/datablocks/weapons/grenadefx.cs index 473cd81b8..2db50a5bd 100644 --- a/Templates/Full/game/art/datablocks/weapons/grenadefx.cs +++ b/Templates/Full/game/art/datablocks/weapons/grenadefx.cs @@ -893,7 +893,7 @@ datablock ProjectileData(GrenadeLauncherProjectile) explosion = GrenadeLauncherExplosion; waterExplosion = GrenadeLauncherWaterExplosion; - decal = ExpBlastDecal; + decal = ScorchRXDecal; splash = GrenadeSplash; particleEmitter = GrenadeProjSmokeTrailEmitter; diff --git a/Templates/Full/game/art/environment/materials.cs b/Templates/Full/game/art/environment/materials.cs new file mode 100644 index 000000000..2b5a81e77 --- /dev/null +++ b/Templates/Full/game/art/environment/materials.cs @@ -0,0 +1,48 @@ +singleton Material(grass1) +{ + mapTo = "grass1.png"; + diffuseMap[0] = "art/environment/grass1.png"; + translucent = true; + materialTag0 = "Foliage"; + alphaTest = "1"; + alphaRef = "80"; +}; + +singleton Material(grass2) +{ + mapTo = "grass2.png"; + diffuseMap[0] = "art/environment/grass2.png"; + translucent = "0"; + materialTag0 = "Foliage"; + alphaTest = "1"; + alphaRef = "80"; +}; + +singleton Material(grass3) +{ + mapTo = "grass3.png"; + diffuseMap[0] = "art/environment/grass3.png"; + translucent = "0"; + materialTag0 = "Foliage"; + alphaTest = "1"; + alphaRef = "80"; +}; + +singleton Material(plant1) +{ + mapTo = "plant1.png"; + diffuseMap[0] = "art/environment/plant1.png"; + materialTag0 = "Foliage"; + alphaTest = "1"; + alphaRef = "80"; +}; + +singleton Material(plant2) +{ + mapTo = "plant2.png"; + diffuseMap[0] = "art/environment/plant2.png"; + translucent = true; + materialTag0 = "Foliage"; + alphaTest = "1"; + alphaRef = "80"; +}; diff --git a/Templates/Full/game/art/shapes/actors/Soldier/soldier_rigged.cs b/Templates/Full/game/art/shapes/actors/Soldier/soldier_rigged.cs index f15fe0265..e5f251e0c 100644 --- a/Templates/Full/game/art/shapes/actors/Soldier/soldier_rigged.cs +++ b/Templates/Full/game/art/shapes/actors/Soldier/soldier_rigged.cs @@ -27,7 +27,6 @@ singleton TSShapeConstructor(SoldierDAE) unit = "1.0"; upAxis = "DEFAULT"; lodType = "TrailingNumber"; - matNamePrefix = ""; ignoreNodeScale = "0"; adjustCenter = "0"; adjustFloor = "0"; @@ -36,266 +35,211 @@ singleton TSShapeConstructor(SoldierDAE) function SoldierDAE::onLoad(%this) { - // BEGIN: Default (Lurker Rifle) Sequences - %this.addSequence( "./Anims/PlayerAnim_Lurker_Back.dae Back", "Back", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Celebrate_01.dae Celebrate_01", "Celebrate_01", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Crouch_Backward.dae Crouch_Backward", "Crouch_Backward", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Crouch_Forward.dae Crouch_Forward", "Crouch_Forward", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Crouch_Side.dae Crouch_Side", "Crouch_Side", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Crouch_Root.dae Crouch_Root", "Crouch_Root", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Death1.dae Death1", "Death1", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Death2.dae Death2", "Death2", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Fall.dae Fall", "Fall", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Head.dae Head", "Head", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Jump.dae Jump", "Jump", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Land.dae Land", "Land", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Look.dae Look", "Look", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Reload.dae Reload", "Reload", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Root.dae Root", "Root", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Run.dae Run", "Run", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Side.dae Side", "Side", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Sitting.dae Sitting", "Sitting", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Swim_Backward.dae Swim_Backward", "Swim_Backward", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Swim_Forward.dae Swim_Forward", "Swim_Forward", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Swim_Root.dae Swim_Root", "Swim_Root", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Swim_Left.dae Swim_Left", "Swim_Left", 0, -1); - %this.addSequence( "./Anims/PlayerAnim_Lurker_Swim_Right.dae Swim_Right", "Swim_Right", 0, -1); - - %this.setSequenceCyclic( "Back", true); - %this.setSequenceCyclic( "Celebrate_01", false); - %this.setSequenceCyclic( "Crouch_Backward", true); - %this.setSequenceCyclic( "Crouch_Forward", true); - %this.setSequenceCyclic( "Crouch_Side", true); - %this.setSequenceCyclic( "Crouch_Root", true); - %this.setSequenceCyclic( "Death1", false); - %this.setSequenceCyclic( "Death2", false); - %this.setSequenceCyclic( "Fall", true); - %this.setSequenceCyclic( "Head", false); - %this.setSequenceCyclic( "Jump", false); - %this.setSequenceCyclic( "Land", false); - %this.setSequenceCyclic( "Look", false); - %this.setSequenceCyclic( "Reload", false); - %this.setSequenceCyclic( "Root", true); - %this.setSequenceCyclic( "Run", true); - %this.setSequenceCyclic( "Side", true); - %this.setSequenceCyclic( "Sitting", true); - %this.setSequenceCyclic( "Swim_Backward", true); - %this.setSequenceCyclic( "Swim_Forward", true); - %this.setSequenceCyclic( "Swim_Root", true); - %this.setSequenceCyclic( "Swim_Left", true); - %this.setSequenceCyclic( "Swim_Right", true); - - %this.setSequenceBlend( "Head", "1", "Root", "0"); - %this.setSequenceBlend( "Look", "1", "Root", "0"); - %this.setSequenceBlend( "Reload", "1", "Root", "0"); - - %this.setSequenceGroundSpeed( "Back", "0 -3.6 0"); - %this.setSequenceGroundSpeed( "Run", "0 5.0 0"); - %this.setSequenceGroundSpeed( "Side", "-3.6 0 0"); - %this.setSequenceGroundSpeed( "Swim_Backward", "0 -1 0"); - %this.setSequenceGroundSpeed( "Swim_Forward", "0 1 0"); - %this.setSequenceGroundSpeed( "Swim_Left", "-1 0 0"); - %this.setSequenceGroundSpeed( "Swim_Right", "1 0 0"); - %this.setSequenceGroundSpeed( "Crouch_Backward", "0 -2 0"); - %this.setSequenceGroundSpeed( "Crouch_Forward", "0 2 0"); - %this.setSequenceGroundSpeed( "Crouch_Side", "1 0 0"); - // END: Lurker Rifle Sequences - - // BEGIN: Ryder Pistol sequences - // Extracted from Ryder - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Back.dae Back", "Pistol_Back", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Crouch_Backward.dae Crouch_Backward", "Pistol_Crouch_Backward", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Crouch_Forward.dae Crouch_Forward", "Pistol_Crouch_Forward", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Crouch_Side.dae Crouch_Side", "Pistol_Crouch_Side", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Crouch_Root.dae Crouch_Root", "Pistol_Crouch_Root", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Death1.dae Death1", "Pistol_Death1", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Death2.dae Death2", "Pistol_Death2", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Fall.dae Fall", "Pistol_Fall", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Head.dae Head", "Pistol_Head", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Jump.dae Jump", "Pistol_Jump", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Land.dae Land", "Pistol_Land", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Look.dae Look", "Pistol_Look", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Reload.dae Reload", "Pistol_Reload", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Root.dae Root", "Pistol_Root", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Run.dae Run", "Pistol_Run", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Side.dae Side", "Pistol_Side", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Sitting.dae Sitting", "Pistol_Sitting", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Swim_Backward.dae Swim_Backward", "Pistol_Swim_Backward", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Swim_Forward.dae Swim_Forward", "Pistol_Swim_Forward", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Swim_Root.dae Swim_Root", "Pistol_Swim_Root", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Swim_Left.dae Swim_Left", "Pistol_Swim_Left", 0, -1); - %this.addSequence( "art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Swim_Right.dae Swim_Right", "Pistol_Swim_Right", 0, -1); - - %this.setSequenceCyclic( "Pistol_Back", true); - %this.setSequenceCyclic( "Pistol_Crouch_Backward", true); - %this.setSequenceCyclic( "Pistol_Crouch_Forward", true); - %this.setSequenceCyclic( "Pistol_Crouch_Side", true); - %this.setSequenceCyclic( "Pistol_Crouch_Root", true); - %this.setSequenceCyclic( "Pistol_Death1", false); - %this.setSequenceCyclic( "Pistol_Death2", false); - %this.setSequenceCyclic( "Pistol_Fall", true); - %this.setSequenceCyclic( "Pistol_Head", false); - %this.setSequenceCyclic( "Pistol_Jump", false); - %this.setSequenceCyclic( "Pistol_Land", false); - %this.setSequenceCyclic( "Pistol_Look", false); - %this.setSequenceCyclic( "Pistol_Reload", false); - %this.setSequenceCyclic( "Pistol_Root", true); - %this.setSequenceCyclic( "Pistol_Run", true); - %this.setSequenceCyclic( "Pistol_Side", true); - %this.setSequenceCyclic( "Pistol_Sitting", true); - %this.setSequenceCyclic( "Pistol_Swim_Backward", true); - %this.setSequenceCyclic( "Pistol_Swim_Forward", true); - %this.setSequenceCyclic( "Pistol_Swim_Root", true); - %this.setSequenceCyclic( "Pistol_Swim_Left", true); - %this.setSequenceCyclic( "Pistol_Swim_Right", true); - - %this.setSequenceBlend( "Pistol_Head", "1", "Pistol_Root", "0"); - %this.setSequenceBlend( "Pistol_Look", "1", "Pistol_Root", "0"); - %this.setSequenceBlend( "Pistol_Reload", "1", "Pistol_Root", "0"); - - %this.setSequenceGroundSpeed( "Pistol_Back", "0 -3.6 0"); - %this.setSequenceGroundSpeed( "Pistol_Run", "0 5.0 0"); - %this.setSequenceGroundSpeed( "Pistol_Side", "3.6 0 0"); - %this.setSequenceGroundSpeed( "Pistol_Swim_Backward", "0 -1 0"); - %this.setSequenceGroundSpeed( "Pistol_Swim_Forward", "0 1 0"); - %this.setSequenceGroundSpeed( "Pistol_Swim_Left", "-1 0 0"); - %this.setSequenceGroundSpeed( "Pistol_Swim_Right", "1 0 0"); - %this.setSequenceGroundSpeed( "Pistol_Crouch_Backward", "0 -2 0"); - %this.setSequenceGroundSpeed( "Pistol_Crouch_Forward", "0 2 0"); - %this.setSequenceGroundSpeed( "Pistol_Crouch_Side", "1 0 0"); - // END: General pistol sequences - - // BEGIN: ProxMine Sequences - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Back.dae Back", "ProxMine_Back", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Crouch_Backward.dae Crouch_Backward", "ProxMine_Crouch_Backward", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Crouch_Forward.dae Crouch_Forward", "ProxMine_Crouch_Forward", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Crouch_Side.dae Crouch_Side", "ProxMine_Crouch_Side", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Crouch_Root.dae Crouch_Root", "ProxMine_Crouch_Root", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Death1.dae Death1", "ProxMine_Death1", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Death2.dae Death2", "ProxMine_Death2", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Fall.dae Fall", "ProxMine_Fall", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Head.dae Head", "ProxMine_Head", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Jump.dae Jump", "ProxMine_Jump", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Land.dae Land", "ProxMine_Land", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Look.dae Look", "ProxMine_Look", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Reload.dae Reload", "ProxMine_Reload", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Fire.dae Fire", "ProxMine_Fire", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Fire_Release.dae Fire_Release", "ProxMine_Fire_Release", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Root.dae Root", "ProxMine_Root", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Run.dae Run", "ProxMine_Run", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Side.dae Side", "ProxMine_Side", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Sitting.dae Sitting", "ProxMine_Sitting", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Swim_Backward.dae Swim_Backward", "ProxMine_Swim_Backward", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Swim_Forward.dae Swim_Forward", "ProxMine_Swim_Forward", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Swim_Root.dae Swim_Root", "ProxMine_Swim_Root", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Swim_Left.dae Swim_Left", "ProxMine_Swim_Left", 0, -1); - %this.addSequence( "art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Swim_Right.dae Swim_Right", "ProxMine_Swim_Right", 0, -1); - - %this.setSequenceCyclic( "ProxMine_Back", true); - %this.setSequenceCyclic( "ProxMine_Crouch_Backward", true); - %this.setSequenceCyclic( "ProxMine_Crouch_Forward", true); - %this.setSequenceCyclic( "ProxMine_Crouch_Side", true); - %this.setSequenceCyclic( "ProxMine_Crouch_Root", true); - %this.setSequenceCyclic( "ProxMine_Death1", false); - %this.setSequenceCyclic( "ProxMine_Death2", false); - %this.setSequenceCyclic( "ProxMine_Fall", true); - %this.setSequenceCyclic( "ProxMine_Head", false); - %this.setSequenceCyclic( "ProxMine_Jump", false); - %this.setSequenceCyclic( "ProxMine_Land", false); - %this.setSequenceCyclic( "ProxMine_Look", false); - %this.setSequenceCyclic( "ProxMine_Reload", false); - %this.setSequenceCyclic( "ProxMine_Fire", false); - %this.setSequenceCyclic( "ProxMine_Fire_Release", false); - %this.setSequenceCyclic( "ProxMine_Root", true); - %this.setSequenceCyclic( "ProxMine_Run", true); - %this.setSequenceCyclic( "ProxMine_Side", true); - %this.setSequenceCyclic( "ProxMine_Sitting", true); - %this.setSequenceCyclic( "ProxMine_Swim_Backward", true); - %this.setSequenceCyclic( "ProxMine_Swim_Forward", true); - %this.setSequenceCyclic( "ProxMine_Swim_Root", true); - %this.setSequenceCyclic( "ProxMine_Swim_Left", true); - %this.setSequenceCyclic( "ProxMine_Swim_Right", true); - - %this.setSequenceBlend( "ProxMine_Head", "1", "ProxMine_Root", "0"); - %this.setSequenceBlend( "ProxMine_Look", "1", "ProxMine_Root", "0"); - %this.setSequenceBlend( "ProxMine_Reload", "1", "ProxMine_Root", "0"); - %this.setSequenceBlend( "ProxMine_Fire", "1", "ProxMine_Root", "0"); - %this.setSequenceBlend( "ProxMine_Fire_Release", "1", "ProxMine_Root", "0"); - - %this.setSequenceGroundSpeed( "ProxMine_Back", "0 -3.6 0"); - %this.setSequenceGroundSpeed( "ProxMine_Run", "0 5.0 0"); - %this.setSequenceGroundSpeed( "ProxMine_Side", "3.6 0 0"); - %this.setSequenceGroundSpeed( "ProxMine_Swim_Backward", "0 -1 0"); - %this.setSequenceGroundSpeed( "ProxMine_Swim_Forward", "0 1 0"); - %this.setSequenceGroundSpeed( "ProxMine_Swim_Left", "-1 0 0"); - %this.setSequenceGroundSpeed( "ProxMine_Swim_Right", "1 0 0"); - %this.setSequenceGroundSpeed( "ProxMine_Crouch_Backward", "0 -2 0"); - %this.setSequenceGroundSpeed( "ProxMine_Crouch_Forward", "0 2 0"); - %this.setSequenceGroundSpeed( "ProxMine_Crouch_Side", "1 0 0"); - // END: ProxMine Sequences - - // BEGIN: Turret Sequences - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Back.dae Back", "Turret_Back", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Crouch_Root.dae Crouch_Root", "Turret_Crouch_Root", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Crouch_Backward.dae Crouch_Backward", "Turret_Crouch_Backward", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Crouch_Forward.dae Crouch_Forward", "Turret_Crouch_Forward", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Crouch_Side.dae Crouch_Side", "Turret_Crouch_Side", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Death1.dae Death1", "Turret_Death1", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Death2.dae Death2", "Turret_Death2", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Fall.dae Fall", "Turret_Fall", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Run.dae Run", "Turret_Run", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Jump.dae Jump", "Turret_Jump", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Land.dae Land", "Turret_Land", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Look.dae Look", "Turret_Look", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Head.dae Head", "Turret_Head", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Recoil.dae Recoil", "Turret_Recoil", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Fire_Release.dae Fire_Release", "Turret_Fire_Release", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Root.dae Root", "Turret_Root", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Side.dae Side", "Turret_Side", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Sitting.dae Sitting", "Turret_Sitting", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Swim_Backward.dae Swim_Backward", "Turret_Swim_Backward", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Swim_Forward.dae Swim_Forward", "Turret_Swim_Forward", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Swim_Root.dae Swim_Root", "Turret_Swim_Root", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Swim_Left.dae Swim_Left", "Turret_Swim_Left", 0, -1); - %this.addSequence( "art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Swim_Right.dae Swim_Right", "Turret_Swim_Right", 0, -1); - - %this.setSequenceCyclic( "Turret_Back", true); - %this.setSequenceCyclic( "Turret_Crouch_Backward", true); - %this.setSequenceCyclic( "Turret_Crouch_Forward", true); - %this.setSequenceCyclic( "Turret_Crouch_Side", true); - %this.setSequenceCyclic( "Turret_Death1", false); - %this.setSequenceCyclic( "Turret_Death2", false); - %this.setSequenceCyclic( "Turret_Fall", true); - %this.setSequenceCyclic( "Turret_Run", true); - %this.setSequenceCyclic( "Turret_Jump", false); - %this.setSequenceCyclic( "Turret_Land", false); - %this.setSequenceCyclic( "Turret_Look", false); - %this.setSequenceCyclic( "Turret_Head", false); - %this.setSequenceCyclic( "Turret_Recoil", false); - %this.setSequenceCyclic( "Turret_Fire_Release", false); - %this.setSequenceCyclic( "Turret_Root", true); - %this.setSequenceCyclic( "Turret_Side", true); - %this.setSequenceCyclic( "Turret_Sitting", true); - %this.setSequenceCyclic( "Turret_Swim_Backward", true); - %this.setSequenceCyclic( "Turret_Swim_Forward", true); - %this.setSequenceCyclic( "Turret_Swim_Root", true); - %this.setSequenceCyclic( "Turret_Swim_Left", true); - %this.setSequenceCyclic( "Turret_Swim_Right", true); - - %this.setSequenceBlend( "Turret_Head", "1", "Turret_Root", "0"); - %this.setSequenceBlend( "Turret_Look", "1", "Turret_Root", "0"); - %this.setSequenceBlend( "Turret_Recoil", "1", "Turret_Root", "0"); - %this.setSequenceBlend( "Turret_Fire_Release", "1", "Turret_Root", "0"); - - %this.setSequenceGroundSpeed( "Turret_Back", "0 -3.6 0"); - %this.setSequenceGroundSpeed( "Turret_Run", "0 5.0 0"); - %this.setSequenceGroundSpeed( "Turret_Side", "3.6 0 0"); - %this.setSequenceGroundSpeed( "Turret_Swim_Backward", "0 -1 0"); - %this.setSequenceGroundSpeed( "Turret_Swim_Forward", "0 1 0"); - %this.setSequenceGroundSpeed( "Turret_Swim_Left", "-1 0 0"); - %this.setSequenceGroundSpeed( "Turret_Swim_Right", "1 0 0"); - %this.setSequenceGroundSpeed( "Turret_Crouch_Backward", "0 -2 0"); - %this.setSequenceGroundSpeed( "Turret_Crouch_Forward", "0 2 0"); - %this.setSequenceGroundSpeed( "Turret_Crouch_Side", "1 0 0"); - // END: Turret Sequences + %this.addSequence("./Anims/PlayerAnim_Lurker_Back.dae Back", "Back", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Celebrate_01.dae Celebrate_01", "Celebrate_01", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Crouch_Backward.dae Crouch_Backward", "Crouch_Backward", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Crouch_Forward.dae Crouch_Forward", "Crouch_Forward", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Crouch_Side.dae Crouch_Side", "Crouch_Side", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Crouch_Root.dae Crouch_Root", "Crouch_Root", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Death1.dae Death1", "Death1", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Death2.dae Death2", "Death2", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Fall.dae Fall", "Fall", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Head.dae Head", "Head", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Jump.dae Jump", "Jump", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Land.dae Land", "Land", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Look.dae Look", "Look", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Reload.dae Reload", "Reload", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Root.dae Root", "Root", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Run.dae Run", "Run", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Side.dae Side", "Side", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Sitting.dae Sitting", "Sitting", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Swim_Backward.dae Swim_Backward", "Swim_Backward", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Swim_Forward.dae Swim_Forward", "Swim_Forward", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Swim_Root.dae Swim_Root", "Swim_Root", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Swim_Left.dae Swim_Left", "Swim_Left", "0", "-1", "1", "0"); + %this.addSequence("./Anims/PlayerAnim_Lurker_Swim_Right.dae Swim_Right", "Swim_Right", "0", "-1", "1", "0"); + %this.setSequenceBlend("Head", "1", "Root", "0"); + %this.setSequenceBlend("Look", "1", "Root", "0"); + %this.setSequenceBlend("Reload", "1", "Root", "0"); + %this.setSequenceGroundSpeed("Back", "0 -3.6 0", "0 0 0"); + %this.setSequenceGroundSpeed("Run", "0 5 0", "0 0 0"); + %this.setSequenceGroundSpeed("Side", "-3.6 0 0", "0 0 0"); + %this.setSequenceGroundSpeed("Swim_Backward", "0 -1 0", "0 0 0"); + %this.setSequenceGroundSpeed("Swim_Forward", "0 1 0", "0 0 0"); + %this.setSequenceGroundSpeed("Swim_Left", "-1 0 0", "0 0 0"); + %this.setSequenceGroundSpeed("Swim_Right", "1 0 0", "0 0 0"); + %this.setSequenceGroundSpeed("Crouch_Backward", "0 -2 0", "0 0 0"); + %this.setSequenceGroundSpeed("Crouch_Forward", "0 2 0", "0 0 0"); + %this.setSequenceGroundSpeed("Crouch_Side", "1 0 0", "0 0 0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Back.dae Back", "Pistol_Back", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Crouch_Backward.dae Crouch_Backward", "Pistol_Crouch_Backward", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Crouch_Forward.dae Crouch_Forward", "Pistol_Crouch_Forward", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Crouch_Side.dae Crouch_Side", "Pistol_Crouch_Side", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Crouch_Root.dae Crouch_Root", "Pistol_Crouch_Root", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Death1.dae Death1", "Pistol_Death1", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Death2.dae Death2", "Pistol_Death2", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Fall.dae Fall", "Pistol_Fall", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Head.dae Head", "Pistol_Head", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Jump.dae Jump", "Pistol_Jump", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Land.dae Land", "Pistol_Land", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Look.dae Look", "Pistol_Look", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Reload.dae Reload", "Pistol_Reload", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Root.dae Root", "Pistol_Root", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Run.dae Run", "Pistol_Run", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Side.dae Side", "Pistol_Side", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Sitting.dae Sitting", "Pistol_Sitting", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Swim_Backward.dae Swim_Backward", "Pistol_Swim_Backward", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Swim_Forward.dae Swim_Forward", "Pistol_Swim_Forward", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Swim_Root.dae Swim_Root", "Pistol_Swim_Root", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Swim_Left.dae Swim_Left", "Pistol_Swim_Left", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Swim_Right.dae Swim_Right", "Pistol_Swim_Right", "0", "-1", "1", "0"); + %this.setSequenceCyclic("Pistol_Fall", "1"); + %this.setSequenceCyclic("Pistol_Sitting", "1"); + %this.setSequenceBlend("Pistol_Head", "1", "Pistol_Root", "0"); + %this.setSequenceBlend("Pistol_Look", "1", "Pistol_Root", "0"); + %this.setSequenceBlend("Pistol_Reload", "1", "Pistol_Root", "0"); + %this.setSequenceGroundSpeed("Pistol_Back", "0 -3.6 0", "0 0 0"); + %this.setSequenceGroundSpeed("Pistol_Run", "0 5 0", "0 0 0"); + %this.setSequenceGroundSpeed("Pistol_Side", "3.6 0 0", "0 0 0"); + %this.setSequenceGroundSpeed("Pistol_Swim_Backward", "0 -1 0", "0 0 0"); + %this.setSequenceGroundSpeed("Pistol_Swim_Forward", "0 1 0", "0 0 0"); + %this.setSequenceGroundSpeed("Pistol_Swim_Left", "-1 0 0", "0 0 0"); + %this.setSequenceGroundSpeed("Pistol_Swim_Right", "1 0 0", "0 0 0"); + %this.setSequenceGroundSpeed("Pistol_Crouch_Backward", "0 -2 0", "0 0 0"); + %this.setSequenceGroundSpeed("Pistol_Crouch_Forward", "0 2 0", "0 0 0"); + %this.setSequenceGroundSpeed("Pistol_Crouch_Side", "1 0 0", "0 0 0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Back.dae Back", "ProxMine_Back", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Crouch_Backward.dae Crouch_Backward", "ProxMine_Crouch_Backward", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Crouch_Forward.dae Crouch_Forward", "ProxMine_Crouch_Forward", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Crouch_Side.dae Crouch_Side", "ProxMine_Crouch_Side", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Crouch_Root.dae Crouch_Root", "ProxMine_Crouch_Root", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Death1.dae Death1", "ProxMine_Death1", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Death2.dae Death2", "ProxMine_Death2", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Fall.dae Fall", "ProxMine_Fall", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Head.dae Head", "ProxMine_Head", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Jump.dae Jump", "ProxMine_Jump", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Land.dae Land", "ProxMine_Land", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Look.dae Look", "ProxMine_Look", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Reload.dae Reload", "ProxMine_Reload", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Fire.dae Fire", "ProxMine_Fire", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Fire_Release.dae Fire_Release", "ProxMine_Fire_Release", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Root.dae Root", "ProxMine_Root", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Run.dae Run", "ProxMine_Run", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Side.dae Side", "ProxMine_Side", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Sitting.dae Sitting", "ProxMine_Sitting", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Swim_Backward.dae Swim_Backward", "ProxMine_Swim_Backward", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Swim_Forward.dae Swim_Forward", "ProxMine_Swim_Forward", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Swim_Root.dae Swim_Root", "ProxMine_Swim_Root", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Swim_Left.dae Swim_Left", "ProxMine_Swim_Left", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/ProxMine/PlayerAnims/PlayerAnim_ProxMine_Swim_Right.dae Swim_Right", "ProxMine_Swim_Right", "0", "-1", "1", "0"); + %this.setSequenceCyclic("ProxMine_Fall", "1"); + %this.setSequenceBlend("ProxMine_Head", "1", "ProxMine_Root", "0"); + %this.setSequenceBlend("ProxMine_Look", "1", "ProxMine_Root", "0"); + %this.setSequenceBlend("ProxMine_Reload", "1", "ProxMine_Root", "0"); + %this.setSequenceBlend("ProxMine_Fire", "1", "ProxMine_Root", "0"); + %this.setSequenceBlend("ProxMine_Fire_Release", "1", "ProxMine_Root", "0"); + %this.setSequenceGroundSpeed("ProxMine_Back", "0 -3.6 0", "0 0 0"); + %this.setSequenceGroundSpeed("ProxMine_Run", "0 5 0", "0 0 0"); + %this.setSequenceGroundSpeed("ProxMine_Side", "3.6 0 0", "0 0 0"); + %this.setSequenceGroundSpeed("ProxMine_Swim_Backward", "0 -1 0", "0 0 0"); + %this.setSequenceGroundSpeed("ProxMine_Swim_Forward", "0 1 0", "0 0 0"); + %this.setSequenceGroundSpeed("ProxMine_Swim_Left", "-1 0 0", "0 0 0"); + %this.setSequenceGroundSpeed("ProxMine_Swim_Right", "1 0 0", "0 0 0"); + %this.setSequenceGroundSpeed("ProxMine_Crouch_Backward", "0 -2 0", "0 0 0"); + %this.setSequenceGroundSpeed("ProxMine_Crouch_Forward", "0 2 0", "0 0 0"); + %this.setSequenceGroundSpeed("ProxMine_Crouch_Side", "1 0 0", "0 0 0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Back.dae Back", "Turret_Back", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Crouch_Root.dae Crouch_Root", "Turret_Crouch_Root", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Crouch_Backward.dae Crouch_Backward", "Turret_Crouch_Backward", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Crouch_Forward.dae Crouch_Forward", "Turret_Crouch_Forward", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Crouch_Side.dae Crouch_Side", "Turret_Crouch_Side", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Death1.dae Death1", "Turret_Death1", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Death2.dae Death2", "Turret_Death2", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Fall.dae Fall", "Turret_Fall", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Run.dae Run", "Turret_Run", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Jump.dae Jump", "Turret_Jump", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Land.dae Land", "Turret_Land", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Look.dae Look", "Turret_Look", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Head.dae Head", "Turret_Head", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Recoil.dae Recoil", "Turret_Recoil", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Fire_Release.dae Fire_Release", "Turret_Fire_Release", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Root.dae Root", "Turret_Root", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Side.dae Side", "Turret_Side", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Sitting.dae Sitting", "Turret_Sitting", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Swim_Backward.dae Swim_Backward", "Turret_Swim_Backward", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Swim_Forward.dae Swim_Forward", "Turret_Swim_Forward", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Swim_Root.dae Swim_Root", "Turret_Swim_Root", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Swim_Left.dae Swim_Left", "Turret_Swim_Left", "0", "-1", "1", "0"); + %this.addSequence("art/shapes/weapons/Turret/PlayerAnims/PlayerAnim_Turret_Swim_Right.dae Swim_Right", "Turret_Swim_Right", "0", "-1", "1", "0"); + %this.setSequenceBlend("Turret_Head", "1", "Turret_Root", "0"); + %this.setSequenceBlend("Turret_Look", "1", "Turret_Root", "0"); + %this.setSequenceBlend("Turret_Recoil", "1", "Turret_Root", "0"); + %this.setSequenceBlend("Turret_Fire_Release", "1", "Turret_Root", "0"); + %this.setSequenceGroundSpeed("Turret_Back", "0 -3.6 0", "0 0 0"); + %this.setSequenceGroundSpeed("Turret_Run", "0 5 0", "0 0 0"); + %this.setSequenceGroundSpeed("Turret_Side", "3.6 0 0", "0 0 0"); + %this.setSequenceGroundSpeed("Turret_Swim_Backward", "0 -1 0", "0 0 0"); + %this.setSequenceGroundSpeed("Turret_Swim_Forward", "0 1 0", "0 0 0"); + %this.setSequenceGroundSpeed("Turret_Swim_Left", "-1 0 0", "0 0 0"); + %this.setSequenceGroundSpeed("Turret_Swim_Right", "1 0 0", "0 0 0"); + %this.setSequenceGroundSpeed("Turret_Crouch_Backward", "0 -2 0", "0 0 0"); + %this.setSequenceGroundSpeed("Turret_Crouch_Forward", "0 2 0", "0 0 0"); + %this.setSequenceGroundSpeed("Turret_Crouch_Side", "1 0 0", "0 0 0"); + %this.addTrigger("Back", "4", "1"); + %this.addTrigger("Back", "13", "2"); + %this.addTrigger("jump", "6", "1"); + %this.addTrigger("Land", "5", "1"); + %this.addTrigger("Run", "8", "1"); + %this.addTrigger("Run", "16", "2"); + %this.addTrigger("Pistol_Back", "6", "1"); + %this.addTrigger("Pistol_Back", "12", "2"); + %this.addTrigger("Crouch_Backward", "8", "1"); + %this.addTrigger("Crouch_Backward", "19", "2"); + %this.addTrigger("Crouch_Forward", "12", "1"); + %this.addTrigger("Crouch_Forward", "24", "2"); + %this.addTrigger("Crouch_Side", "16", "1"); + %this.addTrigger("Crouch_Side", "23", "2"); + %this.addTrigger("Side", "7", "1"); + %this.addTrigger("Side", "17", "2"); + %this.addTrigger("Pistol_Crouch_Backward", "10", "1"); + %this.addTrigger("Pistol_Crouch_Backward", "24", "2"); + %this.addTrigger("Pistol_Crouch_Forward", "9", "1"); + %this.addTrigger("Pistol_Crouch_Forward", "25", "2"); + %this.addTrigger("Pistol_Crouch_Side", "8", "1"); + %this.addTrigger("Pistol_Crouch_Side", "23", "2"); + %this.addTrigger("Pistol_Jump", "5", "1"); + %this.addTrigger("Pistol_Land", "9", "1"); + %this.addTrigger("Pistol_Run", "8", "1"); + %this.addTrigger("Pistol_Run", "16", "2"); + %this.addTrigger("Pistol_Side", "8", "1"); + %this.addTrigger("Pistol_Side", "17", "2"); + %this.addTrigger("ProxMine_Back", "3", "1"); + %this.addTrigger("ProxMine_Back", "12", "2"); + %this.addTrigger("ProxMine_Crouch_Backward", "9", "1"); + %this.addTrigger("ProxMine_Crouch_Backward", "18", "2"); + %this.addTrigger("ProxMine_Crouch_Forward", "12", "1"); + %this.addTrigger("ProxMine_Crouch_Forward", "25", "2"); + %this.addTrigger("ProxMine_Crouch_Side", "12", "1"); + %this.addTrigger("ProxMine_Crouch_Side", "27", "2"); + %this.addTrigger("ProxMine_Fall", "15", "1"); + %this.addTrigger("ProxMine_Jump", "5", "1"); + %this.addTrigger("ProxMine_Land", "7", "1"); + %this.addTrigger("ProxMine_Run", "8", "1"); + %this.addTrigger("ProxMine_Run", "17", "2"); + %this.addTrigger("ProxMine_Side", "7", "1"); + %this.addTrigger("ProxMine_Side", "18", "2"); + %this.addTrigger("Turret_Back", "4", "1"); + %this.addTrigger("Turret_Back", "11", "2"); + %this.addTrigger("Turret_Crouch_Backward", "8", "1"); + %this.addTrigger("Turret_Crouch_Backward", "26", "2"); + %this.addTrigger("Turret_Crouch_Forward", "12", "1"); + %this.addTrigger("Turret_Crouch_Forward", "24", "2"); + %this.addTrigger("Turret_Crouch_Side", "13", "1"); + %this.addTrigger("Turret_Crouch_Side", "24", "2"); + %this.addTrigger("Turret_Run", "7", "1"); + %this.addTrigger("Turret_Run", "17", "2"); + %this.addTrigger("Turret_Jump", "6", "1"); + %this.addTrigger("Turret_Land", "3", "1"); + %this.addTrigger("Turret_Side", "9", "1"); + %this.addTrigger("Turret_Side", "17", "2"); } diff --git a/Templates/Full/game/art/shapes/trees/defaulttree/materials.cs b/Templates/Full/game/art/shapes/trees/defaulttree/materials.cs index ca5adadcd..f82946ccb 100644 --- a/Templates/Full/game/art/shapes/trees/defaulttree/materials.cs +++ b/Templates/Full/game/art/shapes/trees/defaulttree/materials.cs @@ -72,3 +72,11 @@ singleton Material(defaultTree_fronds_material) alphaRef = "114"; translucent = "1"; }; + +singleton Material(defaulttree_ColorEffectR27G177B88_material) +{ + mapTo = "ColorEffectR27G177B88-material"; + diffuseColor[0] = "0.105882 0.694118 0.345098 1"; + specularPower[0] = "10"; + translucentBlendOp = "None"; +}; diff --git a/Templates/Full/game/art/terrains/Outpost_0.ter b/Templates/Full/game/art/terrains/Outpost_0.ter new file mode 100644 index 000000000..5b39c9e70 Binary files /dev/null and b/Templates/Full/game/art/terrains/Outpost_0.ter differ diff --git a/Templates/Full/game/art/terrains/materials.cs b/Templates/Full/game/art/terrains/materials.cs index e49e568f0..c13ab564f 100644 --- a/Templates/Full/game/art/terrains/materials.cs +++ b/Templates/Full/game/art/terrains/materials.cs @@ -24,18 +24,18 @@ // Sample grass // ---------------------------------------------------------------------------- -singleton Material(TerrainFX_grass1) -{ - mapTo = "grass1"; - footstepSoundId = 0; - terrainMaterials = "1"; - ShowDust = "1"; - showFootprints = "1"; - materialTag0 = "Terrain"; +singleton Material(TerrainFX_grass1) +{ + mapTo = "grass1"; + footstepSoundId = 0; + terrainMaterials = "1"; + ShowDust = "1"; + showFootprints = "1"; + materialTag0 = "Terrain"; effectColor[0] = "0.42 0.42 0 1"; effectColor[1] = "0.42 0.42 0 1"; impactSoundId = "0"; -}; +}; new TerrainMaterial() { @@ -49,22 +49,47 @@ new TerrainMaterial() diffuseSize = "200"; }; -singleton Material(TerrainFX_grass1dry) -{ - mapTo = "grass1-dry"; - footstepSoundId = 0; - terrainMaterials = "1"; - ShowDust = "1"; +singleton Material(TerrainFX_grass2) +{ + mapTo = "grass2"; + footstepSoundId = 0; + terrainMaterials = "1"; + ShowDust = "1"; showFootprints = "1"; - materialTag0 = "Terrain"; - effectColor[0] = "0.63 0.55 0 1"; -}; + materialTag0 = "Terrain"; + effectColor[0] = "0.42 0.42 0 1"; + effectColor[1] = "0.42 0.42 0 1"; + impactSoundId = "0"; +}; new TerrainMaterial() { - internalName = "grass1-dry"; - diffuseMap = "art/terrains/Example/grass1-dry"; - detailMap = "art/terrains/Example/grass1-dry_d"; + internalName = "grass2"; + diffuseMap = "art/terrains/Example/grass2"; + detailMap = "art/terrains/Example/grass2_d"; + detailSize = "10"; + isManaged = "1"; + detailBrightness = "1"; + Enabled = "1"; + diffuseSize = "200"; +}; + +singleton Material(TerrainFX_grass1dry) +{ + mapTo = "grass1_dry"; + footstepSoundId = 0; + terrainMaterials = "1"; + ShowDust = "1"; + showFootprints = "1"; + materialTag0 = "Terrain"; + effectColor[0] = "0.63 0.55 0 1"; +}; + +new TerrainMaterial() +{ + internalName = "grass1_dry"; + diffuseMap = "art/terrains/Example/grass1_dry"; + detailMap = "art/terrains/Example/grass1_dry_d"; detailSize = "10"; detailDistance = "100"; isManaged = "1"; @@ -74,17 +99,16 @@ new TerrainMaterial() detailStrength = "2"; }; -singleton Material(TerrainFX_dirt_grass) -{ - mapTo = "dirt_grass"; - footstepSoundId = 0; - terrainMaterials = "1"; - ShowDust = "1"; +singleton Material(TerrainFX_dirt_grass) +{ + mapTo = "dirt_grass"; + footstepSoundId = 0; + terrainMaterials = "1"; + ShowDust = "1"; showFootprints = "1"; - materialTag0 = "Terrain"; + materialTag0 = "Terrain"; effectColor[0] = "0.63 0.55 0 1"; - effectColor[1] = "0.63 0.55 0 0"; -}; +}; new TerrainMaterial() { @@ -103,18 +127,18 @@ new TerrainMaterial() // Sample rock // ---------------------------------------------------------------------------- -singleton Material(TerrainFX_rocktest) -{ - mapTo = "rocktest"; - footstepSoundId = "1"; - terrainMaterials = "1"; - ShowDust = "1"; - showFootprints = "1"; - materialTag0 = "Terrain"; +singleton Material(TerrainFX_rocktest) +{ + mapTo = "rocktest"; + footstepSoundId = "1"; + terrainMaterials = "1"; + ShowDust = "1"; + showFootprints = "1"; + materialTag0 = "Terrain"; impactSoundId = "1"; effectColor[0] = "0.25 0.25 0.25 1"; effectColor[1] = "0.25 0.25 0.25 0"; -}; +}; new TerrainMaterial() { @@ -129,22 +153,52 @@ new TerrainMaterial() diffuseSize = "400"; }; +// ---------------------------------------------------------------------------- +// Sample rock +// ---------------------------------------------------------------------------- + +singleton Material(TerrainFX_stone) +{ + mapTo = "stone"; + footstepSoundId = "1"; + terrainMaterials = "1"; + ShowDust = "1"; + showFootprints = "1"; + materialTag0 = "Terrain"; + impactSoundId = "1"; + effectColor[0] = "0.25 0.25 0.25 1"; + effectColor[1] = "0.25 0.25 0.25 0"; +}; + +new TerrainMaterial() +{ + internalName = "stone"; + diffuseMap = "art/terrains/Example/stone"; + detailMap = "art/terrains/Example/stone_d"; + detailSize = "10"; + detailDistance = "100"; + isManaged = "1"; + detailBrightness = "1"; + Enabled = "1"; + diffuseSize = "400"; + useSideProjection = "0"; +}; // ---------------------------------------------------------------------------- // Sample sand // ---------------------------------------------------------------------------- -singleton Material(TerrainFX_sand) -{ - mapTo = "sand"; - footstepSoundId = "3"; - terrainMaterials = "1"; - ShowDust = "1"; - showFootprints = "1"; - materialTag0 = "Terrain"; +singleton Material(TerrainFX_sand) +{ + mapTo = "sand"; + footstepSoundId = "3"; + terrainMaterials = "1"; + ShowDust = "1"; + showFootprints = "1"; + materialTag0 = "Terrain"; specularPower[0] = "1"; effectColor[0] = "0.84 0.71 0.5 1"; effectColor[1] = "0.84 0.71 0.5 0.349"; -}; +}; new TerrainMaterial() { diff --git a/Templates/Full/game/core/scripts/gui/messageBoxes/messageBox.ed.cs b/Templates/Full/game/core/scripts/gui/messageBoxes/messageBox.ed.cs index d778ae7ee..7c970c341 100644 --- a/Templates/Full/game/core/scripts/gui/messageBoxes/messageBox.ed.cs +++ b/Templates/Full/game/core/scripts/gui/messageBoxes/messageBox.ed.cs @@ -42,8 +42,8 @@ if( isObject( IODropdownDlg ) ) exec("./messageBoxOk.ed.gui"); exec("./messageBoxYesNo.ed.gui"); exec("./messageBoxYesNoCancel.ed.gui"); -exec("./messageBoxOKCancel.ed.gui"); -exec("./messageBoxOKCancelDetailsDlg.ed.gui"); +exec("./messageBoxOkCancel.ed.gui"); +exec("./MessageBoxOKCancelDetailsDlg.ed.gui"); exec("./messagePopup.ed.gui"); exec("./IODropdownDlg.ed.gui"); diff --git a/Templates/Full/game/levels/Outpost.forest b/Templates/Full/game/levels/Outpost.forest new file mode 100644 index 000000000..3e61d4674 Binary files /dev/null and b/Templates/Full/game/levels/Outpost.forest differ diff --git a/Templates/Full/game/levels/Outpost.mis b/Templates/Full/game/levels/Outpost.mis new file mode 100644 index 000000000..97c37c0ae --- /dev/null +++ b/Templates/Full/game/levels/Outpost.mis @@ -0,0 +1,1295 @@ +//--- OBJECT WRITE BEGIN --- +new SimGroup(MissionGroup) { + canSave = "1"; + canSaveDynamicFields = "1"; + enabled = "1"; + + new LevelInfo(theLevelInfo) { + nearClip = "0.1"; + visibleDistance = "2000"; + decalBias = "0.0015"; + fogColor = "0.462745 0.698039 0.729412 1"; + fogDensity = "0.005"; + fogDensityOffset = "10"; + fogAtmosphereHeight = "400"; + canvasClearColor = "233 220 143 255"; + ambientLightBlendPhase = "1"; + ambientLightBlendCurve = "0 0 -1 -1"; + advancedLightmapSupport = "0"; + soundAmbience = "AudioAmbienceDefault"; + soundDistanceModel = "Linear"; + canSave = "1"; + canSaveDynamicFields = "1"; + levelName = "Outpost"; + }; + new ScatterSky() { + skyBrightness = "25"; + sunSize = "1"; + colorizeAmount = "0"; + colorize = "0 0 0 1"; + rayleighScattering = "0.0035"; + sunScale = "1 1 1 1"; + ambientScale = "1 1 1 1"; + fogScale = "1 1 1 1"; + exposure = "1"; + azimuth = "0"; + elevation = "35"; + moonAzimuth = "0"; + moonElevation = "45"; + castShadows = "1"; + brightness = "1"; + flareType = "SunFlareExample"; + flareScale = "1"; + nightColor = "0.0196078 0.0117647 0.109804 1"; + nightFogColor = "0.0196078 0.0117647 0.109804 1"; + moonEnabled = "1"; + moonMat = "Moon_Glow_Mat"; + moonScale = "0.2"; + moonLightColor = "0.223529 0.25098 0.333333 1"; + useNightCubemap = "1"; + nightCubemap = "nightCubemap"; + attenuationRatio = "0 1 1"; + shadowType = "PSSM"; + texSize = "512"; + overDarkFactor = "2000 1000 500 100"; + shadowDistance = "400"; + shadowSoftness = "0.15"; + numSplits = "4"; + logWeight = "0.91"; + fadeStartDistance = "0"; + lastSplitTerrainOnly = "0"; + representedInLightmap = "0"; + shadowDarkenColor = "0 0 0 -1"; + includeLightmappedGeometryInShadow = "0"; + position = "-66.5144 26.6041 496.499"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + mieScattering = "0.0045"; + }; + new TimeOfDay() { + axisTilt = "23.44"; + dayLength = "120"; + startTime = "0.1"; + time = "0.153243"; + play = "1"; + azimuthOverride = "1"; + dayScale = "1"; + nightScale = "2"; + position = "-182.594 54.5451 536.878"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new CloudLayer() { + texture = "art/skies/clouds/clouds_normal_displacement"; + texScale[0] = "1"; + texScale[1] = "1"; + texScale[2] = "1"; + texDirection[0] = "1 0"; + texDirection[1] = "0 1"; + texDirection[2] = "0.5 0"; + texSpeed[0] = "0.005"; + texSpeed[1] = "0.005"; + texSpeed[2] = "0.005"; + baseColor = "0.9 0.9 0.9 1"; + exposure = "1"; + coverage = "0.5"; + windSpeed = "1"; + height = "4"; + position = "-125.952 58.8947 265.293"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new TerrainBlock(theTerrain) { + terrainFile = "art/terrains/Outpost_0.ter"; + castShadows = "1"; + squareSize = "2"; + baseTexSize = "1024"; + lightMapSize = "256"; + screenError = "16"; + position = "-1024 -1024 179.978"; + rotation = "1 0 0 0"; + canSave = "1"; + canSaveDynamicFields = "1"; + scale = "1 1 1"; + tile = "0"; + }; + new SimGroup(PlayerDropPoints) { + canSave = "1"; + canSaveDynamicFields = "1"; + enabled = "1"; + + new SpawnSphere() { + autoSpawn = "0"; + spawnTransform = "0"; + radius = "1"; + sphereWeight = "1"; + indoorWeight = "1"; + outdoorWeight = "1"; + isAIControlled = "0"; + dataBlock = "SpawnSphereMarker"; + position = "0 0 241.772"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + enabled = "1"; + homingCount = "0"; + lockCount = "0"; + }; + }; + new WaterPlane() { + gridSize = "101"; + gridElementSize = "1"; + density = "1"; + viscosity = "1"; + liquidType = "Water"; + baseColor = "45 108 171 255"; + fresnelBias = "0.3"; + fresnelPower = "6"; + specularPower = "48"; + specularColor = "1 1 1 1"; + emissive = "0"; + waveDir[0] = "0 1"; + waveDir[1] = "0.707 0.707"; + waveDir[2] = "0.5 0.86"; + waveSpeed[0] = "1"; + waveSpeed[1] = "1"; + waveSpeed[2] = "1"; + waveMagnitude[0] = "0.2"; + waveMagnitude[1] = "0.2"; + waveMagnitude[2] = "0.2"; + overallWaveMagnitude = "1"; + rippleTex = "art/water/ripple"; + rippleDir[0] = "0 1"; + rippleDir[1] = "0.707 0.707"; + rippleDir[2] = "0.5 0.86"; + rippleSpeed[0] = "0.065"; + rippleSpeed[1] = "0.09"; + rippleSpeed[2] = "0.04"; + rippleTexScale[0] = "7.14 7.14"; + rippleTexScale[1] = "6.25 12.5"; + rippleTexScale[2] = "50 50"; + rippleMagnitude[0] = "1"; + rippleMagnitude[1] = "1"; + rippleMagnitude[2] = "0.3"; + overallRippleMagnitude = "1"; + foamTex = "art/water/foam"; + foamDir[0] = "1 0"; + foamDir[1] = "0 1"; + foamSpeed[0] = "0"; + foamSpeed[1] = "0"; + foamTexScale[0] = "1 1"; + foamTexScale[1] = "3 3"; + foamOpacity[0] = "0"; + foamOpacity[1] = "0"; + overallFoamOpacity = "1"; + foamMaxDepth = "2"; + foamAmbientLerp = "0.5"; + foamRippleInfluence = "0.05"; + fullReflect = "1"; + reflectivity = "0.5"; + reflectPriority = "1"; + reflectMaxRateMs = "15"; + reflectDetailAdjust = "1"; + reflectNormalUp = "1"; + useOcclusionQuery = "1"; + reflectTexSize = "256"; + waterFogDensity = "0.1"; + waterFogDensityOffset = "1"; + wetDepth = "1.5"; + wetDarkening = "0.2"; + depthGradientTex = "art/water/depthcolor_ramp"; + depthGradientMax = "50"; + distortStartDist = "0.1"; + distortEndDist = "20"; + distortFullDepth = "3.5"; + clarity = "0.5"; + underwaterColor = "9 6 5 240"; + position = "0 0 238.69"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GroundCover(g1) { + Material = "grass1"; + radius = "100"; + dissolveRadius = "50"; + reflectScale = "0.25"; + gridSize = "7"; + zOffset = "0"; + seed = "1"; + maxElements = "100000"; + maxBillboardTiltAngle = "90"; + shapeCullRadius = "75"; + shapesCastShadows = "1"; + billboardUVs[0] = "0 0 1 1"; + billboardUVs[1] = "0 0 1 1"; + billboardUVs[2] = "0 0 1 1"; + billboardUVs[3] = "0 0 1 1"; + billboardUVs[4] = "0 0 1 1"; + billboardUVs[5] = "0 0 1 1"; + billboardUVs[6] = "0 0 1 1"; + billboardUVs[7] = "0 0 1 1"; + layer[0] = "0"; + invertLayer[0] = "0"; + invertLayer[1] = "0"; + invertLayer[2] = "0"; + invertLayer[3] = "0"; + invertLayer[4] = "0"; + invertLayer[5] = "0"; + invertLayer[6] = "0"; + invertLayer[7] = "0"; + probability[0] = "1"; + probability[1] = "0"; + probability[2] = "0"; + probability[3] = "0"; + probability[4] = "0"; + probability[5] = "0"; + probability[6] = "0"; + probability[7] = "0"; + sizeMin[0] = "1"; + sizeMin[1] = "1"; + sizeMin[2] = "1"; + sizeMin[3] = "1"; + sizeMin[4] = "1"; + sizeMin[5] = "1"; + sizeMin[6] = "1"; + sizeMin[7] = "1"; + sizeMax[0] = "1"; + sizeMax[1] = "1"; + sizeMax[2] = "1"; + sizeMax[3] = "1"; + sizeMax[4] = "1"; + sizeMax[5] = "1"; + sizeMax[6] = "1"; + sizeMax[7] = "1"; + sizeExponent[0] = "1"; + sizeExponent[1] = "1"; + sizeExponent[2] = "1"; + sizeExponent[3] = "1"; + sizeExponent[4] = "1"; + sizeExponent[5] = "1"; + sizeExponent[6] = "1"; + sizeExponent[7] = "1"; + windScale[0] = "1"; + windScale[1] = "1"; + windScale[2] = "1"; + windScale[3] = "1"; + windScale[4] = "1"; + windScale[5] = "1"; + windScale[6] = "1"; + windScale[7] = "1"; + maxSlope[0] = "0"; + maxSlope[1] = "0"; + maxSlope[2] = "0"; + maxSlope[3] = "0"; + maxSlope[4] = "0"; + maxSlope[5] = "0"; + maxSlope[6] = "0"; + maxSlope[7] = "0"; + minElevation[0] = "-99999"; + minElevation[1] = "-99999"; + minElevation[2] = "-99999"; + minElevation[3] = "-99999"; + minElevation[4] = "-99999"; + minElevation[5] = "-99999"; + minElevation[6] = "-99999"; + minElevation[7] = "-99999"; + maxElevation[0] = "99999"; + maxElevation[1] = "99999"; + maxElevation[2] = "99999"; + maxElevation[3] = "99999"; + maxElevation[4] = "99999"; + maxElevation[5] = "99999"; + maxElevation[6] = "99999"; + maxElevation[7] = "99999"; + minClumpCount[0] = "10"; + minClumpCount[1] = "1"; + minClumpCount[2] = "1"; + minClumpCount[3] = "1"; + minClumpCount[4] = "1"; + minClumpCount[5] = "1"; + minClumpCount[6] = "1"; + minClumpCount[7] = "1"; + maxClumpCount[0] = "20"; + maxClumpCount[1] = "1"; + maxClumpCount[2] = "1"; + maxClumpCount[3] = "1"; + maxClumpCount[4] = "1"; + maxClumpCount[5] = "1"; + maxClumpCount[6] = "1"; + maxClumpCount[7] = "1"; + clumpExponent[0] = "1"; + clumpExponent[1] = "1"; + clumpExponent[2] = "1"; + clumpExponent[3] = "1"; + clumpExponent[4] = "1"; + clumpExponent[5] = "1"; + clumpExponent[6] = "1"; + clumpExponent[7] = "1"; + clumpRadius[0] = "1"; + clumpRadius[1] = "1"; + clumpRadius[2] = "1"; + clumpRadius[3] = "1"; + clumpRadius[4] = "1"; + clumpRadius[5] = "1"; + clumpRadius[6] = "1"; + clumpRadius[7] = "1"; + windDirection = "1 0"; + windGustLength = "20"; + windGustFrequency = "0.5"; + windGustStrength = "0.5"; + windTurbulenceFrequency = "1.2"; + windTurbulenceStrength = "0.125"; + lockFrustum = "0"; + renderCells = "0"; + noBillboards = "0"; + noShapes = "0"; + position = "-21.5457 82.0435 449.083"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GroundCover(g2) { + Material = "grass2"; + radius = "100"; + dissolveRadius = "50"; + reflectScale = "0.25"; + gridSize = "7"; + zOffset = "0"; + seed = "2"; + maxElements = "100000"; + maxBillboardTiltAngle = "90"; + shapeCullRadius = "75"; + shapesCastShadows = "1"; + billboardUVs[0] = "0 0 1 1"; + billboardUVs[1] = "0 0 1 1"; + billboardUVs[2] = "0 0 1 1"; + billboardUVs[3] = "0 0 1 1"; + billboardUVs[4] = "0 0 1 1"; + billboardUVs[5] = "0 0 1 1"; + billboardUVs[6] = "0 0 1 1"; + billboardUVs[7] = "0 0 1 1"; + layer[0] = "grass1"; + invertLayer[0] = "0"; + invertLayer[1] = "0"; + invertLayer[2] = "0"; + invertLayer[3] = "0"; + invertLayer[4] = "0"; + invertLayer[5] = "0"; + invertLayer[6] = "0"; + invertLayer[7] = "0"; + probability[0] = "1"; + probability[1] = "0"; + probability[2] = "0"; + probability[3] = "0"; + probability[4] = "0"; + probability[5] = "0"; + probability[6] = "0"; + probability[7] = "0"; + sizeMin[0] = "1"; + sizeMin[1] = "1"; + sizeMin[2] = "1"; + sizeMin[3] = "1"; + sizeMin[4] = "1"; + sizeMin[5] = "1"; + sizeMin[6] = "1"; + sizeMin[7] = "1"; + sizeMax[0] = "1"; + sizeMax[1] = "1"; + sizeMax[2] = "1"; + sizeMax[3] = "1"; + sizeMax[4] = "1"; + sizeMax[5] = "1"; + sizeMax[6] = "1"; + sizeMax[7] = "1"; + sizeExponent[0] = "1"; + sizeExponent[1] = "1"; + sizeExponent[2] = "1"; + sizeExponent[3] = "1"; + sizeExponent[4] = "1"; + sizeExponent[5] = "1"; + sizeExponent[6] = "1"; + sizeExponent[7] = "1"; + windScale[0] = "1"; + windScale[1] = "1"; + windScale[2] = "1"; + windScale[3] = "1"; + windScale[4] = "1"; + windScale[5] = "1"; + windScale[6] = "1"; + windScale[7] = "1"; + maxSlope[0] = "0"; + maxSlope[1] = "0"; + maxSlope[2] = "0"; + maxSlope[3] = "0"; + maxSlope[4] = "0"; + maxSlope[5] = "0"; + maxSlope[6] = "0"; + maxSlope[7] = "0"; + minElevation[0] = "-99999"; + minElevation[1] = "-99999"; + minElevation[2] = "-99999"; + minElevation[3] = "-99999"; + minElevation[4] = "-99999"; + minElevation[5] = "-99999"; + minElevation[6] = "-99999"; + minElevation[7] = "-99999"; + maxElevation[0] = "99999"; + maxElevation[1] = "99999"; + maxElevation[2] = "99999"; + maxElevation[3] = "99999"; + maxElevation[4] = "99999"; + maxElevation[5] = "99999"; + maxElevation[6] = "99999"; + maxElevation[7] = "99999"; + minClumpCount[0] = "10"; + minClumpCount[1] = "1"; + minClumpCount[2] = "1"; + minClumpCount[3] = "1"; + minClumpCount[4] = "1"; + minClumpCount[5] = "1"; + minClumpCount[6] = "1"; + minClumpCount[7] = "1"; + maxClumpCount[0] = "20"; + maxClumpCount[1] = "1"; + maxClumpCount[2] = "1"; + maxClumpCount[3] = "1"; + maxClumpCount[4] = "1"; + maxClumpCount[5] = "1"; + maxClumpCount[6] = "1"; + maxClumpCount[7] = "1"; + clumpExponent[0] = "1"; + clumpExponent[1] = "1"; + clumpExponent[2] = "1"; + clumpExponent[3] = "1"; + clumpExponent[4] = "1"; + clumpExponent[5] = "1"; + clumpExponent[6] = "1"; + clumpExponent[7] = "1"; + clumpRadius[0] = "1"; + clumpRadius[1] = "1"; + clumpRadius[2] = "1"; + clumpRadius[3] = "1"; + clumpRadius[4] = "1"; + clumpRadius[5] = "1"; + clumpRadius[6] = "1"; + clumpRadius[7] = "1"; + windDirection = "1 0"; + windGustLength = "20"; + windGustFrequency = "0.5"; + windGustStrength = "0.5"; + windTurbulenceFrequency = "1.2"; + windTurbulenceStrength = "0.125"; + lockFrustum = "0"; + renderCells = "0"; + noBillboards = "0"; + noShapes = "0"; + position = "12.8117 0 241.462"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GroundCover(g3) { + Material = "grass3"; + radius = "100"; + dissolveRadius = "50"; + reflectScale = "0.25"; + gridSize = "7"; + zOffset = "0"; + seed = "3"; + maxElements = "100000"; + maxBillboardTiltAngle = "90"; + shapeCullRadius = "75"; + shapesCastShadows = "1"; + billboardUVs[0] = "0 0 1 1"; + billboardUVs[1] = "0 0 1 1"; + billboardUVs[2] = "0 0 1 1"; + billboardUVs[3] = "0 0 1 1"; + billboardUVs[4] = "0 0 1 1"; + billboardUVs[5] = "0 0 1 1"; + billboardUVs[6] = "0 0 1 1"; + billboardUVs[7] = "0 0 1 1"; + layer[0] = "dirt_grass"; + invertLayer[0] = "0"; + invertLayer[1] = "0"; + invertLayer[2] = "0"; + invertLayer[3] = "0"; + invertLayer[4] = "0"; + invertLayer[5] = "0"; + invertLayer[6] = "0"; + invertLayer[7] = "0"; + probability[0] = "1"; + probability[1] = "0"; + probability[2] = "0"; + probability[3] = "0"; + probability[4] = "0"; + probability[5] = "0"; + probability[6] = "0"; + probability[7] = "0"; + sizeMin[0] = "1"; + sizeMin[1] = "1"; + sizeMin[2] = "1"; + sizeMin[3] = "1"; + sizeMin[4] = "1"; + sizeMin[5] = "1"; + sizeMin[6] = "1"; + sizeMin[7] = "1"; + sizeMax[0] = "1"; + sizeMax[1] = "1"; + sizeMax[2] = "1"; + sizeMax[3] = "1"; + sizeMax[4] = "1"; + sizeMax[5] = "1"; + sizeMax[6] = "1"; + sizeMax[7] = "1"; + sizeExponent[0] = "1"; + sizeExponent[1] = "1"; + sizeExponent[2] = "1"; + sizeExponent[3] = "1"; + sizeExponent[4] = "1"; + sizeExponent[5] = "1"; + sizeExponent[6] = "1"; + sizeExponent[7] = "1"; + windScale[0] = "1"; + windScale[1] = "1"; + windScale[2] = "1"; + windScale[3] = "1"; + windScale[4] = "1"; + windScale[5] = "1"; + windScale[6] = "1"; + windScale[7] = "1"; + maxSlope[0] = "0"; + maxSlope[1] = "0"; + maxSlope[2] = "0"; + maxSlope[3] = "0"; + maxSlope[4] = "0"; + maxSlope[5] = "0"; + maxSlope[6] = "0"; + maxSlope[7] = "0"; + minElevation[0] = "-99999"; + minElevation[1] = "-99999"; + minElevation[2] = "-99999"; + minElevation[3] = "-99999"; + minElevation[4] = "-99999"; + minElevation[5] = "-99999"; + minElevation[6] = "-99999"; + minElevation[7] = "-99999"; + maxElevation[0] = "99999"; + maxElevation[1] = "99999"; + maxElevation[2] = "99999"; + maxElevation[3] = "99999"; + maxElevation[4] = "99999"; + maxElevation[5] = "99999"; + maxElevation[6] = "99999"; + maxElevation[7] = "99999"; + minClumpCount[0] = "10"; + minClumpCount[1] = "1"; + minClumpCount[2] = "1"; + minClumpCount[3] = "1"; + minClumpCount[4] = "1"; + minClumpCount[5] = "1"; + minClumpCount[6] = "1"; + minClumpCount[7] = "1"; + maxClumpCount[0] = "20"; + maxClumpCount[1] = "1"; + maxClumpCount[2] = "1"; + maxClumpCount[3] = "1"; + maxClumpCount[4] = "1"; + maxClumpCount[5] = "1"; + maxClumpCount[6] = "1"; + maxClumpCount[7] = "1"; + clumpExponent[0] = "1"; + clumpExponent[1] = "1"; + clumpExponent[2] = "1"; + clumpExponent[3] = "1"; + clumpExponent[4] = "1"; + clumpExponent[5] = "1"; + clumpExponent[6] = "1"; + clumpExponent[7] = "1"; + clumpRadius[0] = "1"; + clumpRadius[1] = "1"; + clumpRadius[2] = "1"; + clumpRadius[3] = "1"; + clumpRadius[4] = "1"; + clumpRadius[5] = "1"; + clumpRadius[6] = "1"; + clumpRadius[7] = "1"; + windDirection = "1 0"; + windGustLength = "20"; + windGustFrequency = "0.5"; + windGustStrength = "0.5"; + windTurbulenceFrequency = "1.2"; + windTurbulenceStrength = "0.125"; + lockFrustum = "0"; + renderCells = "0"; + noBillboards = "0"; + noShapes = "0"; + position = "-21.5457 82.0435 449.083"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GroundCover(g4) { + Material = "plant1"; + radius = "100"; + dissolveRadius = "50"; + reflectScale = "0.25"; + gridSize = "7"; + zOffset = "0"; + seed = "4"; + maxElements = "100000"; + maxBillboardTiltAngle = "90"; + shapeCullRadius = "75"; + shapesCastShadows = "1"; + billboardUVs[0] = "0 0 1 1"; + billboardUVs[1] = "0 0 1 1"; + billboardUVs[2] = "0 0 1 1"; + billboardUVs[3] = "0 0 1 1"; + billboardUVs[4] = "0 0 1 1"; + billboardUVs[5] = "0 0 1 1"; + billboardUVs[6] = "0 0 1 1"; + billboardUVs[7] = "0 0 1 1"; + layer[0] = "sand"; + invertLayer[0] = "1"; + invertLayer[1] = "0"; + invertLayer[2] = "0"; + invertLayer[3] = "0"; + invertLayer[4] = "0"; + invertLayer[5] = "0"; + invertLayer[6] = "0"; + invertLayer[7] = "0"; + probability[0] = "1"; + probability[1] = "0"; + probability[2] = "0"; + probability[3] = "0"; + probability[4] = "0"; + probability[5] = "0"; + probability[6] = "0"; + probability[7] = "0"; + sizeMin[0] = "1"; + sizeMin[1] = "1"; + sizeMin[2] = "1"; + sizeMin[3] = "1"; + sizeMin[4] = "1"; + sizeMin[5] = "1"; + sizeMin[6] = "1"; + sizeMin[7] = "1"; + sizeMax[0] = "1"; + sizeMax[1] = "1"; + sizeMax[2] = "1"; + sizeMax[3] = "1"; + sizeMax[4] = "1"; + sizeMax[5] = "1"; + sizeMax[6] = "1"; + sizeMax[7] = "1"; + sizeExponent[0] = "1"; + sizeExponent[1] = "1"; + sizeExponent[2] = "1"; + sizeExponent[3] = "1"; + sizeExponent[4] = "1"; + sizeExponent[5] = "1"; + sizeExponent[6] = "1"; + sizeExponent[7] = "1"; + windScale[0] = "1"; + windScale[1] = "1"; + windScale[2] = "1"; + windScale[3] = "1"; + windScale[4] = "1"; + windScale[5] = "1"; + windScale[6] = "1"; + windScale[7] = "1"; + maxSlope[0] = "0"; + maxSlope[1] = "0"; + maxSlope[2] = "0"; + maxSlope[3] = "0"; + maxSlope[4] = "0"; + maxSlope[5] = "0"; + maxSlope[6] = "0"; + maxSlope[7] = "0"; + minElevation[0] = "-99999"; + minElevation[1] = "-99999"; + minElevation[2] = "-99999"; + minElevation[3] = "-99999"; + minElevation[4] = "-99999"; + minElevation[5] = "-99999"; + minElevation[6] = "-99999"; + minElevation[7] = "-99999"; + maxElevation[0] = "99999"; + maxElevation[1] = "99999"; + maxElevation[2] = "99999"; + maxElevation[3] = "99999"; + maxElevation[4] = "99999"; + maxElevation[5] = "99999"; + maxElevation[6] = "99999"; + maxElevation[7] = "99999"; + minClumpCount[0] = "10"; + minClumpCount[1] = "1"; + minClumpCount[2] = "1"; + minClumpCount[3] = "1"; + minClumpCount[4] = "1"; + minClumpCount[5] = "1"; + minClumpCount[6] = "1"; + minClumpCount[7] = "1"; + maxClumpCount[0] = "20"; + maxClumpCount[1] = "1"; + maxClumpCount[2] = "1"; + maxClumpCount[3] = "1"; + maxClumpCount[4] = "1"; + maxClumpCount[5] = "1"; + maxClumpCount[6] = "1"; + maxClumpCount[7] = "1"; + clumpExponent[0] = "1"; + clumpExponent[1] = "1"; + clumpExponent[2] = "1"; + clumpExponent[3] = "1"; + clumpExponent[4] = "1"; + clumpExponent[5] = "1"; + clumpExponent[6] = "1"; + clumpExponent[7] = "1"; + clumpRadius[0] = "1"; + clumpRadius[1] = "1"; + clumpRadius[2] = "1"; + clumpRadius[3] = "1"; + clumpRadius[4] = "1"; + clumpRadius[5] = "1"; + clumpRadius[6] = "1"; + clumpRadius[7] = "1"; + windDirection = "1 0"; + windGustLength = "20"; + windGustFrequency = "0.5"; + windGustStrength = "0.5"; + windTurbulenceFrequency = "1.2"; + windTurbulenceStrength = "0.125"; + lockFrustum = "0"; + renderCells = "0"; + noBillboards = "0"; + noShapes = "0"; + position = "-30.6167 167.702 653.717"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new GroundCover(g5) { + Material = "plant2"; + radius = "100"; + dissolveRadius = "50"; + reflectScale = "0.25"; + gridSize = "7"; + zOffset = "0"; + seed = "5"; + maxElements = "100000"; + maxBillboardTiltAngle = "90"; + shapeCullRadius = "75"; + shapesCastShadows = "1"; + billboardUVs[0] = "0 0 1 1"; + billboardUVs[1] = "0 0 1 1"; + billboardUVs[2] = "0 0 1 1"; + billboardUVs[3] = "0 0 1 1"; + billboardUVs[4] = "0 0 1 1"; + billboardUVs[5] = "0 0 1 1"; + billboardUVs[6] = "0 0 1 1"; + billboardUVs[7] = "0 0 1 1"; + layer[0] = "sand"; + invertLayer[0] = "1"; + invertLayer[1] = "0"; + invertLayer[2] = "0"; + invertLayer[3] = "0"; + invertLayer[4] = "0"; + invertLayer[5] = "0"; + invertLayer[6] = "0"; + invertLayer[7] = "0"; + probability[0] = "1"; + probability[1] = "0"; + probability[2] = "0"; + probability[3] = "0"; + probability[4] = "0"; + probability[5] = "0"; + probability[6] = "0"; + probability[7] = "0"; + sizeMin[0] = "1"; + sizeMin[1] = "1"; + sizeMin[2] = "1"; + sizeMin[3] = "1"; + sizeMin[4] = "1"; + sizeMin[5] = "1"; + sizeMin[6] = "1"; + sizeMin[7] = "1"; + sizeMax[0] = "1"; + sizeMax[1] = "1"; + sizeMax[2] = "1"; + sizeMax[3] = "1"; + sizeMax[4] = "1"; + sizeMax[5] = "1"; + sizeMax[6] = "1"; + sizeMax[7] = "1"; + sizeExponent[0] = "1"; + sizeExponent[1] = "1"; + sizeExponent[2] = "1"; + sizeExponent[3] = "1"; + sizeExponent[4] = "1"; + sizeExponent[5] = "1"; + sizeExponent[6] = "1"; + sizeExponent[7] = "1"; + windScale[0] = "1"; + windScale[1] = "1"; + windScale[2] = "1"; + windScale[3] = "1"; + windScale[4] = "1"; + windScale[5] = "1"; + windScale[6] = "1"; + windScale[7] = "1"; + maxSlope[0] = "0"; + maxSlope[1] = "0"; + maxSlope[2] = "0"; + maxSlope[3] = "0"; + maxSlope[4] = "0"; + maxSlope[5] = "0"; + maxSlope[6] = "0"; + maxSlope[7] = "0"; + minElevation[0] = "-99999"; + minElevation[1] = "-99999"; + minElevation[2] = "-99999"; + minElevation[3] = "-99999"; + minElevation[4] = "-99999"; + minElevation[5] = "-99999"; + minElevation[6] = "-99999"; + minElevation[7] = "-99999"; + maxElevation[0] = "99999"; + maxElevation[1] = "99999"; + maxElevation[2] = "99999"; + maxElevation[3] = "99999"; + maxElevation[4] = "99999"; + maxElevation[5] = "99999"; + maxElevation[6] = "99999"; + maxElevation[7] = "99999"; + minClumpCount[0] = "10"; + minClumpCount[1] = "1"; + minClumpCount[2] = "1"; + minClumpCount[3] = "1"; + minClumpCount[4] = "1"; + minClumpCount[5] = "1"; + minClumpCount[6] = "1"; + minClumpCount[7] = "1"; + maxClumpCount[0] = "20"; + maxClumpCount[1] = "1"; + maxClumpCount[2] = "1"; + maxClumpCount[3] = "1"; + maxClumpCount[4] = "1"; + maxClumpCount[5] = "1"; + maxClumpCount[6] = "1"; + maxClumpCount[7] = "1"; + clumpExponent[0] = "1"; + clumpExponent[1] = "1"; + clumpExponent[2] = "1"; + clumpExponent[3] = "1"; + clumpExponent[4] = "1"; + clumpExponent[5] = "1"; + clumpExponent[6] = "1"; + clumpExponent[7] = "1"; + clumpRadius[0] = "1"; + clumpRadius[1] = "1"; + clumpRadius[2] = "1"; + clumpRadius[3] = "1"; + clumpRadius[4] = "1"; + clumpRadius[5] = "1"; + clumpRadius[6] = "1"; + clumpRadius[7] = "1"; + windDirection = "1 0"; + windGustLength = "20"; + windGustFrequency = "0.5"; + windGustStrength = "0.5"; + windTurbulenceFrequency = "1.2"; + windTurbulenceStrength = "0.125"; + lockFrustum = "0"; + renderCells = "0"; + noBillboards = "0"; + noShapes = "0"; + position = "-39.6877 253.361 -165.649"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new DecalRoad() { + Material = "DefaultDecalRoadMaterial"; + textureLength = "5"; + breakAngle = "3"; + renderPriority = "10"; + position = "9.80889 2.39879 240.942"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + + Node = "9.808894 2.398789 240.942383 10.000000"; + Node = "19.435331 -12.021607 242.012695 10.000000"; + Node = "51.340595 -31.241543 242.855469 10.000000"; + Node = "73.327950 -36.401802 244.145020 10.000000"; + Node = "88.747749 -36.281593 242.743652 10.000000"; + Node = "99.256721 -36.545666 242.833008 10.000000"; + Node = "111.722069 -37.935364 242.774414 10.000000"; + Node = "125.051414 -46.665359 241.201172 10.000000"; + Node = "135.392502 -62.546097 240.647461 10.000000"; + Node = "147.920288 -81.505074 241.236816 10.000000"; + Node = "154.947601 -108.118645 239.935059 10.000000"; + Node = "165.949829 -113.423088 242.946289 10.000000"; + Node = "175.869278 -122.958076 246.488770 10.000000"; + Node = "174.005676 -133.564606 247.382813 10.000000"; + Node = "161.754974 -147.751358 244.036133 10.000000"; + Node = "148.839752 -154.680801 239.870117 10.000000"; + Node = "137.597839 -158.807571 242.396484 10.000000"; + Node = "121.395180 -164.599747 242.321289 10.000000"; + Node = "107.988640 -168.540009 240.083984 10.000000"; + Node = "91.170845 -166.981232 241.412109 10.000000"; + Node = "74.749481 -167.035095 241.031738 10.000000"; + Node = "58.921535 -166.261856 240.727539 10.000000"; + Node = "45.656979 -164.615738 240.228027 10.000000"; + Node = "33.351269 -160.648788 240.955566 10.000000"; + Node = "20.763161 -155.455353 241.927734 10.000000"; + Node = "6.109464 -148.071213 241.165039 10.000000"; + Node = "-8.478178 -141.377396 241.548828 10.000000"; + Node = "-20.484320 -137.246552 241.660156 10.000000"; + Node = "-31.985313 -133.914383 241.726563 10.000000"; + Node = "-37.365936 -131.465881 240.782227 10.000000"; + }; + new MeshRoad() { + topMaterial = "DefaultRoadMaterialTop"; + bottomMaterial = "DefaultRoadMaterialOther"; + sideMaterial = "DefaultRoadMaterialOther"; + textureLength = "5"; + breakAngle = "3"; + widthSubdivisions = "0"; + position = "-37.0747 -131.611 241.008"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + + Node = "-37.0747 -131.611 241.008 10 5 0 0 1"; + Node = "-46.5522 -126.509 241.261 10 1 0 0 1"; + Node = "-64.5763 -114.011 241.266 10 1 0 0 1"; + Node = "-76.7738 -105.161 241.264 10 5 0 0 1"; + Node = "-83.4952 -95.8972 241.263 10 5 0 0 1"; + Node = "-90.0231 -85.4595 241.264 10 1 0 0 1"; + Node = "-126.295 -31.1648 241.263 10 1 0 0 1"; + Node = "-130.845 -23.7569 241.263 10 1 0 0 1"; + }; + new DecalRoad() { + Material = "DefaultDecalRoadMaterial"; + textureLength = "5"; + breakAngle = "3"; + renderPriority = "10"; + position = "-130.65 -23.9889 240.977"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + + Node = "-130.650162 -23.988914 240.977051 10.000000"; + Node = "-135.118286 -18.524910 241.336426 10.000000"; + Node = "-145.521835 -13.748994 241.743164 10.000000"; + Node = "-182.085999 -0.641886 246.494141 10.000000"; + Node = "-182.439651 22.376331 246.258789 10.000000"; + Node = "-170.779953 46.080372 249.054199 10.000000"; + Node = "-153.401840 65.100060 250.877930 10.000000"; + Node = "-126.537048 61.379917 249.727051 10.000000"; + Node = "-93.901245 66.011063 248.522949 10.000000"; + Node = "-76.734924 68.635735 252.627930 10.000000"; + Node = "-66.973053 64.809494 252.790039 10.000000"; + Node = "-51.694069 55.059582 253.915527 10.000000"; + Node = "-45.866165 50.427311 254.302246 10.000000"; + Node = "-41.049664 46.311405 253.332031 10.000000"; + }; + new MeshRoad() { + topMaterial = "DefaultRoadMaterialTop"; + bottomMaterial = "DefaultRoadMaterialOther"; + sideMaterial = "DefaultRoadMaterialOther"; + textureLength = "5"; + breakAngle = "3"; + widthSubdivisions = "0"; + position = "-41.7054 46.9005 253.598"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + + Node = "-41.7054 46.9005 253.598 10 5 -0.0955467 -0.111315 0.989181"; + Node = "-36.1458 42.8452 254.174 10 1 -0.047903 -0.055809 0.997292"; + Node = "-30.8174 37.6188 253.983 10 1 0 0 1"; + Node = "-18.3331 29.2615 251.817 10 1 0 0 1"; + Node = "-15.6041 27.3196 251.121 10 20 0 0 1"; + Node = "-12.6183 24.8304 250.138 10 1 0 0 1"; + Node = "1.97645 12.7545 244.672 10 1 0 0 1"; + Node = "8.09555 5.41249 242.162 10 1 0 0 1"; + Node = "13.7057 -5.98533 240.41 10 1 0 0 1"; + }; + new Forest(theForest) { + position = "0 0 0"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + dataFile = "levels/outpost.forest"; + lodReflectScalar = "2"; + }; + new WheeledVehicle() { + disableMove = "0"; + isAIControlled = "0"; + dataBlock = "CheetahCar"; + position = "29.878 -39.733 244.411"; + rotation = "0.279703 -0.957384 -0.0719901 1.72959"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "fab05691-3175-11e4-978f-ce5dedd0cf27"; + leftBrakeLight = "4285"; + mountable = "1"; + rightBrakeLight = "4284"; + }; + new TSStatic() { + shapeName = "art/shapes/rocks/rock1.dts"; + playAmbient = "1"; + meshCulling = "0"; + originSort = "0"; + collisionType = "Collision Mesh"; + decalType = "Collision Mesh"; + allowPlayerStep = "1"; + renderNormals = "0"; + forceDetail = "-1"; + position = "16.9991 -25.9715 240.76"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new TSStatic() { + shapeName = "art/shapes/rocks/rock2.dts"; + playAmbient = "1"; + meshCulling = "0"; + originSort = "0"; + collisionType = "Collision Mesh"; + decalType = "Collision Mesh"; + allowPlayerStep = "1"; + renderNormals = "0"; + forceDetail = "-1"; + position = "39.7956 -43.2913 238.099"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new TSStatic() { + shapeName = "art/shapes/rocks/rock3.dts"; + playAmbient = "1"; + meshCulling = "0"; + originSort = "0"; + collisionType = "Collision Mesh"; + decalType = "Collision Mesh"; + allowPlayerStep = "1"; + renderNormals = "0"; + forceDetail = "-1"; + position = "-2.17366 -10.0803 233.761"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new TSStatic() { + shapeName = "art/shapes/rocks/rock3.dts"; + playAmbient = "1"; + meshCulling = "0"; + originSort = "0"; + collisionType = "Collision Mesh"; + decalType = "Collision Mesh"; + allowPlayerStep = "1"; + renderNormals = "0"; + forceDetail = "-1"; + position = "-56.0141 31.2388 261.771"; + rotation = "0 1 0 180"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new Precipitation() { + numDrops = "1024"; + boxWidth = "100"; + boxHeight = "100"; + dropSize = "0.2"; + splashSize = "0.2"; + splashMS = "250"; + animateSplashes = "1"; + dropAnimateMS = "0"; + fadeDist = "0"; + fadeDistEnd = "0"; + useTrueBillboards = "0"; + useLighting = "0"; + glowIntensity = "0 0 0 0"; + reflect = "0"; + rotateWithCamVel = "1"; + doCollision = "1"; + hitPlayers = "0"; + hitVehicles = "0"; + followCam = "1"; + useWind = "0"; + minSpeed = "1.5"; + maxSpeed = "2"; + minMass = "0.75"; + maxMass = "0.85"; + useTurbulence = "0"; + maxTurbulence = "0.1"; + turbulenceSpeed = "0.2"; + dataBlock = "HeavyRain"; + position = "-68.4306 70.1859 262.98"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new PointLight() { + radius = "25"; + isEnabled = "1"; + color = "1 0.721569 0 1"; + brightness = "5"; + castShadows = "0"; + priority = "1"; + animate = "1"; + animationType = "FireLightAnim"; + animationPeriod = "1"; + animationPhase = "1"; + flareScale = "1"; + attenuationRatio = "0 0.5 0.1"; + shadowType = "DualParaboloidSinglePass"; + texSize = "512"; + overDarkFactor = "2000 1000 500 100"; + shadowDistance = "400"; + shadowSoftness = "0.15"; + numSplits = "1"; + logWeight = "0.91"; + fadeStartDistance = "0"; + lastSplitTerrainOnly = "0"; + representedInLightmap = "0"; + shadowDarkenColor = "0 0 0 -1"; + includeLightmappedGeometryInShadow = "0"; + position = "-52.9507 31.6944 258.435"; + rotation = "1 0 0 0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new ParticleEmitterNode() { + active = "1"; + emitter = "EmberEmitter"; + velocity = "1"; + dataBlock = "EmberNode"; + position = "-53.0636 31.7743 257.986"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new ParticleEmitterNode() { + active = "1"; + emitter = "FireEmitter"; + velocity = "1"; + dataBlock = "EmberNode"; + position = "-53.0636 31.7743 257.986"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new TSStatic() { + shapeName = "art/shapes/station/station01.dts"; + playAmbient = "1"; + meshCulling = "0"; + originSort = "0"; + collisionType = "Visible Mesh"; + decalType = "Visible Mesh"; + allowPlayerStep = "1"; + renderNormals = "0"; + forceDetail = "-1"; + position = "-118.394 34.2259 246.05"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new PhysicalZone() { + velocityMod = "1"; + gravityMod = "-1"; + appliedForce = "0 0 0"; + polyhedron = "-0.5000000 0.5000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 -1.0000000 0.0000000 0.0000000 0.0000000 1.0000000"; + position = "-75.81 34.2165 245.724"; + rotation = "1 0 0 0"; + scale = "4.70489 4.32539 20.7358"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new AITurretShape() { + respawn = "1"; + static = "1"; + rotate = "0"; + isAIControlled = "0"; + dataBlock = "AITurret"; + position = "-140.592 28.5721 245.631"; + rotation = "0 0 1 111.009"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + entranceThread = "-1"; + invAITurretAmmo = "10000"; + invAITurretHead = "1"; + mountable = "0"; + }; + new SimGroup(CameraBookmarks) { + canSave = "1"; + canSaveDynamicFields = "1"; + + new CameraBookmark() { + isAIControlled = "0"; + dataBlock = "CameraBookmarkMarker"; + position = "-54.2205 -122.766 257.705"; + rotation = "-0.0597204 -0.269509 0.961144 204.046"; + scale = "1 1 1"; + internalName = "NewCamera_0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new CameraBookmark() { + isAIControlled = "0"; + dataBlock = "CameraBookmarkMarker"; + position = "-48.0151 -90.5681 272.547"; + rotation = "-0.0406335 -0.246727 0.968233 198.12"; + scale = "1 1 1"; + internalName = "NewCamera_1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + }; + new TSStatic() { + shapeName = "art/shapes/trees/defaulttree/defaulttree.dae"; + playAmbient = "1"; + meshCulling = "0"; + originSort = "0"; + collisionType = "Collision Mesh"; + decalType = "Collision Mesh"; + allowPlayerStep = "1"; + renderNormals = "0"; + forceDetail = "-1"; + position = "-57.5817 -139.689 238.213"; + rotation = "1 0 0 0"; + scale = "3 3 3"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; +}; +//--- OBJECT WRITE END --- diff --git a/Templates/Full/game/levels/Outpost.postfxpreset.cs b/Templates/Full/game/levels/Outpost.postfxpreset.cs new file mode 100644 index 000000000..a86094688 --- /dev/null +++ b/Templates/Full/game/levels/Outpost.postfxpreset.cs @@ -0,0 +1,45 @@ +$PostFXManager::Settings::ColorCorrectionRamp = "core/scripts/client/postFx/null_color_ramp.png"; +$PostFXManager::Settings::DOF::BlurCurveFar = ""; +$PostFXManager::Settings::DOF::BlurCurveNear = ""; +$PostFXManager::Settings::DOF::BlurMax = ""; +$PostFXManager::Settings::DOF::BlurMin = ""; +$PostFXManager::Settings::DOF::EnableAutoFocus = ""; +$PostFXManager::Settings::DOF::EnableDOF = ""; +$PostFXManager::Settings::DOF::FocusRangeMax = ""; +$PostFXManager::Settings::DOF::FocusRangeMin = ""; +$PostFXManager::Settings::EnableDOF = "1"; +$PostFXManager::Settings::EnabledSSAO = "1"; +$PostFXManager::Settings::EnableHDR = "1"; +$PostFXManager::Settings::EnableLightRays = "1"; +$PostFXManager::Settings::EnablePostFX = "1"; +$PostFXManager::Settings::HDR::adaptRate = "2"; +$PostFXManager::Settings::HDR::blueShiftColor = "1.05 0.97 1.27"; +$PostFXManager::Settings::HDR::brightPassThreshold = "1"; +$PostFXManager::Settings::HDR::enableBloom = "1"; +$PostFXManager::Settings::HDR::enableBlueShift = "0"; +$PostFXManager::Settings::HDR::enableToneMapping = "1"; +$PostFXManager::Settings::HDR::gaussMean = "0"; +$PostFXManager::Settings::HDR::gaussMultiplier = "0.3"; +$PostFXManager::Settings::HDR::gaussStdDev = "0.8"; +$PostFXManager::Settings::HDR::keyValue = "0.18"; +$PostFXManager::Settings::HDR::minLuminace = "0.001"; +$PostFXManager::Settings::HDR::whiteCutoff = "1"; +$PostFXManager::Settings::LightRays::brightScalar = "0.75"; +$PostFXManager::Settings::SSAO::blurDepthTol = "0.001"; +$PostFXManager::Settings::SSAO::blurNormalTol = "0.95"; +$PostFXManager::Settings::SSAO::lDepthMax = "2"; +$PostFXManager::Settings::SSAO::lDepthMin = "0.2"; +$PostFXManager::Settings::SSAO::lDepthPow = "0.2"; +$PostFXManager::Settings::SSAO::lNormalPow = "2"; +$PostFXManager::Settings::SSAO::lNormalTol = "-0.5"; +$PostFXManager::Settings::SSAO::lRadius = "1"; +$PostFXManager::Settings::SSAO::lStrength = "10"; +$PostFXManager::Settings::SSAO::overallStrength = "2"; +$PostFXManager::Settings::SSAO::quality = "0"; +$PostFXManager::Settings::SSAO::sDepthMax = "1"; +$PostFXManager::Settings::SSAO::sDepthMin = "0.1"; +$PostFXManager::Settings::SSAO::sDepthPow = "1"; +$PostFXManager::Settings::SSAO::sNormalPow = "1"; +$PostFXManager::Settings::SSAO::sNormalTol = "0"; +$PostFXManager::Settings::SSAO::sRadius = "0.1"; +$PostFXManager::Settings::SSAO::sStrength = "6"; diff --git a/Templates/Full/game/levels/Outpost_preview.png b/Templates/Full/game/levels/Outpost_preview.png new file mode 100644 index 000000000..5a8aece82 Binary files /dev/null and b/Templates/Full/game/levels/Outpost_preview.png differ diff --git a/Templates/Full/game/main.cs b/Templates/Full/game/main.cs index 11c7348d0..96794899a 100644 --- a/Templates/Full/game/main.cs +++ b/Templates/Full/game/main.cs @@ -38,7 +38,10 @@ function createCanvas(%windowTitle) } // Create the Canvas - %foo = new GuiCanvas(Canvas); + %foo = new GuiCanvas(Canvas) + { + displayWindow = false; + }; // Set the window title if (isObject(Canvas)) @@ -246,6 +249,15 @@ if ($displayHelp) { else { onStart(); echo("Engine initialized..."); + + if( !$isDedicated ) + { + // As we know at this point that the initial load is complete, + // we can hide any splash screen we have, and show the canvas. + // This keeps things looking nice, instead of having a blank window + closeSplashWindow(); + Canvas.showWindow(); + } // Auto-load on the 360 if( $platform $= "xenon" ) diff --git a/Templates/Full/game/main.cs.in b/Templates/Full/game/main.cs.in new file mode 100644 index 000000000..d3b5791ef --- /dev/null +++ b/Templates/Full/game/main.cs.in @@ -0,0 +1,292 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// Set the name of our application +$appName = "@TORQUE_APP_NAME@"; + +// The directory it is run from +$defaultGame = "scripts"; + +// Set profile directory +$Pref::Video::ProfilePath = "core/profile"; + +function createCanvas(%windowTitle) +{ + if ($isDedicated) + { + GFXInit::createNullDevice(); + return true; + } + + // Create the Canvas + %foo = new GuiCanvas(Canvas) + { + displayWindow = false; + }; + + // Set the window title + if (isObject(Canvas)) + Canvas.setWindowTitle(getEngineName() @ " - " @ $appName); + + return true; +} + +// Display the optional commandline arguements +$displayHelp = false; + +// Use these to record and play back crashes +//saveJournal("editorOnFileQuitCrash.jrn"); +//playJournal("editorOnFileQuitCrash.jrn", false); + +//------------------------------------------------------------------------------ +// Check if a script file exists, compiled or not. +function isScriptFile(%path) +{ + if( isFile(%path @ ".dso") || isFile(%path) ) + return true; + + return false; +} + +//------------------------------------------------------------------------------ +// Process command line arguments +exec("core/parseArgs.cs"); + +$isDedicated = false; +$dirCount = 2; +$userDirs = $defaultGame @ ";art;levels"; + +// load tools scripts if we're a tool build +if (isToolBuild()) + $userDirs = "tools;" @ $userDirs; + + +// Parse the executable arguments with the standard +// function from core/main.cs +defaultParseArgs(); + + +if($dirCount == 0) { + $userDirs = $defaultGame; + $dirCount = 1; +} + +//----------------------------------------------------------------------------- +// Display a splash window immediately to improve app responsiveness before +// engine is initialized and main window created +if (!$isDedicated) + displaySplashWindow(); + + +//----------------------------------------------------------------------------- +// The displayHelp, onStart, onExit and parseArgs function are overriden +// by mod packages to get hooked into initialization and cleanup. + +function onStart() +{ + // Default startup function +} + +function onExit() +{ + // OnExit is called directly from C++ code, whereas onStart is + // invoked at the end of this file. +} + +function parseArgs() +{ + // Here for mod override, the arguments have already + // been parsed. +} + +function compileFiles(%pattern) +{ + %path = filePath(%pattern); + + %saveDSO = $Scripts::OverrideDSOPath; + %saveIgnore = $Scripts::ignoreDSOs; + + $Scripts::OverrideDSOPath = %path; + $Scripts::ignoreDSOs = false; + %mainCsFile = makeFullPath("main.cs"); + + for (%file = findFirstFileMultiExpr(%pattern); %file !$= ""; %file = findNextFileMultiExpr(%pattern)) + { + // we don't want to try and compile the primary main.cs + if(%mainCsFile !$= %file) + compile(%file, true); + } + + $Scripts::OverrideDSOPath = %saveDSO; + $Scripts::ignoreDSOs = %saveIgnore; + +} + +if($compileAll) +{ + echo(" --- Compiling all files ---"); + compileFiles("*.cs"); + compileFiles("*.gui"); + compileFiles("*.ts"); + echo(" --- Exiting after compile ---"); + quit(); +} + +if($compileTools) +{ + echo(" --- Compiling tools scritps ---"); + compileFiles("tools/*.cs"); + compileFiles("tools/*.gui"); + compileFiles("tools/*.ts"); + echo(" --- Exiting after compile ---"); + quit(); +} + +package Help { + function onExit() { + // Override onExit when displaying help + } +}; + +function displayHelp() { + activatePackage(Help); + + // Notes on logmode: console logging is written to console.log. + // -log 0 disables console logging. + // -log 1 appends to existing logfile; it also closes the file + // (flushing the write buffer) after every write. + // -log 2 overwrites any existing logfile; it also only closes + // the logfile when the application shuts down. (default) + + error( + "Torque Demo command line options:\n"@ + " -log Logging behavior; see main.cs comments for details\n"@ + " -game Reset list of mods to only contain \n"@ + " Works like the -game argument\n"@ + " -dir Add to list of directories\n"@ + " -console Open a separate console\n"@ + " -show Deprecated\n"@ + " -jSave Record a journal\n"@ + " -jPlay Play back a journal\n"@ + " -jDebug Play back a journal and issue an int3 at the end\n"@ + " -help Display this help message\n" + ); +} + + +//-------------------------------------------------------------------------- + +// Default to a new logfile each session. +if( !$logModeSpecified ) +{ + if( $platform !$= "xbox" && $platform !$= "xenon" ) + setLogMode(6); +} + +// Get the first dir on the list, which will be the last to be applied... this +// does not modify the list. +nextToken($userDirs, currentMod, ";"); + +// Execute startup scripts for each mod, starting at base and working up +function loadDir(%dir) +{ + pushback($userDirs, %dir, ";"); + + if (isScriptFile(%dir @ "/main.cs")) + exec(%dir @ "/main.cs"); +} + +echo("--------- Loading DIRS ---------"); +function loadDirs(%dirPath) +{ + %dirPath = nextToken(%dirPath, token, ";"); + if (%dirPath !$= "") + loadDirs(%dirPath); + + if(exec(%token @ "/main.cs") != true) + { + error("Error: Unable to find specified directory: " @ %token ); + $dirCount--; + } +} +loadDirs($userDirs); +echo(""); + +if($dirCount == 0) { + enableWinConsole(true); + error("Error: Unable to load any specified directories"); + quit(); +} +// Parse the command line arguments +echo("--------- Parsing Arguments ---------"); +parseArgs(); + +// Either display the help message or startup the app. +if ($displayHelp) { + enableWinConsole(true); + displayHelp(); + quit(); +} +else { + onStart(); + echo("Engine initialized..."); + + if( !$isDedicated ) + { + // As we know at this point that the initial load is complete, + // we can hide any splash screen we have, and show the canvas. + // This keeps things looking nice, instead of having a blank window + closeSplashWindow(); + Canvas.showWindow(); + } + + // Auto-load on the 360 + if( $platform $= "xenon" ) + { + %mission = "levels/Empty Terrain.mis"; + + echo("Xbox360 Autoloading level: '" @ %mission @ "'"); + + + if ($pref::HostMultiPlayer) + %serverType = "MultiPlayer"; + else + %serverType = "SinglePlayer"; + + createAndConnectToLocalServer( %serverType, %mission ); + } +} + +// Display an error message for unused arguments +for ($i = 1; $i < $Game::argc; $i++) { + if (!$argUsed[$i]) + error("Error: Unknown command line argument: " @ $Game::argv[$i]); +} + +// Automatically start up the appropriate eidtor, if any +if ($startWorldEditor) { + Canvas.setCursor("DefaultCursor"); + Canvas.setContent(EditorChooseLevelGui); +} else if ($startGUIEditor) { + Canvas.setCursor("DefaultCursor"); + Canvas.setContent(EditorChooseGUI); +} diff --git a/Templates/Full/game/runTests.cs b/Templates/Full/game/runTests.cs new file mode 100644 index 000000000..b6d903ff0 --- /dev/null +++ b/Templates/Full/game/runTests.cs @@ -0,0 +1,5 @@ +setLogMode(2); +$Con::LogBufferEnabled = false; +$Testing::CheckMemoryLeaks = false; +runAllUnitTests("-*.Stress*"); +quit(); diff --git a/Templates/Full/game/scripts/client/client.cs b/Templates/Full/game/scripts/client/client.cs index eff6c923a..689b79dff 100644 --- a/Templates/Full/game/scripts/client/client.cs +++ b/Templates/Full/game/scripts/client/client.cs @@ -145,6 +145,9 @@ function clientCmdtoggleVehicleMap(%toggle) if(%toggle) { moveMap.pop(); + // clear movement + $mvForwardAction = 0; + $mvBackwardAction = 0; vehicleMap.push(); } else diff --git a/Templates/Full/game/scripts/client/default.bind.cs b/Templates/Full/game/scripts/client/default.bind.cs index 803124bc0..17092d5b2 100644 --- a/Templates/Full/game/scripts/client/default.bind.cs +++ b/Templates/Full/game/scripts/client/default.bind.cs @@ -734,3 +734,11 @@ vehicleMap.bindCmd(keyboard, "escape", "", "handleEscape();"); vehicleMap.bind( keyboard, v, toggleFreeLook ); // v for vanity //vehicleMap.bind(keyboard, tab, toggleFirstPerson ); vehicleMap.bind(keyboard, "alt c", toggleCamera); +// bind the left thumbstick for steering +vehicleMap.bind( gamepad, thumblx, "D", "-0.23 0.23", gamepadYaw ); +// bind the gas, break, and reverse buttons +vehicleMap.bind( gamepad, btn_a, moveforward ); +vehicleMap.bind( gamepad, btn_b, brake ); +vehicleMap.bind( gamepad, btn_x, movebackward ); +// bind exiting the vehicle to a button +vehicleMap.bindCmd(gamepad, btn_y,"getout();",""); diff --git a/Templates/Full/game/scripts/client/init.cs b/Templates/Full/game/scripts/client/init.cs index 3f7f2d96a..56da1c945 100644 --- a/Templates/Full/game/scripts/client/init.cs +++ b/Templates/Full/game/scripts/client/init.cs @@ -73,8 +73,8 @@ function initClient() // Load up the Game GUIs exec("art/gui/defaultGameProfiles.cs"); - exec("art/gui/PlayGui.gui"); - exec("art/gui/ChatHud.gui"); + exec("art/gui/playGui.gui"); + exec("art/gui/chatHud.gui"); exec("art/gui/playerList.gui"); exec("art/gui/hudlessGui.gui"); diff --git a/Templates/Full/game/shaders/common/gl/blurP.glsl b/Templates/Full/game/shaders/common/gl/blurP.glsl index bc05b992f..5c37ebc6b 100644 --- a/Templates/Full/game/shaders/common/gl/blurP.glsl +++ b/Templates/Full/game/shaders/common/gl/blurP.glsl @@ -26,12 +26,12 @@ uniform vec4 kernel; uniform sampler2D diffuseMap; -varying vec2 texc0, texc1, texc2, texc3; +in vec2 texc0, texc1, texc2, texc3; void main() { - gl_FragColor = texture2D(diffuseMap, texc0) * kernel.x; - gl_FragColor += texture2D(diffuseMap, texc1) * kernel.y; - gl_FragColor += texture2D(diffuseMap, texc2) * kernel.z; - gl_FragColor += texture2D(diffuseMap, texc3) * kernel.w; + OUT_FragColor0 = texture(diffuseMap, texc0) * kernel.x; + OUT_FragColor0 += texture(diffuseMap, texc1) * kernel.y; + OUT_FragColor0 += texture(diffuseMap, texc2) * kernel.z; + OUT_FragColor0 += texture(diffuseMap, texc3) * kernel.w; } diff --git a/Templates/Full/game/shaders/common/gl/blurV.glsl b/Templates/Full/game/shaders/common/gl/blurV.glsl index d5d615fb9..1bfb0cd1b 100644 --- a/Templates/Full/game/shaders/common/gl/blurV.glsl +++ b/Templates/Full/game/shaders/common/gl/blurV.glsl @@ -24,20 +24,25 @@ // Glow shader //***************************************************************************** +in vec4 vPosition; +in vec4 vColor; +in vec2 vTexCoord0; + uniform mat4 modelview; uniform vec2 offset0, offset1, offset2, offset3; -varying vec2 texc0, texc1, texc2, texc3; +out vec2 texc0, texc1, texc2, texc3; void main() { - gl_Position = modelview * gl_Vertex; + gl_Position = modelview * vPosition; - vec2 tc = gl_MultiTexCoord0.st; + vec2 tc = vTexCoord0.st; tc.y = 1.0 - tc.y; texc0 = tc + offset0; texc1 = tc + offset1; texc2 = tc + offset2; texc3 = tc + offset3; + gl_Position.y *= -1; } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/gl/cloudLayerP.glsl b/Templates/Full/game/shaders/common/gl/cloudLayerP.glsl index 326f2d3c6..da3996d58 100644 --- a/Templates/Full/game/shaders/common/gl/cloudLayerP.glsl +++ b/Templates/Full/game/shaders/common/gl/cloudLayerP.glsl @@ -22,12 +22,20 @@ #include "hlslCompat.glsl" -varying vec4 texCoord12; -varying vec4 texCoord34; -varying vec3 vLightTS; // light vector in tangent space, denormalized -varying vec3 vViewTS; // view vector in tangent space, denormalized -varying vec3 vNormalWS; // Normal vector in world space -varying float worldDist; +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- +//ConnectData +in vec4 texCoord12; +#define IN_texCoord12 texCoord12 +in vec4 texCoord34; +#define IN_texCoord34 texCoord34 +in vec3 vLightTS; // light vector in tangent space, denormalized +#define IN_vLightTS vLightTS +in vec3 vViewTS; // view vector in tangent space, denormalized +#define IN_vViewTS vViewTS +in float worldDist; +#define IN_worldDist worldDist //----------------------------------------------------------------------------- // Uniforms @@ -37,6 +45,7 @@ uniform vec3 ambientColor; uniform vec3 sunColor; uniform float cloudCoverage; uniform vec3 cloudBaseColor; +uniform float cloudExposure; //----------------------------------------------------------------------------- // Globals @@ -97,26 +106,25 @@ void main() // Normalize the interpolated vectors: vec3 vViewTS = normalize( vViewTS ); vec3 vLightTS = normalize( vLightTS ); - vec3 vNormalWS = normalize( vNormalWS ); - vec4 cResultColor = float4( 0, 0, 0, 1 ); + vec4 cResultColor = vec4( 0, 0, 0, 1 ); - vec2 texSample = texCoord12.xy; + vec2 texSample = IN_texCoord12.xy; - vec4 noise1 = texture2D( normalHeightMap, texCoord12.zw ); + vec4 noise1 = texture( normalHeightMap, IN_texCoord12.zw ); noise1 = normalize( ( noise1 - 0.5 ) * 2.0 ); //return noise1; - vec4 noise2 = texture2D( normalHeightMap, texCoord34.xy ); + vec4 noise2 = texture( normalHeightMap, IN_texCoord34.xy ); noise2 = normalize( ( noise2 - 0.5 ) * 2.0 ); //return noise2; vec3 noiseNormal = normalize( noise1 + noise2 ).xyz; - //return float4( noiseNormal, 1.0 ); + //return vec4( noiseNormal, 1.0 ); float noiseHeight = noise1.a * noise2.a * ( cloudCoverage / 2.0 + 0.5 ); - vec3 vNormalTS = normalize( texture2D( normalHeightMap, texSample ).xyz * 2.0 - 1.0 ); + vec3 vNormalTS = normalize( texture( normalHeightMap, texSample ).xyz * 2.0 - 1.0 ); vNormalTS += noiseNormal; vNormalTS = normalize( vNormalTS ); @@ -124,16 +132,14 @@ void main() cResultColor.rgb = ComputeIllumination( texSample, vLightTS, vViewTS, vNormalTS ); float coverage = ( cloudCoverage - 0.5 ) * 2.0; - cResultColor.a = texture2D( normalHeightMap, texSample ).a + coverage + noiseHeight; + cResultColor.a = texture( normalHeightMap, texSample ).a + coverage + noiseHeight; if ( cloudCoverage > -1.0 ) cResultColor.a /= 1.0 + coverage; - cResultColor.a = saturate( cResultColor.a * pow( saturate(cloudCoverage), 0.25 ) ); + cResultColor.a = clamp( cResultColor.a * pow( saturate(cloudCoverage), 0.25 ), 0.0, 1.0 ); - cResultColor.a = mix( cResultColor.a, 0.0, 1.0 - pow(worldDist,2.0) ); + cResultColor.a = mix( cResultColor.a, 0.0, 1.0 - pow(IN_worldDist,2.0) ); - // If using HDR rendering, make sure to tonemap the resuld color prior to outputting it. - // But since this example isn't doing that, we just output the computed result color here: - gl_FragColor = cResultColor; + OUT_FragColor0 = cResultColor; } diff --git a/Templates/Full/game/shaders/common/gl/cloudLayerV.glsl b/Templates/Full/game/shaders/common/gl/cloudLayerV.glsl index 39a6f4ba8..395c6f286 100644 --- a/Templates/Full/game/shaders/common/gl/cloudLayerV.glsl +++ b/Templates/Full/game/shaders/common/gl/cloudLayerV.glsl @@ -20,12 +20,24 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -varying vec4 texCoord12; -varying vec4 texCoord34; -varying vec3 vLightTS; // light vector in tangent space, denormalized -varying vec3 vViewTS; // view vector in tangent space, denormalized -varying vec3 vNormalWS; // Normal vector in world space -varying float worldDist; +#include "hlslCompat.glsl" + +in vec4 vPosition; +in vec3 vNormal; +in vec3 vBinormal; +in vec3 vTangent; +in vec2 vTexCoord0; + +out vec4 texCoord12; +#define OUT_texCoord12 texCoord12 +out vec4 texCoord34; +#define OUT_texCoord34 texCoord34 +out vec3 vLightTS; // light vector in tangent space, denormalized +#define OUT_vLightTS vLightTS +out vec3 vViewTS; // view vector in tangent space, denormalized +#define OUT_vViewTS vViewTS +out float worldDist; +#define OUT_worldDist worldDist //----------------------------------------------------------------------------- // Uniforms @@ -43,37 +55,37 @@ uniform vec3 texScale; //----------------------------------------------------------------------------- void main() { - vec4 pos = gl_Vertex; - vec3 normal = gl_Normal; - vec3 binormal = gl_MultiTexCoord0.xyz; - vec3 tangent = gl_MultiTexCoord1.xyz; - vec2 uv0 = gl_MultiTexCoord2.st; + vec4 IN_pos = vPosition; + vec3 IN_normal = vNormal; + vec3 IN_binormal = vBinormal; + vec3 IN_tangent = vTangent; + vec2 IN_uv0 = vTexCoord0.st; - gl_Position = modelview * pos; + gl_Position = modelview * IN_pos; // Offset the uv so we don't have a seam directly over our head. - vec2 uv = uv0 + vec2( 0.5, 0.5 ); + vec2 uv = IN_uv0 + vec2( 0.5, 0.5 ); - texCoord12.xy = uv * texScale.x; - texCoord12.xy += texOffset0; + OUT_texCoord12.xy = uv * texScale.x; + OUT_texCoord12.xy += texOffset0; - texCoord12.zw = uv * texScale.y; - texCoord12.zw += texOffset1; + OUT_texCoord12.zw = uv * texScale.y; + OUT_texCoord12.zw += texOffset1; - texCoord34.xy = uv * texScale.z; - texCoord34.xy += texOffset2; + OUT_texCoord34.xy = uv * texScale.z; + OUT_texCoord34.xy += texOffset2; - texCoord34.z = pos.z; - texCoord34.w = 0.0; + OUT_texCoord34.z = IN_pos.z; + OUT_texCoord34.w = 0.0; // Transform the normal, tangent and binormal vectors from object space to // homogeneous projection space: - vNormalWS = -normal; - vec3 vTangentWS = -tangent; - vec3 vBinormalWS = -binormal; + vec3 vNormalWS = -IN_normal; + vec3 vTangentWS = -IN_tangent; + vec3 vBinormalWS = -IN_binormal; // Compute position in world space: - vec4 vPositionWS = pos + vec4( eyePosWorld, 1 ); //mul( pos, objTrans ); + vec4 vPositionWS = IN_pos + vec4( eyePosWorld, 1 ); //tMul( IN_pos, objTrans ); // Compute and output the world view vector (unnormalized): vec3 vViewWS = eyePosWorld - vPositionWS.xyz; @@ -81,12 +93,14 @@ void main() // Compute denormalized light vector in world space: vec3 vLightWS = -sunVec; - // Normalize the light and view vectors and transform it to the tangent space: + // Normalize the light and view vectors and transform it to the IN_tangent space: mat3 mWorldToTangent = mat3( vTangentWS, vBinormalWS, vNormalWS ); // Propagate the view and the light vectors (in tangent space): - vLightTS = mWorldToTangent * vLightWS; - vViewTS = vViewWS * mWorldToTangent; - - worldDist = clamp( pow( pos.z, 2.0 ), 0.0, 1.0 ); + OUT_vLightTS = vLightWS * mWorldToTangent; + OUT_vViewTS = mWorldToTangent * vViewWS; + + OUT_worldDist = clamp( pow( max( IN_pos.z, 0 ), 2 ), 0.0, 1.0 ); + + correctSSP(gl_Position); } diff --git a/Templates/Full/game/shaders/common/gl/foliage.glsl b/Templates/Full/game/shaders/common/gl/foliage.glsl index 2fee902e3..38b66e767 100644 --- a/Templates/Full/game/shaders/common/gl/foliage.glsl +++ b/Templates/Full/game/shaders/common/gl/foliage.glsl @@ -46,7 +46,19 @@ uniform vec3 gc_gustInfo; uniform vec2 gc_turbInfo; -//static float sMovableCorner[4] = { 0.0, 0.0, 1.0, 1.0 }; +const float sCornerRight[4] = float[]( -0.5, 0.5, 0.5, -0.5 ); + +const float sCornerUp[4] = float[]( 0, 0, 1, 1 ); + +const float sMovableCorner[4] = float[]( 0, 0, 1, 1 ); + +const vec2 sUVCornerExtent[4] = vec2[] +( + vec2( 0, 1 ), + vec2( 1, 1 ), + vec2( 1, 0 ), + vec2( 0, 0 ) +); /////////////////////////////////////////////////////////////////////////////// @@ -106,34 +118,13 @@ vec2 windEffect( float bbPhase, void foliageProcessVert( inout vec3 position, inout vec4 diffuse, - in vec4 texCoord, - out vec2 outTexCoord, + inout vec4 texCoord, inout vec3 normal, inout vec3 T, in vec3 eyePos ) { - - float sCornerRight[4]; - sCornerRight[0] = -0.5; - sCornerRight[1] = 0.5; - sCornerRight[2] = 0.5; - sCornerRight[3] = -0.5; - - float sCornerUp[4]; - sCornerUp[0] = 0.0; - sCornerUp[1] = 0.0; - sCornerUp[2] = 1.0; - sCornerUp[3] = 1.0; - - vec2 sUVCornerExtent[4]; - sUVCornerExtent[0] = vec2( 0.0, 1.0 ); - sUVCornerExtent[1] = vec2( 1.0, 1.0 ); - sUVCornerExtent[2] = vec2( 1.0, 0.0 ); - sUVCornerExtent[3] = vec2( 0.0, 0.0 ); - - // Assign the normal and tagent values. - //normal = cross( gc_camUp, gc_camRight ); + //normal = vec3( 0, 0, 1 );//cross( gc_camUp, gc_camRight ); T = gc_camRight; // Pull out local vars we need for work. @@ -172,8 +163,8 @@ void foliageProcessVert( inout vec3 position, // Grab the uv set and setup the texture coord. vec4 uvSet = gc_typeRects[type]; - outTexCoord.x = uvSet.x + ( uvSet.z * sUVCornerExtent[corner].x ); - outTexCoord.y = uvSet.y + ( uvSet.w * sUVCornerExtent[corner].y ); + texCoord.x = uvSet.x + ( uvSet.z * sUVCornerExtent[corner].x ); + texCoord.y = uvSet.y + ( uvSet.w * sUVCornerExtent[corner].y ); // Animate the normal to get lighting changes // across the the wind swept foliage. @@ -184,7 +175,6 @@ void foliageProcessVert( inout vec3 position, normal.xy += wind.xy * ( 10.0 * texCoord.w ); normal = normalize( normal ); - // Get the alpha fade value. float fadeStart = gc_fadeParams.x; diff --git a/Templates/Full/game/shaders/common/gl/fxFoliageReplicatorP.glsl b/Templates/Full/game/shaders/common/gl/fxFoliageReplicatorP.glsl index 9e5b34caa..fb5abb91e 100644 --- a/Templates/Full/game/shaders/common/gl/fxFoliageReplicatorP.glsl +++ b/Templates/Full/game/shaders/common/gl/fxFoliageReplicatorP.glsl @@ -26,15 +26,15 @@ uniform sampler2D diffuseMap, alphaMap; uniform vec4 groundAlpha; -varying vec4 color, groundAlphaCoeff; -varying vec2 outTexCoord, alphaLookup; +in vec4 color, groundAlphaCoeff; +in vec2 outTexCoord, alphaLookup; //----------------------------------------------------------------------------- // Main //----------------------------------------------------------------------------- void main() { - vec4 alpha = texture2D(alphaMap, alphaLookup); - gl_FragColor = color * texture2D(diffuseMap, outTexCoord); - gl_FragColor.a = gl_FragColor.a * min(alpha, groundAlpha + groundAlphaCoeff.x).x; + vec4 alpha = texture(alphaMap, alphaLookup); + OUT_FragColor0 = color * texture(diffuseMap, outTexCoord); + OUT_FragColor0.a = OUT_FragColor0.a * min(alpha, groundAlpha + groundAlphaCoeff.x).x; } diff --git a/Templates/Full/game/shaders/common/gl/fxFoliageReplicatorV.glsl b/Templates/Full/game/shaders/common/gl/fxFoliageReplicatorV.glsl index 94a7af2b0..c8dcf1ddb 100644 --- a/Templates/Full/game/shaders/common/gl/fxFoliageReplicatorV.glsl +++ b/Templates/Full/game/shaders/common/gl/fxFoliageReplicatorV.glsl @@ -23,13 +23,20 @@ //----------------------------------------------------------------------------- // Data //----------------------------------------------------------------------------- +in vec4 vPosition; +in vec3 vNormal; +in vec4 vColor; +in vec2 vTexCoord0; +in vec2 vTexCoord1; +in vec2 vTexCoord2; + uniform mat4 projection, world; uniform vec3 CameraPos; uniform float GlobalSwayPhase, SwayMagnitudeSide, SwayMagnitudeFront, GlobalLightPhase, LuminanceMagnitude, LuminanceMidpoint, DistanceRange; -varying vec4 color, groundAlphaCoeff; -varying vec2 outTexCoord, alphaLookup; +out vec4 color, groundAlphaCoeff; +out vec2 outTexCoord, alphaLookup; //----------------------------------------------------------------------------- // Main @@ -42,9 +49,9 @@ void main() trans[1][1] = 1.0; trans[2][2] = 1.0; trans[3][3] = 1.0; - trans[3][0] = gl_Vertex.x; - trans[3][1] = gl_Vertex.y; - trans[3][2] = gl_Vertex.z; + trans[3][0] = vPosition.x; + trans[3][1] = vPosition.y; + trans[3][2] = vPosition.z; // Billboard transform * world matrix mat4 o = world; @@ -64,28 +71,29 @@ void main() // Handle sway. Sway is stored in a texture coord. The x coordinate is the sway phase multiplier, // the y coordinate determines if this vertex actually sways or not. float xSway, ySway; - float wavePhase = GlobalSwayPhase * gl_MultiTexCoord1.x; + float wavePhase = GlobalSwayPhase * vTexCoord1.x; ySway = sin(wavePhase); xSway = cos(wavePhase); - xSway = xSway * gl_MultiTexCoord1.y * SwayMagnitudeSide; - ySway = ySway * gl_MultiTexCoord1.y * SwayMagnitudeFront; + xSway = xSway * vTexCoord1.y * SwayMagnitudeSide; + ySway = ySway * vTexCoord1.y * SwayMagnitudeFront; vec4 p; - p = o * vec4(gl_Normal.x + xSway, ySway, gl_Normal.z, 1.0); + p = o * vec4(vNormal.x + xSway, ySway, vNormal.z, 1.0); // Project the point gl_Position = projection * p; // Lighting - float Luminance = LuminanceMidpoint + LuminanceMagnitude * cos(GlobalLightPhase + gl_Normal.y); + float Luminance = LuminanceMidpoint + LuminanceMagnitude * cos(GlobalLightPhase + vNormal.y); // Alpha - vec3 worldPos = vec3(gl_Vertex.x, gl_Vertex.y, gl_Vertex.z); + vec3 worldPos = vec3(vPosition.x, vPosition.y, vPosition.z); float alpha = abs(distance(worldPos, CameraPos)) / DistanceRange; alpha = clamp(alpha, 0.0, 1.0); //pass it through alphaLookup = vec2(alpha, 0.0); - bool alphaCoeff = bool(gl_Normal.z); + bool alphaCoeff = bool(vNormal.z); groundAlphaCoeff = vec4(float(alphaCoeff)); - outTexCoord = gl_MultiTexCoord0.st; + outTexCoord = vTexCoord0.st; color = vec4(Luminance, Luminance, Luminance, 1.0); + gl_Position.y *= -1; } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/gl/guiMaterialV.glsl b/Templates/Full/game/shaders/common/gl/guiMaterialV.glsl index cd44de2f2..de3845ee7 100644 --- a/Templates/Full/game/shaders/common/gl/guiMaterialV.glsl +++ b/Templates/Full/game/shaders/common/gl/guiMaterialV.glsl @@ -20,16 +20,20 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +in vec4 vPosition; +in vec2 vTexCoord0; + uniform mat4x4 modelview; -varying vec4 hpos; -varying vec2 uv0; +out vec4 hpos; +out vec2 uv0; void main() { - hpos = vec4( modelview * gl_Vertex ); + hpos = vec4( modelview * vPosition ); gl_Position = hpos; - uv0 = gl_MultiTexCoord0.st; + uv0 = vTexCoord0.st; + gl_Position.y *= -1; } diff --git a/Templates/Full/game/shaders/common/gl/hlslCompat.glsl b/Templates/Full/game/shaders/common/gl/hlslCompat.glsl index be5c63340..0815df51f 100644 --- a/Templates/Full/game/shaders/common/gl/hlslCompat.glsl +++ b/Templates/Full/game/shaders/common/gl/hlslCompat.glsl @@ -27,17 +27,79 @@ #define float3 vec3 #define float2 vec2 -#define texCUBE textureCube -#define tex2D texture2D +#define half float +#define half2 vec2 +#define half3 vec3 +#define half4 vec4 + +#define float4x4 mat4 +#define float3x3 mat3 +#define float2x2 mat2 + +#define texCUBE texture +#define tex2D texture +#define tex1D texture +#define tex2Dproj textureProj +#define tex2Dlod( sampler, texCoord ) textureLod(sampler, texCoord.xy, texCoord.w) + +#define samplerCUBE samplerCube + +#define frac fract #define lerp mix -float saturate( float val ) { return clamp( val, 0.0, 1.0 ); } -vec2 saturate( vec2 val ) { return clamp( val, 0.0, 1.0 ); } -vec3 saturate( vec3 val ) { return clamp( val, 0.0, 1.0 ); } -vec4 saturate( vec4 val ) { return clamp( val, 0.0, 1.0 ); } +void tSetMatrixRow(out float3x3 m, int row, float3 value) +{ + m[0][row] = value.x; + m[1][row] = value.y; + m[2][row] = value.z; +} -float round( float n ) { return sign( n ) * floor( abs( n ) + 0.5 ); } -vec2 round( vec2 n ) { return sign( n ) * floor( abs( n ) + 0.5 ); } -vec3 round( vec3 n ) { return sign( n ) * floor( abs( n ) + 0.5 ); } -vec4 round( vec4 n ) { return sign( n ) * floor( abs( n ) + 0.5 ); } +void tSetMatrixRow(out float4x4 m, int row, float4 value) +{ + m[0][row] = value.x; + m[1][row] = value.y; + m[2][row] = value.z; + m[3][row] = value.w; +} + +#define tGetMatrix3Row(matrix, row) float3(matrix[0][row], matrix[1][row], matrix[2][row]) +#define tGetMatrix4Row(matrix, row) float4(matrix[0][row], matrix[1][row], matrix[2][row], matrix[3][row]) + +float3x3 float4x4to3x3(float4x4 m) +{ + return float3x3( vec3(m[0]).xyz, m[1].xyz, m[2].xyz); +} + +float3x3 float4x4to3x3_(float4x4 m) +{ + return float3x3( vec3(m[0]), m[1].xyz, m[2].xyz); +} + +mat4 mat4FromRow( float r0c0, float r0c1, float r0c2, float r0c3, + float r1c0, float r1c1, float r1c2, float r1c3, + float r2c0, float r2c1, float r2c2, float r2c3, + float r3c0, float r3c1, float r3c2, float r3c3 ) +{ + return mat4( r0c0, r1c0, r2c0, r3c0, + r0c1, r1c1, r2c1, r3c1, + r0c2, r1c2, r2c2, r3c2, + r0c3, r1c3, r2c3, r3c3 ); +} + + +#define saturate( val ) clamp( val, 0.0, 1.0 ) + +#define round( n ) (sign( n ) * floor( abs( n ) + 0.5 )) + +#define tMul(a, b) (a*b) + +#define inversesqrt( n ) inversesqrt( n ) + +#define correctSSP(vec) vec.y *= -1 + +#ifdef TORQUE_PIXEL_SHADER + void clip(float a) { if(a < 0) discard;} + + out vec4 OUT_FragColor0; +#endif diff --git a/Templates/Full/game/shaders/common/gl/lighting.glsl b/Templates/Full/game/shaders/common/gl/lighting.glsl index 3f8867d3b..4483c7526 100644 --- a/Templates/Full/game/shaders/common/gl/lighting.glsl +++ b/Templates/Full/game/shaders/common/gl/lighting.glsl @@ -20,73 +20,181 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- + +#ifndef TORQUE_SHADERGEN + // These are the uniforms used by most lighting shaders. -uniform vec3 inLightPos[4]; +uniform vec4 inLightPos[3]; uniform vec4 inLightInvRadiusSq; uniform vec4 inLightColor[4]; + +#ifndef TORQUE_BL_NOSPOTLIGHT + uniform vec4 inLightSpotDir[3]; + uniform vec4 inLightSpotAngle; + uniform vec4 inLightSpotFalloff; +#endif + uniform vec4 ambient; uniform float specularPower; uniform vec4 specularColor; - -// This is used to limit the maximum processed -// lights in the compute4Lights down for really -// low end GPUs. -// -// NOTE: If you want to support 10.5.x, this needs to be changed to 2. -#define C4L_MAX_LIGHTS 4 +#endif // !TORQUE_SHADERGEN void compute4Lights( vec3 wsView, vec3 wsPosition, - vec3 wsNormal, + vec3 wsNormal, + vec4 shadowMask, + + #ifdef TORQUE_SHADERGEN + + vec4 inLightPos[3], + vec4 inLightInvRadiusSq, + vec4 inLightColor[4], + vec4 inLightSpotDir[3], + vec4 inLightSpotAngle, + vec4 inLightSpotFalloff, + float specularPower, + vec4 specularColor, + + #endif // TORQUE_SHADERGEN + out vec4 outDiffuse, out vec4 outSpecular ) { - #ifdef PHONG_SPECULAR - // (R.V)^c - float reflected = reflect( wsView, wsNormal ); - #endif - - vec4 nDotL = vec4( 0.0 ); - vec4 rDotL = vec4( 0.0 ); - vec4 sqDists = vec4( 0.0 ); + // NOTE: The light positions and spotlight directions + // are stored in SoA order, so inLightPos[0] is the + // x coord for all 4 lights... inLightPos[1] is y... etc. + // + // This is the key to fully utilizing the vector units and + // saving a huge amount of instructions. + // + // For example this change saved more than 10 instructions + // over a simple for loop for each light. + int i; - for ( i = 0; i < C4L_MAX_LIGHTS; ++i ) - { - vec3 lightVector = inLightPos[i] - wsPosition; - vec3 lightDirection = normalize( lightVector ); + vec4 lightVectors[3]; + for ( i = 0; i < 3; i++ ) + lightVectors[i] = wsPosition[i] - inLightPos[i]; - nDotL[i] = max( dot( lightDirection, wsNormal ), 0.0 ); + vec4 squareDists = vec4(0); + for ( i = 0; i < 3; i++ ) + squareDists += lightVectors[i] * lightVectors[i]; - #ifdef PHONG_SPECULAR - rDotL[i] = saturate( dot( lightDirection, reflected ) ); - #else - // (N.H)^c [Blinn-Phong, TGEA style, default] - rDotL[i] = dot( wsNormal, normalize( lightDirection + wsView ) ); - #endif + // Accumulate the dot product between the light + // vector and the normal. + // + // The normal is negated because it faces away from + // the surface and the light faces towards the + // surface... this keeps us from needing to flip + // the light vector direction which complicates + // the spot light calculations. + // + // We normalize the result a little later. + // + vec4 nDotL = vec4(0); + for ( i = 0; i < 3; i++ ) + nDotL += lightVectors[i] * -wsNormal[i]; - sqDists[i] = dot( lightVector, lightVector ); - } + vec4 rDotL = vec4(0); + #ifndef TORQUE_BL_NOSPECULAR - // Attenuation - vec4 atten = vec4( 1.0 ) - ( sqDists * inLightInvRadiusSq ); + // We're using the Phong specular reflection model + // here where traditionally Torque has used Blinn-Phong + // which has proven to be more accurate to real materials. + // + // We do so because its cheaper as do not need to + // calculate the half angle for all 4 lights. + // + // Advanced Lighting still uses Blinn-Phong, but the + // specular reconstruction it does looks fairly similar + // to this. + // + vec3 R = reflect( wsView, -wsNormal ); + + for ( i = 0; i < 3; i++ ) + rDotL += lightVectors[i] * R[i]; + + #endif + + // Normalize the dots. + // + // Notice we're using the half type here to get a + // much faster sqrt via the rsq_pp instruction at + // the loss of some precision. + // + // Unless we have some extremely large point lights + // i don't believe the precision loss will matter. + // + half4 correction = half4(inversesqrt( squareDists )); + nDotL = saturate( nDotL * correction ); + rDotL = clamp( rDotL * correction, 0.00001, 1.0 ); + + // First calculate a simple point light linear + // attenuation factor. + // + // If this is a directional light the inverse + // radius should be greater than the distance + // causing the attenuation to have no affect. + // + vec4 atten = saturate( 1.0 - ( squareDists * inLightInvRadiusSq ) ); + + #ifndef TORQUE_BL_NOSPOTLIGHT + + // The spotlight attenuation factor. This is really + // fast for what it does... 6 instructions for 4 spots. + + vec4 spotAtten = vec4(0); + for ( i = 0; i < 3; i++ ) + spotAtten += lightVectors[i] * inLightSpotDir[i]; + + vec4 cosAngle = ( spotAtten * correction ) - inLightSpotAngle; + atten *= saturate( cosAngle * inLightSpotFalloff ); + + #endif + + // Finally apply the shadow masking on the attenuation. + atten *= shadowMask; + + // Get the final light intensity. + vec4 intensity = nDotL * atten; // Combine the light colors for output. - vec4 diffuse = clamp( nDotL * atten, vec4( 0.0 ), vec4( 1.0 ) ); - outDiffuse = vec4( 0.0 ); - for ( i = 0; i < C4L_MAX_LIGHTS; ++i ) - outDiffuse += vec4( diffuse[i] ) * inLightColor[i]; + outDiffuse = vec4(0); + for ( i = 0; i < 4; i++ ) + outDiffuse += intensity[i] * inLightColor[i]; // Output the specular power. - rDotL = max( rDotL, vec4( 0.00001 ) ); - outSpecular = pow( rDotL, vec4( specularPower ) ); + vec4 specularIntensity = pow( rDotL, vec4(specularPower) ) * atten; + + // Apply the per-light specular attenuation. + vec4 specular = vec4(0,0,0,1); + for ( i = 0; i < 4; i++ ) + specular += vec4( inLightColor[i].rgb * inLightColor[i].a * specularIntensity[i], 1 ); + + // Add the final specular intensity values together + // using a single dot product operation then get the + // final specular lighting color. + outSpecular = specularColor * specular; } -/// The standard specular calculation. +// This value is used in AL as a constant power to raise specular values +// to, before storing them into the light info buffer. The per-material +// specular value is then computer by using the integer identity of +// exponentiation: +// +// (a^m)^n = a^(m*n) +// +// or +// +// (specular^constSpecular)^(matSpecular/constSpecular) = specular^(matSpecular*constSpecular) +// +#define AL_ConstantSpecularPower 12.0f + +/// The specular calculation used in Advanced Lighting. /// /// @param toLight Normalized vector representing direction from the pixel /// being lit, to the light source, in world space. @@ -96,11 +204,7 @@ void compute4Lights( vec3 wsView, /// @param toEye The normalized vector representing direction from the pixel /// being lit to the camera. /// -/// @param specPwr The specular exponent. -/// -/// @param specScale A scalar on the specular output used in RGB accumulation. -/// -float calcSpecular( vec3 toLight, vec3 normal, vec3 toEye, float specPwr ) +float AL_CalcSpecular( vec3 toLight, vec3 normal, vec3 toEye ) { #ifdef PHONG_SPECULAR // (R.V)^c @@ -111,5 +215,5 @@ float calcSpecular( vec3 toLight, vec3 normal, vec3 toEye, float specPwr ) #endif // Return the specular factor. - return pow( max( specVal, 0.00001f ), specPwr ); + return pow( max( specVal, 0.00001f ), AL_ConstantSpecularPower ); } diff --git a/Templates/Full/game/shaders/common/gl/particleCompositeP.glsl b/Templates/Full/game/shaders/common/gl/particleCompositeP.glsl index 4f2d9b359..6971e1013 100644 --- a/Templates/Full/game/shaders/common/gl/particleCompositeP.glsl +++ b/Templates/Full/game/shaders/common/gl/particleCompositeP.glsl @@ -21,6 +21,13 @@ //----------------------------------------------------------------------------- #include "torque.glsl" +#include "hlslCompat.glsl" + +in vec4 offscreenPos; +in vec4 backbufferPos; + +#define IN_offscreenPos offscreenPos +#define IN_backbufferPos backbufferPos uniform sampler2D colorSource; uniform vec4 offscreenTargetParams; @@ -31,8 +38,6 @@ uniform sampler2D edgeSource; uniform vec4 edgeTargetParams; #endif -varying vec4 backbufferPos; -varying vec4 offscreenPos; void main() { @@ -47,11 +52,10 @@ void main() #ifdef REJECT_EDGES // Cut out particles along the edges, this will create the stencil mask uvScene.zw = viewportCoordToRenderTarget(uvScene.zw, edgeTargetParams); - float edge = texture2D( edgeSource, uvScene.zw ).r; - if (-edge < 0.0) - discard; + float edge = texture( edgeSource, uvScene.zw ).r; + clip( -edge ); #endif // Sample offscreen target and return - gl_FragColor = texture2D( colorSource, uvScene.xy ); -} + OUT_FragColor0 = texture( colorSource, uvScene.xy ); +} \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/gl/particleCompositeV.glsl b/Templates/Full/game/shaders/common/gl/particleCompositeV.glsl index 88a9431d1..8c8f840d1 100644 --- a/Templates/Full/game/shaders/common/gl/particleCompositeV.glsl +++ b/Templates/Full/game/shaders/common/gl/particleCompositeV.glsl @@ -20,16 +20,29 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -uniform mat4 modelViewProj; -uniform mat4 targetModelViewProj; +#include "hlslCompat.glsl" -varying vec4 offscreenPos; -varying vec4 backbufferPos; +in vec2 vTexCoord0; +#define uvCoord vTexCoord0 + +out vec4 offscreenPos; +out vec4 backbufferPos; + +#define OUT_hpos gl_Position +#define OUT_offscreenPos offscreenPos +#define OUT_backbufferPos backbufferPos + +uniform vec4 screenRect; // point, extent void main() { - gl_Position = modelViewProj * gl_Vertex; - backbufferPos = gl_Position; - offscreenPos = targetModelViewProj * gl_Vertex; + OUT_hpos = vec4(uvCoord.xy, 1.0, 1.0); + OUT_hpos.xy *= screenRect.zw; + OUT_hpos.xy += screenRect.xy; + + OUT_backbufferPos = OUT_hpos; + OUT_offscreenPos = OUT_hpos; + + correctSSP(gl_Position); } diff --git a/Templates/Full/game/shaders/common/gl/particlesP.glsl b/Templates/Full/game/shaders/common/gl/particlesP.glsl index 66a3fee28..efd930302 100644 --- a/Templates/Full/game/shaders/common/gl/particlesP.glsl +++ b/Templates/Full/game/shaders/common/gl/particlesP.glsl @@ -20,63 +20,92 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -#include "hlslCompat.glsl" #include "torque.glsl" - +#include "hlslCompat.glsl" + // With advanced lighting we get soft particles. #ifdef TORQUE_LINEAR_DEPTH #define SOFTPARTICLES #endif -#define CLIP_Z // TODO: Make this a proper macro - -uniform sampler2D diffuseMap; - #ifdef SOFTPARTICLES #include "shadergen:/autogenConditioners.h" uniform float oneOverSoftness; uniform float oneOverFar; - uniform sampler2D prepassTex; + uniform sampler2D prepassTex; //uniform vec3 vEye; uniform vec4 prePassTargetParams; #endif +#define CLIP_Z // TODO: Make this a proper macro + +in vec4 color; +in vec2 uv0; +in vec4 pos; + +#define IN_color color +#define IN_uv0 uv0 +#define IN_pos pos + +uniform sampler2D diffuseMap; + +uniform sampler2D paraboloidLightMap; + +vec4 lmSample( vec3 nrm ) +{ + bool calcBack = (nrm.z < 0.0); + if ( calcBack ) + nrm.z = nrm.z * -1.0; + + vec2 lmCoord; + lmCoord.x = (nrm.x / (2*(1 + nrm.z))) + 0.5; + lmCoord.y = 1-((nrm.y / (2*(1 + nrm.z))) + 0.5); + + + // If this is the back, offset in the atlas + if ( calcBack ) + lmCoord.x += 1.0; + + // Atlasing front and back maps, so scale + lmCoord.x *= 0.5; + + return texture(paraboloidLightMap, lmCoord); +} + + uniform float alphaFactor; uniform float alphaScale; -varying vec4 color; -varying vec2 uv0; -varying vec4 pos; - - void main() { - float softBlend = 1.0; + float softBlend = 1; #ifdef SOFTPARTICLES - float2 tc = pos.xy * vec2(1.0, -1.0 ) / pos.w; + vec2 tc = IN_pos.xy * vec2(1.0, -1.0) / IN_pos.w; tc = viewportCoordToRenderTarget(saturate( ( tc + 1.0 ) * 0.5 ), prePassTargetParams); float sceneDepth = prepassUncondition( prepassTex, tc ).w; - float depth = pos.w * oneOverFar; - float diff = sceneDepth - depth; + float depth = IN_pos.w * oneOverFar; + float diff = sceneDepth - depth; #ifdef CLIP_Z // If drawing offscreen, this acts as the depth test, since we don't line up with the z-buffer // When drawing high-res, though, we want to be able to take advantage of hi-z // so this is #ifdef'd out - if (diff < 0.0) - discard; + //clip(diff); #endif softBlend = saturate( diff * oneOverSoftness ); #endif - - vec4 diffuse = texture2D( diffuseMap, uv0 ); + + vec4 diffuse = texture( diffuseMap, IN_uv0 ); + + //OUT_FragColor0 = vec4( lmSample(vec3(0, 0, -1)).rgb, IN_color.a * diffuse.a * softBlend * alphaScale); // Scale output color by the alpha factor (turn LerpAlpha into pre-multiplied alpha) - vec3 colorScale = ( alphaFactor < 0.0 ? color.rgb * diffuse.rgb : ( alphaFactor > 0.0 ? vec3(color.a * alphaFactor * diffuse.a * softBlend) : vec3(softBlend) ) ); + vec3 colorScale = ( alphaFactor < 0.0 ? IN_color.rgb * diffuse.rgb : vec3( alphaFactor > 0.0 ? IN_color.a * diffuse.a * alphaFactor * softBlend : softBlend ) ); - gl_FragColor = hdrEncode( vec4(color.rgb * diffuse.rgb * colorScale, softBlend * color.a * diffuse.a * alphaScale) ); + OUT_FragColor0 = hdrEncode( vec4( IN_color.rgb * diffuse.rgb * colorScale, + IN_color.a * diffuse.a * softBlend * alphaScale ) ); } diff --git a/Templates/Full/game/shaders/common/gl/particlesV.glsl b/Templates/Full/game/shaders/common/gl/particlesV.glsl index da896431f..3d75a6fb6 100644 --- a/Templates/Full/game/shaders/common/gl/particlesV.glsl +++ b/Templates/Full/game/shaders/common/gl/particlesV.glsl @@ -20,18 +20,35 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -varying vec4 color; -varying vec2 uv0; -varying vec4 pos; +#include "hlslCompat.glsl" + +in vec4 vPosition; +in vec4 vColor; +in vec2 vTexCoord0; + +#define In_pos vPosition +#define In_color vColor +#define In_uv0 vTexCoord0 + +out vec4 color; +out vec2 uv0; +out vec4 pos; + +#define OUT_hpos gl_Position +#define OUT_color color +#define OUT_uv0 uv0 +#define OUT_pos pos uniform mat4 modelViewProj; uniform mat4 fsModelViewProj; void main() { - gl_Position = modelViewProj * gl_Vertex; - pos = fsModelViewProj * gl_Vertex; - color = gl_Color; - uv0 = gl_MultiTexCoord0.st; + OUT_hpos = tMul( modelViewProj, In_pos ); + OUT_pos = tMul( fsModelViewProj, In_pos ); + OUT_color = In_color; + OUT_uv0 = In_uv0; + + correctSSP(gl_Position); } diff --git a/Templates/Full/game/shaders/common/gl/planarReflectBumpP.glsl b/Templates/Full/game/shaders/common/gl/planarReflectBumpP.glsl index 00413aa3b..334c70a70 100644 --- a/Templates/Full/game/shaders/common/gl/planarReflectBumpP.glsl +++ b/Templates/Full/game/shaders/common/gl/planarReflectBumpP.glsl @@ -26,8 +26,8 @@ uniform sampler2D diffuseMap, refractMap, bumpMap; uniform vec4 shadeColor; -varying vec2 TEX0; -varying vec4 TEX1; +in vec2 TEX0; +in vec4 TEX1; //----------------------------------------------------------------------------- // Fade edges of axis for texcoord passed in @@ -49,7 +49,7 @@ float fadeAxis( float val ) //----------------------------------------------------------------------------- void main() { - vec3 bumpNorm = texture2D( bumpMap, TEX0 ).rgb * 2.0 - 1.0; + vec3 bumpNorm = texture( bumpMap, TEX0 ).rgb * 2.0 - 1.0; vec2 offset = vec2( bumpNorm.x, bumpNorm.y ); vec4 texIndex = TEX1; @@ -61,8 +61,8 @@ void main() const float distortion = 0.2; texIndex.xy += offset * distortion * fadeVal; - vec4 diffuseColor = texture2D( diffuseMap, TEX0 ); - vec4 reflectColor = texture2DProj( refractMap, texIndex ); + vec4 diffuseColor = texture( diffuseMap, TEX0 ); + vec4 reflectColor = textureProj( refractMap, texIndex ); - gl_FragColor = diffuseColor + reflectColor * diffuseColor.a; + OUT_FragColor0 = diffuseColor + reflectColor * diffuseColor.a; } diff --git a/Templates/Full/game/shaders/common/gl/planarReflectBumpV.glsl b/Templates/Full/game/shaders/common/gl/planarReflectBumpV.glsl index 820bdf698..90bcd27d8 100644 --- a/Templates/Full/game/shaders/common/gl/planarReflectBumpV.glsl +++ b/Templates/Full/game/shaders/common/gl/planarReflectBumpV.glsl @@ -23,10 +23,13 @@ //----------------------------------------------------------------------------- // Data //----------------------------------------------------------------------------- +in vec4 vPosition; +in vec2 vTexCoord0; + uniform mat4 modelview; -varying vec2 TEX0; -varying vec4 TEX1; +out vec2 TEX0; +out vec4 TEX1; //----------------------------------------------------------------------------- // Main @@ -38,11 +41,11 @@ void main() 0.0, 0.0, 1.0, 0.0, 0.5, 0.5, 0.0, 1.0); - gl_Position = modelview * gl_Vertex; + gl_Position = modelview * vPosition; - TEX0 = gl_MultiTexCoord0.st; + TEX0 = vTexCoord0.st; TEX1 = texGenTest * gl_Position; TEX1.y = -TEX1.y; - + gl_Position.y *= -1; } diff --git a/Templates/Full/game/shaders/common/gl/planarReflectP.glsl b/Templates/Full/game/shaders/common/gl/planarReflectP.glsl index b4f4fab39..77914b80e 100644 --- a/Templates/Full/game/shaders/common/gl/planarReflectP.glsl +++ b/Templates/Full/game/shaders/common/gl/planarReflectP.glsl @@ -26,16 +26,16 @@ uniform sampler2D diffuseMap, refractMap; uniform vec4 shadeColor; -varying vec2 TEX0; -varying vec4 TEX1; +in vec2 TEX0; +in vec4 TEX1; //----------------------------------------------------------------------------- // Main //----------------------------------------------------------------------------- void main() { - vec4 diffuseColor = texture2D( diffuseMap, TEX0 ); - vec4 reflectColor = texture2DProj( refractMap, TEX1 ); + vec4 diffuseColor = texture( diffuseMap, TEX0 ); + vec4 reflectColor = textureProj( refractMap, TEX1 ); - gl_FragColor = diffuseColor + reflectColor * diffuseColor.a; + OUT_FragColor0 = diffuseColor + reflectColor * diffuseColor.a; } diff --git a/Templates/Full/game/shaders/common/gl/planarReflectV.glsl b/Templates/Full/game/shaders/common/gl/planarReflectV.glsl index 820bdf698..ba2484f66 100644 --- a/Templates/Full/game/shaders/common/gl/planarReflectV.glsl +++ b/Templates/Full/game/shaders/common/gl/planarReflectV.glsl @@ -23,10 +23,13 @@ //----------------------------------------------------------------------------- // Data //----------------------------------------------------------------------------- +in vec4 vPosition; +in vec2 vTexCoord0; + uniform mat4 modelview; -varying vec2 TEX0; -varying vec4 TEX1; +out vec2 TEX0; +out vec4 TEX1; //----------------------------------------------------------------------------- // Main @@ -38,9 +41,9 @@ void main() 0.0, 0.0, 1.0, 0.0, 0.5, 0.5, 0.0, 1.0); - gl_Position = modelview * gl_Vertex; + gl_Position = modelview * vPosition; - TEX0 = gl_MultiTexCoord0.st; + TEX0 = vTexCoord0; TEX1 = texGenTest * gl_Position; TEX1.y = -TEX1.y; diff --git a/Templates/Full/game/shaders/common/gl/precipP.glsl b/Templates/Full/game/shaders/common/gl/precipP.glsl index a04f16e4b..3c669517d 100644 --- a/Templates/Full/game/shaders/common/gl/precipP.glsl +++ b/Templates/Full/game/shaders/common/gl/precipP.glsl @@ -25,13 +25,13 @@ //----------------------------------------------------------------------------- uniform sampler2D diffuseMap; -varying vec4 color; -varying vec2 texCoord; +in vec4 color; +in vec2 texCoord; //----------------------------------------------------------------------------- // Main //----------------------------------------------------------------------------- void main() { - gl_FragColor = texture2D(diffuseMap, texCoord) * color; + OUT_FragColor0 = texture(diffuseMap, texCoord) * color; } diff --git a/Templates/Full/game/shaders/common/gl/precipV.glsl b/Templates/Full/game/shaders/common/gl/precipV.glsl index 3535f2f38..29f921630 100644 --- a/Templates/Full/game/shaders/common/gl/precipV.glsl +++ b/Templates/Full/game/shaders/common/gl/precipV.glsl @@ -23,28 +23,32 @@ //----------------------------------------------------------------------------- // Data //----------------------------------------------------------------------------- +in vec4 vPosition; +in vec2 vTexCoord0; + uniform mat4 modelview; uniform vec3 cameraPos, ambient; uniform vec2 fadeStartEnd; -varying vec4 color; -varying vec2 texCoord; +out vec4 color; +out vec2 texCoord; //----------------------------------------------------------------------------- // Main //----------------------------------------------------------------------------- void main() { - gl_Position = modelview * gl_Vertex; - texCoord = gl_MultiTexCoord0.st; + gl_Position = modelview * vPosition; + texCoord = vTexCoord0.st; color = vec4( ambient.r, ambient.g, ambient.b, 1.0 ); // Do we need to do a distance fade? if ( fadeStartEnd.x < fadeStartEnd.y ) { - float distance = length( cameraPos - gl_Vertex.xyz ); + float distance = length( cameraPos - vPosition.xyz ); color.a = abs( clamp( ( distance - fadeStartEnd.x ) / ( fadeStartEnd.y - fadeStartEnd.x ), 0.0, 1.0 ) - 1.0 ); } + gl_Position.y *= -1; } diff --git a/Templates/Full/game/shaders/common/gl/projectedShadowP.glsl b/Templates/Full/game/shaders/common/gl/projectedShadowP.glsl index 1dc963a4f..8ce0fba13 100644 --- a/Templates/Full/game/shaders/common/gl/projectedShadowP.glsl +++ b/Templates/Full/game/shaders/common/gl/projectedShadowP.glsl @@ -20,9 +20,11 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -varying vec2 texCoord; -varying vec4 color; -varying float fade; +in vec2 texCoord; +in vec4 color; +in float fade; + +out vec4 OUT_FragColor0; uniform sampler2D inputTex; uniform vec4 ambient; @@ -30,17 +32,6 @@ uniform vec4 ambient; void main() { - vec3 LUMINANCE_VECTOR = vec3(0.2125f, 0.4154f, 0.1721f); - float esmFactor = 200.0; - - float lum = dot( ambient.rgb, LUMINANCE_VECTOR ); - - gl_FragColor.rgb = ambient.rgb * lum; - gl_FragColor.a = 0.0; - float depth = texture2D(inputTex, texCoord).a; - - depth = depth * exp(depth - 10.0); - depth = exp(esmFactor * depth) - 1.0; - - gl_FragColor.a = clamp(depth * 300.0, 0.0, 1.0) * (1.0 - lum) * fade * color.a; + float shadow = texture( inputTex, texCoord ).a * color.a; + OUT_FragColor0 = ( ambient * shadow ) + ( 1 - shadow ); } diff --git a/Templates/Full/game/shaders/common/gl/projectedShadowV.glsl b/Templates/Full/game/shaders/common/gl/projectedShadowV.glsl index c8abde742..b5de84181 100644 --- a/Templates/Full/game/shaders/common/gl/projectedShadowV.glsl +++ b/Templates/Full/game/shaders/common/gl/projectedShadowV.glsl @@ -20,13 +20,16 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -//***************************************************************************** -// Precipitation vertex shader -//***************************************************************************** +#include "hlslCompat.glsl" -varying vec2 texCoord; -varying vec4 color; -varying float fade; +in vec4 vPosition; +in vec4 vColor; +in vec2 vTexCoord0; +in vec2 vTexCoord1; + +out vec2 texCoord; +out vec4 color; +out float fade; uniform mat4 modelview; uniform float shadowLength; @@ -34,11 +37,13 @@ uniform vec3 shadowCasterPosition; void main() { - gl_Position = modelview * vec4(gl_Vertex.xyz, 1.0); + gl_Position = modelview * vec4(vPosition.xyz, 1.0); - color = gl_Color; - texCoord = gl_MultiTexCoord1.st; + color = vColor; + texCoord = vTexCoord1.st; - float fromCasterDist = length(gl_Vertex.xyz - shadowCasterPosition) - shadowLength; - fade = 1.0 - clamp(fromCasterDist/shadowLength, 0.0, 1.0); + float fromCasterDist = length(vPosition.xyz - shadowCasterPosition) - shadowLength; + fade = 1.0 - clamp( fromCasterDist / shadowLength , 0.0, 1.0 ); + + correctSSP(gl_Position); } diff --git a/Templates/Full/game/shaders/common/gl/scatterSkyP.glsl b/Templates/Full/game/shaders/common/gl/scatterSkyP.glsl index 6a6b9b97c..691567a37 100644 --- a/Templates/Full/game/shaders/common/gl/scatterSkyP.glsl +++ b/Templates/Full/game/shaders/common/gl/scatterSkyP.glsl @@ -21,36 +21,32 @@ //----------------------------------------------------------------------------- #include "torque.glsl" +#include "hlslCompat.glsl" -// Calculates the Mie phase function -float getMiePhase(float fCos, float fCos2, float g, float g2) -{ - return 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos2) / pow(abs(1.0 + g2 - 2.0*g*fCos), 1.5); -} -// Calculates the Rayleigh phase function -float getRayleighPhase(float fCos2) -{ - //return 1.0; - return 0.75 + 0.75*fCos2; -} +// Conn +in vec4 rayleighColor; +#define IN_rayleighColor rayleighColor +in vec4 mieColor; +#define IN_mieColor mieColor +in vec3 v3Direction; +#define IN_v3Direction v3Direction +in float zPosition; +#define IN_zPosition zPosition +in vec3 pos; +#define IN_pos pos -varying vec4 rayleighColor; -varying vec4 mieColor; -varying vec3 v3Direction; -varying float zPosition; -varying vec3 pos; - -uniform samplerCube nightSky; +uniform samplerCube nightSky ; uniform vec4 nightColor; uniform vec2 nightInterpAndExposure; uniform float useCubemap; uniform vec3 lightDir; uniform vec3 sunDir; -void main() +void main() { - float fCos = dot( lightDir, v3Direction ) / length(v3Direction); + + float fCos = dot( lightDir, IN_v3Direction ) / length(IN_v3Direction); float fCos2 = fCos*fCos; float g = -0.991; @@ -58,15 +54,15 @@ void main() float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos2) / pow(abs(1.0 + g2 - 2.0*g*fCos), 1.5); - vec4 color = rayleighColor + fMiePhase * mieColor; + vec4 color = IN_rayleighColor + fMiePhase * IN_mieColor; color.a = color.b; - vec4 nightSkyColor = textureCube(nightSky, -v3Direction); + vec4 nightSkyColor = texture(nightSky, -v3Direction); nightSkyColor = mix(nightColor, nightSkyColor, useCubemap); float fac = dot( normalize( pos ), sunDir ); fac = max( nightInterpAndExposure.y, pow( clamp( fac, 0.0, 1.0 ), 2 ) ); - gl_FragColor = mix( color, nightSkyColor, nightInterpAndExposure.y ); + OUT_FragColor0 = mix( color, nightSkyColor, nightInterpAndExposure.y ); // Clip based on the camera-relative // z position of the vertex, passed through @@ -74,6 +70,6 @@ void main() if(zPosition < 0.0) discard; - gl_FragColor.a = 1; - gl_FragColor = hdrEncode( gl_FragColor ); + OUT_FragColor0.a = 1; + OUT_FragColor0 = hdrEncode( OUT_FragColor0 ); } diff --git a/Templates/Full/game/shaders/common/gl/scatterSkyV.glsl b/Templates/Full/game/shaders/common/gl/scatterSkyV.glsl index 53abd5a6b..61580d785 100644 --- a/Templates/Full/game/shaders/common/gl/scatterSkyV.glsl +++ b/Templates/Full/game/shaders/common/gl/scatterSkyV.glsl @@ -20,12 +20,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -const int nSamples = 4; -const float fSamples = 4.0; - -// The scale depth (the altitude at which the average atmospheric density is found) -const float fScaleDepth = 0.25; -const float fInvScaleDepth = 1.0 / 0.25; +#include "hlslCompat.glsl" // The scale equation calculated by Vernier's Graphical Analysis float vernierScale(float fCos) @@ -40,12 +35,27 @@ float vernierScale(float fCos) return 0.25 * outx; } +in vec4 vPosition; +in vec3 vNormal; +in vec4 vColor; +in vec2 vTexCoord0; + +// This is the shader input vertex structure. +#define IN_position vPosition +#define IN_normal vNormal +#define IN_color vColor + // This is the shader output data. -varying vec4 rayleighColor; -varying vec4 mieColor; -varying vec3 v3Direction; -varying float zPosition; -varying vec3 pos; +out vec4 rayleighColor; +#define OUT_rayleighColor rayleighColor +out vec4 mieColor; +#define OUT_mieColor mieColor +out vec3 v3Direction; +#define OUT_v3Direction v3Direction +out float zPosition; +#define OUT_zPosition zPosition +out vec3 pos; +#define OUT_pos pos uniform mat4 modelView; uniform vec4 misc; @@ -54,13 +64,16 @@ uniform vec4 scatteringCoeffs; uniform vec3 camPos; uniform vec3 lightDir; uniform vec4 invWaveLength; - -void main() -{ - vec4 position = gl_Vertex.xyzw; - vec3 normal = gl_Normal.xyz; - vec4 color = gl_MultiTexCoord0.xyzw; +uniform vec4 colorize; +vec3 desaturate(const vec3 color, const float desaturation) +{ + const vec3 gray_conv = vec3 (0.30, 0.59, 0.11); + return mix(color, vec3(dot(gray_conv , color)), desaturation); +} + +void main() +{ // Pull some variables out: float camHeight = misc.x; float camHeightSqr = misc.y; @@ -83,7 +96,7 @@ void main() // Get the ray from the camera to the vertex, // and its length (which is the far point of the ray // passing through the atmosphere). - vec3 v3Pos = position.xyz / 6378000.0;// / outerRadius; + vec3 v3Pos = vec3(IN_position / 6378000.0);// / outerRadius; vec3 newCamPos = vec3( 0, 0, camHeight ); v3Pos.z += innerRadius; vec3 v3Ray = v3Pos.xyz - newCamPos; @@ -97,16 +110,7 @@ void main() float fDepth = exp(scaleOverScaleDepth * (innerRadius - camHeight)); float fStartAngle = dot(v3Ray, v3Start) / fHeight; - float x = 1.0 - fStartAngle; - float x5 = x * 5.25; - float x5p6 = (-6.80 + x5); - float xnew = (3.83 + x * x5p6); - float xfinal = (0.459 + x * xnew); - float xfinal2 = -0.00287 + x * xfinal; - float othx = exp( xfinal2 ); - float vscale1 = 0.25 * othx; - - float fStartOffset = fDepth * vscale1;//vernierScale(fStartAngle); + float fStartOffset = fDepth * vernierScale( fStartAngle ); // Initialize the scattering loop variables. float fSampleLength = fFar / 2.0; @@ -123,24 +127,8 @@ void main() float fLightAngle = dot(lightDir, v3SamplePoint) / fHeight; float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight; - x = 1.0 - fCameraAngle; - x5 = x * 5.25; - x5p6 = (-6.80 + x5); - xnew = (3.83 + x * x5p6); - xfinal = (0.459 + x * xnew); - xfinal2 = -0.00287 + x * xfinal; - othx = exp( xfinal2 ); - float vscale3 = 0.25 * othx; - - - x = 1.0 - fLightAngle; - x5 = x * 5.25; - x5p6 = (-6.80 + x5); - xnew = (3.83 + x * x5p6); - xfinal = (0.459 + x * xnew); - xfinal2 = -0.00287 + x * xfinal; - othx = exp( xfinal2 ); - float vscale2 = 0.25 * othx; + float vscale3 = vernierScale( fCameraAngle ); + float vscale2 = vernierScale( fLightAngle ); float fScatter = (fStartOffset + fDepth*(vscale2 - vscale3)); vec3 v3Attenuate = exp(-fScatter * (invWaveLength.xyz * rayleigh4PI + mie4PI)); @@ -150,16 +138,24 @@ void main() // Finally, scale the Mie and Rayleigh colors // and set up the varying variables for the pixel shader. - gl_Position = modelView * position; - mieColor.rgb = v3FrontColor * mieBrightness; - mieColor.a = 1.0; - rayleighColor.rgb = v3FrontColor * (invWaveLength.xyz * rayleighBrightness); - rayleighColor.a = 1.0; - v3Direction = newCamPos - v3Pos.xyz; + gl_Position = modelView * IN_position; + OUT_mieColor.rgb = v3FrontColor * mieBrightness; + OUT_mieColor.a = 1.0; + OUT_rayleighColor.rgb = v3FrontColor * (invWaveLength.xyz * rayleighBrightness); + OUT_rayleighColor.a = 1.0; + OUT_v3Direction = newCamPos - v3Pos.xyz; + OUT_pos = IN_position.xyz; - // This offset is to get rid of the black line between the atmosky and the waterPlane - // along the horizon. - zPosition = position.z + 4000.0; - pos = position.xyz; +#ifdef USE_COLORIZE + + OUT_rayleighColor.rgb = desaturate(OUT_rayleighColor.rgb, 1) * colorize.a; + + OUT_rayleighColor.r *= colorize.r; + OUT_rayleighColor.g *= colorize.g; + OUT_rayleighColor.b *= colorize.b; + +#endif + + correctSSP(gl_Position); } diff --git a/Templates/Full/game/shaders/common/gl/torque.glsl b/Templates/Full/game/shaders/common/gl/torque.glsl index dc73a706f..a98ef859f 100644 --- a/Templates/Full/game/shaders/common/gl/torque.glsl +++ b/Templates/Full/game/shaders/common/gl/torque.glsl @@ -117,6 +117,7 @@ mat3x3 quatToMat( vec4 quat ) return mat; } + /// The number of additional substeps we take when refining /// the results of the offset parallax mapping function below. /// @@ -129,19 +130,20 @@ mat3x3 quatToMat( vec4 quat ) /// Performs fast parallax offset mapping using /// multiple refinement steps. -////// @param texMap The texture map whos alpha channel we sample the parallax depth. +/// +/// @param texMap The texture map whos alpha channel we sample the parallax depth. /// @param texCoord The incoming texture coordinate for sampling the parallax depth. /// @param negViewTS The negative view vector in tangent space. /// @param depthScale The parallax factor used to scale the depth result. /// vec2 parallaxOffset( sampler2D texMap, vec2 texCoord, vec3 negViewTS, float depthScale ) { - float depth = texture2D( texMap, texCoord ).a; + float depth = texture( texMap, texCoord ).a; vec2 offset = negViewTS.xy * ( depth * depthScale ); for ( int i=0; i < PARALLAX_REFINE_STEPS; i++ ) { - depth = ( depth + texture2D( texMap, texCoord + offset ).a ) * 0.5; + depth = ( depth + texture( texMap, texCoord + offset ).a ) * 0.5; offset = negViewTS.xy * ( depth * depthScale ); } @@ -151,59 +153,61 @@ vec2 parallaxOffset( sampler2D texMap, vec2 texCoord, vec3 negViewTS, float dept /// The maximum value for 16bit per component integer HDR encoding. const float HDR_RGB16_MAX = 100.0; -/// The maximum value for 10bit per component integer HDR encoding.const float HDR_RGB10_MAX = 4.0; +/// The maximum value for 10bit per component integer HDR encoding. +const float HDR_RGB10_MAX = 4.0; /// Encodes an HDR color for storage into a target. -vec3 hdrEncode( vec3 sample ){ +vec3 hdrEncode( vec3 _sample ) +{ #if defined( TORQUE_HDR_RGB16 ) - return sample / HDR_RGB16_MAX; + return _sample / HDR_RGB16_MAX; #elif defined( TORQUE_HDR_RGB10 ) - return sample / HDR_RGB10_MAX; + return _sample / HDR_RGB10_MAX; #else // No encoding. - return sample; + return _sample; #endif } /// Encodes an HDR color for storage into a target. -vec4 hdrEncode( vec4 sample ) +vec4 hdrEncode( vec4 _sample ) { - return vec4( hdrEncode( sample.rgb ), sample.a ); + return vec4( hdrEncode( _sample.rgb ), _sample.a ); } /// Decodes an HDR color from a target. -vec3 hdrDecode( vec3 sample ) +vec3 hdrDecode( vec3 _sample ) { #if defined( TORQUE_HDR_RGB16 ) - return sample * HDR_RGB16_MAX; + return _sample * HDR_RGB16_MAX; #elif defined( TORQUE_HDR_RGB10 ) - return sample * HDR_RGB10_MAX; + return _sample * HDR_RGB10_MAX; #else // No encoding. - return sample; + return _sample; #endif } /// Decodes an HDR color from a target. -vec4 hdrDecode( vec4 sample ) +vec4 hdrDecode( vec4 _sample ) { - return vec4( hdrDecode( sample.rgb ), sample.a ); + return vec4( hdrDecode( _sample.rgb ), _sample.a ); } /// Returns the luminance for an HDR pixel. -float hdrLuminance( vec3 sample ) +float hdrLuminance( vec3 _sample ) { // There are quite a few different ways to // calculate luminance from an rgb value. @@ -216,7 +220,7 @@ float hdrLuminance( vec3 sample ) // // Max component luminance. // - //float lum = max( sample.r, max( sample.g, sample.b ) ); + //float lum = max( _sample.r, max( _sample.g, _sample.b ) ); //////////////////////////////////////////////////////////////////////////// // The perceptual relative luminance. @@ -224,23 +228,45 @@ float hdrLuminance( vec3 sample ) // See http://en.wikipedia.org/wiki/Luminance_(relative) // const vec3 RELATIVE_LUMINANCE = vec3( 0.2126, 0.7152, 0.0722 ); - float lum = dot( sample, RELATIVE_LUMINANCE ); + float lum = dot( _sample, RELATIVE_LUMINANCE ); //////////////////////////////////////////////////////////////////////////// // // The average component luminance. // //const vec3 AVERAGE_LUMINANCE = vec3( 0.3333, 0.3333, 0.3333 ); - //float lum = dot( sample, AVERAGE_LUMINANCE ); + //float lum = dot( _sample, AVERAGE_LUMINANCE ); return lum; } +#ifdef TORQUE_PIXEL_SHADER +/// Called from the visibility feature to do screen +/// door transparency for fading of objects. +void fizzle(vec2 vpos, float visibility) +{ + // NOTE: The magic values below are what give us + // the nice even pattern during the fizzle. + // + // These values can be changed to get different + // patterns... some better than others. + // + // Horizontal Blinds - { vpos.x, 0.916, vpos.y, 0 } + // Vertical Lines - { vpos.x, 12.9898, vpos.y, 78.233 } + // + // I'm sure there are many more patterns here to + // discover for different effects. + + mat2x2 m = mat2x2( vpos.x, vpos.y, 0.916, 0.350 ); + if( (visibility - fract( determinant( m ) )) < 0 ) //if(a < 0) discard; + discard; +} +#endif //TORQUE_PIXEL_SHADER /// Basic assert macro. If the condition fails, then the shader will output color. /// @param condition This should be a bvec[2-4]. If any items is false, condition is considered to fail. /// @param color The color that should be outputted if the condition fails. /// @note This macro will only work in the void main() method of a pixel shader. -#define assert(condition, color) { if(!any(condition)) { gl_FragColor = color; return; } } +#define assert(condition, color) { if(!any(condition)) { OUT_FragColor0 = color; return; } } #endif // _TORQUE_GLSL_ diff --git a/Templates/Full/game/shaders/common/gl/wavesP.glsl b/Templates/Full/game/shaders/common/gl/wavesP.glsl index 24bd8cbb4..ddb683947 100644 --- a/Templates/Full/game/shaders/common/gl/wavesP.glsl +++ b/Templates/Full/game/shaders/common/gl/wavesP.glsl @@ -28,10 +28,10 @@ uniform float specularPower; uniform vec4 ambient; uniform float accumTime; -varying vec2 TEX0; -varying vec4 outLightVec; -varying vec3 outPos; -varying vec3 outEyePos; +in vec2 TEX0; +in vec4 outLightVec; +in vec3 outPos; +in vec3 outEyePos; void main() { @@ -42,14 +42,14 @@ void main() texOffset.x = TEX0.x + sinOffset1 + sinOffset2; texOffset.y = TEX0.y + cos( accumTime * 3.0 + TEX0.x * 6.28319 * 2.0 ) * 0.05; - vec4 bumpNorm = texture2D(bumpMap, texOffset) * 2.0 - 1.0; - vec4 diffuse = texture2D(diffMap, texOffset); + vec4 bumpNorm = texture(bumpMap, texOffset) * 2.0 - 1.0; + vec4 diffuse = texture(diffMap, texOffset); - gl_FragColor = diffuse * (clamp(dot(outLightVec.xyz, bumpNorm.xyz), 0.0, 1.0) + ambient); + OUT_FragColor0 = diffuse * (clamp(dot(outLightVec.xyz, bumpNorm.xyz), 0.0, 1.0) + ambient); vec3 eyeVec = normalize(outEyePos - outPos); vec3 halfAng = normalize(eyeVec + outLightVec.xyz); float specular = clamp(dot(bumpNorm.xyz, halfAng), 0.0, 1.0) * outLightVec.w; specular = pow(specular, specularPower); - gl_FragColor += specularColor * specular; + OUT_FragColor0 += specularColor * specular; } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/convexGeometryV.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/convexGeometryV.glsl index 6d3e36e7e..1807ac43f 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/convexGeometryV.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/convexGeometryV.glsl @@ -20,16 +20,33 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -varying vec4 wsEyeDir; -varying vec4 ssPos; +#include "../../../gl/hlslCompat.glsl" + +in vec4 vPosition; + +#define IN_pos vPosition + +out vec4 wsEyeDir; +out vec4 ssPos; +out vec4 vsEyeDir; + +#define OUT_hpos gl_Position +#define OUT_wsEyeDir wsEyeDir +#define OUT_ssPos ssPos +#define OUT_vsEyeDir vsEyeDir uniform mat4 modelview; uniform mat4 objTrans; +uniform mat4 worldViewOnly; uniform vec3 eyePosWorld; void main() { - gl_Position = modelview * gl_Vertex; - wsEyeDir = objTrans * gl_Vertex - vec4( eyePosWorld, 0.0 ); - ssPos = gl_Position; + OUT_hpos = tMul( modelview, IN_pos ); + OUT_wsEyeDir = tMul( objTrans, IN_pos ) - vec4( eyePosWorld, 0.0 ); + OUT_vsEyeDir = tMul( worldViewOnly, IN_pos ); + OUT_ssPos = OUT_hpos; + + correctSSP(gl_Position); } + diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgDepthVisualizeP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgDepthVisualizeP.glsl index 4a954ae84..e3ee59c8a 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgDepthVisualizeP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgDepthVisualizeP.glsl @@ -20,14 +20,15 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../../gl/hlslCompat.glsl" #include "shadergen:/autogenConditioners.h" -varying vec2 uv0; +in vec2 uv0; uniform sampler2D prepassBuffer; uniform sampler1D depthViz; void main() { float depth = prepassUncondition( prepassBuffer, uv0 ).w; - gl_FragColor = vec4( texture1D( depthViz, depth ).rgb, 1 ); + OUT_FragColor0 = vec4( texture( depthViz, depth ).rgb, 1.0 ); } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl index 580204487..aa17df4d6 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl @@ -20,15 +20,16 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../../gl/hlslCompat.glsl" #include "shadergen:/autogenConditioners.h" -varying vec2 uv0; +in vec2 uv0; uniform sampler2D lightInfoBuffer; void main() { - vec3 lightcolor; + vec3 lightcolor; float nl_Att, specular; - lightinfoUncondition( texture2DLod( lightInfoBuffer, uv0 ), lightcolor, nl_Att, specular ); - gl_FragColor = vec4( lightcolor, 1.0 ); + lightinfoUncondition( texture( lightInfoBuffer, uv0 ), lightcolor, nl_Att, specular ); + OUT_FragColor0 = vec4( lightcolor, 1.0 ); } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl index 6f7c52486..e549922ff 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl @@ -20,15 +20,16 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../../gl/hlslCompat.glsl" #include "shadergen:/autogenConditioners.h" -varying vec2 uv0; +in vec2 uv0; uniform sampler2D lightInfoBuffer; void main() { - vec3 lightcolor; + vec3 lightcolor; float nl_Att, specular; - lightinfoUncondition( texture2DLod( lightInfoBuffer, uv0 ), lightcolor, nl_Att, specular ); - gl_FragColor = vec4( specular, specular, specular, 1.0 ); + lightinfoUncondition( texture( lightInfoBuffer, uv0 ), lightcolor, nl_Att, specular ); + OUT_FragColor0 = vec4( specular, specular, specular, 1.0 ); } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgNormalVisualizeP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgNormalVisualizeP.glsl index 96b645524..f61706393 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgNormalVisualizeP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgNormalVisualizeP.glsl @@ -20,14 +20,14 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../../gl/hlslCompat.glsl" #include "shadergen:/autogenConditioners.h" - -varying vec2 uv0; -uniform sampler2D prepassTex; +in vec2 uv0; +uniform sampler2D prepassBuffer; void main() { - vec3 normal = prepassUncondition( prepassTex, uv0 ).xyz; - gl_FragColor = vec4( ( normal + 1.0 ) * 0.5, 1.0 ); + vec3 normal = prepassUncondition( prepassBuffer, uv0 ).xyz; + OUT_FragColor0 = vec4( ( normal + 1.0 ) * 0.5, 1.0 ); } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgShadowVisualizeP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgShadowVisualizeP.glsl index 51609fc6b..e997950ab 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgShadowVisualizeP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgShadowVisualizeP.glsl @@ -19,13 +19,14 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../../gl/hlslCompat.glsl" -varying vec2 uv0; +in vec2 uv0; uniform sampler2D shadowMap; uniform sampler1D depthViz; void main() { - float depth = clamp( texture2DLod( shadowMap, uv0, 0 ).r, 0.0, 1.0 ); - gl_FragColor = vec4( texture1D( depthViz, depth ).rgb, 1.0 ); + float depth = saturate( texture( shadowMap, uv0 ).r ); + OUT_FragColor0 = vec4( texture( depthViz, depth ).rgb, 1 ); } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/farFrustumQuad.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/farFrustumQuad.glsl index 866a39b0b..76054eb09 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/farFrustumQuad.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/farFrustumQuad.glsl @@ -24,7 +24,7 @@ vec2 getUVFromSSPos( vec3 ssPos, vec4 rtParams ) { vec2 outPos = ( ssPos.xy + 1.0 ) / 2.0; + outPos.y = 1.0 - outPos.y; outPos = ( outPos * rtParams.zw ) + rtParams.xy; - //outPos.y = 1.0 - outPos.y; return outPos; } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/farFrustumQuadV.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/farFrustumQuadV.glsl index ce5c2ad81..a80e856ed 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/farFrustumQuadV.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/farFrustumQuadV.glsl @@ -20,24 +20,32 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../../gl/hlslCompat.glsl" #include "farFrustumQuad.glsl" -uniform vec4 renderTargetParams; - -varying vec4 hpos; -varying vec2 uv0; -varying vec3 wsEyeRay; +in vec4 vPosition; +in vec3 vNormal; +in vec3 vTangent; +in vec2 vTexCoord0; +uniform vec4 rtParams0; +out vec4 hpos; +out vec2 uv0; +out vec3 wsEyeRay; +out vec3 vsEyeRay; void main() -{ - // Expand the SS coordinate (stored in uv0) - hpos = vec4( gl_MultiTexCoord0.st * 2.0 - 1.0, 1.0, 1.0 ); - gl_Position = hpos; - +{ + hpos = vec4( vTexCoord0, 0, 1 ); + // Get a RT-corrected UV from the SS coord - uv0 = getUVFromSSPos( hpos.xyz, renderTargetParams ); + uv0 = getUVFromSSPos( hpos.xyz, rtParams0 ); + gl_Position = hpos; - // Interpolators will generate eye ray from far-frustum corners - wsEyeRay = gl_Vertex.xyz; + // Interpolators will generate eye rays the + // from far-frustum corners. + wsEyeRay = vTangent; + vsEyeRay = vNormal; + + correctSSP(gl_Position); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl index b135f1aa8..c0610508b 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl @@ -21,34 +21,26 @@ //----------------------------------------------------------------------------- #include "../../../gl/hlslCompat.glsl" -#include "farFrustumQuad.glsl" -#include "lightingUtils.glsl" -#include "../../shadowMap/shadowMapIO_GLSL.h" #include "shadergen:/autogenConditioners.h" +#include "farFrustumQuad.glsl" +#include "lightingUtils.glsl" +#include "../../../gl/lighting.glsl" +#include "../../shadowMap/shadowMapIO_GLSL.h" +#include "softShadow.glsl" -#if TORQUE_SM >= 30 +in vec4 wsEyeDir; +in vec4 ssPos; +in vec4 vsEyeDir; - // Enables high quality soft shadow - // filtering for SM3.0 and above. - #define SOFTSHADOW_SM3 - - #include "softShadow.glsl" - -#else +#ifdef USE_COOKIE_TEX +/// The texture for cookie rendering. +uniform samplerCube cookieMap ; #endif - -// I am not sure if we should do this in a better way -//#define SHADOW_CUBE -//#define SHADOW_PARABOLOID -#define SHADOW_DUALPARABOLOID -#define SHADOW_DUALPARABOLOID_SINGLE_PASS - - #ifdef SHADOW_CUBE vec3 decodeShadowCoord( vec3 shadowCoord ) @@ -56,39 +48,47 @@ return shadowCoord; } - vec4 shadowSample( samplerCUBE shadowMap, vec3 shadowCoord ) + vec4 shadowSample( samplerCube shadowMap, vec3 shadowCoord ) { - return textureCUBE( shadowMap, shadowCoord ); + return texture( shadowMap, shadowCoord ); } - -#elif defined( SHADOW_DUALPARABOLOID ) + +#else vec3 decodeShadowCoord( vec3 paraVec ) { - // Swizzle z and y + // Flip y and z paraVec = paraVec.xzy; - #ifdef SHADOW_DUALPARABOLOID_SINGLE_PASS + #ifndef SHADOW_PARABOLOID bool calcBack = (paraVec.z < 0.0); - if(calcBack) + if ( calcBack ) + { paraVec.z = paraVec.z * -1.0; + + #ifdef SHADOW_DUALPARABOLOID + paraVec.x = -paraVec.x; + #endif + } #endif vec3 shadowCoord; - shadowCoord.x = (paraVec.x / (2.0*(1.0 + paraVec.z))) + 0.5; - shadowCoord.y = ((paraVec.y / (2.0*(1.0 + paraVec.z))) + 0.5); + shadowCoord.x = (paraVec.x / (2*(1 + paraVec.z))) + 0.5; + shadowCoord.y = 1-((paraVec.y / (2*(1 + paraVec.z))) + 0.5); shadowCoord.z = 0; // adjust the co-ordinate slightly if it is near the extent of the paraboloid // this value was found via experementation - shadowCoord.xy *= 0.997; + // NOTE: this is wrong, it only biases in one direction, not towards the uv + // center ( 0.5 0.5 ). + //shadowCoord.xy *= 0.997; - #ifdef SHADOW_DUALPARABOLOID_SINGLE_PASS + #ifndef SHADOW_PARABOLOID // If this is the back, offset in the atlas - if(calcBack) + if ( calcBack ) shadowCoord.x += 1.0; // Atlasing front and back maps, so scale @@ -99,51 +99,35 @@ return shadowCoord; } -#else - - #error Unknown shadow type! - #endif -varying vec4 wsEyeDir; -varying vec4 ssPos; - - uniform sampler2D prePassBuffer; #ifdef SHADOW_CUBE - uniform samplerCube shadowMap; + uniform samplerCube shadowMap; #else - uniform sampler2D shadowMap; -#endif -#ifdef ACCUMULATE_LUV - uniform sampler2D scratchTarget; + uniform sampler2D shadowMap; #endif -uniform vec4 renderTargetParams; +uniform vec4 rtParams0; uniform vec3 lightPosition; uniform vec4 lightColor; -uniform float lightBrightness; -uniform float lightRange; +uniform float lightBrightness; +uniform float lightRange; uniform vec2 lightAttenuation; uniform vec4 lightMapParams; - -uniform vec3 eyePosWorld; -uniform vec4 farPlane; -uniform float negFarPlaneDotEye; -uniform mat3x3 worldToLightProj; - +uniform vec4 vsFarPlane; +uniform mat3 viewToLightProj; uniform vec4 lightParams; uniform float shadowSoftness; -uniform float constantSpecularPower; + - -void main() -{ +void main() +{ // Compute scene UV - vec3 ssPosP = ssPos.xyz / ssPos.w; - vec2 uvScene = getUVFromSSPos( ssPosP, renderTargetParams ); + vec3 ssPos = ssPos.xyz / ssPos.w; + vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); // Sample/unpack the normal/z data vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene ); @@ -151,21 +135,17 @@ void main() float depth = prepassSample.a; // Eye ray - Eye -> Pixel - vec3 eyeRay = getDistanceVectorToPlane( negFarPlaneDotEye, wsEyeDir.xyz / wsEyeDir.w , farPlane ); - - // Get world space pixel position - vec3 worldPos = eyePosWorld + eyeRay * depth; + vec3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane ); + vec3 viewSpacePos = eyeRay * depth; // Build light vec, get length, clip pixel if needed - vec3 lightVec = lightPosition - worldPos; + vec3 lightVec = lightPosition - viewSpacePos; float lenLightV = length( lightVec ); - if ( lightRange - lenLightV < 0.0 ) - discard; - + clip( lightRange - lenLightV ); + // Get the attenuated falloff. float atten = attenuate( lightColor, lightAttenuation, lenLightV ); - if ( atten - 1e-6 < 0.0 ) - discard; + clip( atten - 1e-6 ); // Normalize lightVec lightVec /= lenLightV; @@ -181,61 +161,73 @@ void main() #else - // Convert the light vector into a shadow map - // here once instead of in the filtering loop. - vec4 shadowCoord = vec4(0.0); - #ifdef SHADOW_CUBE - shadowCoord.xy = decodeShadowCoord( -lightVec ); - #else - shadowCoord.xy = decodeShadowCoord( worldToLightProj * -lightVec ).xy; - #endif - // Get a linear depth from the light source. - float distToLight = lenLightV / lightRange; + float distToLight = lenLightV / lightRange; - #ifdef SOFTSHADOW_SM3 + #ifdef SHADOW_CUBE + + // TODO: We need to fix shadow cube to handle soft shadows! + float occ = texture( shadowMap, tMul( viewToLightProj, -lightVec ) ).r; + float shadowed = saturate( exp( lightParams.y * ( occ - distToLight ) ) ); + + #else + vec2 shadowCoord = decodeShadowCoord( tMul( viewToLightProj, -lightVec ) ).xy; + float shadowed = softShadow_filter( shadowMap, - gTapRotationTex, - ssPosP.xy, - shadowCoord.xy, + ssPos.xy, + shadowCoord, shadowSoftness, distToLight, nDotL, lightParams.y ); - - #else // !SOFTSHADOW_SM3 - - // TODO: Implement the SM2 lower quality - // shadow filtering method. #endif #endif // !NO_SHADOW - + + #ifdef USE_COOKIE_TEX + + // Lookup the cookie sample. + vec4 cookie = texture( cookieMap, tMul( viewToLightProj, -lightVec ) ); + + // Multiply the light with the cookie tex. + lightColor.rgb *= cookie.rgb; + + // Use a maximum channel luminance to attenuate + // the lighting else we get specular in the dark + // regions of the cookie texture. + atten *= max( cookie.r, max( cookie.g, cookie.b ) ); + + #endif + // NOTE: Do not clip on fully shadowed pixels as it would // cause the hardware occlusion query to disable the shadow. // Specular term - float specular = calcSpecular( lightVec, - normal, - normalize( -eyeRay ), - constantSpecularPower, - shadowed * atten * lightBrightness ); - - // N.L * Attenuation - float Sat_NL_Att = clamp( nDotL * atten * shadowed, 0.0, 1.0 ); - - // In LUV color mode we need to blend in the - // output from the previous target. - vec4 previousPix = vec4(0.0); - #ifdef ACCUMULATE_LUV - previousPix = texture2DLod( scratchTarget, uvScene, 0 ); - #endif + float specular = AL_CalcSpecular( lightVec, + normal, + normalize( -eyeRay ) ) * lightBrightness * atten * shadowed; - // Output - gl_FragColor = lightinfoCondition( lightColor.rgb * lightBrightness, - Sat_NL_Att, - specular, - previousPix ) * lightMapParams; + float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness; + vec3 lightColorOut = lightMapParams.rgb * lightColor.rgb; + vec4 addToResult = vec4(0.0); + + // TODO: This needs to be removed when lightmapping is disabled + // as its extra work per-pixel on dynamic lit scenes. + // + // Special lightmapping pass. + if ( lightMapParams.a < 0.0 ) + { + // This disables shadows on the backsides of objects. + shadowed = nDotL < 0.0f ? 1.0f : shadowed; + + Sat_NL_Att = 1.0f; + shadowed = mix( 1.0f, shadowed, atten ); + lightColorOut = vec3(shadowed); + specular *= lightBrightness; + addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); + } + + OUT_FragColor0 = lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult ); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/softShadow.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/softShadow.glsl index 8ef09ed2f..a14213946 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/softShadow.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/softShadow.glsl @@ -19,113 +19,141 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- - - -#define NUM_TAPS 12 - -#define NUM_PRE_TAPS 4 - -/// The non-uniform poisson disk used in the -/// high quality shadow filtering. -vec2 sNonUniformTaps[NUM_TAPS]; -void initNonUniformTaps() + +#if defined( SOFTSHADOW ) && defined( SOFTSHADOW_HIGH_QUALITY ) + +#define NUM_PRE_TAPS 4 +#define NUM_TAPS 12 + +/// The non-uniform poisson disk used in the +/// high quality shadow filtering. +vec2 sNonUniformTaps[NUM_TAPS] = vec2[] +( + // These first 4 taps are located around the edges + // of the disk and are used to predict fully shadowed + // or unshadowed areas. + vec2( 0.992833, 0.979309 ), + vec2( -0.998585, 0.985853 ), + vec2( 0.949299, -0.882562 ), + vec2( -0.941358, -0.893924 ), + + // The rest of the samples. + vec2( 0.545055, -0.589072 ), + vec2( 0.346526, 0.385821 ), + vec2( -0.260183, 0.334412 ), + vec2( 0.248676, -0.679605 ), + vec2( -0.569502, -0.390637 ), + vec2( -0.614096, 0.212577 ), + vec2( -0.259178, 0.876272 ), + vec2( 0.649526, 0.864333 ) +); + +#else + +#define NUM_PRE_TAPS 5 + +/// The non-uniform poisson disk used in the +/// high quality shadow filtering. +vec2 sNonUniformTaps[NUM_PRE_TAPS] = vec2[] +( + vec2( 0.892833, 0.959309 ), + vec2( -0.941358, -0.873924 ), + vec2( -0.260183, 0.334412 ), + vec2( 0.348676, -0.679605 ), + vec2( -0.569502, -0.390637 ) +); + +#endif + + +/// The texture used to do per-pixel pseudorandom +/// rotations of the filter taps. +uniform sampler2D gTapRotationTex ; + + +float softShadow_sampleTaps( sampler2D shadowMap, + vec2 sinCos, + vec2 shadowPos, + float filterRadius, + float distToLight, + float esmFactor, + int startTap, + int endTap ) { - // These first 4 taps are located around the edges - // of the disk and are used to predict fully shadowed - // or unshadowed areas. - sNonUniformTaps[0] = vec2( 0.992833, 0.979309 ); - sNonUniformTaps[1] = vec2( -0.998585, 0.985853 ); - sNonUniformTaps[2] = vec2( 0.949299, -0.882562 ); - sNonUniformTaps[3] = vec2( -0.941358, -0.893924 ); - - // The rest of the samples. - sNonUniformTaps[4] = vec2( 0.545055, -0.589072 ); - sNonUniformTaps[5] = vec2( 0.346526, 0.385821 ); - sNonUniformTaps[6] = vec2( -0.260183, 0.334412 ); - sNonUniformTaps[7] = vec2( 0.248676, -0.679605 ); - sNonUniformTaps[8] = vec2( -0.569502, -0.390637 ); - sNonUniformTaps[9] = vec2( -0.014096, 0.012577 ); - sNonUniformTaps[10] = vec2( -0.259178, 0.876272 ); - sNonUniformTaps[11] = vec2( 0.649526, 0.664333 ); + float shadow = 0; + + vec2 tap = vec2(0); + for ( int t = startTap; t < endTap; t++ ) + { + tap.x = ( sNonUniformTaps[t].x * sinCos.y - sNonUniformTaps[t].y * sinCos.x ) * filterRadius; + tap.y = ( sNonUniformTaps[t].y * sinCos.y + sNonUniformTaps[t].x * sinCos.x ) * filterRadius; + float occluder = tex2Dlod( shadowMap, vec4( shadowPos + tap, 0, 0 ) ).r; + + float esm = saturate( exp( esmFactor * ( occluder - distToLight ) ) ); + shadow += esm / float( endTap - startTap ); + } + + return shadow; } - -/// The texture used to do per-pixel pseudorandom -/// rotations of the filter taps. -uniform sampler2D gTapRotationTex; - - -float softShadow_sampleTaps( sampler2D shadowMap, - vec2 sinCos, - vec2 shadowPos, - float filterRadius, - float distToLight, - float esmFactor, - int startTap, - int endTap ) -{ - initNonUniformTaps(); - float shadow = 0.0; - - vec2 tap = vec2(0.0); - for ( int t = startTap; t < endTap; t++ ) - { - tap.x = ( sNonUniformTaps[t].x * sinCos.y - sNonUniformTaps[t].y * sinCos.x ) * filterRadius; - tap.y = ( sNonUniformTaps[t].y * sinCos.y + sNonUniformTaps[t].x * sinCos.x ) * filterRadius; - float occluder = texture2DLod( shadowMap, shadowPos + tap, 0.0 ).r; - - float esm = clamp( exp( esmFactor * ( occluder - distToLight ) ), 0.0, 1.0 ); - shadow += esm / float( endTap - startTap ); - } - - return shadow; -} - - -// HACK! HACK! HACK! -// We take the noise texture directly as the second parameter to ensure that it -// is the "last used" sampler, and thus doesn't collide with the prepass buffer -// or shadow map. If we use gTapRotationTex directly here, then it is the first -// used sampler and will collide with the prepass buffer. -float softShadow_filter( sampler2D shadowMap, - sampler2D noiseTexture, - vec2 vpos, - vec2 shadowPos, - float filterRadius, - float distToLight, - float dotNL, - float esmFactor ) -{ - // Lookup the random rotation for this screen pixel. - vec2 sinCos = ( texture2DLod( noiseTexture, vpos * 16.0, 0.0 ).rg - 0.5 ) * 2.0; - - // Do the prediction taps first. - float shadow = softShadow_sampleTaps( shadowMap, - sinCos, - shadowPos, - filterRadius, - distToLight, - esmFactor, - 0, - NUM_PRE_TAPS ); - - // Only do the expensive filtering if we're really - // in a partially shadowed area. - if ( shadow * ( 1.0 - shadow ) * max( dotNL, 0.0 ) > 0.06 ) - { - shadow += softShadow_sampleTaps( shadowMap, - sinCos, - shadowPos, - filterRadius, - distToLight, - esmFactor, - NUM_PRE_TAPS, - NUM_TAPS ); - - // This averages the taps above with the results - // of the prediction samples. - shadow *= 0.5; - } - - return shadow; -} \ No newline at end of file + + +float softShadow_filter( sampler2D shadowMap, + vec2 vpos, + vec2 shadowPos, + float filterRadius, + float distToLight, + float dotNL, + float esmFactor ) +{ + #ifndef SOFTSHADOW + + // If softshadow is undefined then we skip any complex + // filtering... just do a single sample ESM. + + float occluder = tex2Dlod( shadowMap, vec4( shadowPos, 0, 0 ) ).r; + float shadow = saturate( exp( esmFactor * ( occluder - distToLight ) ) ); + + #else + + // Lookup the random rotation for this screen pixel. + vec2 sinCos = ( tex2Dlod( gTapRotationTex, vec4( vpos * 16, 0, 0 ) ).rg - 0.5 ) * 2; + + // Do the prediction taps first. + float shadow = softShadow_sampleTaps( shadowMap, + sinCos, + shadowPos, + filterRadius, + distToLight, + esmFactor, + 0, + NUM_PRE_TAPS ); + + // We live with only the pretap results if we don't + // have high quality shadow filtering enabled. + #ifdef SOFTSHADOW_HIGH_QUALITY + + // Only do the expensive filtering if we're really + // in a partially shadowed area. + if ( shadow * ( 1.0 - shadow ) * max( dotNL, 0 ) > 0.06 ) + { + shadow += softShadow_sampleTaps( shadowMap, + sinCos, + shadowPos, + filterRadius, + distToLight, + esmFactor, + NUM_PRE_TAPS, + NUM_TAPS ); + + // This averages the taps above with the results + // of the prediction samples. + shadow *= 0.5; + } + + #endif // SOFTSHADOW_HIGH_QUALITY + + #endif // SOFTSHADOW + + return shadow; +} \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl index d29f5edb0..c07be1f34 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl @@ -25,58 +25,49 @@ #include "lightingUtils.glsl" #include "../../shadowMap/shadowMapIO_GLSL.h" #include "shadergen:/autogenConditioners.h" +#include "softShadow.glsl" +#include "../../../gl/lighting.glsl" +in vec4 wsEyeDir; +in vec4 ssPos; +in vec4 vsEyeDir; -#if TORQUE_SM >= 30 +#define IN_wsEyeDir wsEyeDir +#define IN_ssPos ssPos +#define IN_vsEyeDir vsEyeDir - // Enables high quality soft shadow - // filtering for SM3.0 and above. - #define SOFTSHADOW_SM3 - - #include "softShadow.glsl" - -#else +#ifdef USE_COOKIE_TEX +/// The texture for cookie rendering. +uniform sampler2D cookieMap; #endif - -varying vec4 ssPos; -varying vec4 wsEyeDir; - - uniform sampler2D prePassBuffer; uniform sampler2D shadowMap; -#ifdef ACCUMULATE_LUV - uniform sampler2D scratchTarget; -#endif -uniform vec4 renderTargetParams; +uniform vec4 rtParams0; uniform vec3 lightPosition; uniform vec4 lightColor; -uniform float lightBrightness; -uniform float lightRange; +uniform float lightBrightness; +uniform float lightRange; uniform vec2 lightAttenuation; uniform vec3 lightDirection; uniform vec4 lightSpotParams; uniform vec4 lightMapParams; -uniform vec3 eyePosWorld; -uniform vec4 farPlane; -uniform float negFarPlaneDotEye; -uniform mat4x4 worldToLightProj; +uniform vec4 vsFarPlane; +uniform mat4 viewToLightProj; uniform vec4 lightParams; uniform float shadowSoftness; -uniform float constantSpecularPower; - void main() -{ +{ // Compute scene UV - vec3 ssPosP = ssPos.xyz / ssPos.w; - vec2 uvScene = getUVFromSSPos( ssPosP, renderTargetParams ); + vec3 ssPos = IN_ssPos.xyz / IN_ssPos.w; + vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); // Sample/unpack the normal/z data vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene ); @@ -84,85 +75,92 @@ void main() float depth = prepassSample.a; // Eye ray - Eye -> Pixel - vec3 eyeRay = getDistanceVectorToPlane( negFarPlaneDotEye, wsEyeDir.xyz / wsEyeDir.w , farPlane ); - - // Get world space pixel position - vec3 worldPos = eyePosWorld + eyeRay * depth; + vec3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN_vsEyeDir.xyz, vsFarPlane ); + vec3 viewSpacePos = eyeRay * depth; // Build light vec, get length, clip pixel if needed - vec3 lightToPxlVec = worldPos - lightPosition; + vec3 lightToPxlVec = viewSpacePos - lightPosition; float lenLightV = length( lightToPxlVec ); lightToPxlVec /= lenLightV; - //lightDirection = float3( -lightDirection.xy, lightDirection.z ); //float3( 0, 0, -1 ); + //lightDirection = vec3( -lightDirection.xy, lightDirection.z ); //vec3( 0, 0, -1 ); float cosAlpha = dot( lightDirection, lightToPxlVec ); - if ( cosAlpha - lightSpotParams.x < 0.0 ) discard; - if ( lightRange - lenLightV < 0.0 ) discard; + clip( cosAlpha - lightSpotParams.x ); + clip( lightRange - lenLightV ); float atten = attenuate( lightColor, lightAttenuation, lenLightV ); atten *= ( cosAlpha - lightSpotParams.x ) / lightSpotParams.y; - if ( atten - 1e-6 < 0.0 ) discard; + clip( atten - 1e-6 ); + atten = saturate( atten ); float nDotL = dot( normal, -lightToPxlVec ); + // Get the shadow texture coordinate + vec4 pxlPosLightProj = tMul( viewToLightProj, vec4( viewSpacePos, 1 ) ); + vec2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 ); + shadowCoord.y = 1.0f - shadowCoord.y; + #ifdef NO_SHADOW float shadowed = 1.0; #else - // Find Shadow coordinate - vec4 pxlPosLightProj = vec4( worldToLightProj * vec4( worldPos, 1.0 ) ); - vec2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 ); - // Get a linear depth from the light source. float distToLight = pxlPosLightProj.z / lightRange; - #ifdef SOFTSHADOW_SM3 - - float shadowed = softShadow_filter( shadowMap, - gTapRotationTex, - ssPosP.xy, - shadowCoord, - shadowSoftness, - distToLight, - nDotL, - lightParams.y ); - - #else // !SOFTSHADOW_SM3 - - // Simple exponential shadow map. - float occluder = decodeShadowMap( texture2DLod( shadowMap, shadowCoord, 0.0 ) ); - float esmFactor = lightParams.y; - float shadowed = clamp( exp( esmFactor * ( occluder - distToLight ) ), 0.0, 1.0 ); - - #endif + float shadowed = softShadow_filter( shadowMap, + ssPos.xy, + shadowCoord, + shadowSoftness, + distToLight, + nDotL, + lightParams.y ); #endif // !NO_SHADOW - + + #ifdef USE_COOKIE_TEX + + // Lookup the cookie sample. + vec4 cookie = texture( cookieMap, shadowCoord ); + + // Multiply the light with the cookie tex. + lightColor.rgb *= cookie.rgb; + + // Use a maximum channel luminance to attenuate + // the lighting else we get specular in the dark + // regions of the cookie texture. + atten *= max( cookie.r, max( cookie.g, cookie.b ) ); + + #endif + // NOTE: Do not clip on fully shadowed pixels as it would // cause the hardware occlusion query to disable the shadow. // Specular term - float specular = calcSpecular( -lightToPxlVec, - normal, - normalize( -eyeRay ), - constantSpecularPower, - shadowed * atten * lightBrightness ); - - // N.L * Attenuation - float Sat_NL_Att = clamp( nDotL * atten * shadowed, 0.0, 1.0 ); - - // In LUV color mode we need to blend in the - // output from the previous target. - vec4 previousPix = vec4(0.0); - #ifdef ACCUMULATE_LUV - previousPix = texture2DLod( scratchTarget, uvScene, 0.0 ); - #endif + float specular = AL_CalcSpecular( -lightToPxlVec, + normal, + normalize( -eyeRay ) ) * lightBrightness * atten * shadowed; - // Output - gl_FragColor = lightinfoCondition( lightColor.rgb * lightBrightness, - Sat_NL_Att, - specular, - previousPix ) * lightMapParams; + float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness; + vec3 lightColorOut = lightMapParams.rgb * lightColor.rgb; + vec4 addToResult = vec4(0.0); + + // TODO: This needs to be removed when lightmapping is disabled + // as its extra work per-pixel on dynamic lit scenes. + // + // Special lightmapping pass. + if ( lightMapParams.a < 0.0 ) + { + // This disables shadows on the backsides of objects. + shadowed = nDotL < 0.0f ? 1.0f : shadowed; + + Sat_NL_Att = 1.0f; + shadowed = mix( 1.0f, shadowed, atten ); + lightColorOut = vec3(shadowed); + specular *= lightBrightness; + addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); + } + + OUT_FragColor0 = lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult ); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl index bbd567fd0..0178c35ea 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl @@ -22,40 +22,32 @@ #include "../../../gl/hlslCompat.glsl" #include "shadergen:/autogenConditioners.h" +#include "farFrustumQuad.glsl" +#include "../../../gl/torque.glsl" +#include "../../../gl/lighting.glsl" #include "lightingUtils.glsl" #include "../../shadowMap/shadowMapIO_GLSL.h" +#include "softShadow.glsl" -varying vec2 uv0; -varying vec3 wsEyeRay; +in vec4 hpos; +in vec2 uv0; +in vec3 wsEyeRay; +in vec3 vsEyeRay; -uniform sampler2D prePassBuffer; -uniform sampler2D ShadowMap; +uniform sampler2D ShadowMap ; -#if TORQUE_SM >= 30 - - // Enables high quality soft shadow - // filtering for SM3.0 and above. - #define SOFTSHADOW_SM3 - - #include "softShadow.glsl" - -#else - - - +#ifdef USE_SSAO_MASK +uniform sampler2D ssaoMask ; +uniform vec4 rtParams2; #endif - + +uniform sampler2D prePassBuffer; uniform vec3 lightDirection; uniform vec4 lightColor; -uniform float lightBrightness; -uniform vec4 lightAmbient; -uniform vec4 lightTrilight; - -uniform vec3 eyePosWorld; - -uniform mat4 worldToLightProj; -uniform vec4 splitDistStart; -uniform vec4 splitDistEnd; +uniform float lightBrightness; +uniform vec4 lightAmbient; +uniform vec3 eyePosWorld; +uniform mat4x4 worldToLightProj; uniform vec4 scaleX; uniform vec4 scaleY; uniform vec4 offsetX; @@ -65,16 +57,12 @@ uniform vec4 atlasYOffset; uniform vec2 atlasScale; uniform vec4 zNearFarInvNearFar; uniform vec4 lightMapParams; - -uniform float constantSpecularPower; uniform vec2 fadeStartLength; uniform vec4 farPlaneScalePSSM; -uniform vec4 splitFade; uniform vec4 overDarkPSSM; uniform float shadowSoftness; - -void main() +void main() { // Sample/unpack the normal/z data vec4 prepassSample = prepassUncondition( prePassBuffer, uv0 ); @@ -83,148 +71,162 @@ void main() // Use eye ray to get ws pos vec4 worldPos = vec4(eyePosWorld + wsEyeRay * depth, 1.0f); - + // Get the light attenuation. float dotNL = dot(-lightDirection, normal); + + #ifdef PSSM_DEBUG_RENDER + vec3 debugColor = vec3(0); + #endif #ifdef NO_SHADOW // Fully unshadowed. float shadowed = 1.0; + #ifdef PSSM_DEBUG_RENDER + debugColor = vec3(1.0); + #endif + #else - + // Compute shadow map coordinate - vec4 pxlPosLightProj = worldToLightProj * worldPos; + vec4 pxlPosLightProj = tMul(worldToLightProj, worldPos); vec2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w; - - float distOffset = 0.0; - float shadowed = 0.0; - float fadeAmt = 0.0; - vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth); - - // Calculate things dependant on the shadowmap split - for ( int i = 0; i < 2; i++ ) - { - float zDistSplit = zDist.x + distOffset; - vec4 mask0; - mask0.x = float(zDistSplit >= splitDistStart.x); - mask0.y = float(zDistSplit >= splitDistStart.y); - mask0.z = float(zDistSplit >= splitDistStart.z); - mask0.w = float(zDistSplit >= splitDistStart.w); + + // Distance to light, in shadowmap space + float distToLight = pxlPosLightProj.z / pxlPosLightProj.w; - vec4 mask1; - mask1.x = float(zDistSplit < splitDistEnd.x); - mask1.y = float(zDistSplit < splitDistEnd.y); - mask1.z = float(zDistSplit < splitDistEnd.z); - mask1.w = float(zDistSplit < splitDistEnd.w); + // Figure out which split to sample from. Basically, we compute the shadowmap sample coord + // for all of the splits and then check if its valid. + vec4 shadowCoordX = vec4( baseShadowCoord.x ); + vec4 shadowCoordY = vec4( baseShadowCoord.y ); + vec4 farPlaneDists = vec4( distToLight ); + shadowCoordX *= scaleX; + shadowCoordY *= scaleY; + shadowCoordX += offsetX; + shadowCoordY += offsetY; + farPlaneDists *= farPlaneScalePSSM; + + // If the shadow sample is within -1..1 and the distance + // to the light for this pixel is less than the far plane + // of the split, use it. + vec4 finalMask; + if ( shadowCoordX.x > -0.99 && shadowCoordX.x < 0.99 && + shadowCoordY.x > -0.99 && shadowCoordY.x < 0.99 && + farPlaneDists.x < 1.0 ) + finalMask = vec4(1, 0, 0, 0); + + else if ( shadowCoordX.y > -0.99 && shadowCoordX.y < 0.99 && + shadowCoordY.y > -0.99 && shadowCoordY.y < 0.99 && + farPlaneDists.y < 1.0 ) + finalMask = vec4(0, 1, 0, 0); + + else if ( shadowCoordX.z > -0.99 && shadowCoordX.z < 0.99 && + shadowCoordY.z > -0.99 && shadowCoordY.z < 0.99 && + farPlaneDists.z < 1.0 ) + finalMask = vec4(0, 0, 1, 0); - vec4 finalMask = mask0 * mask1; + else + finalMask = vec4(0, 0, 0, 1); - float splitFadeDist = dot( finalMask, splitFade ); - vec2 finalScale; - finalScale.x = dot(finalMask, scaleX); - finalScale.y = dot(finalMask, scaleY); + #ifdef PSSM_DEBUG_RENDER + if ( finalMask.x > 0 ) + debugColor += vec3( 1, 0, 0 ); + else if ( finalMask.y > 0 ) + debugColor += vec3( 0, 1, 0 ); + else if ( finalMask.z > 0 ) + debugColor += vec3( 0, 0, 1 ); + else if ( finalMask.w > 0 ) + debugColor += vec3( 1, 1, 0 ); + #endif - vec2 finalOffset; - finalOffset.x = dot(finalMask, offsetX); - finalOffset.y = dot(finalMask, offsetY); - - vec2 shadowCoord; - shadowCoord = baseShadowCoord * finalScale; - shadowCoord += finalOffset; + // Here we know what split we're sampling from, so recompute the texcoord location + // Yes, we could just use the result from above, but doing it this way actually saves + // shader instructions. + vec2 finalScale; + finalScale.x = dot(finalMask, scaleX); + finalScale.y = dot(finalMask, scaleY); - // Convert to texcoord space - shadowCoord = 0.5 * shadowCoord + vec2(0.5, 0.5); - //shadowCoord.y = 1.0f - shadowCoord.y; + vec2 finalOffset; + finalOffset.x = dot(finalMask, offsetX); + finalOffset.y = dot(finalMask, offsetY); - // Move around inside of atlas - vec2 aOffset; - aOffset.x = dot(finalMask, atlasXOffset); - aOffset.y = dot(finalMask, atlasYOffset); + vec2 shadowCoord; + shadowCoord = baseShadowCoord * finalScale; + shadowCoord += finalOffset; - shadowCoord *= atlasScale; - shadowCoord += aOffset; - - // Distance to light, in shadowmap space - float distToLight = pxlPosLightProj.z / pxlPosLightProj.w; - - // Each split has a different far plane, take this into account. - float farPlaneScale = dot( farPlaneScalePSSM, finalMask ); - distToLight *= farPlaneScale; - - #ifdef SOFTSHADOW_SM3 + // Convert to texcoord space + shadowCoord = 0.5 * shadowCoord + vec2(0.5, 0.5); + shadowCoord.y = 1.0f - shadowCoord.y; - float esmShadow = softShadow_filter( ShadowMap, - gTapRotationTex, - uv0.xy, - shadowCoord, - farPlaneScale * shadowSoftness, - distToLight, - dotNL, - dot( finalMask, overDarkPSSM ) ); - - #else // !SOFTSHADOW_SM3 + // Move around inside of atlas + vec2 aOffset; + aOffset.x = dot(finalMask, atlasXOffset); + aOffset.y = dot(finalMask, atlasYOffset); - float occluder = decodeShadowMap( texture2DLod( ShadowMap, shadowCoord, 0.0 ) ); - float overDark = dot( finalMask, overDarkPSSM ); - float esmShadow = saturate( exp( esmFactor * ( occluder - distToLight ) ) ); - - #endif - - if ( i == 0 ) - { - float endDist = dot(splitDistEnd, finalMask); - fadeAmt = smoothstep(endDist - splitFadeDist, endDist, zDist).x; - shadowed = esmShadow * ( 1.0 - fadeAmt ); - } - else - shadowed += esmShadow * fadeAmt; - - distOffset += splitFadeDist; - } + shadowCoord *= atlasScale; + shadowCoord += aOffset; + + // Each split has a different far plane, take this into account. + float farPlaneScale = dot( farPlaneScalePSSM, finalMask ); + distToLight *= farPlaneScale; + + float shadowed = softShadow_filter( ShadowMap, + uv0.xy, + shadowCoord, + farPlaneScale * shadowSoftness, + distToLight, + dotNL, + dot( finalMask, overDarkPSSM ) ); // Fade out the shadow at the end of the range. + vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth); float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y; - shadowed = mix( shadowed, 1.0, clamp( fadeOutAmt, 0.0, 1.0 ) ); + shadowed = mix( shadowed, 1.0, saturate( fadeOutAmt ) ); + + #ifdef PSSM_DEBUG_RENDER + if ( fadeOutAmt > 1.0 ) + debugColor = vec3(1.0); + #endif #endif // !NO_SHADOW - - // Calc lighting coefficents - float specular = calcSpecular( -lightDirection, - normal, - normalize(-wsEyeRay), - constantSpecularPower, - shadowed * lightBrightness ); - - float Sat_NL_Att = clamp(dotNL, 0.0, 1.0) * shadowed; - - // Trilight, described by Tom Forsyth - // http://home.comcast.net/~tom_forsyth/papers/trilight/trilight.html -#ifdef ACCUMULATE_LUV - // In LUV multiply in the brightness of the light color (normaly done in the attenuate function) - Sat_NL_Att *= lightColor.a; + // Specular term + float specular = AL_CalcSpecular( -lightDirection, + normal, + normalize(-vsEyeRay) ) * lightBrightness * shadowed; - vec4 ambientBlend = lightAmbient; - ambientBlend.b *= clamp(-dotNL, 0.0, 1.0); - - vec3 trilight = lightTrilight.rgb; - trilight.b *= clamp(1.0 - abs(dotNL), 0.0, 1.0); - - ambientBlend.rg = mix(ambientBlend.rg, trilight.rg, clamp(0.5 * trilight.b / lightAmbient.b, 0.0, 1.0)); - ambientBlend.b += trilight.b; + float Sat_NL_Att = saturate( dotNL * shadowed ) * lightBrightness; + vec3 lightColorOut = lightMapParams.rgb * lightColor.rgb; + vec4 addToResult = lightAmbient; -#else + // TODO: This needs to be removed when lightmapping is disabled + // as its extra work per-pixel on dynamic lit scenes. + // + // Special lightmapping pass. + if ( lightMapParams.a < 0.0 ) + { + // This disables shadows on the backsides of objects. + shadowed = dotNL < 0.0f ? 1.0f : shadowed; - // RGB - // TODO: Trilight seems broken... it does lighting in shadows! - //vec4 ambientBlend = vec4(lightTrilight.rgb * clamp(1.0 - abs(dotNL), 0.0, 1.0) + lightAmbient.rgb * clamp(-dotNL, 0.0, 1.0), 0.0); - vec4 ambientBlend = vec4(lightAmbient.rgb, 0.0); + Sat_NL_Att = 1.0f; + lightColorOut = vec3(shadowed); + specular *= lightBrightness; + addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); + } -#endif + // Sample the AO texture. + #ifdef USE_SSAO_MASK + float ao = 1.0 - texture( ssaoMask, viewportCoordToRenderTarget( uv0.xy, rtParams2 ) ).r; + addToResult *= ao; + #endif + + #ifdef PSSM_DEBUG_RENDER + lightColorOut = debugColor; + #endif + + OUT_FragColor0 = lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult ); - // Output - gl_FragColor = lightinfoCondition( lightColor.rgb * lightBrightness, Sat_NL_Att, specular, ambientBlend) * lightMapParams; } diff --git a/Templates/Full/game/shaders/common/lighting/basic/gl/shadowFilterP.glsl b/Templates/Full/game/shaders/common/lighting/basic/gl/shadowFilterP.glsl index 238721e5e..4e97fa347 100644 --- a/Templates/Full/game/shaders/common/lighting/basic/gl/shadowFilterP.glsl +++ b/Templates/Full/game/shaders/common/lighting/basic/gl/shadowFilterP.glsl @@ -20,35 +20,27 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../../gl/hlslCompat.glsl" + uniform sampler2D diffuseMap; -varying vec2 uv; +in vec2 uv; uniform vec2 oneOverTargetSize; +const float offset[3] = float[]( 0.0, 1.3846153846, 3.2307692308 ); +const float weight[3] = float[]( 0.2270270270, 0.3162162162, 0.0702702703 ); + void main() { - vec2 sNonUniformTaps[8]; - - sNonUniformTaps[0] = vec2(0.992833, 0.979309); - sNonUniformTaps[1] = vec2(-0.998585, 0.985853); - sNonUniformTaps[2] = vec2(0.949299, -0.882562); - sNonUniformTaps[3] = vec2(-0.941358, -0.893924); - sNonUniformTaps[4] = vec2(0.545055, -0.589072); - sNonUniformTaps[5] = vec2(0.346526, 0.385821); - sNonUniformTaps[6] = vec2(-0.260183, 0.334412); - sNonUniformTaps[7] = vec2(0.248676, -0.679605); + vec4 OUT = texture( diffuseMap, uv ) * weight[0]; - gl_FragColor = vec4(0.0); - - vec2 texScale = vec2(1.0); - - for ( int i=0; i < 4; i++ ) + for ( int i=1; i < 3; i++ ) { - vec2 offset = (oneOverTargetSize * texScale) * sNonUniformTaps[i]; - gl_FragColor += texture2D( diffuseMap, uv + offset ); + vec2 _sample = (BLUR_DIR * offset[i]) * oneOverTargetSize; + OUT += texture( diffuseMap, uv + _sample ) * weight[i]; + OUT += texture( diffuseMap, uv - _sample ) * weight[i]; } - - gl_FragColor /= vec4(4.0); - gl_FragColor.rgb = vec3(0.0); + + OUT_FragColor0 = OUT; } diff --git a/Templates/Full/game/shaders/common/lighting/basic/gl/shadowFilterV.glsl b/Templates/Full/game/shaders/common/lighting/basic/gl/shadowFilterV.glsl index cbf3696be..0eeb2e0fd 100644 --- a/Templates/Full/game/shaders/common/lighting/basic/gl/shadowFilterV.glsl +++ b/Templates/Full/game/shaders/common/lighting/basic/gl/shadowFilterV.glsl @@ -22,13 +22,16 @@ #include "../../../../../../shaders/common/gl/torque.glsl" -uniform vec2 oneOverTargetSize; +in vec4 vPosition; +in vec2 vTexCoord0; + uniform vec4 rtParams0; -varying vec2 uv; +out vec2 uv; void main() { - gl_Position = gl_Vertex; - uv = viewportCoordToRenderTarget( gl_MultiTexCoord0.st, rtParams0 ); + gl_Position = vPosition; + uv = viewportCoordToRenderTarget( vTexCoord0.st, rtParams0 ); + gl_Position.y *= -1; //correct ssp } diff --git a/Templates/Full/game/shaders/common/lighting/shadowMap/gl/boxFilterP.glsl b/Templates/Full/game/shaders/common/lighting/shadowMap/gl/boxFilterP.glsl index 2800a3f17..0f568c716 100644 --- a/Templates/Full/game/shaders/common/lighting/shadowMap/gl/boxFilterP.glsl +++ b/Templates/Full/game/shaders/common/lighting/shadowMap/gl/boxFilterP.glsl @@ -26,7 +26,7 @@ uniform sampler2D diffuseMap0; uniform float texSize; uniform vec2 blurDimension; -varying vec2 tex0; +in vec2 tex0; void main() { @@ -40,8 +40,8 @@ void main() vec4 accum = vec4(0.0, 0.0, 0.0, 0.0); for(int i = 0; i < int(blurSamples); i++) { - accum += texture2D(diffuseMap0, BaseTexCoord + float(i) * SampleOffset); + accum += texture(diffuseMap0, BaseTexCoord + float(i) * SampleOffset); } accum /= blurSamples; - gl_FragColor = accum; + OUT_FragColor0 = accum; } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/shadowMap/gl/boxFilterV.glsl b/Templates/Full/game/shaders/common/lighting/shadowMap/gl/boxFilterV.glsl index 3850f83c7..9fc436f6c 100644 --- a/Templates/Full/game/shaders/common/lighting/shadowMap/gl/boxFilterV.glsl +++ b/Templates/Full/game/shaders/common/lighting/shadowMap/gl/boxFilterV.glsl @@ -20,12 +20,15 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +in vec4 vPosition; +in vec2 vTexCoord0; + uniform mat4 modelview; -varying vec2 tex0; +out vec2 tex0; void main() { - gl_Position = modelview * gl_Vertex; - tex0 = gl_MultiTexCoord0.st; + gl_Position = modelview * vPosition; + tex0 = vTexCoord0.st; } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/postFx/lightRay/lightRayOccludeP.hlsl b/Templates/Full/game/shaders/common/postFx/lightRay/lightRayOccludeP.hlsl index 8769905f6..e8870b3c4 100644 --- a/Templates/Full/game/shaders/common/postFx/lightRay/lightRayOccludeP.hlsl +++ b/Templates/Full/game/shaders/common/postFx/lightRay/lightRayOccludeP.hlsl @@ -45,7 +45,7 @@ float4 main( PFXVertToPix IN ) : COLOR0 col = tex2D( backBuffer, IN.uv0 ); //col = 1 - exp(-120000 * col); - col += dot( col, LUMINANCE_VECTOR ) + 0.0001f; + col += dot( col.rgb, LUMINANCE_VECTOR ) + 0.0001f; col *= brightScalar; } diff --git a/Templates/Full/game/shaders/common/postFx/lightRay/lightRayP.hlsl b/Templates/Full/game/shaders/common/postFx/lightRay/lightRayP.hlsl index 7dd334607..ff44abfae 100644 --- a/Templates/Full/game/shaders/common/postFx/lightRay/lightRayP.hlsl +++ b/Templates/Full/game/shaders/common/postFx/lightRay/lightRayP.hlsl @@ -59,7 +59,7 @@ float4 main( PFXVertToPix IN ) : COLOR0 half2 deltaTexCoord = (half2)( texCoord.xy - screenSunPos ); // Divide by number of samples and scale by control factor. - deltaTexCoord *= 1.0 / (half)samples * density; + deltaTexCoord *= (half)(1.0 / samples * density); // Evaluate summation from Equation 3 NUM_SAMPLES iterations. for ( int i = 0; i < samples; i++ ) @@ -71,13 +71,13 @@ float4 main( PFXVertToPix IN ) : COLOR0 half3 sample = (half3)tex2Dlod( frameSampler, texCoord ); // Apply sample attenuation scale/decay factors. - sample *= illuminationDecay * weight; + sample *= half(illuminationDecay * weight); // Accumulate combined color. color += sample; // Update exponential decay factor. - illuminationDecay *= decay; + illuminationDecay *= half(decay); } //return saturate( amount ) * color * Exposure; diff --git a/Templates/Full/game/shaders/common/postFx/postFxV.glsl b/Templates/Full/game/shaders/common/postFx/postFxV.glsl index 3aded2e0f..96a5ec819 100644 --- a/Templates/Full/game/shaders/common/postFx/postFxV.glsl +++ b/Templates/Full/game/shaders/common/postFx/postFxV.glsl @@ -22,27 +22,30 @@ #include "./../gl/torque.glsl" +in vec4 vPosition; +in vec2 vTexCoord0; +in vec3 vTexCoord1; uniform vec4 rtParams0; uniform vec4 rtParams1; uniform vec4 rtParams2; uniform vec4 rtParams3; -varying vec2 uv0; -varying vec2 uv1; -varying vec2 uv2; -varying vec2 uv3; -varying vec3 wsEyeRay; +out vec2 uv0; +out vec2 uv1; +out vec2 uv2; +out vec2 uv3; +out vec3 wsEyeRay; void main() { - gl_Position = gl_Vertex; + gl_Position = vPosition; - uv0 = viewportCoordToRenderTarget( gl_MultiTexCoord0.st, rtParams0 ); - uv1 = viewportCoordToRenderTarget( gl_MultiTexCoord0.st, rtParams1 ); - uv2 = viewportCoordToRenderTarget( gl_MultiTexCoord0.st, rtParams2 ); - uv3 = viewportCoordToRenderTarget( gl_MultiTexCoord0.st, rtParams3 ); + uv0 = viewportCoordToRenderTarget( vTexCoord0, rtParams0 ); + uv1 = viewportCoordToRenderTarget( vTexCoord0, rtParams1 ); + uv2 = viewportCoordToRenderTarget( vTexCoord0, rtParams2 ); + uv3 = viewportCoordToRenderTarget( vTexCoord0, rtParams3 ); - wsEyeRay = gl_MultiTexCoord1.xyz; + wsEyeRay = vTexCoord1; } diff --git a/Templates/Full/game/shaders/common/terrain/gl/blendP.glsl b/Templates/Full/game/shaders/common/terrain/gl/blendP.glsl index 3817e1de2..a2e4af787 100644 --- a/Templates/Full/game/shaders/common/terrain/gl/blendP.glsl +++ b/Templates/Full/game/shaders/common/terrain/gl/blendP.glsl @@ -23,8 +23,10 @@ #include "../terrain.glsl" #include "../../gl/hlslCompat.glsl" -varying vec2 layerCoord; -varying vec2 texCoord; +in vec2 layerCoord; +#define IN_layerCoord layerCoord +in vec2 texCoord; +#define IN_texCoord texCoord uniform sampler2D layerTex; uniform sampler2D textureMap; @@ -33,12 +35,12 @@ uniform float layerSize; void main() { - vec4 layerSample = round(texture2D( layerTex, layerCoord ) * 255.0); + vec4 layerSample = round(texture( layerTex, IN_layerCoord ) * 255.0); - float blend = calcBlend( texId, layerCoord, layerSize, layerSample ); + float blend = calcBlend( texId, IN_layerCoord, layerSize, layerSample ); if(blend - 0.0001 < 0.0) discard; - gl_FragColor = vec4( texture2D( textureMap, texCoord ).rgb, blend ); + OUT_FragColor0 = vec4( texture( textureMap, IN_texCoord ).rgb, blend ); } diff --git a/Templates/Full/game/shaders/common/terrain/gl/blendV.glsl b/Templates/Full/game/shaders/common/terrain/gl/blendV.glsl index 44362085b..dc7b7befa 100644 --- a/Templates/Full/game/shaders/common/terrain/gl/blendV.glsl +++ b/Templates/Full/game/shaders/common/terrain/gl/blendV.glsl @@ -23,14 +23,19 @@ /// The vertex shader used in the generation and caching of the /// base terrain texture. -varying vec2 layerCoord; -varying vec2 texCoord; +in vec4 vPosition; +in vec2 vTexCoord0; + +out vec2 layerCoord; +out vec2 texCoord; uniform vec2 texScale; void main() { - gl_Position = vec4(gl_Vertex.xyz, 1.0); - layerCoord = gl_MultiTexCoord0.st; - texCoord = gl_MultiTexCoord0.st * texScale; + gl_Position = vec4(vPosition.xyz, 1.0); + layerCoord = vTexCoord0.st; + texCoord = vTexCoord0.st * texScale; + + gl_Position.y *= -1; } diff --git a/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl b/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl index 72232622a..44207dea9 100644 --- a/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl +++ b/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl @@ -31,7 +31,7 @@ #define FRESNEL_BIAS miscParams[0] #define FRESNEL_POWER miscParams[1] #define CLARITY miscParams[2] -#define ISRIVER miscParams[3] +#define ISRIVER miscParams[3] // reflectParams #define REFLECT_PLANE_Z reflectParams[0] @@ -45,40 +45,49 @@ #define DISTORT_FULL_DEPTH distortionParams[2] // ConnectData.misc -#define LIGHT_VEC misc.xyz -#define WORLD_Z objPos.w +#define LIGHT_VEC IN_misc.xyz +#define WORLD_Z IN_objPos.w // specularParams #define SPEC_POWER specularParams[3] #define SPEC_COLOR specularParams.xyz +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- + // TexCoord 0 and 1 (xy,zw) for ripple texture lookup -varying vec4 rippleTexCoord01; +in vec4 rippleTexCoord01; +#define IN_rippleTexCoord01 rippleTexCoord01 // TexCoord 2 for ripple texture lookup -varying vec2 rippleTexCoord2; +in vec2 rippleTexCoord2; +#define IN_rippleTexCoord2 rippleTexCoord2 // Screenspace vert position BEFORE wave transformation -varying vec4 posPreWave; +in vec4 posPreWave; +#define IN_posPreWave posPreWave // Screenspace vert position AFTER wave transformation -varying vec4 posPostWave; +in vec4 posPostWave; +#define IN_posPostWave posPostWave // Worldspace unit distance/depth of this vertex/pixel -varying float pixelDist; - -// Objectspace vert position BEFORE wave transformation -// w coord is world space z position. -varying vec4 objPos; +in float pixelDist; +#define IN_pixelDist pixelDist -varying vec3 misc; +in vec4 objPos; +#define IN_objPos objPos + +in vec3 misc; +#define IN_misc misc //----------------------------------------------------------------------------- // approximate Fresnel function //----------------------------------------------------------------------------- float fresnel(float NdotV, float bias, float power) { - return bias + (1.0-bias)*pow(abs(1.0 - max(NdotV, 0.0)), power); + return bias + (1.0-bias)*pow(abs(1.0 - max(NdotV, 0)), power); } //----------------------------------------------------------------------------- @@ -89,7 +98,7 @@ uniform sampler2D bumpMap; uniform sampler2D reflectMap; uniform sampler2D refractBuff; uniform samplerCube skyMap; -//uniform sampler foamMap; +//uniform sampler2D foamMap; uniform vec4 baseColor; uniform vec4 miscParams; uniform vec4 reflectParams; @@ -98,8 +107,9 @@ uniform vec3 eyePos; uniform vec3 distortionParams; uniform vec3 fogData; uniform vec4 fogColor; -uniform vec3 rippleMagnitude; +uniform vec4 rippleMagnitude; uniform vec4 specularParams; +uniform mat4 modelMat; //----------------------------------------------------------------------------- // Main @@ -107,31 +117,35 @@ uniform vec4 specularParams; void main() { // Modulate baseColor by the ambientColor. - vec4 waterBaseColor = baseColor * vec4( ambientColor.rgb, 1.0 ); + vec4 waterBaseColor = baseColor * vec4( ambientColor.rgb, 1 ); // Get the bumpNorm... - vec3 bumpNorm = ( texture2D( bumpMap, rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x; - bumpNorm += ( texture2D( bumpMap, rippleTexCoord01.zw ).rgb * 2.0 - 1.0 ) * rippleMagnitude.y; - bumpNorm += ( texture2D( bumpMap, rippleTexCoord2 ).rgb * 2.0 - 1.0 ) * rippleMagnitude.z; - + vec3 bumpNorm = ( texture( bumpMap, IN_rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x; + bumpNorm += ( texture( bumpMap, IN_rippleTexCoord01.zw ).rgb * 2.0 - 1.0 ) * rippleMagnitude.y; + bumpNorm += ( texture( bumpMap, IN_rippleTexCoord2 ).rgb * 2.0 - 1.0 ) * rippleMagnitude.z; + + bumpNorm = normalize( bumpNorm ); + bumpNorm = mix( bumpNorm, vec3(0,0,1), 1.0 - rippleMagnitude.w ); + // We subtract a little from it so that we don't // distort where the water surface intersects the // camera near plane. - float distortAmt = saturate( pixelDist / 1.0 ) * 0.8; + float distortAmt = saturate( IN_pixelDist / 1.0 ) * 0.8; - vec4 distortPos = posPostWave; + vec4 distortPos = IN_posPostWave; distortPos.xy += bumpNorm.xy * distortAmt; #ifdef UNDERWATER - gl_FragColor = texture2DProj( refractBuff, distortPos.xyz ); + OUT_FragColor0 = hdrEncode( textureProj( refractBuff, distortPos ) ); #else - vec3 eyeVec = objPos.xyz - eyePos; - vec3 reflectionVec = reflect( eyeVec, normalize(bumpNorm) ); + vec3 eyeVec = IN_objPos.xyz - eyePos; + eyeVec = tMul( mat3(modelMat), eyeVec ); + vec3 reflectionVec = reflect( eyeVec, bumpNorm ); // Color that replaces the reflection color when we do not // have one that is appropriate. - vec4 fakeColor = vec4(ambientColor,1.0); + vec4 fakeColor = vec4(ambientColor,1); // Use fakeColor for ripple-normals that are angled towards the camera eyeVec = -eyeVec; @@ -140,58 +154,61 @@ void main() float fakeColorAmt = ang; // Get reflection map color - vec4 refMapColor = texture2DProj( reflectMap, distortPos ); + vec4 refMapColor = hdrDecode( textureProj( reflectMap, distortPos ) ); // If we do not have a reflection texture then we use the cubemap. - refMapColor = mix( refMapColor, textureCube( skyMap, -reflectionVec ), NO_REFLECT ); + refMapColor = mix( refMapColor, texture( skyMap, reflectionVec ), NO_REFLECT ); // Combine reflection color and fakeColor. vec4 reflectColor = mix( refMapColor, fakeColor, fakeColorAmt ); //return refMapColor; // Get refract color - vec4 refractColor = texture2DProj( refractBuff, distortPos.xyz ); + vec4 refractColor = hdrDecode( textureProj( refractBuff, distortPos ) ); // calc "diffuse" color by lerping from the water color // to refraction image based on the water clarity. - vec4 diffuseColor = mix( refractColor, waterBaseColor, 1.0 - CLARITY ); + vec4 diffuseColor = mix( refractColor, waterBaseColor, 1.0f - CLARITY ); // fresnel calculation float fresnelTerm = fresnel( ang, FRESNEL_BIAS, FRESNEL_POWER ); + //return vec4( fresnelTerm.rrr, 1 ); // Also scale the frensel by our distance to the // water surface. This removes the hard reflection // when really close to the water surface. - fresnelTerm *= saturate( pixelDist - 0.1 ); + fresnelTerm *= saturate( IN_pixelDist - 0.1 ); // Combine the diffuse color and reflection image via the // fresnel term and set out output color. - gl_FragColor = mix( diffuseColor, reflectColor, fresnelTerm ); - + vec4 OUT = mix( diffuseColor, reflectColor, fresnelTerm ); + #ifdef WATER_SPEC // Get some specular reflection. vec3 newbump = bumpNorm; newbump.xy *= 3.5; newbump = normalize( bumpNorm ); - vec3 halfAng = normalize( eyeVec + -LIGHT_VEC ); + half3 halfAng = normalize( eyeVec + -LIGHT_VEC ); float specular = saturate( dot( newbump, halfAng ) ); specular = pow( specular, SPEC_POWER ); - gl_FragColor.rgb = gl_FragColor.rgb + ( SPEC_COLOR * specular.xxx ); + OUT.rgb = OUT.rgb + ( SPEC_COLOR * specular.xxx ); #else // Disable fogging if spec is on because otherwise we run out of instructions. // Fog it. float factor = computeSceneFog( eyePos, - objPos.xyz, + IN_objPos.xyz, WORLD_Z, fogData.x, fogData.y, fogData.z ); - gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor.rgb, 1.0 - saturate( factor ) ); - - #endif + //OUT.rgb = mix( OUT.rgb, fogColor.rgb, 1.0 - saturate( factor ) ); + #endif + + OUT_FragColor0 = OUT; + #endif } diff --git a/Templates/Full/game/shaders/common/water/gl/waterBasicV.glsl b/Templates/Full/game/shaders/common/water/gl/waterBasicV.glsl index bb2a0c954..1634fd2de 100644 --- a/Templates/Full/game/shaders/common/water/gl/waterBasicV.glsl +++ b/Templates/Full/game/shaders/common/water/gl/waterBasicV.glsl @@ -27,23 +27,30 @@ //----------------------------------------------------------------------------- // TexCoord 0 and 1 (xy,zw) for ripple texture lookup -varying vec4 rippleTexCoord01; +out vec4 rippleTexCoord01; +#define OUT_rippleTexCoord01 rippleTexCoord01 // TexCoord 2 for ripple texture lookup -varying vec2 rippleTexCoord2; +out vec2 rippleTexCoord2; +#define OUT_rippleTexCoord2 rippleTexCoord2 // Screenspace vert position BEFORE wave transformation -varying vec4 posPreWave; +out vec4 posPreWave; +#define OUT_posPreWave posPreWave // Screenspace vert position AFTER wave transformation -varying vec4 posPostWave; +out vec4 posPostWave; +#define OUT_posPostWave posPostWave // Worldspace unit distance/depth of this vertex/pixel -varying float pixelDist; +out float pixelDist; +#define OUT_pixelDist pixelDist -varying vec4 objPos; +out vec4 objPos; +#define OUT_objPos objPos -varying vec3 misc; +out vec3 misc; +#define OUT_misc misc //----------------------------------------------------------------------------- // Uniforms @@ -63,49 +70,56 @@ uniform float gridElementSize; uniform float elapsedTime; uniform float undulateMaxDist; +in vec4 vPosition; +in vec3 vNormal; +in vec4 vColor; +in vec2 vTexCoord0; +in vec4 vTexCoord1; + //----------------------------------------------------------------------------- // Main //----------------------------------------------------------------------------- void main() { - vec4 position = gl_Vertex; - vec3 normal = gl_Normal; - vec2 undulateData = gl_MultiTexCoord0.st; - vec4 horizonFactor = gl_MultiTexCoord1; + vec4 IN_position = vPosition; + vec3 IN_normal = vNormal; + vec2 IN_undulateData = vTexCoord0; + vec4 IN_horizonFactor = vTexCoord1; + vec4 OUT_hpos = vec4(0); // use projection matrix for reflection / refraction texture coords - mat4 texGen = mat4(0.5, 0.0, 0.0, 0.0, - 0.0, 0.5, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.5, 0.5, 0.0, 1.0); + mat4 texGen = mat4FromRow( 0.5, 0.0, 0.0, 0.5, + 0.0, -0.5, 0.0, 0.5, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 ); // Move the vertex based on the horizonFactor if specified to do so for this vert. - //if ( horizonFactor.z > 0.0 ) - //{ - //vec2 offsetXY = eyePos.xy - mod(eyePos.xy, gridElementSize); - //position.xy += offsetXY; - //undulateData += offsetXY; - //} + // if ( IN_horizonFactor.z > 0 ) + // { + // vec2 offsetXY = eyePos.xy - eyePos.xy % gridElementSize; + // IN_position.xy += offsetXY; + // IN_undulateData += offsetXY; + // } - vec4 worldPos = modelMat * position; - //fogPos = position.xyz; - position.z = mix( position.z, eyePos.z, horizonFactor.x ); - - objPos.xyz = position.xyz; - objPos.w = worldPos.z; + vec4 worldPos = tMul( modelMat, IN_position ); + + IN_position.z = mix( IN_position.z, eyePos.z, IN_horizonFactor.x ); + + //OUT_objPos = worldPos; + OUT_objPos.xyz = IN_position.xyz; + OUT_objPos.w = worldPos.z; // Send pre-undulation screenspace position - posPreWave = modelview * position; - posPreWave = texGen * posPreWave; + OUT_posPreWave = tMul( modelview, IN_position ); + OUT_posPreWave = tMul( texGen, OUT_posPreWave ); // Calculate the undulation amount for this vertex. - vec2 undulatePos = (modelMat * vec4( undulateData.xy, 0, 1 )).xy; - - //if ( undulatePos.x < 0.0 ) - //undulatePos = position.xy; - - float undulateAmt = 0.0; + vec2 undulatePos = tMul( modelMat, vec4( IN_undulateData.xy, 0, 1 ) ).xy; + //if ( undulatePos.x < 0 ) + // undulatePos = IN_position.xy; + float undulateAmt = 0.0; + undulateAmt += waveData[0].y * sin( elapsedTime * waveData[0].x + undulatePos.x * waveDir[0].x + undulatePos.y * waveDir[0].y ); @@ -114,118 +128,84 @@ void main() undulatePos.y * waveDir[1].y ); undulateAmt += waveData[2].y * sin( elapsedTime * waveData[2].x + undulatePos.x * waveDir[2].x + - undulatePos.y * waveDir[2].y ); - - float undulateFade = 1.0; - - // Scale down wave magnitude amount based on distance from the camera. - float dist = length( position.xyz - eyePos ); + undulatePos.y * waveDir[2].y ); + + float undulateFade = 1; + + // Scale down wave magnitude amount based on distance from the camera. + float dist = distance( IN_position.xyz, eyePos ); dist = clamp( dist, 1.0, undulateMaxDist ); - undulateFade *= ( 1.0 - dist / undulateMaxDist ); + undulateFade *= ( 1 - dist / undulateMaxDist ); // Also scale down wave magnitude if the camera is very very close. - undulateFade *= saturate( ( length( position.xyz - eyePos ) - 0.5 ) / 10.0 ); - + undulateFade *= saturate( ( distance( IN_position.xyz, eyePos ) - 0.5 ) / 10.0 ); + undulateAmt *= undulateFade; + //#endif //undulateAmt = 0; // Apply wave undulation to the vertex. - posPostWave = position; - posPostWave.xyz += normal.xyz * undulateAmt; + OUT_posPostWave = IN_position; + OUT_posPostWave.xyz += IN_normal.xyz * undulateAmt; // Save worldSpace position of this pixel/vert - //worldPos = posPostWave.xyz; + //OUT_worldPos = OUT_posPostWave.xyz; + //OUT_worldPos = tMul( modelMat, OUT_posPostWave.xyz ); + //OUT_worldPos.z += objTrans[2][2]; //91.16; - //worldSpaceZ = ( modelMat * vec4(fogPos,1.0) ).z; - //if ( horizonFactor.x > 0.0 ) - //{ - //vec3 awayVec = normalize( fogPos.xyz - eyePos ); - //fogPos.xy += awayVec.xy * 1000.0; - //} + // OUT_misc.w = tMul( modelMat, OUT_fogPos ).z; + // if ( IN_horizonFactor.x > 0 ) + // { + // vec3 awayVec = normalize( OUT_fogPos.xyz - eyePos ); + // OUT_fogPos.xy += awayVec.xy * 1000.0; + // } // Convert to screen - posPostWave = modelview * posPostWave; + OUT_posPostWave = tMul( modelview, OUT_posPostWave ); // tMul( modelview, vec4( OUT_posPostWave.xyz, 1 ) ); // Setup the OUT position symantic variable - gl_Position = posPostWave; - //gl_Position.z = mix(gl_Position.z, gl_Position.w, horizonFactor.x); + OUT_hpos = OUT_posPostWave; // tMul( modelview, vec4( IN_position.xyz, 1 ) ); //vec4( OUT_posPostWave.xyz, 1 ); + //OUT_hpos.z = mix( OUT_hpos.z, OUT_hpos.w, IN_horizonFactor.x ); // Save world space camera dist/depth of the outgoing pixel - pixelDist = gl_Position.z; + OUT_pixelDist = OUT_hpos.z; // Convert to reflection texture space - posPostWave = texGen * posPostWave; + OUT_posPostWave = tMul( texGen, OUT_posPostWave ); vec2 txPos = undulatePos; - if ( horizonFactor.x > 0.0 ) + if ( bool(IN_horizonFactor.x) ) txPos = normalize( txPos ) * 50000.0; - - - // set up tex coordinates for the 3 interacting normal maps - rippleTexCoord01.xy = txPos * rippleTexScale[0]; - rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; + + // set up tex coordinates for the 3 interacting normal maps + OUT_rippleTexCoord01.xy = txPos * rippleTexScale[0]; + OUT_rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; mat2 texMat; texMat[0][0] = rippleMat[0].x; texMat[1][0] = rippleMat[0].y; texMat[0][1] = rippleMat[0].z; texMat[1][1] = rippleMat[0].w; - rippleTexCoord01.xy = texMat * rippleTexCoord01.xy ; + OUT_rippleTexCoord01.xy = tMul( texMat, OUT_rippleTexCoord01.xy ); - rippleTexCoord01.zw = txPos * rippleTexScale[1]; - rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; + OUT_rippleTexCoord01.zw = txPos * rippleTexScale[1]; + OUT_rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; texMat[0][0] = rippleMat[1].x; texMat[1][0] = rippleMat[1].y; texMat[0][1] = rippleMat[1].z; texMat[1][1] = rippleMat[1].w; - rippleTexCoord01.zw = texMat * rippleTexCoord01.zw ; + OUT_rippleTexCoord01.zw = tMul( texMat, OUT_rippleTexCoord01.zw ); - rippleTexCoord2.xy = txPos * rippleTexScale[2]; - rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; + OUT_rippleTexCoord2.xy = txPos * rippleTexScale[2]; + OUT_rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; texMat[0][0] = rippleMat[2].x; texMat[1][0] = rippleMat[2].y; texMat[0][1] = rippleMat[2].z; texMat[1][1] = rippleMat[2].w; - rippleTexCoord2.xy = texMat * rippleTexCoord2.xy ; - - - /*rippleTexCoord01.xy = mix( position.xy * rippleTexScale[0], txPos.xy * rippleTexScale[0], horizonFactor.x ); - rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; - - rippleTexCoord01.zw = mix( position.xy * rippleTexScale[1], txPos.xy * rippleTexScale[1], horizonFactor.x ); - rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; - - rippleTexCoord2.xy = mix( position.xy * rippleTexScale[2], txPos.xy * rippleTexScale[2], horizonFactor.x ); - rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; */ - - - /*rippleTexCoord01.xy = mix( position.xy * rippleTexScale[0], txPos.xy * rippleTexScale[0], horizonFactor.x ); - rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; - mat2 texMat; - texMat[0][0] = rippleMat[0].x; - texMat[1][0] = rippleMat[0].y; - texMat[0][1] = rippleMat[0].z; - texMat[1][1] = rippleMat[0].w; - rippleTexCoord01.xy = texMat * rippleTexCoord01.xy ; - - rippleTexCoord01.zw = mix( position.xy * rippleTexScale[1], txPos.xy * rippleTexScale[1], horizonFactor.x ); - rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; - texMat[0][0] = rippleMat[1].x; - texMat[1][0] = rippleMat[1].y; - texMat[0][1] = rippleMat[1].z; - texMat[1][1] = rippleMat[1].w; - rippleTexCoord01.zw = texMat * rippleTexCoord01.zw ; - - rippleTexCoord2.xy = mix( position.xy * rippleTexScale[2], txPos.xy * rippleTexScale[2], horizonFactor.x ); - rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; - texMat[0][0] = rippleMat[2].x; - texMat[1][0] = rippleMat[2].y; - texMat[0][1] = rippleMat[2].z; - texMat[1][1] = rippleMat[2].w; - rippleTexCoord2.xy = texMat * rippleTexCoord2.xy ;*/ + OUT_rippleTexCoord2.xy = tMul( texMat, OUT_rippleTexCoord2.xy ); #ifdef WATER_SPEC @@ -234,8 +214,8 @@ void main() vec3 normal; for ( int i = 0; i < 3; i++ ) { - binormal.z += undulateFade * waveDir[i].x * waveData[i].y * cos( waveDir[i].x * undulateData.x + waveDir[i].y * undulateData.y + elapsedTime * waveData[i].x ); - tangent.z += undulateFade * waveDir[i].y * waveData[i].y * cos( waveDir[i].x * undulateData.x + waveDir[i].y * undulateData.y + elapsedTime * waveData[i].x ); + binormal.z += undulateFade * waveDir[i].x * waveData[i].y * cos( waveDir[i].x * IN_undulateData.x + waveDir[i].y * IN_undulateData.y + elapsedTime * waveData[i].x ); + tangent.z += undulateFade * waveDir[i].y * waveData[i].y * cos( waveDir[i].x * IN_undulateData.x + waveDir[i].y * IN_undulateData.y + elapsedTime * waveData[i].x ); } binormal = normalize( binormal ); @@ -246,15 +226,19 @@ void main() worldToTangent[0] = binormal; worldToTangent[1] = tangent; worldToTangent[2] = normal; + + worldToTangent = transpose(worldToTangent); - misc.xyz = inLightVec * modelMat; - misc.xyz = worldToTangent * misc.xyz; + OUT_misc.xyz = tMul( inLightVec, modelMat ); + OUT_misc.xyz = tMul( worldToTangent, OUT_misc.xyz ); #else - misc.xyz = inLightVec; - + OUT_misc.xyz = inLightVec; + #endif - + + gl_Position = OUT_hpos; + correctSSP(gl_Position); } diff --git a/Templates/Full/game/shaders/common/water/gl/waterP.glsl b/Templates/Full/game/shaders/common/water/gl/waterP.glsl index bf482d724..3e15fe576 100644 --- a/Templates/Full/game/shaders/common/water/gl/waterP.glsl +++ b/Templates/Full/game/shaders/common/water/gl/waterP.glsl @@ -20,6 +20,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../gl/hlslCompat.glsl" #include "shadergen:/autogenConditioners.h" #include "../../gl/torque.glsl" @@ -27,10 +28,7 @@ // Defines //----------------------------------------------------------------------------- -#ifdef TORQUE_BASIC_LIGHTING - #define BASIC -#endif - +#define PIXEL_DIST IN_rippleTexCoord2.z // miscParams #define FRESNEL_BIAS miscParams[0] #define FRESNEL_POWER miscParams[1] @@ -57,33 +55,54 @@ #define DISTORT_FULL_DEPTH distortionParams[2] // foamParams -#define FOAM_SCALE foamParams[0] +#define FOAM_OPACITY foamParams[0] #define FOAM_MAX_DEPTH foamParams[1] +#define FOAM_AMBIENT_LERP foamParams[2] +#define FOAM_RIPPLE_INFLUENCE foamParams[3] -// Incoming data -// Worldspace position of this pixel -varying vec3 worldPos; +// specularParams +#define SPEC_POWER specularParams[3] +#define SPEC_COLOR specularParams.xyz + +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- + +//ConnectData IN + +in vec4 hpos; // TexCoord 0 and 1 (xy,zw) for ripple texture lookup -varying vec4 rippleTexCoord01; +in vec4 rippleTexCoord01; -// TexCoord 2 for ripple texture lookup -varying vec2 rippleTexCoord2; +// xy is TexCoord 2 for ripple texture lookup +// z is the Worldspace unit distance/depth of this vertex/pixel +// w is amount of the crestFoam ( more at crest of waves ). +in vec4 rippleTexCoord2; // Screenspace vert position BEFORE wave transformation -varying vec4 posPreWave; +in vec4 posPreWave; // Screenspace vert position AFTER wave transformation -varying vec4 posPostWave; +in vec4 posPostWave; -// Worldspace unit distance/depth of this vertex/pixel -varying float pixelDist; +// Objectspace vert position BEFORE wave transformation +// w coord is world space z position. +in vec4 objPos; -varying vec3 fogPos; +in vec4 foamTexCoords; -varying float worldSpaceZ; +in mat3 tangentMat; -varying vec4 foamTexCoords; + +#define IN_hpos hpos +#define IN_rippleTexCoord01 rippleTexCoord01 +#define IN_rippleTexCoord2 rippleTexCoord2 +#define IN_posPreWave posPreWave +#define IN_posPostWave posPostWave +#define IN_objPos objPos +#define IN_foamTexCoords foamTexCoords +#define IN_tangentMat tangentMat //----------------------------------------------------------------------------- // approximate Fresnel function @@ -100,10 +119,10 @@ uniform sampler2D bumpMap; uniform sampler2D prepassTex; uniform sampler2D reflectMap; uniform sampler2D refractBuff; -uniform samplerCUBE skyMap; +uniform samplerCube skyMap; uniform sampler2D foamMap; -uniform vec4 specularColor; -uniform float specularPower; +uniform sampler1D depthGradMap; +uniform vec4 specularParams; uniform vec4 baseColor; uniform vec4 miscParams; uniform vec2 fogParams; @@ -112,64 +131,45 @@ uniform vec3 reflectNormal; uniform vec2 wetnessParams; uniform float farPlaneDist; uniform vec3 distortionParams; -//uniform vec4 renderTargetParams; -uniform vec2 foamParams; -uniform vec3 foamColorMod; +uniform vec4 foamParams; uniform vec3 ambientColor; -uniform vec3 eyePos; -uniform vec3 inLightVec; +uniform vec3 eyePos; // This is in object space! uniform vec3 fogData; uniform vec4 fogColor; -//uniform vec4 rtParams; -uniform vec2 rtScale; -uniform vec2 rtHalfPixel; -uniform vec4 rtOffset; -uniform vec3 rippleMagnitude; +uniform vec4 rippleMagnitude; +uniform vec4 rtParams1; +uniform float depthGradMax; +uniform vec3 inLightVec; +uniform mat4 modelMat; +uniform vec4 sunColor; +uniform float sunBrightness; +uniform float reflectivity; //----------------------------------------------------------------------------- // Main //----------------------------------------------------------------------------- void main() { - vec4 rtParams = vec4( rtOffset.x / rtOffset.z + rtHalfPixel.x, - rtOffset.y / rtOffset.w + rtHalfPixel.x, - rtScale ); - - // Modulate baseColor by the ambientColor. - vec4 waterBaseColor = baseColor * vec4( ambientColor.rgb, 1 ); - // Get the bumpNorm... - vec3 bumpNorm = ( tex2D( bumpMap, IN.rippleTexCoord01.xy ) * 2.0 - 1.0 ) * rippleMagnitude.x; - bumpNorm += ( tex2D( bumpMap, IN.rippleTexCoord01.zw ) * 2.0 - 1.0 ) * rippleMagnitude.y; - bumpNorm += ( tex2D( bumpMap, IN.rippleTexCoord2 ) * 2.0 - 1.0 ) * rippleMagnitude.z; - - // JCF: this was here, but seems to make the dot product against the bump - // normal we use below for cubeMap fade-in to be less reliable. - //bumpNorm.xy *= 0.75; - //bumpNorm = normalize( bumpNorm ); - //return vec4( bumpNorm, 1 ); + vec3 bumpNorm = ( texture( bumpMap, IN_rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x; + bumpNorm += ( texture( bumpMap, IN_rippleTexCoord01.zw ).rgb * 2.0 - 1.0 ) * rippleMagnitude.y; + bumpNorm += ( texture( bumpMap, IN_rippleTexCoord2.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.z; + + bumpNorm = normalize( bumpNorm ); + bumpNorm = mix( bumpNorm, vec3(0,0,1), 1.0 - rippleMagnitude.w ); + bumpNorm = tMul( bumpNorm, IN_tangentMat ); // Get depth of the water surface (this pixel). // Convert from WorldSpace to EyeSpace. - float pixelDepth = IN.pixelDist / farPlaneDist; + float pixelDepth = PIXEL_DIST / farPlaneDist; - // Get prepass depth at the undistorted pixel. - //vec4 prepassCoord = IN.posPostWave; - //prepassCoord.xy += renderTargetParams.xy; - vec2 prepassCoord = viewportCoordToRenderTarget( IN.posPostWave, rtParams ); - //vec2 prepassCoord = IN.posPostWave.xy; + vec2 prepassCoord = viewportCoordToRenderTarget( IN_posPostWave, rtParams1 ); - float startDepth = prepassUncondition( tex2D( prepassTex, prepassCoord ) ).w; - //return vec4( startDepth.rrr, 1 ); + float startDepth = prepassUncondition( prepassTex, prepassCoord ).w; // The water depth in world units of the undistorted pixel. float startDelta = ( startDepth - pixelDepth ); - if ( startDelta <= 0.0 ) - { - //return vec4( 1, 0, 0, 1 ); - startDelta = 0; - } - + startDelta = max( startDelta, 0.0 ); startDelta *= farPlaneDist; // Calculate the distortion amount for the water surface. @@ -177,23 +177,22 @@ void main() // We subtract a little from it so that we don't // distort where the water surface intersects the // camera near plane. - float distortAmt = saturate( ( IN.pixelDist - DISTORT_START_DIST ) / DISTORT_END_DIST ); + float distortAmt = saturate( ( PIXEL_DIST - DISTORT_START_DIST ) / DISTORT_END_DIST ); // Scale down distortion in shallow water. distortAmt *= saturate( startDelta / DISTORT_FULL_DEPTH ); - //distortAmt = 0; // Do the intial distortion... we might remove it below. vec2 distortDelta = bumpNorm.xy * distortAmt; - vec4 distortPos = IN.posPostWave; + vec4 distortPos = IN_posPostWave; distortPos.xy += distortDelta; - prepassCoord = viewportCoordToRenderTarget( distortPos, rtParams ); - //prepassCoord = distortPos; - //prepassCoord.xy += renderTargetParams.xy; + prepassCoord = viewportCoordToRenderTarget( distortPos, rtParams1 ); // Get prepass depth at the position of this distorted pixel. - float prepassDepth = prepassUncondition( tex2D( prepassTex, prepassCoord ) ).w; + float prepassDepth = prepassUncondition( prepassTex, prepassCoord ).w; + if ( prepassDepth > 0.99 ) + prepassDepth = 5.0; float delta = ( prepassDepth - pixelDepth ) * farPlaneDist; @@ -202,7 +201,7 @@ void main() // If we got a negative delta then the distorted // sample is above the water surface. Mask it out // by removing the distortion. - distortPos = IN.posPostWave; + distortPos = IN_posPostWave; delta = startDelta; distortAmt = 0; } @@ -212,20 +211,20 @@ void main() if ( diff < 0 ) { - distortAmt = saturate( ( IN.pixelDist - DISTORT_START_DIST ) / DISTORT_END_DIST ); + distortAmt = saturate( ( PIXEL_DIST - DISTORT_START_DIST ) / DISTORT_END_DIST ); distortAmt *= saturate( delta / DISTORT_FULL_DEPTH ); distortDelta = bumpNorm.xy * distortAmt; - distortPos = IN.posPostWave; + distortPos = IN_posPostWave; distortPos.xy += distortDelta; - prepassCoord = viewportCoordToRenderTarget( distortPos, rtParams ); - //prepassCoord = distortPos; - //prepassCoord.xy += renderTargetParams.xy; + prepassCoord = viewportCoordToRenderTarget( distortPos, rtParams1 ); // Get prepass depth at the position of this distorted pixel. - prepassDepth = prepassUncondition( tex2D( prepassTex, prepassCoord ) ).w; + prepassDepth = prepassUncondition( prepassTex, prepassCoord ).w; + if ( prepassDepth > 0.99 ) + prepassDepth = 5.0; delta = ( prepassDepth - pixelDepth ) * farPlaneDist; } @@ -234,133 +233,78 @@ void main() // If we got a negative delta then the distorted // sample is above the water surface. Mask it out // by removing the distortion. - distortPos = IN.posPostWave; + distortPos = IN_posPostWave; delta = startDelta; distortAmt = 0; } } - //return vec4( prepassDepth.rrr, 1 ); - - vec4 temp = IN.posPreWave; + vec4 temp = IN_posPreWave; temp.xy += bumpNorm.xy * distortAmt; - vec2 reflectCoord = viewportCoordToRenderTarget( temp, rtParams ); + vec2 reflectCoord = viewportCoordToRenderTarget( temp, rtParams1 ); - vec2 refractCoord = viewportCoordToRenderTarget( distortPos, rtParams ); + vec2 refractCoord = viewportCoordToRenderTarget( distortPos, rtParams1 ); - // Use cubemap colors instead of reflection colors in several cases... - - // First lookup the CubeMap color - // JCF: which do we want to use here, the reflectNormal or the bumpNormal - // neithor of them is exactly right and how can we combine the two together? - //bumpNorm = reflectNormal; - vec3 eyeVec = IN.worldPos - eyePos; + vec4 fakeColor = vec4(ambientColor,1); + vec3 eyeVec = IN_objPos.xyz - eyePos; + eyeVec = tMul( mat3(modelMat), eyeVec ); + eyeVec = tMul( IN_tangentMat, eyeVec ); vec3 reflectionVec = reflect( eyeVec, bumpNorm ); - //vec4 cubeColor = texCUBE( skyMap, reflectionVec ); - //return cubeColor; - // JCF: using ambient color instead of cubeColor for waterPlane, how do we still use the cubemap for rivers? - vec4 cubeColor = vec4(ambientColor,1); - //cubeColor.rgb = vec3( 0, 0, 1 ); - // Use cubeColor for waves that are angled towards camera + // Use fakeColor for ripple-normals that are angled towards the camera eyeVec = -eyeVec; eyeVec = normalize( eyeVec ); float ang = saturate( dot( eyeVec, bumpNorm ) ); - float cubeAmt = ang; + float fakeColorAmt = ang; - //float rplaneDist = (reflectPlane.x * IN.pos.x + reflectPlane.y * IN.pos.y + reflectPlane.z * IN.pos.z) + reflectPlane.w; - //rplaneDist = saturate( abs( rplaneDist ) / 0.5 ); - - -//#ifdef RIVER // for verts far from the reflect plane z position - float rplaneDist = abs( REFLECT_PLANE_Z - IN.worldPos.z ); + float rplaneDist = abs( REFLECT_PLANE_Z - IN_objPos.w ); rplaneDist = saturate( ( rplaneDist - 1.0 ) / 2.0 ); - //rplaneDist = REFLECT_PLANE_Z / eyePos.z; rplaneDist *= ISRIVER; - cubeAmt = max( cubeAmt, rplaneDist ); -//#endif - - //rplaneDist = IN.worldPos.z / eyePos.z; - - //return vec4( rplaneDist.rrr, 1 ); - //return vec4( (reflectParams[REFLECT_PLANE_Z] / 86.0 ).rrr, 1 ); - - // and for verts farther from the camera - //float cubeAmt = ( eyeDist - reflectParams[REFLECT_MIN_DIST] ) / ( reflectParams[REFLECT_MAX_DIST] - reflectParams[REFLECT_MIN_DIST] ); - //cubeAmt = saturate ( cubeAmt ); - - //float temp = ( eyeDist - reflectParams[REFLECT_MIN_DIST] ) / ( reflectParams[REFLECT_MAX_DIST] - reflectParams[REFLECT_MIN_DIST] ); - //temp = saturate ( temp ); - - // If the camera is very very close to the reflect plane. - //float eyeToPlaneDist = eyePos.z - REFLECT_PLANE_Z; // dot( reflectNormal, eyePos ) + REFLECT_PLANE_Z; - //eyeToPlaneDist = abs( eyeToPlaneDist ); - //eyeToPlaneDist = 1.0 - saturate( abs( eyeToPlaneDist ) / 1 ); - - //return vec4( eyeToPlaneDist.rrr, 1 ); - - //cubeAmt = max( cubeAmt, eyeToPlaneDist ); - //cubeAmt = max( cubeAmt, rplaneDist ); - //cubeAmt = max( cubeAmt, ang ); - //cubeAmt = max( cubeAmt, rplaneDist ); - //cubeAmt = max( cubeAmt, IN.depth.w ); - - // All cubemap if fullReflect is specifically user disabled - cubeAmt = max( cubeAmt, NO_REFLECT ); + fakeColorAmt = max( fakeColorAmt, rplaneDist ); #ifndef UNDERWATER - // Get foam color and amount - IN.foamTexCoords.xy += distortDelta * 0.5; - IN.foamTexCoords.zw += distortDelta * 0.5; + vec2 foamRippleOffset = bumpNorm.xy * FOAM_RIPPLE_INFLUENCE; + vec4 IN_foamTexCoords = IN_foamTexCoords; + IN_foamTexCoords.xy += foamRippleOffset; + IN_foamTexCoords.zw += foamRippleOffset; - vec4 foamColor = tex2D( foamMap, IN.foamTexCoords.xy ); - foamColor += tex2D( foamMap, IN.foamTexCoords.zw ); - //foamColor += tex2D( foamMap, IN.rippleTexCoord2 ) * 0.3; + vec4 foamColor = texture( foamMap, IN_foamTexCoords.xy ); + foamColor += texture( foamMap, IN_foamTexCoords.zw ); foamColor = saturate( foamColor ); - // Modulate foam color by ambient color so we don't have glowing white - // foam at night. - foamColor.rgb = lerp( foamColor.rgb, ambientColor.rgb, foamColorMod.rgb ); + + // Modulate foam color by ambient color + // so we don't have glowing white foam at night. + foamColor.rgb = mix( foamColor.rgb, ambientColor.rgb, FOAM_AMBIENT_LERP ); float foamDelta = saturate( delta / FOAM_MAX_DEPTH ); - float foamAmt = 1.0 - foamDelta; + float foamAmt = 1 - pow( foamDelta, 2 ); // Fade out the foam in very very low depth, // this improves the shoreline a lot. float diff = 0.8 - foamAmt; if ( diff < 0.0 ) - { - //return vec4( 1,0,0,1 ); foamAmt -= foamAmt * abs( diff ) / 0.2; - } - //return vec4( foamAmt.rrr, 1 ); - - foamAmt *= FOAM_SCALE * foamColor.a; - //return vec4( foamAmt.rrr, 1 ); - // Get reflection map color - vec4 refMapColor = tex2D( reflectMap, reflectCoord ); + foamAmt *= FOAM_OPACITY * foamColor.a; - //cubeAmt = 0; + foamColor.rgb *= FOAM_OPACITY * foamAmt * foamColor.a; - // Combine cube and foam colors into reflect color - vec4 reflectColor = lerp( refMapColor, cubeColor, cubeAmt ); - //return refMapColor; + // Get reflection map color. + vec4 refMapColor = hdrDecode( texture( reflectMap, reflectCoord ) ); - // This doesn't work because REFLECT_PLANE_Z is in worldSpace - // while eyePos is actually in objectSpace! + // If we do not have a reflection texture then we use the cubemap. + refMapColor = mix( refMapColor, texture( skyMap, reflectionVec ), NO_REFLECT ); - //float eyeToPlaneDist = eyePos.z - REFLECT_PLANE_Z; // dot( reflectNormal, eyePos ) + REFLECT_PLANE_Z; - //float transitionFactor = 1.0 - saturate( ( abs( eyeToPlaneDist ) - 0.5 ) / 5 ); - //reflectColor = lerp( reflectColor, waterBaseColor, transitionFactor ); - - //return reflectColor; + fakeColor = ( texture( skyMap, reflectionVec ) ); + fakeColor.a = 1; + // Combine reflection color and fakeColor. + vec4 reflectColor = mix( refMapColor, fakeColor, fakeColorAmt ); // Get refract color - vec4 refractColor = tex2D( refractBuff, refractCoord ); - //return refractColor; + vec4 refractColor = hdrDecode( texture( refractBuff, refractCoord ) ); // We darken the refraction color a bit to make underwater // elements look wet. We fade out this darkening near the @@ -371,86 +315,80 @@ void main() // Add Water fog/haze. float fogDelta = delta - FOG_DENSITY_OFFSET; - //return vec4( fogDelta.rrr, 1 ); + if ( fogDelta < 0.0 ) fogDelta = 0.0; float fogAmt = 1.0 - saturate( exp( -FOG_DENSITY * fogDelta ) ); - //return vec4( fogAmt.rrr, 1 ); + + // Calculate the water "base" color based on depth. + vec4 waterBaseColor = baseColor * texture( depthGradMap, saturate( delta / depthGradMax ) ); + + // Modulate baseColor by the ambientColor. + waterBaseColor *= vec4( ambientColor.rgb, 1 ); // calc "diffuse" color by lerping from the water color // to refraction image based on the water clarity. - vec4 diffuseColor = lerp( refractColor, waterBaseColor, fogAmt ); + vec4 diffuseColor = mix( refractColor, waterBaseColor, fogAmt ); // fresnel calculation float fresnelTerm = fresnel( ang, FRESNEL_BIAS, FRESNEL_POWER ); - //return vec4( fresnelTerm.rrr, 1 ); // Scale the frensel strength by fog amount // so that parts that are very clear get very little reflection. fresnelTerm *= fogAmt; - //return vec4( fresnelTerm.rrr, 1 ); // Also scale the frensel by our distance to the // water surface. This removes the hard reflection // when really close to the water surface. - fresnelTerm *= saturate( IN.pixelDist - 0.1 ); + fresnelTerm *= saturate( PIXEL_DIST - 0.1 ); + + fresnelTerm *= reflectivity; // Combine the diffuse color and reflection image via the // fresnel term and set out output color. - vec4 gl_FragColor = lerp( diffuseColor, reflectColor, fresnelTerm ); + vec4 OUT = mix( diffuseColor, reflectColor, fresnelTerm ); - //float brightness = saturate( 1.0 - ( waterHeight - eyePosWorld.z - 5.0 ) / 50.0 ); - //gl_FragColor.rgb *= brightness; + vec3 lightVec = inLightVec; + + // Get some specular reflection. + vec3 newbump = bumpNorm; + newbump.xy *= 3.5; + newbump = normalize( bumpNorm ); + vec3 halfAng = normalize( eyeVec + -lightVec ); + float specular = saturate( dot( newbump, halfAng ) ); + specular = pow( specular, SPEC_POWER ); + + // Scale down specularity in very shallow water to improve the transparency of the shoreline. + specular *= saturate( delta / 2 ); + OUT.rgb = OUT.rgb + ( SPEC_COLOR * vec3(specular) ); #else - vec4 refractColor = tex2D( refractBuff, refractCoord ); - vec4 gl_FragColor = refractColor; + + vec4 refractColor = hdrDecode( texture( refractBuff, refractCoord ) ); + vec4 OUT = refractColor; + #endif #ifndef UNDERWATER - gl_FragColor.rgb = lerp( gl_FragColor.rgb, foamColor.rgb, foamAmt ); -#endif - gl_FragColor.a = 1.0; - - // specular experiments - -// 1: -/* - float fDot = dot( bumpNorm, inLightVec ); - vec3 reflect = normalize( 2.0 * bumpNorm * fDot - eyeVec ); - // float specular = saturate(dot( reflect, inLightVec ) ); - float specular = pow( reflect, specularPower ); - gl_FragColor += specularColor * specular; -*/ - - -// 2: This almost looks good -/* - bumpNorm.xy *= 2.0; - bumpNorm = normalize( bumpNorm ); - - vec3 halfAng = normalize( eyeVec + inLightVec ); - float specular = saturate( dot( bumpNorm, halfAng) ); - specular = pow(specular, specularPower); - gl_FragColor += specularColor * specular; -*/ - -#ifndef UNDERWATER + OUT.rgb = OUT.rgb + foamColor.rgb; float factor = computeSceneFog( eyePos, - IN.fogPos, - IN.worldSpaceZ, + IN_objPos.xyz, + IN_objPos.w, fogData.x, fogData.y, fogData.z ); - gl_FragColor.rgb = lerp( gl_FragColor.rgb, fogColor.rgb, 1.0 - saturate( factor ) ); + OUT.rgb = mix( OUT.rgb, fogColor.rgb, 1.0 - saturate( factor ) ); + + //OUT.rgb = fogColor.rgb; #endif - //return vec4( refMapColor.rgb, 1 ); - gl_FragColor.a = 1.0; + OUT.a = 1.0; + + //return OUT; - return gl_FragColor; + OUT_FragColor0 = hdrEncode( OUT ); } diff --git a/Templates/Full/game/shaders/common/water/gl/waterV.glsl b/Templates/Full/game/shaders/common/water/gl/waterV.glsl index d4337476f..490af63a7 100644 --- a/Templates/Full/game/shaders/common/water/gl/waterV.glsl +++ b/Templates/Full/game/shaders/common/water/gl/waterV.glsl @@ -20,58 +20,86 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#include "../../gl/hlslCompat.glsl" #include "shadergen:/autogenConditioners.h" +//----------------------------------------------------------------------------- +// Structures +//----------------------------------------------------------------------------- +struct VertData +{ + vec4 position ;// POSITION; + vec3 normal ;// NORMAL; + vec2 undulateData ;// TEXCOORD0; + vec4 horizonFactor ;// TEXCOORD1; +}; + //----------------------------------------------------------------------------- // Defines //----------------------------------------------------------------------------- +//VertData IN +in vec4 vPosition; +in vec3 vNormal; +in vec2 vTexCoord0; +in vec4 vTexCoord1; -// waveData -#define WAVE_SPEED(i) waveData[i].x -#define WAVE_MAGNITUDE(i) waveData[i].y +#define IN_position_ vPosition +#define IN_normal vNormal +#define IN_undulateData vTexCoord0 +#define IN_horizonFactor vTexCoord1 -// Outgoing data -// Worldspace position of this pixel -varying vec3 worldPos; +//ConnectData OUT +// + out vec4 hpos ; // TexCoord 0 and 1 (xy,zw) for ripple texture lookup -varying vec4 rippleTexCoord01; +out vec4 rippleTexCoord01; -// TexCoord 2 for ripple texture lookup -varying vec2 rippleTexCoord2; + // xy is TexCoord 2 for ripple texture lookup + // z is the Worldspace unit distance/depth of this vertex/pixel + // w is amount of the crestFoam ( more at crest of waves ). + out vec4 rippleTexCoord2 ; // Screenspace vert position BEFORE wave transformation -varying vec4 posPreWave; +out vec4 posPreWave; // Screenspace vert position AFTER wave transformation -varying vec4 posPostWave; +out vec4 posPostWave; -// Worldspace unit distance/depth of this vertex/pixel -varying float pixelDist; + // Objectspace vert position BEFORE wave transformation + // w coord is world space z position. + out vec4 objPos ; -varying vec3 fogPos; + out vec4 foamTexCoords ; -varying float worldSpaceZ; + out mat3 tangentMat ; +// -varying vec4 foamTexCoords; +#define OUT_hpos hpos +#define OUT_rippleTexCoord01 rippleTexCoord01 +#define OUT_rippleTexCoord2 rippleTexCoord2 +#define OUT_posPreWave posPreWave +#define OUT_posPostWave posPostWave +#define OUT_objPos objPos +#define OUT_foamTexCoords foamTexCoords +#define OUT_tangentMat tangentMat //----------------------------------------------------------------------------- // Uniforms //----------------------------------------------------------------------------- uniform mat4 modelMat; uniform mat4 modelview; -uniform mat3 cubeTrans; -uniform mat4 objTrans; -uniform vec3 cubeEyePos; +uniform vec4 rippleMat[3]; uniform vec3 eyePos; uniform vec2 waveDir[3]; uniform vec2 waveData[3]; uniform vec2 rippleDir[3]; uniform vec2 rippleTexScale[3]; uniform vec3 rippleSpeed; -uniform vec2 reflectTexSize; +uniform vec4 foamDir; +uniform vec4 foamTexScale; +uniform vec2 foamSpeed; uniform vec3 inLightVec; -uniform vec3 reflectNormal; uniform float gridElementSize; uniform float elapsedTime; uniform float undulateMaxDist; @@ -81,97 +109,133 @@ uniform float undulateMaxDist; //----------------------------------------------------------------------------- void main() { - // Copy incoming attributes into locals so we can modify them in place. - vec4 position = gl_Vertex.xyzw; - vec3 normal = gl_Normal.xyz; - vec2 undulateData = gl_MultiTexCoord0.st; - vec4 horizonFactor = gl_MultiTexCoord1.xyzw; + vec4 IN_position = IN_position_; // use projection matrix for reflection / refraction texture coords - mat4 texGen = { 0.5, 0.0, 0.0, 0.5, //+ 0.5 / reflectTexSize.x, - 0.0, 0.5, 0.0, 0.5, //+ 1.0 / reflectTexSize.y, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0 }; + mat4 texGen = mat4FromRow( 0.5, 0.0, 0.0, 0.5, + 0.0, -0.5, 0.0, 0.5, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 ); - // Move the vertex based on the horizonFactor if specified to do so for this vert. - if ( horizonFactor.z > 0 ) - { - vec2 offsetXY = eyePos.xy - eyePos.xy % gridElementSize; - position.xy += offsetXY; - undulateData += offsetXY; - } + IN_position.z = mix( IN_position.z, eyePos.z, IN_horizonFactor.x ); - fogPos = position; - position.z = mix( position.z, eyePos.z, horizonFactor.x ); + OUT_objPos = IN_position; + OUT_objPos.w = tMul( modelMat, IN_position ).z; // Send pre-undulation screenspace position - posPreWave = modelview * position; - posPreWave = texGen * posPreWave; + OUT_posPreWave = tMul( modelview, IN_position ); + OUT_posPreWave = tMul( texGen, OUT_posPreWave ); // Calculate the undulation amount for this vertex. - vec2 undulatePos = undulateData; - float undulateAmt = 0; + vec2 undulatePos = tMul( modelMat, vec4 ( IN_undulateData.xy, 0, 1 ) ).xy; + float undulateAmt = 0.0; - for ( int i = 0; i < 3; i++ ) - { - undulateAmt += WAVE_MAGNITUDE(i) * sin( elapsedTime * WAVE_SPEED(i) + - undulatePos.x * waveDir[i].x + - undulatePos.y * waveDir[i].y ); - } + undulateAmt += waveData[0].y * sin( elapsedTime * waveData[0].x + + undulatePos.x * waveDir[0].x + + undulatePos.y * waveDir[0].y ); + undulateAmt += waveData[1].y * sin( elapsedTime * waveData[1].x + + undulatePos.x * waveDir[1].x + + undulatePos.y * waveDir[1].y ); + undulateAmt += waveData[2].y * sin( elapsedTime * waveData[2].x + + undulatePos.x * waveDir[2].x + + undulatePos.y * waveDir[2].y ); + + float undulateFade = 1; // Scale down wave magnitude amount based on distance from the camera. - float dist = distance( position, eyePos ); + float dist = distance( IN_position.xyz, eyePos ); dist = clamp( dist, 1.0, undulateMaxDist ); - undulateAmt *= ( 1 - dist / undulateMaxDist ); + undulateFade *= ( 1 - dist / undulateMaxDist ); // Also scale down wave magnitude if the camera is very very close. - undulateAmt *= clamp( ( distance( IN.position, eyePos ) - 0.5 ) / 10.0, 0.0, 1.0 ); + undulateFade *= saturate( ( distance( IN_position.xyz, eyePos ) - 0.5 ) / 10.0 ); + + undulateAmt *= undulateFade; + + OUT_rippleTexCoord2.w = undulateAmt / ( waveData[0].y + waveData[1].y + waveData[2].y ); + OUT_rippleTexCoord2.w = saturate( OUT_rippleTexCoord2.w - 0.2 ) / 0.8; // Apply wave undulation to the vertex. - posPostWave = position; - posPostWave.xyz += normal.xyz * undulateAmt; - - // Save worldSpace position of this pixel/vert - worldPos = posPostWave.xyz; + OUT_posPostWave = IN_position; + OUT_posPostWave.xyz += IN_normal.xyz * undulateAmt; // Convert to screen - posPostWave = modelview * posPostWave; + OUT_posPostWave = tMul( modelview, OUT_posPostWave ); // Setup the OUT position symantic variable - gl_Position = posPostWave; - gl_Position.z = mix(gl_Position.z, gl_Position.w, horizonFactor.x); + OUT_hpos = OUT_posPostWave; + //OUT_hpos.z = mix( OUT_hpos.z, OUT_hpos.w, IN_horizonFactor.x ); - worldSpaceZ = modelMat * vec4(fogPos, 1.0) ).z; - if ( horizonFactor.x > 0.0 ) - { - vec3 awayVec = normalize( fogPos.xyz - eyePos ); - fogPos.xy += awayVec.xy * 1000.0; - } + // if ( IN_horizonFactor.x > 0 ) + // { + // vec3 awayVec = normalize( OUT_objPos.xyz - eyePos ); + // OUT_objPos.xy += awayVec.xy * 1000.0; + // } // Save world space camera dist/depth of the outgoing pixel - pixelDist = gl_Position.z; + OUT_rippleTexCoord2.z = OUT_hpos.z; // Convert to reflection texture space - posPostWave = texGen * posPostWave; + OUT_posPostWave = tMul( texGen, OUT_posPostWave ); - float2 ripplePos = undulateData; - float2 txPos = normalize( ripplePos ); - txPos *= 50000.0; - ripplePos = mix( ripplePos, txPos, IN.horizonFactor.x ); + vec2 txPos = undulatePos; + if ( bool(IN_horizonFactor.x) ) + txPos = normalize( txPos ) * 50000.0; // set up tex coordinates for the 3 interacting normal maps - rippleTexCoord01.xy = mix( ripplePos * rippleTexScale[0], txPos.xy * rippleTexScale[0], IN.horizonFactor.x ); - rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; + OUT_rippleTexCoord01.xy = txPos * rippleTexScale[0]; + OUT_rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x; - rippleTexCoord01.zw = mix( ripplePos * rippleTexScale[1], txPos.xy * rippleTexScale[1], IN.horizonFactor.x ); - rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; + mat2 texMat; + texMat[0][0] = rippleMat[0].x; + texMat[1][0] = rippleMat[0].y; + texMat[0][1] = rippleMat[0].z; + texMat[1][1] = rippleMat[0].w; + OUT_rippleTexCoord01.xy = tMul( texMat, OUT_rippleTexCoord01.xy ); - rippleTexCoord2.xy = mix( ripplePos * rippleTexScale[2], txPos.xy * rippleTexScale[2], IN.horizonFactor.x ); - rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; + OUT_rippleTexCoord01.zw = txPos * rippleTexScale[1]; + OUT_rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y; + + texMat[0][0] = rippleMat[1].x; + texMat[1][0] = rippleMat[1].y; + texMat[0][1] = rippleMat[1].z; + texMat[1][1] = rippleMat[1].w; + OUT_rippleTexCoord01.zw = tMul( texMat, OUT_rippleTexCoord01.zw ); - foamTexCoords.xy = mix( ripplePos * 0.2, txPos.xy * rippleTexScale[0], IN.horizonFactor.x ); - foamTexCoords.xy += rippleDir[0] * sin( ( elapsedTime + 500.0 ) * -0.4 ) * 0.15; + OUT_rippleTexCoord2.xy = txPos * rippleTexScale[2]; + OUT_rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; - foamTexCoords.zw = mix( ripplePos * 0.3, txPos.xy * rippleTexScale[1], IN.horizonFactor.x ); - foamTexCoords.zw += rippleDir[1] * sin( elapsedTime * 0.4 ) * 0.15; + texMat[0][0] = rippleMat[2].x; + texMat[1][0] = rippleMat[2].y; + texMat[0][1] = rippleMat[2].z; + texMat[1][1] = rippleMat[2].w; + OUT_rippleTexCoord2.xy = tMul( texMat, OUT_rippleTexCoord2.xy ); + + OUT_foamTexCoords.xy = txPos * foamTexScale.xy + foamDir.xy * foamSpeed.x * elapsedTime; + OUT_foamTexCoords.zw = txPos * foamTexScale.zw + foamDir.zw * foamSpeed.y * elapsedTime; + + + vec3 binormal = vec3 ( 1, 0, 0 ); + vec3 tangent = vec3 ( 0, 1, 0 ); + vec3 normal; + for ( int i = 0; i < 3; i++ ) + { + binormal.z += undulateFade * waveDir[i].x * waveData[i].y * cos( waveDir[i].x * undulatePos.x + waveDir[i].y * undulatePos.y + elapsedTime * waveData[i].x ); + tangent.z += undulateFade * waveDir[i].y * waveData[i].y * cos( waveDir[i].x * undulatePos.x + waveDir[i].y * undulatePos.y + elapsedTime * waveData[i].x ); + } + + binormal = binormal; + tangent = tangent; + normal = cross( binormal, tangent ); + + mat3 worldToTangent; + worldToTangent[0] = binormal; + worldToTangent[1] = tangent; + worldToTangent[2] = normal; + + OUT_tangentMat = transpose(worldToTangent); + + gl_Position = OUT_hpos; + correctSSP(gl_Position); } + diff --git a/Templates/Full/game/tools/gui/openFileDialog.ed.cs b/Templates/Full/game/tools/gui/openFileDialog.ed.cs index 00a388789..b988d3361 100644 --- a/Templates/Full/game/tools/gui/openFileDialog.ed.cs +++ b/Templates/Full/game/tools/gui/openFileDialog.ed.cs @@ -42,3 +42,29 @@ function getLoadFilename(%filespec, %callback, %currentFile) %dlg.delete(); } + +// Opens a choose file dialog with format filters already loaded +// in. This avoids the issue of passing a massive list of format +// filters into a function as an arguement. +function getLoadFormatFilename(%callback, %currentFile) +{ + %dlg = new OpenFileDialog() + { + Filters = getFormatFilters() @ "(All Files (*.*)|*.*|"; + DefaultFile = %currentFile; + ChangePath = false; + MustExist = true; + MultipleFiles = false; + }; + + if ( filePath( %currentFile ) !$= "" ) + %dlg.DefaultPath = filePath(%currentFile); + + if ( %dlg.Execute() ) + { + eval(%callback @ "(\"" @ %dlg.FileName @ "\");"); + $Tools::FileDialogs::LastFilePath = filePath( %dlg.FileName ); + } + + %dlg.delete(); +} diff --git a/Templates/Full/game/tools/gui/profiles.ed.cs b/Templates/Full/game/tools/gui/profiles.ed.cs index 8d6718601..b3a5b2295 100644 --- a/Templates/Full/game/tools/gui/profiles.ed.cs +++ b/Templates/Full/game/tools/gui/profiles.ed.cs @@ -764,7 +764,7 @@ singleton GuiControlProfile( GuiInspectorGroupProfile ) opaque = false; border = false; - bitmap = "tools/editorclasses/gui/images/rollout"; + bitmap = "tools/editorClasses/gui/images/rollout"; textOffset = "20 0"; diff --git a/Templates/Full/game/tools/particleEditor/particleEmitterEditor.ed.cs b/Templates/Full/game/tools/particleEditor/particleEmitterEditor.ed.cs index 11678a053..8d290f0a3 100644 --- a/Templates/Full/game/tools/particleEditor/particleEmitterEditor.ed.cs +++ b/Templates/Full/game/tools/particleEditor/particleEmitterEditor.ed.cs @@ -84,6 +84,9 @@ function PE_EmitterEditor::guiSync( %this ) PE_EmitterEditor-->PEE_ejectionOffset_slider.setValue( %data.ejectionOffset ); PE_EmitterEditor-->PEE_ejectionOffset_textEdit.setText( %data.ejectionOffset ); + PE_EmitterEditor-->PEE_ejectionOffsetVariance_slider.setValue( %data.ejectionOffsetVariance ); + PE_EmitterEditor-->PEE_ejectionOffsetVariance_textEdit.setText( %data.ejectionOffsetVariance ); + %blendTypeId = PE_EmitterEditor-->PEE_blendType.findText( %data.blendStyle ); PE_EmitterEditor-->PEE_blendType.setSelected( %blendTypeId, false ); diff --git a/Templates/Full/game/tools/riverEditor/main.cs b/Templates/Full/game/tools/riverEditor/main.cs index b51bd5273..eafb3c3c8 100644 --- a/Templates/Full/game/tools/riverEditor/main.cs +++ b/Templates/Full/game/tools/riverEditor/main.cs @@ -25,8 +25,8 @@ function initializeRiverEditor() echo(" % - Initializing River Editor"); exec( "./riverEditor.cs" ); - exec( "./riverEditorGui.gui" ); - exec( "./riverEditorToolbar.gui" ); + exec( "./RiverEditorGui.gui" ); + exec( "./RiverEditorToolbar.gui" ); exec( "./riverEditorGui.cs" ); // Add ourselves to EditorGui, where all the other tools reside diff --git a/Templates/Full/game/tools/roadEditor/main.cs b/Templates/Full/game/tools/roadEditor/main.cs index cb7ea052c..f45823670 100644 --- a/Templates/Full/game/tools/roadEditor/main.cs +++ b/Templates/Full/game/tools/roadEditor/main.cs @@ -25,8 +25,8 @@ function initializeRoadEditor() echo( " - Initializing Road and Path Editor" ); exec( "./roadEditor.cs" ); - exec( "./roadEditorGui.gui" ); - exec( "./roadEditorToolbar.gui"); + exec( "./RoadEditorGui.gui" ); + exec( "./RoadEditorToolbar.gui"); exec( "./roadEditorGui.cs" ); // Add ourselves to EditorGui, where all the other tools reside diff --git a/Templates/Full/game/tools/shapeEditor/gui/Profiles.ed.cs b/Templates/Full/game/tools/shapeEditor/gui/Profiles.ed.cs index 0b92a30e2..cb42ef169 100644 --- a/Templates/Full/game/tools/shapeEditor/gui/Profiles.ed.cs +++ b/Templates/Full/game/tools/shapeEditor/gui/Profiles.ed.cs @@ -41,7 +41,7 @@ singleton GuiControlProfile(GuiShapeEdTextListProfile : ToolsGuiTextListProfile) singleton GuiControlProfile(GuiShapeEdRolloutProfile : GuiInspectorRolloutProfile0) { - bitmap = "tools/editorclasses/gui/images/rollout"; + bitmap = "tools/editorClasses/gui/images/rollout"; category = "Editor"; }; diff --git a/Templates/Full/game/tools/shapeEditor/main.cs b/Templates/Full/game/tools/shapeEditor/main.cs index f033bae86..721313e95 100644 --- a/Templates/Full/game/tools/shapeEditor/main.cs +++ b/Templates/Full/game/tools/shapeEditor/main.cs @@ -33,7 +33,7 @@ function initializeShapeEditor() exec("./gui/shapeEdPreviewWindow.ed.gui"); exec("./gui/shapeEdAnimWindow.ed.gui"); exec("./gui/shapeEdAdvancedWindow.ed.gui"); - exec("./gui/shapeEditorToolbar.ed.gui"); + exec("./gui/ShapeEditorToolbar.ed.gui"); exec("./gui/shapeEdSelectWindow.ed.gui"); exec("./gui/shapeEdPropWindow.ed.gui"); diff --git a/Templates/Full/game/tools/shapeEditor/scripts/shapeEditor.ed.cs b/Templates/Full/game/tools/shapeEditor/scripts/shapeEditor.ed.cs index 5eb26f3c0..6282f32ce 100644 --- a/Templates/Full/game/tools/shapeEditor/scripts/shapeEditor.ed.cs +++ b/Templates/Full/game/tools/shapeEditor/scripts/shapeEditor.ed.cs @@ -366,7 +366,7 @@ function ShapeEdSelectWindow::navigate( %this, %address ) %this-->shapeLibrary.clear(); ShapeEdSelectMenu.clear(); - %filePatterns = "*.dts" TAB "*.dae" TAB "*.kmz"; + %filePatterns = getFormatExtensions(); %fullPath = findFirstFileMultiExpr( %filePatterns ); while ( %fullPath !$= "" ) @@ -1632,7 +1632,7 @@ function ShapeEdSequences::onAddSequence( %this, %name ) if ( %from $= "" ) { // No sequence selected => open dialog to browse for one - getLoadFilename( "DSQ Files|*.dsq|COLLADA Files|*.dae|Google Earth Files|*.kmz", %this @ ".onAddSequenceFromBrowse", ShapeEdFromMenu.lastPath ); + getLoadFormatFilename( %this @ ".onAddSequenceFromBrowse", ShapeEdFromMenu.lastPath ); return; } else @@ -1740,7 +1740,7 @@ function ShapeEdSeqFromMenu::onSelect( %this, %id, %text ) %this.setText( %seqFrom ); // Allow the user to browse for an external source of animation data - getLoadFilename( "DSQ Files|*.dsq|COLLADA Files|*.dae|Google Earth Files|*.kmz", %this @ ".onBrowseSelect", %this.lastPath ); + getLoadFormatFilename( %this @ ".onBrowseSelect", %this.lastPath ); } else { @@ -2862,7 +2862,7 @@ function ShapeEdDetails::onAddMeshFromFile( %this, %path ) { if ( %path $= "" ) { - getLoadFilename( "DTS Files|*.dts|COLLADA Files|*.dae|Google Earth Files|*.kmz", %this @ ".onAddMeshFromFile", %this.lastPath ); + getLoadFormatFilename( %this @ ".onAddMeshFromFile", %this.lastPath ); return; } @@ -3291,7 +3291,7 @@ function ShapeEdMountShapeMenu::onSelect( %this, %id, %text ) if ( %text $= "Browse..." ) { // Allow the user to browse for an external model file - getLoadFilename( "DTS Files|*.dts|COLLADA Files|*.dae|Google Earth Files|*.kmz", %this @ ".onBrowseSelect", %this.lastPath ); + getLoadFormatFilename( %this @ ".onBrowseSelect", %this.lastPath ); } else { diff --git a/Templates/Full/game/tools/worldEditor/gui/ProceduralTerrainPainterGui.gui b/Templates/Full/game/tools/worldEditor/gui/ProceduralTerrainPainterGui.gui index d2eccdbb7..c00e31e4f 100644 --- a/Templates/Full/game/tools/worldEditor/gui/ProceduralTerrainPainterGui.gui +++ b/Templates/Full/game/tools/worldEditor/gui/ProceduralTerrainPainterGui.gui @@ -20,7 +20,7 @@ HorizSizing = "right"; VertSizing = "bottom"; Position = "285 83"; - Extent = "175 209"; + Extent = "175 233"; MinExtent = "8 2"; canSave = "1"; Visible = "1"; @@ -52,7 +52,7 @@ Profile = "ToolsGuiButtonProfile"; HorizSizing = "right"; VertSizing = "bottom"; - Position = "19 164"; + Position = "19 193"; Extent = "140 30"; MinExtent = "8 2"; canSave = "1"; @@ -305,6 +305,83 @@ sinkAllKeyEvents = "0"; passwordMask = "*"; }; + + + new GuiTextCtrl() { + text = "COVERAGE"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "10 165"; + extent = "55 13"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "1"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "97 162"; + extent = "66 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiTextEditProfile"; + visible = "1"; + active = "1"; + variable = "$TPPCoverage"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "%"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "77 164"; + extent = "11 14"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; }; }; //--- OBJECT WRITE END --- @@ -313,6 +390,7 @@ $TPPHeightMin = -10000; $TPPHeightMax = 10000; $TPPSlopeMin = 0; $TPPSlopeMax = 90; +$TPPCoverage = 100; function autoLayers() { @@ -322,5 +400,6 @@ function autoLayers() function generateProceduralTerrainMask() { Canvas.popDialog(ProceduralTerrainPainterGui); - ETerrainEditor.autoMaterialLayer($TPPHeightMin, $TPPHeightMax, $TPPSlopeMin, $TPPSlopeMax); + ETerrainEditor.autoMaterialLayer($TPPHeightMin, $TPPHeightMax, $TPPSlopeMin, $TPPSlopeMax, $TPPCoverage); } + diff --git a/Templates/Full/game/tools/worldEditor/main.cs b/Templates/Full/game/tools/worldEditor/main.cs index 1b20201e0..773dbac17 100644 --- a/Templates/Full/game/tools/worldEditor/main.cs +++ b/Templates/Full/game/tools/worldEditor/main.cs @@ -29,7 +29,7 @@ function initializeWorldEditor() exec("./scripts/cursors.ed.cs"); exec("./gui/guiCreateNewTerrainGui.gui" ); - exec("./gui/genericPromptDialog.ed.gui" ); + exec("./gui/GenericPromptDialog.ed.gui" ); exec("./gui/guiTerrainImportGui.gui" ); exec("./gui/guiTerrainExportGui.gui" ); exec("./gui/EditorGui.ed.gui"); diff --git a/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs b/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs index 2e0a3165c..d63542d67 100644 --- a/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs +++ b/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs @@ -324,13 +324,13 @@ function EWCreatorWindow::navigate( %this, %address ) if ( %this.tab $= "Meshes" ) { - %fullPath = findFirstFileMultiExpr( "*.dts" TAB "*.dae" TAB "*.kmz" TAB "*.dif" ); + %fullPath = findFirstFileMultiExpr( getFormatExtensions() ); while ( %fullPath !$= "" ) { if (strstr(%fullPath, "cached.dts") != -1) { - %fullPath = findNextFileMultiExpr( "*.dts" TAB "*.dae" TAB "*.kmz" TAB "*.dif" ); + %fullPath = findNextFileMultiExpr( getFormatExtensions() ); continue; } @@ -338,7 +338,7 @@ function EWCreatorWindow::navigate( %this, %address ) %splitPath = strreplace( %fullPath, "/", " " ); if( getWord(%splitPath, 0) $= "tools" ) { - %fullPath = findNextFileMultiExpr( "*.dts" TAB "*.dae" TAB "*.kmz" TAB "*.dif" ); + %fullPath = findNextFileMultiExpr( getFormatExtensions() ); continue; } @@ -396,7 +396,7 @@ function EWCreatorWindow::navigate( %this, %address ) } } - %fullPath = findNextFileMultiExpr( "*.dts" TAB "*.dae" TAB "*.kmz" TAB "*.dif" ); + %fullPath = findNextFileMultiExpr( getFormatExtensions() ); } } diff --git a/Tools/CMake/CMakeLists.txt b/Tools/CMake/CMakeLists.txt new file mode 100644 index 000000000..741cc6b1c --- /dev/null +++ b/Tools/CMake/CMakeLists.txt @@ -0,0 +1,30 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +include(basics.cmake) + +setupVersionNumbers() + +# the main engine, should come last +include(torque3d.cmake) + +#setupPackaging() \ No newline at end of file diff --git a/Tools/CMake/app-debug-win.bat.in b/Tools/CMake/app-debug-win.bat.in new file mode 100644 index 000000000..8885f2e5b --- /dev/null +++ b/Tools/CMake/app-debug-win.bat.in @@ -0,0 +1,15 @@ +:: little debug helper script that helps you starting Torque3D with command line arguments. + +:: possible args: +:: -log +:: -console +:: -level +:: -worldeditor +:: -guieditor +:: -help + +:: as example, we just show the console +"@PROJECT_NAME@.exe" -console + +:: or load a level and open the editor: +:: "@PROJECT_NAME@.exe" -console -level mylevel.mis -worldeditor diff --git a/Tools/CMake/basics.cmake b/Tools/CMake/basics.cmake new file mode 100644 index 000000000..7761ca9fc --- /dev/null +++ b/Tools/CMake/basics.cmake @@ -0,0 +1,404 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project("Torque3DEngine") + +if( CMAKE_CXX_SIZEOF_DATA_PTR EQUAL 8 ) + set( TORQUE_CPU_X64 ON ) +elseif( CMAKE_CXX_SIZEOF_DATA_PTR EQUAL 4 ) + set( TORQUE_CPU_X32 ON ) +endif() + +if(NOT TORQUE_TEMPLATE) + set(TORQUE_TEMPLATE "Full" CACHE STRING "the template to use") +endif() +if(NOT TORQUE_APP_DIR) + set(TORQUE_APP_DIR "${CMAKE_SOURCE_DIR}/My Projects/${TORQUE_APP_NAME}") +endif() +if(NOT projectOutDir) + set(projectOutDir "${TORQUE_APP_DIR}/game") +endif() +if(NOT projectSrcDir) + set(projectSrcDir "${TORQUE_APP_DIR}/source") +endif() +set(libDir "${CMAKE_SOURCE_DIR}/Engine/lib") +set(srcDir "${CMAKE_SOURCE_DIR}/Engine/source") +set(cmakeDir "${CMAKE_SOURCE_DIR}/Tools/CMake") + +# hide some things +mark_as_advanced(CMAKE_INSTALL_PREFIX) +mark_as_advanced(CMAKE_CONFIGURATION_TYPES) + +# output folders +#set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${projectOutDir}/game) +#set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${projectOutDir}/game) +#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${projectOutDir}/game) + +############################################################################### +### Source File Handling +############################################################################### + +# finds and adds sources files in a folder +macro(addPath dir) + set(tmp_files "") + set(glob_config GLOB) + if(${ARGC} GREATER 1 AND "${ARGV1}" STREQUAL "REC") + set(glob_config GLOB_RECURSE) + endif() + file(${glob_config} tmp_files + ${dir}/*.cpp + ${dir}/*.c + ${dir}/*.cc + ${dir}/*.h + ${dir}/*.asm) + LIST(APPEND ${PROJECT_NAME}_files "${tmp_files}") + LIST(APPEND ${PROJECT_NAME}_paths "${dir}") + #message(STATUS "addPath ${PROJECT_NAME} : ${tmp_files}") +endmacro() + +# adds a file to the sources +macro(addFile filename) + LIST(APPEND ${PROJECT_NAME}_files "${filename}") + #message(STATUS "addFile ${PROJECT_NAME} : ${filename}") +endmacro() + +# finds and adds sources files in a folder recursively +macro(addPathRec dir) + addPath("${dir}" "REC") +endmacro() + +############################################################################### +### Definition Handling +############################################################################### +macro(__addDef def config) + # two possibilities: a) target already known, so add it directly, or b) target not yet known, so add it to its cache + if(TARGET ${PROJECT_NAME}) + #message(STATUS "directly applying defs: ${PROJECT_NAME} with config ${config}: ${def}") + if("${config}" STREQUAL "") + set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "${def}") + else() + set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY COMPILE_DEFINITIONS_${config} "${def}") + endif() + else() + list(APPEND ${PROJECT_NAME}_defs_${config} ${def}) + #message(STATUS "added definition to cache: ${PROJECT_NAME}_defs_${config}: ${${PROJECT_NAME}_defs_${config}}") + endif() +endmacro() + +# adds a definition: argument 1: Nothing(for all), _DEBUG, _RELEASE, +macro(addDef def) + set(def_configs "") + if(${ARGC} GREATER 1) + foreach(config "${ARGV1}") + __addDef(${def} ${config}) + endforeach() + else() + __addDef(${def} "") + endif() +endmacro() + +# this applies cached definitions onto the target +macro(_process_defs) + if(DEFINED ${PROJECT_NAME}_defs_) + set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "${${PROJECT_NAME}_defs_}") + #message(STATUS "applying defs to project ${PROJECT_NAME} on all configs: ${${PROJECT_NAME}_defs_}") + endif() + foreach(def_config ${CMAKE_CONFIGURATION_TYPES}) + string(TOUPPER "${def_config}" def_config) + if(DEFINED ${PROJECT_NAME}_defs_${def_config}) + set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY COMPILE_DEFINITIONS_${def_config} "${${PROJECT_NAME}_defs_${def_config}}") + #message(STATUS "applying defs to project ${PROJECT_NAME} on config ${def_config}: ${${PROJECT_NAME}_defs_${def_config}}") + endif() + endforeach() +endmacro() + +############################################################################### +### Source Library Handling +############################################################################### +macro(addLibSrc libPath) + set(cached_project_name ${PROJECT_NAME}) + include(${libPath}) + project(${cached_project_name}) +endmacro() + +############################################################################### +### Linked Library Handling +############################################################################### +macro(addLib libs) + foreach(lib ${libs}) + # check if we can build it ourselfs + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libraries/${lib}.cmake") + addLibSrc("${CMAKE_CURRENT_SOURCE_DIR}/libraries/${lib}.cmake") + endif() + # then link against it + # two possibilities: a) target already known, so add it directly, or b) target not yet known, so add it to its cache + if(TARGET ${PROJECT_NAME}) + target_link_libraries(${PROJECT_NAME} "${lib}") + else() + list(APPEND ${PROJECT_NAME}_libs ${lib}) + endif() + endforeach() +endmacro() + +# this applies cached definitions onto the target +macro(_process_libs) + if(DEFINED ${PROJECT_NAME}_libs) + target_link_libraries(${PROJECT_NAME} "${${PROJECT_NAME}_libs}") + endif() +endmacro() + +############################################################################### +### Include Handling +############################################################################### +macro(addInclude incPath) + if(TARGET ${PROJECT_NAME}) + set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY INCLUDE_DIRECTORIES "${incPath}") + else() + list(APPEND ${PROJECT_NAME}_includes ${incPath}) + endif() +endmacro() + +# this applies cached definitions onto the target +macro(_process_includes) + if(DEFINED ${PROJECT_NAME}_includes) + set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY INCLUDE_DIRECTORIES "${${PROJECT_NAME}_includes}") + endif() +endmacro() + +############################################################################### + +macro(_postTargetProcess) + _process_includes() + _process_defs() + _process_libs() +endmacro() + +# adds a path to search for libs +macro(addLibPath dir) + link_directories(${dir}) +endmacro() + +# creates a proper filter for VS +macro(generateFilters relDir) + foreach(f ${${PROJECT_NAME}_files}) + # Get the path of the file relative to ${DIRECTORY}, + # then alter it (not compulsory) + file(RELATIVE_PATH SRCGR ${relDir} ${f}) + set(SRCGR "${PROJECT_NAME}/${SRCGR}") + # Extract the folder, ie remove the filename part + string(REGEX REPLACE "(.*)(/[^/]*)$" "\\1" SRCGR ${SRCGR}) + # do not have any ../ dirs + string(REPLACE "../" "" SRCGR ${SRCGR}) + # Source_group expects \\ (double antislash), not / (slash) + string(REPLACE / \\ SRCGR ${SRCGR}) + #STRING(REPLACE "//" "/" SRCGR ${SRCGR}) + #message(STATUS "FILE: ${f} -> ${SRCGR}") + source_group("${SRCGR}" FILES ${f}) + endforeach() +endmacro() + +# creates a proper filter for VS +macro(generateFiltersSpecial relDir) + foreach(f ${${PROJECT_NAME}_files}) + # Get the path of the file relative to ${DIRECTORY}, + # then alter it (not compulsory) + file(RELATIVE_PATH SRCGR ${relDir} ${f}) + set(SRCGR "torque3d/${SRCGR}") + # Extract the folder, ie remove the filename part + string(REGEX REPLACE "(.*)(/[^/]*)$" "\\1" SRCGR ${SRCGR}) + # do not have any ../ dirs + string(REPLACE "../" "" SRCGR ${SRCGR}) + IF("${SRCGR}" MATCHES "^torque3d/My Projects/.*$") + string(REPLACE "torque3d/My Projects/${PROJECT_NAME}/" "" SRCGR ${SRCGR}) + string(REPLACE "/source" "" SRCGR ${SRCGR}) + endif() + # Source_group expects \\ (double antislash), not / (slash) + string(REPLACE / \\ SRCGR ${SRCGR}) + #STRING(REPLACE "//" "/" SRCGR ${SRCGR}) + IF(EXISTS "${f}" AND NOT IS_DIRECTORY "${f}") + #message(STATUS "FILE: ${f} -> ${SRCGR}") + source_group("${SRCGR}" FILES ${f}) + endif() + endforeach() +endmacro() + +# macro to add a static library +macro(finishLibrary) + # more paths? + if(${ARGC} GREATER 0) + foreach(dir ${ARGV0}) + addPath("${dir}") + endforeach() + endif() + # now inspect the paths we got + set(firstDir "") + foreach(dir ${${PROJECT_NAME}_paths}) + if("${firstDir}" STREQUAL "") + set(firstDir "${dir}") + endif() + endforeach() + generateFilters("${firstDir}") + + # set per target compile flags + if(TORQUE_CXX_FLAGS_${PROJECT_NAME}) + set_source_files_properties(${${PROJECT_NAME}_files} PROPERTIES COMPILE_FLAGS "${TORQUE_CXX_FLAGS_${PROJECT_NAME}}") + else() + set_source_files_properties(${${PROJECT_NAME}_files} PROPERTIES COMPILE_FLAGS "${TORQUE_CXX_FLAGS_LIBS}") + endif() + + if(TORQUE_STATIC) + add_library("${PROJECT_NAME}" STATIC ${${PROJECT_NAME}_files}) + else() + add_library("${PROJECT_NAME}" SHARED ${${PROJECT_NAME}_files}) + endif() + + # omg - only use the first folder ... otherwise we get lots of header name collisions + #foreach(dir ${${PROJECT_NAME}_paths}) + addInclude("${firstDir}") + #endforeach() + + _postTargetProcess() +endmacro() + +# macro to add an executable +macro(finishExecutable) + # now inspect the paths we got + set(firstDir "") + foreach(dir ${${PROJECT_NAME}_paths}) + if("${firstDir}" STREQUAL "") + set(firstDir "${dir}") + endif() + endforeach() + generateFiltersSpecial("${firstDir}") + + # set per target compile flags + if(TORQUE_CXX_FLAGS_${PROJECT_NAME}) + set_source_files_properties(${${PROJECT_NAME}_files} PROPERTIES COMPILE_FLAGS "${TORQUE_CXX_FLAGS_${PROJECT_NAME}}") + else() + set_source_files_properties(${${PROJECT_NAME}_files} PROPERTIES COMPILE_FLAGS "${TORQUE_CXX_FLAGS_EXECUTABLES}") + endif() + + add_executable("${PROJECT_NAME}" WIN32 ${${PROJECT_NAME}_files}) + addInclude("${firstDir}") + + _postTargetProcess() +endmacro() + +macro(setupVersionNumbers) + set(TORQUE_APP_VERSION_MAJOR 1 CACHE INTEGER "") + set(TORQUE_APP_VERSION_MINOR 0 CACHE INTEGER "") + set(TORQUE_APP_VERSION_PATCH 0 CACHE INTEGER "") + set(TORQUE_APP_VERSION_TWEAK 0 CACHE INTEGER "") + mark_as_advanced(TORQUE_APP_VERSION_TWEAK) + MATH(EXPR TORQUE_APP_VERSION "${TORQUE_APP_VERSION_MAJOR} * 1000 + ${TORQUE_APP_VERSION_MINOR} * 100 + ${TORQUE_APP_VERSION_PATCH} * 10 + ${TORQUE_APP_VERSION_TWEAK}") + set(TORQUE_APP_VERSION_STRING "${TORQUE_APP_VERSION_MAJOR}.${TORQUE_APP_VERSION_MINOR}.${TORQUE_APP_VERSION_PATCH}.${TORQUE_APP_VERSION_TWEAK}") + #message(STATUS "version numbers: ${TORQUE_APP_VERSION} / ${TORQUE_APP_VERSION_STRING}") +endmacro() + +macro(setupPackaging) + INCLUDE(CPack) + # only enable zips for now + set(CPACK_BINARY_NSIS OFF CACHE INTERNAL "" FORCE) + set(CPACK_BINARY_ZIP ON CACHE INTERNAL "" FORCE) + set(CPACK_SOURCE_ZIP OFF CACHE INTERNAL "" FORCE) + SET(CPACK_GENERATOR "ZIP") + SET(CPACK_PACKAGE_VENDOR "${PROJECT_NAME}") + SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_NAME}") + SET(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 1) + SET(CPACK_OUTPUT_FILE_PREFIX "${TORQUE_APP_DIR}/packages/${PROJECT_NAME}") + SET(CPACK_PACKAGE_INSTALL_DIRECTORY "") + #SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ReadMe.txt") + #SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt") + SET(CPACK_PACKAGE_VERSION_MAJOR "${TORQUE_APP_VERSION_MAJOR}") + SET(CPACK_PACKAGE_VERSION_MINOR "${TORQUE_APP_VERSION_MINOR}") + SET(CPACK_PACKAGE_VERSION_PATCH "${TORQUE_APP_VERSION_PATCH}") + #SET(CPACK_PACKAGE_EXECUTABLES "${PROJECT_NAME}" "${PROJECT_NAME}") + SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${TORQUE_APP_VERSION_STRING}") + #SET(CPACK_SOURCE_STRIP_FILES "") +endmacro() +# always static for now +set(TORQUE_STATIC ON) +#option(TORQUE_STATIC "enables or disable static" OFF) + +if(WIN32) + set(TORQUE_CXX_FLAGS_EXECUTABLES "/wd4018 /wd4100 /wd4121 /wd4127 /wd4130 /wd4244 /wd4245 /wd4389 /wd4511 /wd4512 /wd4800 /wd4995 " CACHE TYPE STRING) + mark_as_advanced(TORQUE_CXX_FLAGS_EXECUTABLES) + + set(TORQUE_CXX_FLAGS_LIBS "/W0" CACHE TYPE STRING) + mark_as_advanced(TORQUE_CXX_FLAGS_LIBS) + + set(TORQUE_CXX_FLAGS_COMMON_DEFAULT "-DUNICODE -D_UNICODE /MP /O2 /Ob2 /Oi /Ot /Oy /GT /Zi /W4 /nologo /GF /EHsc /GS- /Gy- /Qpar- /fp:fast /fp:except- /GR /Zc:wchar_t- /D_CRT_SECURE_NO_WARNINGS" ) + if( TORQUE_CPU_X32 ) + set(TORQUE_CXX_FLAGS_COMMON_DEFAULT ${TORQUE_CXX_FLAGS_COMMON_DEFAULT}" /arch:SSE2") + endif() + set(TORQUE_CXX_FLAGS_COMMON ${TORQUE_CXX_FLAGS_COMMON_DEFAULT} CACHE TYPE STRING) + + mark_as_advanced(TORQUE_CXX_FLAGS_COMMON) + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORQUE_CXX_FLAGS_COMMON}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "/LARGEADDRESSAWARE") + #set(STATIC_LIBRARY_FLAGS "/OPT:NOREF") + + # Force static runtime libraries + if(TORQUE_STATIC) + FOREACH(flag + CMAKE_C_FLAGS_RELEASE + CMAKE_C_FLAGS_RELWITHDEBINFO + CMAKE_C_FLAGS_DEBUG + CMAKE_C_FLAGS_DEBUG_INIT + CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_DEBUG_INIT) + STRING(REPLACE "/MD" "/MT" "${flag}" "${${flag}}") + SET("${flag}" "${${flag}} /EHsc") + ENDFOREACH() + endif() +else() + # TODO: improve default settings on other platforms + set(TORQUE_CXX_FLAGS_EXECUTABLES "" CACHE TYPE STRING) + mark_as_advanced(TORQUE_CXX_FLAGS_EXECUTABLES) + set(TORQUE_CXX_FLAGS_LIBS "" CACHE TYPE STRING) + mark_as_advanced(TORQUE_CXX_FLAGS_LIBS) + set(TORQUE_CXX_FLAGS_COMMON "" CACHE TYPE STRING) + mark_as_advanced(TORQUE_CXX_FLAGS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORQUE_CXX_FLAGS}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS}") +endif() + +if(UNIX) + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${projectOutDir}") + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${projectOutDir}") + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${projectOutDir}") + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${projectOutDir}") +endif() + +# fix the debug/release subfolders on windows +if(MSVC) + FOREACH(CONF ${CMAKE_CONFIGURATION_TYPES}) + # Go uppercase (DEBUG, RELEASE...) + STRING(TOUPPER "${CONF}" CONF) + #SET("CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CONF}" "${projectOutDir}") + SET("CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONF}" "${projectOutDir}") + ENDFOREACH() +endif() diff --git a/Tools/CMake/cleanup-win.bat.in b/Tools/CMake/cleanup-win.bat.in new file mode 100644 index 000000000..c8c3a4fad --- /dev/null +++ b/Tools/CMake/cleanup-win.bat.in @@ -0,0 +1,47 @@ +@ECHO off + +:: Delete procedural shaders +echo shaders +del /q /a:-R shaders\procedural\*.* +:: Delete dumped shader disassembly files +for /R %%a IN (*._dis.txt) do IF EXIST "%%a._dis.txt" del "%%a._dis.txt" + +:: Delete fonts +echo fonts +del /q /a:-R core\fonts\*.* + +:: CEF cache +echo browser cache +del /q /a:-R cache + + +:: the cached meshes and alike +echo meshes and alike +for /R %%a IN (*.dae) do IF EXIST "%%~pna.cached.dts" del "%%~pna.cached.dts" +for /R %%a IN (*.imposter*.dds) do del "%%a" + +:: the torque script compilations +echo compiled script +for /R %%a IN (*.cs) do IF EXIST "%%a.dso" del "%%a.dso" +for /R %%a IN (*.cs) do IF EXIST "%%a.edso" del "%%a.edso" +for /R %%a IN (*.gui) do IF EXIST "%%a.dso" del "%%a.dso" +for /R %%a IN (*.gui) do IF EXIST "%%a.edso" del "%%a.edso" +for /R %%a IN (*.ts) do IF EXIST "%%a.dso" del "%%a.dso" +for /R %%a IN (*.ts) do IF EXIST "%%a.edso" del "%%a.edso" + +:: the user settings and alike +echo settings +IF EXIST "prefs.cs" del /s prefs.cs +IF EXIST "core\prefs.cs" del /s core\prefs.cs +::IF EXIST "scripts\client\prefs.cs" del /s scripts\client\prefs.cs +IF EXIST "scripts\server\banlist.cs" del /s scripts\server\banlist.cs +IF EXIST "scripts\server\prefs.cs" del /s scripts\server\prefs.cs +IF EXIST "client\config.cs" del /s client\config.cs +IF EXIST "config.cs" del /s config.cs +IF EXIST "tools\settings.xml" del /s tools\settings.xml +IF EXIST "banlist.cs" del /s banlist.cs + +:: logs +echo logs +IF EXIST "torque3d.log" del /s torque3d.log +echo DONE! diff --git a/Tools/CMake/libraries/collada.cmake b/Tools/CMake/libraries/collada.cmake new file mode 100644 index 000000000..aa8ada02d --- /dev/null +++ b/Tools/CMake/libraries/collada.cmake @@ -0,0 +1,39 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project(collada) + +addPath("${libDir}/collada/src/1.4/dom") +addPath("${libDir}/collada/src/dae") +addPath("${libDir}/collada/src/modules/LIBXMLPlugin") +addPath("${libDir}/collada/src/modules/stdErrPlugin") +addPath("${libDir}/collada/src/modules/STLDatabase") + +addDef(DOM_INCLUDE_TINYXML) +addDef(PCRE_STATIC) + +addInclude(${libDir}/collada/include) +addInclude(${libDir}/collada/include/1.4) +addInclude(${libDir}/pcre) +addInclude(${libDir}/tinyxml) + +finishLibrary() diff --git a/Tools/CMake/libraries/convexDecomp.cmake b/Tools/CMake/libraries/convexDecomp.cmake new file mode 100644 index 000000000..6bf2c29d8 --- /dev/null +++ b/Tools/CMake/libraries/convexDecomp.cmake @@ -0,0 +1,29 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project(convexDecomp) + +if(UNIX) + addDef(LINUX) +endif() + +finishLibrary("${libDir}/convexDecomp") diff --git a/Tools/CMake/libraries/libogg.cmake b/Tools/CMake/libraries/libogg.cmake new file mode 100644 index 000000000..c68617264 --- /dev/null +++ b/Tools/CMake/libraries/libogg.cmake @@ -0,0 +1,29 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project(libogg) + +addPath("${libDir}/libogg" REC) + +addInclude(${libDir}/libogg/include) + +finishLibrary() diff --git a/Tools/CMake/libraries/libtheora.cmake b/Tools/CMake/libraries/libtheora.cmake new file mode 100644 index 000000000..ca003a9ce --- /dev/null +++ b/Tools/CMake/libraries/libtheora.cmake @@ -0,0 +1,44 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project(libtheora) + +addPath( "${libDir}/libtheora" ) +addPathRec( "${libDir}/libtheora/include" ) +addPath( "${libDir}/libtheora/lib" ) +addPath( "${libDir}/libtheora/lib/dec" ) +addPath( "${libDir}/libtheora/lib/enc" ) + +if(WIN32) + addPath( "${libDir}/libtheora/lib/dec/x86_vc" ) + addPath( "${libDir}/libtheora/lib/enc/x86_32_vs" ) +else() + addPath( "${libDir}/libtheora/lib/dec/x86" ) + addPath( "${libDir}/libtheora/lib/enc/x86_32" ) +endif() + +addDef(TORQUE_OGGTHEORA) +addDef(TORQUE_OGGVORIBS) +addInclude(${libDir}/libogg/include) +addInclude(${libDir}/libtheora/include) + +finishLibrary() diff --git a/Tools/CMake/libraries/libvorbis.cmake b/Tools/CMake/libraries/libvorbis.cmake new file mode 100644 index 000000000..43913eb64 --- /dev/null +++ b/Tools/CMake/libraries/libvorbis.cmake @@ -0,0 +1,35 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project(libvorbis) + +addPathRec("${libDir}/libvorbis") + +addDef(TORQUE_OGGVORBIS) +addInclude(${libDir}/libvorbis/include) +addInclude(${libDir}/libogg/include) + +if(UNIX) + addInclude(${libDir}/libvorbis/lib) +endif() + +finishLibrary() diff --git a/Tools/CMake/libraries/ljpeg.cmake b/Tools/CMake/libraries/ljpeg.cmake new file mode 100644 index 000000000..dbe65cb7f --- /dev/null +++ b/Tools/CMake/libraries/ljpeg.cmake @@ -0,0 +1,25 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project(ljpeg) + +finishLibrary("${libDir}/ljpeg") diff --git a/Tools/CMake/libraries/lmng.cmake b/Tools/CMake/libraries/lmng.cmake new file mode 100644 index 000000000..3564e362d --- /dev/null +++ b/Tools/CMake/libraries/lmng.cmake @@ -0,0 +1,32 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project(lmng) + + +addDef(MNG_OPTIMIZE_OBJCLEANUP) + +addInclude(${libDir}/lpng) +addInclude(${libDir}/zlib) +addInclude(${libDir}/ljpeg) + +finishLibrary("${libDir}/${PROJECT_NAME}") diff --git a/Tools/CMake/libraries/lpng.cmake b/Tools/CMake/libraries/lpng.cmake new file mode 100644 index 000000000..44271904a --- /dev/null +++ b/Tools/CMake/libraries/lpng.cmake @@ -0,0 +1,29 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project(lpng) + +# addDef(PNG_NO_ASSEMBLER_CODE) + +addInclude(${libDir}/zlib) + +finishLibrary("${libDir}/${PROJECT_NAME}") diff --git a/Tools/CMake/libraries/lungif.cmake b/Tools/CMake/libraries/lungif.cmake new file mode 100644 index 000000000..910a9922f --- /dev/null +++ b/Tools/CMake/libraries/lungif.cmake @@ -0,0 +1,28 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project(lungif) + +addDef(_GBA_NO_FILEIO) + + +finishLibrary("${libDir}/${PROJECT_NAME}") diff --git a/Tools/CMake/libraries/opcode.cmake b/Tools/CMake/libraries/opcode.cmake new file mode 100644 index 000000000..e41b61af3 --- /dev/null +++ b/Tools/CMake/libraries/opcode.cmake @@ -0,0 +1,31 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project(opcode) + +addPath("${libDir}/${PROJECT_NAME}") +addPath("${libDir}/${PROJECT_NAME}/Ice") + +addDef(TORQUE_OPCODE) +addDef(ICE_NO_DLL) + +finishLibrary() diff --git a/Tools/CMake/libraries/pcre.cmake b/Tools/CMake/libraries/pcre.cmake new file mode 100644 index 000000000..9cf0ce67c --- /dev/null +++ b/Tools/CMake/libraries/pcre.cmake @@ -0,0 +1,32 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project(pcre) + +addDef(PCRE_STATIC) +addDef(HAVE_CONFIG_H) + +finishLibrary("${libDir}/pcre") + +if(WIN32) + set_property(TARGET pcre PROPERTY COMPILE_FLAGS /TP) #/TP = compile as C++ +endif() \ No newline at end of file diff --git a/Tools/CMake/libraries/recast.cmake b/Tools/CMake/libraries/recast.cmake new file mode 100644 index 000000000..5422f73cd --- /dev/null +++ b/Tools/CMake/libraries/recast.cmake @@ -0,0 +1,40 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +# Recast library +project(recast) + +# Source +addPathRec( "${libDir}/recast/DebugUtils/Source" ) +addPathRec( "${libDir}/recast/Recast/Source" ) +addPathRec( "${libDir}/recast/Detour/Source" ) +addPathRec( "${libDir}/recast/DetourCrowd/Source" ) +addPathRec( "${libDir}/recast/DetourTileCache/Source" ) + +# Additional includes +addInclude( "${libDir}/recast/DebugUtils/Include" ) +addInclude( "${libDir}/recast/Recast/Include" ) +addInclude( "${libDir}/recast/Detour/Include" ) +addInclude( "${libDir}/recast/DetourTileCache/Include" ) +addInclude( "${libDir}/recast/DetourCrowd/Include" ) + +finishLibrary() \ No newline at end of file diff --git a/Tools/CMake/libraries/squish.cmake b/Tools/CMake/libraries/squish.cmake new file mode 100644 index 000000000..9eff59405 --- /dev/null +++ b/Tools/CMake/libraries/squish.cmake @@ -0,0 +1,25 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project(squish) + +finishLibrary("${libDir}/${PROJECT_NAME}") diff --git a/Tools/CMake/libraries/tinyxml.cmake b/Tools/CMake/libraries/tinyxml.cmake new file mode 100644 index 000000000..0c535bbbe --- /dev/null +++ b/Tools/CMake/libraries/tinyxml.cmake @@ -0,0 +1,25 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project(tinyxml) + +finishLibrary("${libDir}/${PROJECT_NAME}") diff --git a/Tools/CMake/libraries/zlib.cmake b/Tools/CMake/libraries/zlib.cmake new file mode 100644 index 000000000..72a5df4c5 --- /dev/null +++ b/Tools/CMake/libraries/zlib.cmake @@ -0,0 +1,25 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project(zlib) + +finishLibrary("${libDir}/${PROJECT_NAME}") diff --git a/Tools/CMake/modules/module_hydra.cmake b/Tools/CMake/modules/module_hydra.cmake new file mode 100644 index 000000000..32e5d6ef6 --- /dev/null +++ b/Tools/CMake/modules/module_hydra.cmake @@ -0,0 +1,41 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +# module OculusVR + +# Source +addPathRec( "${srcDir}/platform/input/razerHydra" ) + +# Includes +addInclude( "${TORQUE_RAZERHYDRA_SDK_PATH}/include" ) + +# Install +if( WIN32 ) + # File Copy for Release + INSTALL(FILES "${TORQUE_RAZERHYDRA_SDK_PATH}/bin/win32/release_dll/sixense.dll" DESTINATION "${projectOutDir}") + + # File Copy for Debug + INSTALL(FILES "${TORQUE_RAZERHYDRA_SDK_PATH}/bin/win32/debug_dll/sixensed.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS "Debug" ) + # Only needed by the debug sixense library + INSTALL(FILES "${TORQUE_RAZERHYDRA_SDK_PATH}/samples/win32/sixense_simple3d/DeviceDLL.dll" DESTINATION "${projectOutDir}" CONFIGURATIONS "Debug" ) +endif() + diff --git a/Tools/CMake/modules/module_navigation.cmake b/Tools/CMake/modules/module_navigation.cmake new file mode 100644 index 000000000..04064cd26 --- /dev/null +++ b/Tools/CMake/modules/module_navigation.cmake @@ -0,0 +1,37 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +# Navigation module + +addDef( "TORQUE_NAVIGATION_ENABLED" ) +addLib( "recast" ) + +# files +addPathRec( "${srcDir}/navigation" ) + +# include paths +addInclude( "${libDir}/recast/DebugUtils/Include" ) +addInclude( "${libDir}/recast/Recast/Include" ) +addInclude( "${libDir}/recast/Detour/Include" ) +addInclude( "${libDir}/recast/DetourTileCache/Include" ) +addInclude( "${libDir}/recast/DetourCrowd/Include" ) + diff --git a/Tools/CMake/modules/module_oculusVR.cmake b/Tools/CMake/modules/module_oculusVR.cmake new file mode 100644 index 000000000..17a37b7d6 --- /dev/null +++ b/Tools/CMake/modules/module_oculusVR.cmake @@ -0,0 +1,37 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +# module OculusVR + +# Source +addPathRec( "${srcDir}/platform/input/oculusVR" ) + +# Includes +addInclude( "${TORQUE_OCULUSVR_SDK_PATH}/LibOVR/Include" ) +addInclude( "${TORQUE_OCULUSVR_SDK_PATH}/LibOVR/Src" ) + +# Libs +if( WIN32 ) + link_directories( "${TORQUE_OCULUSVR_SDK_PATH}/LibOVR/Lib/Win32" ) + addLib( "libovr" ) + addLib( "libovrd" ) +endif() \ No newline at end of file diff --git a/Tools/CMake/modules/module_testing.cmake b/Tools/CMake/modules/module_testing.cmake new file mode 100644 index 000000000..f1b128403 --- /dev/null +++ b/Tools/CMake/modules/module_testing.cmake @@ -0,0 +1,37 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +option(TORQUE_TESTS_ENABLED "TORQUE_TESTS_ENABLED" OFF) + +if(TORQUE_TESTS_ENABLED) + + # Project defines + addDef( "TORQUE_TESTS_ENABLED" ) + addDef( "_VARIADIC_MAX" 10 ) + + # Add source files + addPathRec( "${srcDir}/testing" ) + + # Add include paths + addInclude( "${libDir}/gtest/fused-src/" ) + +endif() \ No newline at end of file diff --git a/Tools/CMake/template.cmake b/Tools/CMake/template.cmake new file mode 100644 index 000000000..c48aaa676 --- /dev/null +++ b/Tools/CMake/template.cmake @@ -0,0 +1,43 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +# this is a template file that should help you write a new cmake build script for a new library + + +# 1st thing: the project name +project(pcre) + +# add the paths where the source code is + +addPath("${libDir}/pcre") +addPathRec("${libDir}/pcre") + +# then add definitions +addDef(PCRE_STATIC) +addDef(HAVE_CONFIG_H) + +# and maybe more include paths +addInclude(${libDir}/libvorbis/include) +addInclude(${libDir}/libogg/include) + +# finally: add finishLibrary() +finishLibrary() diff --git a/Tools/CMake/template.torsion.in b/Tools/CMake/template.torsion.in new file mode 100644 index 000000000..f832ad13b --- /dev/null +++ b/Tools/CMake/template.torsion.in @@ -0,0 +1,39 @@ + +@TORQUE_APP_NAME@ + +main.cs +dbgSetParameters( #port#, "#password#", true ); + +core +scripts +art +levels +shaders +tools + +cs; gui + + +Release +@TORQUE_APP_NAME@.exe + +true +true +true +false + + +Debug +@TORQUE_APP_NAME@.exe + +true +true +true +false + + + +@TORQUE_APP_NAME@ +HEAD +true + diff --git a/Tools/CMake/torque-win.rc.in b/Tools/CMake/torque-win.rc.in new file mode 100644 index 000000000..498d1e95e --- /dev/null +++ b/Tools/CMake/torque-win.rc.in @@ -0,0 +1,123 @@ +//Microsoft Developer Studio generated resource script. +// +#define IDI_ICON1 103 +#define IDI_ICON2 107 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 108 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "windows.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "torque.ico" +IDI_ICON2 ICON DISCARDABLE "torque.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @TORQUE_APP_VERSION_MAJOR@,@TORQUE_APP_VERSION_MINOR@,@TORQUE_APP_VERSION_PATCH@,@TORQUE_APP_VERSION_TWEAK@ + PRODUCTVERSION @TORQUE_APP_VERSION_MAJOR@,@TORQUE_APP_VERSION_MINOR@,@TORQUE_APP_VERSION_PATCH@,@TORQUE_APP_VERSION_TWEAK@ + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "@PROJECT_NAME@" + VALUE "FileDescription", "@PROJECT_NAME@" + VALUE "FileVersion", "@TORQUE_APP_VERSION_STRING@" + VALUE "InternalName", "@PROJECT_NAME@" + VALUE "LegalCopyright", "Copyright (C) 2014" + VALUE "OriginalFilename", "@PROJECT_NAME@" + VALUE "ProductName", "@PROJECT_NAME@" + VALUE "ProductVersion", "@TORQUE_APP_VERSION_STRING@" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/Tools/CMake/torque.ico b/Tools/CMake/torque.ico new file mode 100644 index 000000000..22ac1a3d1 Binary files /dev/null and b/Tools/CMake/torque.ico differ diff --git a/Tools/CMake/torque3d.cmake b/Tools/CMake/torque3d.cmake new file mode 100644 index 000000000..cd6e1a199 --- /dev/null +++ b/Tools/CMake/torque3d.cmake @@ -0,0 +1,589 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014 GarageGames, LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ----------------------------------------------------------------------------- + +project(${TORQUE_APP_NAME}) + +if(UNIX) + # default compiler flags + # force compile 32 bit + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -Wall -Wundef -msse -pipe -Wfatal-errors ${TORQUE_ADDITIONAL_LINKER_FLAGS}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -Wall -Wundef -msse -pipe -Wfatal-errors ${TORQUE_ADDITIONAL_LINKER_FLAGS}") + + # for asm files + SET (CMAKE_ASM_NASM_OBJECT_FORMAT "elf") + ENABLE_LANGUAGE (ASM_NASM) +endif() + +# TODO: fmod support + +############################################################################### +# modules +############################################################################### +option(TORQUE_SFX_VORBIS "Vorbis Sound" ON) +mark_as_advanced(TORQUE_SFX_VORBIS) +option(TORQUE_THEORA "Theora Video Support" ON) +mark_as_advanced(TORQUE_THEORA) +option(TORQUE_ADVANCED_LIGHTING "Advanced Lighting" ON) +mark_as_advanced(TORQUE_ADVANCED_LIGHTING) +option(TORQUE_BASIC_LIGHTING "Basic Lighting" ON) +mark_as_advanced(TORQUE_BASIC_LIGHTING) +if(WIN32) + option(TORQUE_SFX_DirectX "DirectX Sound" ON) + mark_as_advanced(TORQUE_SFX_DirectX) +else() + set(TORQUE_SFX_DirectX OFF) +endif() +option(TORQUE_SFX_OPENAL "OpenAL Sound" ON) +mark_as_advanced(TORQUE_SFX_OPENAL) +option(TORQUE_HIFI "HIFI? support" OFF) +mark_as_advanced(TORQUE_HIFI) +option(TORQUE_EXTENDED_MOVE "Extended move support" OFF) +mark_as_advanced(TORQUE_EXTENDED_MOVE) +option(TORQUE_NAVIGATION "Enable Navigation module" OFF) +#mark_as_advanced(TORQUE_NAVIGATION) +option(TORQUE_TESTING "Enable unit test module" OFF) +mark_as_advanced(TORQUE_TESTING) +if(WIN32) + option(TORQUE_OPENGL "Allow OpenGL render" OFF) + #mark_as_advanced(TORQUE_OPENGL) +else() + set(TORQUE_OPENGL ON) # we need OpenGL to render on Linux/Mac + option(TORQUE_DEDICATED "Torque dedicated" OFF) +endif() + +#Oculus VR +option(TORQUE_OCULUSVR "Enable OCULUSVR module" OFF) +mark_as_advanced(TORQUE_OCULUSVR) +if(TORQUE_OCULUSVR) + set(TORQUE_OCULUSVR_SDK_PATH "" CACHE PATH "OCULUSVR library path" FORCE) +else() # hide variable + set(TORQUE_OCULUSVR_SDK_PATH "" CACHE INTERNAL "" FORCE) +endif() + +#Hydra +option(TORQUE_HYDRA "Enable HYDRA module" OFF) +mark_as_advanced(TORQUE_HYDRA) +if(TORQUE_HYDRA) + set(TORQUE_HYDRA_SDK_PATH "" CACHE PATH "HYDRA library path" FORCE) +else() # hide variable + set(TORQUE_HYDRA_SDK_PATH "" CACHE INTERNAL "" FORCE) +endif() + +############################################################################### +# options +############################################################################### +if(NOT MSVC) # handle single-configuration generator + set(TORQUE_BUILD_TYPE "Debug" CACHE STRING "Select one of Debug, Release and RelWithDebInfo") + set_property(CACHE TORQUE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "RelWithDebInfo") + + set(TORQUE_ADDITIONAL_LINKER_FLAGS "" CACHE STRING "Additional linker flags") + mark_as_advanced(TORQUE_ADDITIONAL_LINKER_FLAGS) +endif() + +option(TORQUE_MULTITHREAD "Multi Threading" ON) +mark_as_advanced(TORQUE_MULTITHREAD) + +option(TORQUE_DISABLE_MEMORY_MANAGER "Disable memory manager" ON) +mark_as_advanced(TORQUE_DISABLE_MEMORY_MANAGER) + +option(TORQUE_DISABLE_VIRTUAL_MOUNT_SYSTEM "Disable virtual mount system" OFF) +mark_as_advanced(TORQUE_DISABLE_VIRTUAL_MOUNT_SYSTEM) + +option(TORQUE_PLAYER "Playback only?" OFF) +mark_as_advanced(TORQUE_PLAYER) + +option(TORQUE_TOOLS "Enable or disable the tools" ON) +mark_as_advanced(TORQUE_TOOLS) + +option(TORQUE_ENABLE_PROFILER "Enable or disable the profiler" OFF) +mark_as_advanced(TORQUE_ENABLE_PROFILER) + +option(TORQUE_DEBUG "T3D Debug mode" OFF) +mark_as_advanced(TORQUE_DEBUG) + +option(TORQUE_SHIPPING "T3D Shipping build?" OFF) +mark_as_advanced(TORQUE_SHIPPING) + +option(TORQUE_DEBUG_NET "debug network" OFF) +mark_as_advanced(TORQUE_DEBUG_NET) + +option(TORQUE_DEBUG_NET_MOVES "debug network moves" OFF) +mark_as_advanced(TORQUE_DEBUG_NET_MOVES) + +option(TORQUE_ENABLE_ASSERTS "enables or disable asserts" OFF) +mark_as_advanced(TORQUE_ENABLE_ASSERTS) + +option(TORQUE_DEBUG_GFX_MODE "triggers graphics debug mode" OFF) +mark_as_advanced(TORQUE_DEBUG_GFX_MODE) + +#option(DEBUG_SPEW "more debug" OFF) +set(TORQUE_NO_DSO_GENERATION ON) + +if(WIN32) + # warning C4800: 'XXX' : forcing value to bool 'true' or 'false' (performance warning) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4800") + # warning C4018: '<' : signed/unsigned mismatch + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4018") + # warning C4244: 'initializing' : conversion from 'XXX' to 'XXX', possible loss of data + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4244") + + if( TORQUE_CPU_X64 ) + link_directories($ENV{DXSDK_DIR}/Lib/x64) + else() + link_directories($ENV{DXSDK_DIR}/Lib/x86) + endif() +endif() + +############################################################################### +# Always enabled paths first +############################################################################### +addPath("${srcDir}/") # must come first :) +addPathRec("${srcDir}/app") +addPath("${srcDir}/sfx/media") +addPath("${srcDir}/sfx/null") +addPath("${srcDir}/sfx") +addPath("${srcDir}/component") +addPath("${srcDir}/component/interfaces") +addPath("${srcDir}/console") +addPath("${srcDir}/core") +addPath("${srcDir}/core/stream") +addPath("${srcDir}/core/strings") +addPath("${srcDir}/core/util") +addPath("${srcDir}/core/util/test") +addPath("${srcDir}/core/util/journal") +addPath("${srcDir}/core/util/journal/test") +addPath("${srcDir}/core/util/zip") +addPath("${srcDir}/core/util/zip/test") +addPath("${srcDir}/core/util/zip/compressors") +addPath("${srcDir}/i18n") +addPath("${srcDir}/sim") +addPath("${srcDir}/util") +addPath("${srcDir}/windowManager") +addPath("${srcDir}/windowManager/torque") +addPath("${srcDir}/windowManager/test") +addPath("${srcDir}/math") +addPath("${srcDir}/math/util") +addPath("${srcDir}/math/test") +addPath("${srcDir}/platform") +addPath("${srcDir}/cinterface") +addPath("${srcDir}/platform/nativeDialogs") +if( NOT TORQUE_DEDICATED ) + addPath("${srcDir}/platform/menus") +endif() +addPath("${srcDir}/platform/test") +addPath("${srcDir}/platform/threads") +addPath("${srcDir}/platform/async") +addPath("${srcDir}/platform/async/test") +addPath("${srcDir}/platform/input") +addPath("${srcDir}/platform/output") +addPath("${srcDir}/app") +addPath("${srcDir}/app/net") +addPath("${srcDir}/util/messaging") +addPath("${srcDir}/gfx/Null") +addPath("${srcDir}/gfx/test") +addPath("${srcDir}/gfx/bitmap") +addPath("${srcDir}/gfx/bitmap/loaders") +addPath("${srcDir}/gfx/util") +addPath("${srcDir}/gfx/video") +addPath("${srcDir}/gfx") +addPath("${srcDir}/shaderGen") +addPath("${srcDir}/gfx/sim") +addPath("${srcDir}/gui/buttons") +addPath("${srcDir}/gui/containers") +addPath("${srcDir}/gui/controls") +addPath("${srcDir}/gui/core") +addPath("${srcDir}/gui/game") +addPath("${srcDir}/gui/shiny") +addPath("${srcDir}/gui/utility") +addPath("${srcDir}/gui") +addPath("${srcDir}/collision") +addPath("${srcDir}/materials") +addPath("${srcDir}/lighting") +addPath("${srcDir}/lighting/common") +addPath("${srcDir}/renderInstance") +addPath("${srcDir}/scene") +addPath("${srcDir}/scene/culling") +addPath("${srcDir}/scene/zones") +addPath("${srcDir}/scene/mixin") +addPath("${srcDir}/shaderGen") +addPath("${srcDir}/terrain") +addPath("${srcDir}/environment") +addPath("${srcDir}/forest") +addPath("${srcDir}/forest/ts") +addPath("${srcDir}/ts") +addPath("${srcDir}/ts/arch") +addPath("${srcDir}/physics") +addPath("${srcDir}/gui/3d") +addPath("${srcDir}/postFx") +addPath("${srcDir}/T3D") +addPath("${srcDir}/T3D/examples") +addPath("${srcDir}/T3D/fps") +addPath("${srcDir}/T3D/fx") +addPath("${srcDir}/T3D/vehicles") +addPath("${srcDir}/T3D/physics") +addPath("${srcDir}/T3D/decal") +addPath("${srcDir}/T3D/sfx") +addPath("${srcDir}/T3D/gameBase") +addPath("${srcDir}/T3D/turret") +addPath("${srcDir}/main/") +addPathRec("${srcDir}/ts/collada") +addPathRec("${srcDir}/ts/loader") +addPathRec("${projectSrcDir}") + +############################################################################### +# modular paths +############################################################################### +# lighting +if(TORQUE_ADVANCED_LIGHTING) + addPath("${srcDir}/lighting/advanced") + addPathRec("${srcDir}/lighting/shadowMap") + if(WIN32) + addPathRec("${srcDir}/lighting/advanced/hlsl") + endif() + if(TORQUE_OPENGL) + addPathRec("${srcDir}/lighting/advanced/glsl") + endif() + addDef(TORQUE_ADVANCED_LIGHTING) +endif() +if(TORQUE_BASIC_LIGHTING) + addPathRec("${srcDir}/lighting/basic") + addPathRec("${srcDir}/lighting/shadowMap") + addDef(TORQUE_BASIC_LIGHTING) +endif() + +# DirectX Sound +if(TORQUE_SFX_DirectX) + addLib(x3daudio.lib) + addPathRec("${srcDir}/sfx/dsound") + addPathRec("${srcDir}/sfx/xaudio") +endif() + +# OpenAL +if(TORQUE_SFX_OPENAL AND NOT TORQUE_DEDICATED) + addPath("${srcDir}/sfx/openal") + #addPath("${srcDir}/sfx/openal/mac") + if(WIN32) + addPath("${srcDir}/sfx/openal/win32") + addInclude("${libDir}/openal/win32") + endif() + if(UNIX) + addPath("${srcDir}/sfx/openal/linux") + endif() + +endif() + +# Vorbis +if(TORQUE_SFX_VORBIS) + addInclude(${libDir}/libvorbis/include) + addDef(TORQUE_OGGVORBIS) + addLib(libvorbis) + addLib(libogg) +endif() + +# Theora +if(TORQUE_THEORA) + addPath("${srcDir}/core/ogg") + addPath("${srcDir}/gfx/video") + addPath("${srcDir}/gui/theora") + + addDef(TORQUE_OGGTHEORA) + addDef(TORQUE_OGGVORIBS) + addInclude(${libDir}/libtheora/include) + addLib(libtheora) +endif() + +# Include tools for non-tool builds (or define player if a tool build) +if(TORQUE_TOOLS) + addPath("${srcDir}/gui/worldEditor") + addPath("${srcDir}/environment/editors") + addPath("${srcDir}/forest/editor") + addPath("${srcDir}/gui/editor") + addPath("${srcDir}/gui/editor/inspector") +endif() + +if(TORQUE_HIFI) + addPath("${srcDir}/T3D/gameBase/hifi") + addDef(TORQUE_HIFI_NET) +endif() + +if(TORQUE_EXTENDED_MOVE) + addPath("${srcDir}/T3D/gameBase/extended") + addDef(TORQUE_EXTENDED_MOVE) +else() + addPath("${srcDir}/T3D/gameBase/std") +endif() + +if(TORQUE_TESTING) + include( "modules/module_testing.cmake" ) +endif() + +if(TORQUE_NAVIGATION) + include( "modules/module_navigation.cmake" ) +endif() + +if(TORQUE_OCULUSVR) + include( "modules/module_oculusVR.cmake" ) +endif() + +if(TORQUE_HYDRA) + include( "modules/module_hydra.cmake" ) +endif() + +if(TORQUE_DEDICATED) + addDef(TORQUE_DEDICATED) +endif() + +include( "modules/module_testing.cmake" ) + + +############################################################################### +# platform specific things +############################################################################### +if(WIN32) + addPath("${srcDir}/platformWin32") + addPath("${srcDir}/platformWin32/nativeDialogs") + addPath("${srcDir}/platformWin32/menus") + addPath("${srcDir}/platformWin32/threads") + addPath("${srcDir}/platformWin32/videoInfo") + addPath("${srcDir}/platformWin32/minidump") + addPath("${srcDir}/windowManager/win32") + #addPath("${srcDir}/gfx/D3D8") + addPath("${srcDir}/gfx/D3D") + addPath("${srcDir}/gfx/D3D9") + addPath("${srcDir}/gfx/D3D9/pc") + addPath("${srcDir}/shaderGen/HLSL") + addPath("${srcDir}/terrain/hlsl") + addPath("${srcDir}/forest/hlsl") + # add windows rc file for the icon + addFile("${projectSrcDir}/torque.rc") +endif() + +if(APPLE) + addPath("${srcDir}/platformMac") + addPath("${srcDir}/platformMac/menus") + addPath("${srcDir}/platformPOSIX") + addPath("${srcDir}/windowManager/mac") + addPath("${srcDir}/gfx/gl") + addPath("${srcDir}/gfx/gl/ggl") + addPath("${srcDir}/gfx/gl/ggl/mac") + addPath("${srcDir}/gfx/gl/ggl/generated") + addPath("${srcDir}/shaderGen/GLSL") + addPath("${srcDir}/terrain/glsl") + addPath("${srcDir}/forest/glsl") +endif() + +if(XBOX360) + addPath("${srcDir}/platformXbox") + addPath("${srcDir}/platformXbox/threads") + addPath("${srcDir}/windowManager/360") + addPath("${srcDir}/gfx/D3D9") + addPath("${srcDir}/gfx/D3D9/360") + addPath("${srcDir}/shaderGen/HLSL") + addPath("${srcDir}/shaderGen/360") + addPath("${srcDir}/ts/arch/360") + addPath("${srcDir}/terrain/hlsl") + addPath("${srcDir}/forest/hlsl") +endif() + +if(PS3) + addPath("${srcDir}/platformPS3") + addPath("${srcDir}/platformPS3/threads") + addPath("${srcDir}/windowManager/ps3") + addPath("${srcDir}/gfx/gl") + addPath("${srcDir}/gfx/gl/ggl") + addPath("${srcDir}/gfx/gl/ggl/ps3") + addPath("${srcDir}/gfx/gl/ggl/generated") + addPath("${srcDir}/shaderGen/GLSL") + addPath("${srcDir}/ts/arch/ps3") + addPath("${srcDir}/terrain/glsl") + addPath("${srcDir}/forest/glsl") +endif() + +if(UNIX) + if(TORQUE_DEDICATED) + addPath("${srcDir}/windowManager/dedicated") + # ${srcDir}/platformX86UNIX/*.client.* files are not needed + # @todo: move to separate file + file( GLOB tmp_files + ${srcDir}/platformX86UNIX/*.cpp + ${srcDir}/platformX86UNIX/*.c + ${srcDir}/platformX86UNIX/*.cc + ${srcDir}/platformX86UNIX/*.h ) + file( GLOB tmp_remove_files ${srcDir}/platformX86UNIX/*client.* ) + LIST( REMOVE_ITEM tmp_files ${tmp_remove_files} ) + foreach( f ${tmp_files} ) + addFile( ${f} ) + endforeach() + else() + addPath("${srcDir}/platformX86UNIX") + endif() + + addPath("${srcDir}/platformX86UNIX/threads") + addPath("${srcDir}/platformPOSIX") +endif() + +if( TORQUE_OPENGL ) + addPath("${srcDir}/shaderGen/GLSL") + if( TORQUE_OPENGL AND NOT TORQUE_DEDICATED ) + addPath("${srcDir}/gfx/gl") + addPath("${srcDir}/gfx/gl/tGL") + addPath("${srcDir}/terrain/glsl") + addPath("${srcDir}/forest/glsl") + endif() + + if(WIN32 AND NOT TORQUE_SDL) + addPath("${srcDir}/gfx/gl/win32") + endif() +endif() + +############################################################################### +############################################################################### +finishExecutable() +############################################################################### +############################################################################### + +message(STATUS "writing ${projectSrcDir}/torqueConfig.h") +CONFIGURE_FILE("${cmakeDir}/torqueConfig.h.in" "${projectSrcDir}/torqueConfig.h") + +# configure the relevant files only once +if(NOT EXISTS "${projectSrcDir}/torque.ico") + CONFIGURE_FILE("${cmakeDir}/torque.ico" "${projectSrcDir}/torque.ico" COPYONLY) +endif() +if(NOT EXISTS "${projectOutDir}/${PROJECT_NAME}.torsion") + CONFIGURE_FILE("${cmakeDir}/template.torsion.in" "${projectOutDir}/${PROJECT_NAME}.torsion") +endif() +if(EXISTS "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/main.cs.in" AND NOT EXISTS "${projectOutDir}/main.cs") + CONFIGURE_FILE("${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/main.cs.in" "${projectOutDir}/main.cs") +endif() +if(WIN32) + if(NOT EXISTS "${projectSrcDir}/torque.rc") + CONFIGURE_FILE("${cmakeDir}/torque-win.rc.in" "${projectSrcDir}/torque.rc") + endif() + if(NOT EXISTS "${projectOutDir}/${PROJECT_NAME}-debug.bat") + CONFIGURE_FILE("${cmakeDir}/app-debug-win.bat.in" "${projectOutDir}/${PROJECT_NAME}-debug.bat") + endif() + if(NOT EXISTS "${projectOutDir}/cleanup.bat") + CONFIGURE_FILE("${cmakeDir}/cleanup-win.bat.in" "${projectOutDir}/cleanup.bat") + endif() +endif() + +############################################################################### +# Common Libraries +############################################################################### +addLib(lmng) +addLib(lpng) +addLib(lungif) +addLib(ljpeg) +addLib(zlib) +addLib(tinyxml) +addLib(opcode) +addLib(squish) +addLib(collada) +addLib(pcre) +addLib(convexDecomp) + +if(WIN32) + # copy pasted from T3D build system, some might not be needed + set(TORQUE_EXTERNAL_LIBS "COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;d3d9.lib;d3dx9.lib;DxErr.lib;ole32.lib;shell32.lib;oleaut32.lib;version.lib" CACHE STRING "external libs to link against") + mark_as_advanced(TORQUE_EXTERNAL_LIBS) + addLib("${TORQUE_EXTERNAL_LIBS}") +endif() + +if(UNIX) + # copy pasted from T3D build system, some might not be needed + set(TORQUE_EXTERNAL_LIBS "rt dl Xxf86vm Xext X11 Xft stdc++ pthread GL" CACHE STRING "external libs to link against") + mark_as_advanced(TORQUE_EXTERNAL_LIBS) + + string(REPLACE " " ";" TORQUE_EXTERNAL_LIBS_LIST ${TORQUE_EXTERNAL_LIBS}) + addLib( "${TORQUE_EXTERNAL_LIBS_LIST}" ) +endif() + +############################################################################### +# Always enabled Definitions +############################################################################### +addDef(TORQUE_DEBUG DEBUG) +addDef(TORQUE_ENABLE_ASSERTS "DEBUG;RelWithDebInfo") +addDef(TORQUE_DEBUG_GFX_MODE "RelWithDebInfo") +addDef(TORQUE_SHADERGEN) +addDef(INITGUID) +addDef(NTORQUE_SHARED) +addDef(UNICODE) +addDef(_UNICODE) # for VS +addDef(TORQUE_UNICODE) +#addDef(TORQUE_SHARED) # not used anymore as the game is the executable directly +addDef(LTC_NO_PROTOTYPES) # for libTomCrypt +addDef(BAN_OPCODE_AUTOLINK) +addDef(ICE_NO_DLL) +addDef(TORQUE_OPCODE) +addDef(TORQUE_COLLADA) +addDef(DOM_INCLUDE_TINYXML) +addDef(PCRE_STATIC) +addDef(_CRT_SECURE_NO_WARNINGS) +addDef(_CRT_SECURE_NO_DEPRECATE) + +if(UNIX) + addDef(LINUX) +endif() + +############################################################################### +# Include Paths +############################################################################### +addInclude("${projectSrcDir}") +addInclude("${srcDir}/") +addInclude("${libDir}/lmpg") +addInclude("${libDir}/lpng") +addInclude("${libDir}/ljpeg") +addInclude("${libDir}/lungif") +addInclude("${libDir}/zlib") +addInclude("${libDir}/") # for tinyxml +addInclude("${libDir}/tinyxml") +addInclude("${libDir}/squish") +addInclude("${libDir}/convexDecomp") +addInclude("${libDir}/libogg/include") +addInclude("${libDir}/opcode") +addInclude("${libDir}/collada/include") +addInclude("${libDir}/collada/include/1.4") + +# external things +if(WIN32) + set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY INCLUDE_DIRECTORIES $ENV{DXSDK_DIR}/Include) +endif() + +if(UNIX) + addInclude("/usr/include/freetype2/freetype") + addInclude("/usr/include/freetype2") +endif() + +############################################################################### +# Installation +############################################################################### + +if(TORQUE_TEMPLATE) + message("Prepare Template(${TORQUE_TEMPLATE}) install...") + INSTALL(DIRECTORY "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game" DESTINATION "${TORQUE_APP_DIR}") + if(WIN32) + INSTALL(FILES "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/cleanShaders.bat" DESTINATION "${TORQUE_APP_DIR}") + INSTALL(FILES "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/DeleteCachedDTSs.bat" DESTINATION "${TORQUE_APP_DIR}") + INSTALL(FILES "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/DeleteDSOs.bat" DESTINATION "${TORQUE_APP_DIR}") + INSTALL(FILES "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/DeletePrefs.bat" DESTINATION "${TORQUE_APP_DIR}") + endif() +endif() diff --git a/Tools/CMake/torqueConfig.h.in b/Tools/CMake/torqueConfig.h.in new file mode 100644 index 000000000..9acb419df --- /dev/null +++ b/Tools/CMake/torqueConfig.h.in @@ -0,0 +1,208 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#pragma once + +//----------------------------------------------------------------------------- +//Hi, and welcome to the Torque Config file. +// +//This file is a central reference for the various configuration flags that +//you'll be using when controlling what sort of a Torque build you have. In +//general, the information here is global for your entire codebase, applying +//not only to your game proper, but also to all of your tools. + +/// What's the name of your application? Used in a variety of places. +#define TORQUE_APP_NAME "@TORQUE_APP_NAME@" + +/// What version of the application specific source code is this? +/// +/// Version number is major * 1000 + minor * 100 + revision * 10. +#define TORQUE_APP_VERSION @TORQUE_APP_VERSION@ + +/// Human readable application version string. +#define TORQUE_APP_VERSION_STRING "@TORQUE_APP_VERSION_STRING@" + +/// Define me if you want to enable multithreading support. +#cmakedefine TORQUE_MULTITHREAD + +/// Define me if you want to disable Torque memory manager. +#cmakedefine TORQUE_DISABLE_MEMORY_MANAGER + +/// Define me if you want to disable the virtual mount system. +#cmakedefine TORQUE_DISABLE_VIRTUAL_MOUNT_SYSTEM + +/// Define me if you want to disable looking for the root of a given path +/// within a zip file. This means that the zip file name itself must be +/// the root of the path. Requires the virtual mount system to be active. +#cmakedefine TORQUE_DISABLE_FIND_ROOT_WITHIN_ZIP + +//Uncomment this define if you want to use the alternative zip support where you can +//define your directories and files inside the zip just like you would on disk +//instead of the default zip support that treats the zip as an extra directory. +#cmakedefine TORQUE_ZIP_DISK_LAYOUT + +/// Define me if you don't want Torque to compile dso's +#cmakedefine TORQUE_NO_DSO_GENERATION + +// Define me if this build is a tools build +#cmakedefine TORQUE_PLAYER +#cmakedefine TORQUE_TOOLS + +/// Define me if you want to enable the profiler. +/// See also the TORQUE_SHIPPING block below +#cmakedefine TORQUE_ENABLE_PROFILER + +/// Define me to enable debug mode; enables a great number of additional +/// sanity checks, as well as making AssertFatal and AssertWarn do something. +/// This is usually defined by the build target. + +// TORQUE_DEBUG is now set dynamically and not here anymore +// #cmakedefine TORQUE_DEBUG + +#cmakedefine DEBUG_SPEW +#cmakedefine TORQUE_DEBUG_GFX_MODE + +/// Define me if this is a shipping build; if defined I will instruct Torque +/// to batten down some hatches and generally be more "final game" oriented. +/// Notably this disables a liberal resource manager file searching, and +/// console help strings. +#cmakedefine TORQUE_SHIPPING + +/// Define me to enable a variety of network debugging aids. +/// +/// - NetConnection packet logging. +/// - DebugChecksum guards to detect mismatched pack/unpacks. +/// - Detection of invalid destination ghosts. +/// +#cmakedefine TORQUE_DEBUG_NET + +/// Define me to enable detailed console logging of net moves. +#cmakedefine TORQUE_DEBUG_NET_MOVES + +/// Enable this define to change the default Net::MaxPacketDataSize +/// Do this at your own risk since it has the potential to cause packets +/// to be split up by old routers and Torque does not have a mechanism to +/// stitch split packets back together. Using this define can be very useful +/// in controlled network hardware environments (like a LAN) or for singleplayer +/// games (like BArricade and its large paths) +//#define MAXPACKETSIZE 1500 + +/// Modify me to enable metric gathering code in the renderers. +/// +/// 0 does nothing; higher numbers enable higher levels of metric gathering. +//#define TORQUE_GATHER_METRICS 0 + +/// Define me if you want to enable debug guards in the memory manager. +/// +/// Debug guards are known values placed before and after every block of +/// allocated memory. They are checked periodically by Memory::validate(), +/// and if they are modified (indicating an access to memory the app doesn't +/// "own"), an error is flagged (ie, you'll see a crash in the memory +/// manager's validate code). Using this and a debugger, you can track down +/// memory corruption issues quickly. +//#define TORQUE_DEBUG_GUARD + +/// Define me if you want to enable instanced-static behavior +//#define TORQUE_ENABLE_THREAD_STATICS + +/// Define me if you want to gather static-usage metrics +//#define TORQUE_ENABLE_THREAD_STATIC_METRICS + +/// Define me if you want to enable debug guards on the FrameAllocator. +/// +/// This is similar to the above memory manager guards, but applies only to the +/// fast FrameAllocator temporary pool memory allocations. The guards are only +/// checked when the FrameAllocator frees memory (when it's water mark changes). +/// This is most useful for detecting buffer overruns when using FrameTemp<> . +/// A buffer overrun in the FrameAllocator is unlikely to cause a crash, but may +/// still result in unexpected behavior, if other FrameTemp's are stomped. +//#define FRAMEALLOCATOR_DEBUG_GUARD + +/// This #define is used by the FrameAllocator to set the size of the frame. +/// +/// It was previously set to 3MB but I've increased it to 16MB due to the +/// FrameAllocator being used as temporary storage for bitmaps in the D3D9 +/// texture manager. +#define TORQUE_FRAME_SIZE 16 << 20 + +// Finally, we define some dependent #defines. This enables some subsidiary +// functionality to get automatically turned on in certain configurations. + +#ifdef TORQUE_DEBUG + + #define TORQUE_GATHER_METRICS 0 + #define TORQUE_ENABLE_PROFILE_PATH + #ifndef TORQUE_DEBUG_GUARD + #define TORQUE_DEBUG_GUARD + #endif + #ifndef TORQUE_NET_STATS + #define TORQUE_NET_STATS + #endif + + // Enables the C++ assert macros AssertFatal, AssertWarn, etc. + #ifndef TORQUE_ENABLE_ASSERTS + #define TORQUE_ENABLE_ASSERTS + #endif + +#endif + +#ifdef TORQUE_RELEASE + // If it's not DEBUG, it's a RELEASE build, put appropriate things here. +#endif + +#ifdef TORQUE_SHIPPING + + // TORQUE_SHIPPING flags here. + +#else + + // Enable the profiler by default, if we're not doing a shipping build. + #define TORQUE_ENABLE_PROFILER + + // Enable the TorqueScript assert() instruction if not shipping. + #define TORQUE_ENABLE_SCRIPTASSERTS + + // We also enable GFX debug events for use in Pix and other graphics + // debugging tools. + #define TORQUE_ENABLE_GFXDEBUGEVENTS + +#endif + +#ifdef TORQUE_TOOLS +# define TORQUE_INSTANCE_EXCLUSION "TorqueToolsTest" +#else +# define TORQUE_INSTANCE_EXCLUSION "TorqueTest" +#endif + +// Someday, it might make sense to do some pragma magic here so we error +// on inconsistent flags. + +// The Xbox360 has it's own profiling tools, the Torque Profiler should not be used +#ifdef TORQUE_OS_XENON +# ifdef TORQUE_ENABLE_PROFILER +# undef TORQUE_ENABLE_PROFILER +# endif +# +# ifdef TORQUE_ENABLE_PROFILE_PATH +# undef TORQUE_ENABLE_PROFILE_PATH +#endif +#endif diff --git a/Tools/dae2dts/source/main.cpp b/Tools/dae2dts/source/main.cpp index 64a78c82e..f92b9fa24 100644 --- a/Tools/dae2dts/source/main.cpp +++ b/Tools/dae2dts/source/main.cpp @@ -31,7 +31,7 @@ #include "ts/tsShape.h" #include "ts/tsShapeConstruct.h" -#ifdef TORQUE_OS_WIN32 +#ifdef TORQUE_OS_WIN #include "platformWin32/platformWin32.h" #include "platformWin32/winConsole.h" #endif diff --git a/Tools/projectGenerator/btargets/targets.inc b/Tools/projectGenerator/btargets/targets.inc index 5637164aa..0f010c936 100644 --- a/Tools/projectGenerator/btargets/targets.inc +++ b/Tools/projectGenerator/btargets/targets.inc @@ -184,7 +184,7 @@ $c->setDontCompilePatterns( "*\.h*", "*win32*", "*\.win\.*", "/D3D.*/", "#/gl/#" ///////////////////////////// Build ///////////////////////////// -// 'buildManifest_'.$name.'_'.Generator::$platform.'.txt', +// 'buildManifest_'.$name.'_'.T3D_Generator::$platform.'.txt', $c = BuildTarget::add( 'build', // Name 'buildFiles', // Solution output directory diff --git a/Tools/projectGenerator/classes/Generator.php b/Tools/projectGenerator/classes/Generator.php index 257b3933b..564339594 100644 --- a/Tools/projectGenerator/classes/Generator.php +++ b/Tools/projectGenerator/classes/Generator.php @@ -37,7 +37,7 @@ require_once( "NPWebPlugin.php"); require_once( "SafariWebPlugin.php"); -class Generator +class T3D_Generator { public static $app_name; public static $paths = array(); @@ -275,14 +275,14 @@ class Generator array_push( self::$libGuard, $lib ); // if currently in a project, delay the include - if (Generator::inProjectConfig()) + if (T3D_Generator::inProjectConfig()) { array_push( self::$project_cur->lib_includes, $lib ); return; } // otherwise include it immediately - require( Generator::getGeneratorLibsPath() . $lib . '.conf' ); + require( T3D_Generator::getGeneratorLibsPath() . $lib . '.conf' ); } static function addProjectDependency( $pd ) @@ -335,7 +335,7 @@ class Generator if( !self::$module_cur ) self::$module_cur = $name; else - echo( "Generator::beginModule() - already in module!" ); + echo( "T3D_Generator::beginModule() - already in module!" ); } static function endModule() @@ -343,7 +343,7 @@ class Generator if( self::$module_cur ) self::$module_cur = null; else - trigger_error( "Generator::endModule() - no active module!", E_USER_ERROR ); + trigger_error( "T3D_Generator::endModule() - no active module!", E_USER_ERROR ); } static function inProjectConfig() @@ -367,7 +367,7 @@ class Generator self::$config_projects[ $name ] = self::$project_cur; } else - trigger_error( "Generator::beginProjectConfig() - a project is already open!", E_USER_ERROR ); + trigger_error( "T3D_Generator::beginProjectConfig() - a project is already open!", E_USER_ERROR ); } static function endProjectConfig( $type ) @@ -424,14 +424,14 @@ class Generator // Now include any libraries included in the modules foreach( $p->lib_includes as $libName ) - require( Generator::getGeneratorLibsPath() . $libName . '.conf' ); + require( T3D_Generator::getGeneratorLibsPath() . $libName . '.conf' ); } else - trigger_error( "Generator::endProjectConfig() - closing type mismatch!", E_USER_ERROR ); + trigger_error( "T3D_Generator::endProjectConfig() - closing type mismatch!", E_USER_ERROR ); } else - trigger_error( "Generator::endProjectConfig() - no currently open project!", E_USER_ERROR ); + trigger_error( "T3D_Generator::endProjectConfig() - no currently open project!", E_USER_ERROR ); } static function beginActiveXConfig( $lib_name, $guid = '', $game_dir = 'game', $output_name = '' ) @@ -571,7 +571,7 @@ class Generator self::$solutions[ $name ] = self::$solution_cur; } else - trigger_error( "Generator::beginSolution() - tried to start $name but already in the ".self::$solution_cur->name." solution!", E_USER_ERROR ); + trigger_error( "T3D_Generator::beginSolution() - tried to start $name but already in the ".self::$solution_cur->name." solution!", E_USER_ERROR ); } static function addSolutionProjectRef( $pname ) @@ -579,7 +579,7 @@ class Generator if( isset( self::$solution_cur ) ) self::$solution_cur->addProjectRef( $pname ); else - trigger_error( "Generator::addSolutionProjectRef(): no such project - " . $pname . "\n", E_USER_ERROR ); + trigger_error( "T3D_Generator::addSolutionProjectRef(): no such project - " . $pname . "\n", E_USER_ERROR ); } static function addSolutionProjectRefExt( $pname, $ppath, $pguid ) @@ -587,7 +587,7 @@ class Generator if( isset( self::$solution_cur ) ) self::$solution_cur->addSolutionProjectRefExt( $pname, $ppath, $pguid ); else - trigger_error( "Generator::addSolutionProjectRefExt(): no such project - " . $pname . "\n", E_USER_ERROR ); + trigger_error( "T3D_Generator::addSolutionProjectRefExt(): no such project - " . $pname . "\n", E_USER_ERROR ); } static function endSolution() @@ -599,7 +599,7 @@ class Generator self::$solution_cur = null; } else - trigger_error( "Generator::endSolution(): no active solution!\n", E_USER_ERROR ); + trigger_error( "T3D_Generator::endSolution(): no active solution!\n", E_USER_ERROR ); } static function generateSolutions( $tpl ) diff --git a/Tools/projectGenerator/classes/Project.php b/Tools/projectGenerator/classes/Project.php index 068174c70..50a9343ac 100644 --- a/Tools/projectGenerator/classes/Project.php +++ b/Tools/projectGenerator/classes/Project.php @@ -165,7 +165,7 @@ class Project foreach( $this->dependencies as $pname ) { - $p = Generator::lookupProjectByName( $pname ); + $p = T3D_Generator::lookupProjectByName( $pname ); if( $p ) array_push( $pguids, $p->guid ); @@ -200,10 +200,10 @@ class Project { // This could be consolidated into a single OR statement but it is easier to // read as two separate if's - if ( !Generator::$absPath ) + if ( !T3D_Generator::$absPath ) $newEntry->path = $output->project_rel_path . $newEntry->path; - if ( Generator::$absPath && !stristr($newEntry->path, Generator::$absPath) ) + if ( T3D_Generator::$absPath && !stristr($newEntry->path, T3D_Generator::$absPath) ) $newEntry->path = $output->project_rel_path . $newEntry->path; } @@ -230,10 +230,10 @@ class Project $curPath = FileUtil::collapsePath( $output->base_dir . $dir ); $pathWalk = &$projectFiles[ $projName ]; - if ( Generator::$absPath ) + if ( T3D_Generator::$absPath ) { if ( stristr($curPath, getEngineSrcDir()) || stristr($curPath, getLibSrcDir()) ) - $curPath = Generator::$absPath . "/". str_replace("../", "", $curPath); + $curPath = T3D_Generator::$absPath . "/". str_replace("../", "", $curPath); } // Check if its a file or a directory. @@ -344,7 +344,7 @@ class Project $tpl->assign_by_ref( 'projModuleDefinitionFile', $this->moduleDefinitionFile ); $tpl->assign_by_ref( 'projSubSystem', $this->projSubSystem ); - if (Generator::$useDLLRuntime) + if (T3D_Generator::$useDLLRuntime) { // /MD and /MDd $tpl->assign( 'projRuntimeRelease', 2 ); @@ -381,7 +381,7 @@ class Project foreach ($this->dependencies as $pname) { - $p = Generator::lookupProjectByName( $pname ); + $p = T3D_Generator::lookupProjectByName( $pname ); $projectDepends[$pname] = $p; if ( $p ) @@ -394,18 +394,18 @@ class Project // Assign some handy paths for the template to reference $tpl->assign( 'projectOffset', $output->project_rel_path ); - if ( Generator::$absPath ) - $tpl->assign( 'srcDir', Generator::$absPath . "/". str_replace("../", "", getAppEngineSrcDir()) ); + if ( T3D_Generator::$absPath ) + $tpl->assign( 'srcDir', T3D_Generator::$absPath . "/". str_replace("../", "", getAppEngineSrcDir()) ); else $tpl->assign( 'srcDir', $output->project_rel_path . getAppEngineSrcDir() ); - if ( Generator::$absPath ) - $tpl->assign( 'libDir', Generator::$absPath . "/". str_replace("../", "", getAppLibSrcDir()) ); + if ( T3D_Generator::$absPath ) + $tpl->assign( 'libDir', T3D_Generator::$absPath . "/". str_replace("../", "", getAppLibSrcDir()) ); else $tpl->assign( 'libDir', $output->project_rel_path . getAppLibSrcDir() ); - if ( Generator::$absPath ) - $tpl->assign( 'binDir', Generator::$absPath . "/". str_replace("../", "", getAppEngineBinDir()) ); + if ( T3D_Generator::$absPath ) + $tpl->assign( 'binDir', T3D_Generator::$absPath . "/". str_replace("../", "", getAppEngineBinDir()) ); else $tpl->assign( 'binDir', $output->project_rel_path . getAppEngineBinDir() ); @@ -427,18 +427,18 @@ class Project $libDirs = $output->project_rel_path . $libDirs; } - if ( Generator::$absPath ) + if ( T3D_Generator::$absPath ) { foreach ($this->includes as &$include) { if ( stristr($include, getEngineSrcDir()) || stristr($include, getLibSrcDir()) ) - $include = Generator::$absPath . "/". str_replace("../", "", $include); + $include = T3D_Generator::$absPath . "/". str_replace("../", "", $include); } foreach ($this->lib_dirs as &$libDirs) { if ( stristr($libDirs, getEngineSrcDir()) || stristr($libDirs, getLibSrcDir()) ) - $libDirs = Generator::$absPath . "/". str_replace("../", "", $libDirs); + $libDirs = T3D_Generator::$absPath . "/". str_replace("../", "", $libDirs); } } } diff --git a/Tools/projectGenerator/classes/Solution.php b/Tools/projectGenerator/classes/Solution.php index ad352b9af..dbc52f1c2 100644 --- a/Tools/projectGenerator/classes/Solution.php +++ b/Tools/projectGenerator/classes/Solution.php @@ -85,7 +85,7 @@ class Solution // Look up each project ref and add its info to the list foreach( $refs as $pname ) { - $project = Generator::lookupProjectByName( $pname ); + $project = T3D_Generator::lookupProjectByName( $pname ); if( isset( $project ) ) { diff --git a/Tools/projectGenerator/classes/Torque3D.php b/Tools/projectGenerator/classes/Torque3D.php index 64c088a55..b682092c6 100644 --- a/Tools/projectGenerator/classes/Torque3D.php +++ b/Tools/projectGenerator/classes/Torque3D.php @@ -45,7 +45,7 @@ class Torque3D includeLib( 'convexDecomp' ); // Use FMOD on consoles - if ( Generator::$platform != "360" && Generator::$platform != "ps3" ) + if ( T3D_Generator::$platform != "360" && T3D_Generator::$platform != "ps3" ) { includeLib( 'libvorbis' ); includeLib( 'libogg' ); @@ -63,12 +63,12 @@ class Torque3D self::includeDefaultLibs(); $ext = "DLL"; - if ( Generator::$platform == "mac" ) + if ( T3D_Generator::$platform == "mac" ) $ext = "Bundle"; //some platforms will not want a shared config - if ( Generator::$platform == "360" || Generator::$platform == "ps3" ) + if ( T3D_Generator::$platform == "360" || T3D_Generator::$platform == "ps3" ) self::$sharedConfig = false; //begin either a shared lib config, or a static app config @@ -105,7 +105,7 @@ class Torque3D addLibIncludePath( "squish" ); addLibIncludePath( 'convexDecomp' ); - if ( Generator::$platform != "360" && Generator::$platform != "ps3" ) + if ( T3D_Generator::$platform != "360" && T3D_Generator::$platform != "ps3" ) { addLibIncludePath( "libvorbis/include" ); addLibIncludePath( "libogg/include" ); @@ -121,13 +121,13 @@ class Torque3D includeModule( 'basicLighting' ); includeModule( 'collada' ); - if ( Generator::$platform != "360" && Generator::$platform != "ps3" ) + if ( T3D_Generator::$platform != "360" && T3D_Generator::$platform != "ps3" ) { includeModule( 'vorbis' ); includeModule( 'theora' ); } - if(Generator::$platform == "mac" || Generator::$platform == "win32") + if(T3D_Generator::$platform == "mac" || T3D_Generator::$platform == "win32") includeModule( 'openal' ); @@ -145,20 +145,20 @@ class Torque3D addProjectDependency( 'pcre' ); addProjectDependency( 'convexDecomp' ); - if ( Generator::$platform != "360" && Generator::$platform != "ps3" ) + if ( T3D_Generator::$platform != "360" && T3D_Generator::$platform != "ps3" ) { addProjectDependency( 'libvorbis' ); addProjectDependency( 'libogg' ); addProjectDependency( 'libtheora' ); } - if ( Generator::$platform == "mac" ) + if ( T3D_Generator::$platform == "mac" ) { addProjectDefine( '__MACOSX__' ); addProjectDefine( 'LTM_DESC' ); } - if (Generator::$platform == "win32") + if (T3D_Generator::$platform == "win32") { setProjectModuleDefinitionFile('../../' . getLibSrcDir() . 'Torque3D/msvc/torque3d.def'); @@ -209,13 +209,13 @@ class Torque3D addEngineSrcDir( 'main' ); - if (Generator::$platform == "win32") + if (T3D_Generator::$platform == "win32") { addProjectDefine( 'WIN32' ); addProjectDependency( getGameProjectName() . ' DLL' ); } - if (Generator::$platform == "mac") + if (T3D_Generator::$platform == "mac") { addProjectDefine( '__MACOSX__' ); addProjectDependency( getGameProjectName() . ' Bundle' ); @@ -226,7 +226,7 @@ class Torque3D } // Add solution references for Visual Studio projects - if (Generator::$platform == "win32" || Generator::$platform == "360" || Generator::$platform == "ps3") + if (T3D_Generator::$platform == "win32" || T3D_Generator::$platform == "360" || T3D_Generator::$platform == "ps3") { if ( !self::$sharedConfig ) beginSolutionConfig( getGameProjectName(), '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}' ); @@ -247,7 +247,7 @@ class Torque3D addSolutionProjectRef( 'zlib' ); addSolutionProjectRef( 'convexDecomp' ); - if (Generator::$platform == "win32") + if (T3D_Generator::$platform == "win32") { addSolutionProjectRef( 'libogg' ); addSolutionProjectRef( 'libvorbis' ); diff --git a/Tools/projectGenerator/libs/Torque3D.conf b/Tools/projectGenerator/libs/Torque3D.conf index 7ddc28cef..83833c2d5 100644 --- a/Tools/projectGenerator/libs/Torque3D.conf +++ b/Tools/projectGenerator/libs/Torque3D.conf @@ -35,7 +35,7 @@ includeLib( 'pcre' ); includeLib( 'convexDecomp' ); // Use FMOD on consoles -if ( Generator::$platform != "360" && Generator::$platform != "ps3" ) +if ( T3D_Generator::$platform != "360" && T3D_Generator::$platform != "ps3" ) { includeLib( 'libvorbis' ); includeLib( 'libogg' ); @@ -43,7 +43,7 @@ if ( Generator::$platform != "360" && Generator::$platform != "ps3" ) } $ext = "DLL"; -if ( Generator::$platform == "mac" ) +if ( T3D_Generator::$platform == "mac" ) $ext = "Bundle"; // We need to pick the right physics engine to include. @@ -52,7 +52,7 @@ global $PHYSX_SDK_PATH; //some platforms will not want a shared config $useSharedConfig = true; -if ( Generator::$platform == "360" || Generator::$platform == "ps3" ) +if ( T3D_Generator::$platform == "360" || T3D_Generator::$platform == "ps3" ) $useSharedConfig = false; //begin either a shared lib config, or a static app config @@ -89,7 +89,7 @@ else addLibIncludePath( "squish" ); addLibIncludePath( "convexDecomp" ); - if ( Generator::$platform != "360" && Generator::$platform != "ps3" ) + if ( T3D_Generator::$platform != "360" && T3D_Generator::$platform != "ps3" ) { addLibIncludePath( "libvorbis/include" ); addLibIncludePath( "libogg/include" ); @@ -107,13 +107,13 @@ else includeModule( 'basicLighting' ); includeModule( 'collada' ); - if ( Generator::$platform != "360" && Generator::$platform != "ps3" ) + if ( T3D_Generator::$platform != "360" && T3D_Generator::$platform != "ps3" ) { includeModule( 'vorbis' ); includeModule( 'theora' ); } - if(Generator::$platform == "mac" || Generator::$platform == "win32") + if(T3D_Generator::$platform == "mac" || T3D_Generator::$platform == "win32") includeModule( 'openal' ); // Demo functionality @@ -142,7 +142,7 @@ else addProjectDependency( 'pcre' ); addProjectDependency( 'convexDecomp' ); - if ( Generator::$platform != "360" && Generator::$platform != "ps3" ) + if ( T3D_Generator::$platform != "360" && T3D_Generator::$platform != "ps3" ) { addProjectDependency( 'libvorbis' ); addProjectDependency( 'libogg' ); @@ -162,13 +162,13 @@ else addProjectDependency( 'nxuStream' ); } - if ( Generator::$platform == "mac" ) + if ( T3D_Generator::$platform == "mac" ) { addProjectDefine( '__MACOSX__' ); addProjectDefine( 'LTM_DESC' ); } - if (Generator::$platform == "win32") + if (T3D_Generator::$platform == "win32") { setProjectModuleDefinitionFile('../../' . getLibSrcDir() . 'Torque3D/msvc/torque3d.def'); @@ -216,13 +216,13 @@ beginSharedAppConfig( getGameProjectName(), '{CDECDFF9-E125-523F-87BC-2D89DB971C addEngineSrcDir( 'main' ); - if (Generator::$platform == "win32") + if (T3D_Generator::$platform == "win32") { addProjectDefine( 'WIN32' ); addProjectDependency( getGameProjectName() . ' DLL' ); } - if (Generator::$platform == "mac") + if (T3D_Generator::$platform == "mac") { addProjectDefine( '__MACOSX__' ); addProjectDependency( getGameProjectName() . ' Bundle' ); @@ -233,7 +233,7 @@ endSharedAppConfig(); } // Add solution references for Visual Studio projects -if (Generator::$platform == "win32" || Generator::$platform == "360" || Generator::$platform == "ps3") +if (T3D_Generator::$platform == "win32" || T3D_Generator::$platform == "360" || T3D_Generator::$platform == "ps3") { if ( !$useSharedConfig ) beginSolutionConfig( getGameProjectName(), '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}' ); @@ -253,7 +253,7 @@ if ( !$useSharedConfig ) addSolutionProjectRef( 'zlib' ); addSolutionProjectRef( 'convexDecomp' ); - if (Generator::$platform == "win32") + if (T3D_Generator::$platform == "win32") { addSolutionProjectRef( 'libogg' ); addSolutionProjectRef( 'libvorbis' ); diff --git a/Tools/projectGenerator/libs/WebDeploy.conf b/Tools/projectGenerator/libs/WebDeploy.conf index b92f21f41..11c3619e0 100644 --- a/Tools/projectGenerator/libs/WebDeploy.conf +++ b/Tools/projectGenerator/libs/WebDeploy.conf @@ -21,7 +21,7 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- -if (Generator::$platform == "win32") +if (T3D_Generator::$platform == "win32") { // Include the web deployment settings $webDeployConf = realpath($argv[1])."/buildFiles/config/webDeploy.conf"; @@ -55,7 +55,7 @@ if (Generator::$platform == "win32") } -if (Generator::$platform == "mac") +if (T3D_Generator::$platform == "mac") { // Include the web deployment settings $webDeployConf = realpath($argv[1])."/buildFiles/config/webDeploy.mac.conf"; diff --git a/Tools/projectGenerator/libs/convexDecomp.conf b/Tools/projectGenerator/libs/convexDecomp.conf index 4cc356883..b38352ce1 100644 --- a/Tools/projectGenerator/libs/convexDecomp.conf +++ b/Tools/projectGenerator/libs/convexDecomp.conf @@ -29,13 +29,13 @@ beginLibConfig( 'convexDecomp', '{4EF87A4E-16ED-4E64-BF04-841B2675AEE0}' ); // Additional includes addLibIncludePath( 'convexDecomp' ); - if ( Generator::$platform == "360" ) + if ( T3D_Generator::$platform == "360" ) addProjectDefine( '_XBOX' ); - else if ( Generator::$platform == "ps3" ) + else if ( T3D_Generator::$platform == "ps3" ) addProjectDefine( '__CELLOS_LV2__' ); - else if ( Generator::$platform == "mac" ) + else if ( T3D_Generator::$platform == "mac" ) addProjectDefine( '__APPLE__' ); - else if ( Generator::$platform == "win32" ) + else if ( T3D_Generator::$platform == "win32" ) addProjectDefine( 'WIN32' ); endLibConfig(); diff --git a/Tools/projectGenerator/libs/libbullet.conf b/Tools/projectGenerator/libs/libbullet.conf index faaceb832..a4a7d9e0b 100644 --- a/Tools/projectGenerator/libs/libbullet.conf +++ b/Tools/projectGenerator/libs/libbullet.conf @@ -39,8 +39,8 @@ beginLibConfig( 'libbullet', '{4368B65C-F5EF-4D28-B533-B02A04EBE921}' ); addLibSrcDir( 'bullet/src/LinearMath' ); // TODO: Can we do multicore on OSX? - if ( Generator::$platform == "win32" || - Generator::$platform == "360" ) + if ( T3D_Generator::$platform == "win32" || + T3D_Generator::$platform == "360" ) { addProjectDefine( 'WIN32' ); diff --git a/Tools/projectGenerator/libs/librecast.conf b/Tools/projectGenerator/libs/librecast.conf index bb0aa66f7..3033fc07e 100644 --- a/Tools/projectGenerator/libs/librecast.conf +++ b/Tools/projectGenerator/libs/librecast.conf @@ -24,11 +24,11 @@ beginLibConfig( 'librecast', '{F2C0209B-1B90-4F73-816A-A0920FF8B107}' ); // Source - addSrcDir( Generator::getLibSrcDir() . 'recast/DebugUtils/Source', true ); - addSrcDir( Generator::getLibSrcDir() . 'recast/Recast/Source', true ); - addSrcDir( Generator::getLibSrcDir() . 'recast/Detour/Source', true ); - addSrcDir( Generator::getLibSrcDir() . 'recast/DetourCrowd/Source', true ); - addSrcDir( Generator::getLibSrcDir() . 'recast/DetourTileCache/Source', true ); + addSrcDir( T3D_Generator::getLibSrcDir() . 'recast/DebugUtils/Source', true ); + addSrcDir( T3D_Generator::getLibSrcDir() . 'recast/Recast/Source', true ); + addSrcDir( T3D_Generator::getLibSrcDir() . 'recast/Detour/Source', true ); + addSrcDir( T3D_Generator::getLibSrcDir() . 'recast/DetourCrowd/Source', true ); + addSrcDir( T3D_Generator::getLibSrcDir() . 'recast/DetourTileCache/Source', true ); // Additional includes addLibIncludePath( 'recast/DebugUtils/Include' ); diff --git a/Tools/projectGenerator/modules/T3D.inc b/Tools/projectGenerator/modules/T3D.inc index f72a12908..df256468a 100644 --- a/Tools/projectGenerator/modules/T3D.inc +++ b/Tools/projectGenerator/modules/T3D.inc @@ -74,7 +74,7 @@ else addEngineSrcDir('T3D/gameBase/std'); // Plstform specific stuff. -switch( Generator::$platform ) +switch( T3D_Generator::$platform ) { case "360": addEngineSrcDir('ts/arch/360'); diff --git a/Tools/projectGenerator/modules/advancedLighting.inc b/Tools/projectGenerator/modules/advancedLighting.inc index 9e013dc2d..ec2ff3890 100644 --- a/Tools/projectGenerator/modules/advancedLighting.inc +++ b/Tools/projectGenerator/modules/advancedLighting.inc @@ -28,7 +28,7 @@ beginModule( 'advancedLighting' ); addEngineSrcDir( 'lighting/advanced' ); addEngineSrcDir( 'lighting/shadowMap' ); - switch( Generator::$platform ) + switch( T3D_Generator::$platform ) { case "win32": addEngineSrcDir( 'lighting/advanced/hlsl' ); diff --git a/Tools/projectGenerator/modules/core.inc b/Tools/projectGenerator/modules/core.inc index a6f3cae5a..3860705f0 100644 --- a/Tools/projectGenerator/modules/core.inc +++ b/Tools/projectGenerator/modules/core.inc @@ -29,9 +29,10 @@ addEngineSrcDir('sfx'); // Components addEngineSrcDir('component'); addEngineSrcDir('component/interfaces'); +addEngineSrcDir('component/test'); // Core -if (Generator::isApp()) +if (T3D_Generator::isApp()) addSrcDir( '../source' ); addEngineSrcDir('console'); @@ -43,12 +44,10 @@ addEngineSrcDir('core/util/test'); addEngineSrcDir('core/util/journal'); addEngineSrcDir('core/util/journal/test'); addEngineSrcDir('core/util/zip'); -addEngineSrcDir('core/util/zip/unitTests'); +addEngineSrcDir('core/util/zip/test'); addEngineSrcDir('core/util/zip/compressors'); addEngineSrcDir('i18n'); addEngineSrcDir('sim'); -addEngineSrcDir('unit/tests'); -addEngineSrcDir('unit'); addEngineSrcDir('util'); addEngineSrcDir('windowManager'); addEngineSrcDir('windowManager/torque'); @@ -59,7 +58,7 @@ addEngineSrcDir('math/test'); addEngineSrcDir('platform'); addEngineSrcDir('cinterface'); -switch( Generator::$platform ) +switch( T3D_Generator::$platform ) { case "win32": case "mac": @@ -71,7 +70,9 @@ switch( Generator::$platform ) } addEngineSrcDir('platform/threads'); +addEngineSrcDir('platform/threads/test'); addEngineSrcDir('platform/async'); +addEngineSrcDir('platform/async/test'); addEngineSrcDir('platform/input'); addEngineSrcDir('platform/output'); addEngineSrcDir('app'); @@ -80,7 +81,7 @@ addEngineSrcDir('app/net'); // Moved this here temporarily because PopupMenu uses on it and is currently in core addEngineSrcDir('util/messaging'); -switch( Generator::$platform ) +switch( T3D_Generator::$platform ) { case "win32": addEngineSrcDir('platformWin32'); @@ -124,7 +125,6 @@ switch( Generator::$platform ) // GFX addEngineSrcDir( 'gfx/Null' ); -addEngineSrcDir( 'gfx/test' ); addEngineSrcDir( 'gfx/bitmap' ); addEngineSrcDir( 'gfx/bitmap/loaders' ); addEngineSrcDir( 'gfx/util' ); @@ -132,7 +132,7 @@ addEngineSrcDir( 'gfx/video' ); addEngineSrcDir( 'gfx' ); addEngineSrcDir( 'shaderGen' ); -switch( Generator::$platform ) +switch( T3D_Generator::$platform ) { case "win32": //addEngineSrcDir( 'gfx/D3D8' ); @@ -199,7 +199,7 @@ addIncludePath( '../../source' ); // product source (relative to solution ou addIncludePath( getAppEngineSrcDir() ); // main engine source dir relative to app project file addIncludePath( getAppLibSrcDir() ); // main lib source dir relative to app project file -if ( Generator::$platform == "win32" ) +if ( T3D_Generator::$platform == "win32" ) { addIncludePath( getAppLibSrcDir() . 'directx8' ); addIncludePath( getAppLibSrcDir() . 'openal/win32' ); diff --git a/Tools/projectGenerator/modules/dsound.inc b/Tools/projectGenerator/modules/dsound.inc index 178d910ff..5fc82c28d 100644 --- a/Tools/projectGenerator/modules/dsound.inc +++ b/Tools/projectGenerator/modules/dsound.inc @@ -23,13 +23,13 @@ beginModule( 'dsound' ); - if ( Generator::$platform == "win32" ) + if ( T3D_Generator::$platform == "win32" ) { addEngineSrcDir('sfx/dsound'); addEngineSrcDir('sfx/xaudio'); addProjectLibInput('x3daudio.lib'); } - else if ( Generator::$platform == "360" ) + else if ( T3D_Generator::$platform == "360" ) addEngineSrcDir('sfx/xaudio'); endModule(); diff --git a/Tools/projectGenerator/modules/fmod.inc b/Tools/projectGenerator/modules/fmod.inc index 377ec798f..2bb15d48e 100644 --- a/Tools/projectGenerator/modules/fmod.inc +++ b/Tools/projectGenerator/modules/fmod.inc @@ -25,7 +25,7 @@ beginModule( 'fmod' ); $allgood = true; // Additional includes - switch( Generator::$platform ) + switch( T3D_Generator::$platform ) { case "win32": case "mac": diff --git a/Tools/projectGenerator/modules/jpeg.inc b/Tools/projectGenerator/modules/jpeg.inc index 1fe72955b..16d3fd688 100644 --- a/Tools/projectGenerator/modules/jpeg.inc +++ b/Tools/projectGenerator/modules/jpeg.inc @@ -30,7 +30,7 @@ addLibSrcDir( 'ljpeg' ); addLibIncludePath( 'ljpeg' ); // Defines - if ( Generator::$platform == "360" ) + if ( T3D_Generator::$platform == "360" ) addProjectDefines( 'NO_GETENV;' ); endModule(); diff --git a/Tools/projectGenerator/modules/leapMotion.inc b/Tools/projectGenerator/modules/leapMotion.inc index d25e8df4c..5ffd9dfc8 100644 --- a/Tools/projectGenerator/modules/leapMotion.inc +++ b/Tools/projectGenerator/modules/leapMotion.inc @@ -61,7 +61,7 @@ beginModule( 'leapMotion' ); } // Only Windows is supported at this time - if ( Generator::$platform == "win32" ) + if ( T3D_Generator::$platform == "win32" ) { // Source addEngineSrcDir( "platform/input/leapMotion" ); diff --git a/Tools/projectGenerator/modules/libtheora.inc b/Tools/projectGenerator/modules/libtheora.inc index dfba45845..e1467201f 100644 --- a/Tools/projectGenerator/modules/libtheora.inc +++ b/Tools/projectGenerator/modules/libtheora.inc @@ -27,7 +27,7 @@ addLibSrcDir( 'libtheora/include/theora' ); addLibSrcDir( 'libtheora/lib' ); addLibSrcDir( 'libtheora/lib/dec' ); -switch( Generator::$platform ) +switch( T3D_Generator::$platform ) { case "win32": addLibSrcDir( 'libtheora/lib/dec/x86_vc' ); @@ -41,7 +41,7 @@ switch( Generator::$platform ) // As we don't use the encoder, disable this for now. addLibSrcDir( 'libtheora/lib/enc' ); -switch( Generator::$platform ) +switch( T3D_Generator::$platform ) { case "win32": addLibSrcDir( 'libtheora/lib/enc/x86_32_vs' ); diff --git a/Tools/projectGenerator/modules/oculusVR.inc b/Tools/projectGenerator/modules/oculusVR.inc index 4945a9ad9..bcf2a3199 100644 --- a/Tools/projectGenerator/modules/oculusVR.inc +++ b/Tools/projectGenerator/modules/oculusVR.inc @@ -61,7 +61,7 @@ beginModule( 'oculusVR' ); } // Only Windows is supported at this time - if ( Generator::$platform == "win32" ) + if ( T3D_Generator::$platform == "win32" ) { // Source addEngineSrcDir( "platform/input/oculusVR" ); diff --git a/Tools/projectGenerator/modules/openal.inc b/Tools/projectGenerator/modules/openal.inc index d3356b55f..471b4e42f 100644 --- a/Tools/projectGenerator/modules/openal.inc +++ b/Tools/projectGenerator/modules/openal.inc @@ -26,7 +26,7 @@ addEngineSrcDir('sfx/openal'); addEngineSrcDir('sfx/openal/mac'); addEngineSrcDir('sfx/openal/win32'); -if ( Generator::$platform == "win32" ) +if ( T3D_Generator::$platform == "win32" ) addIncludePath( getAppLibSrcDir() . 'openal/win32' ); ?> diff --git a/Tools/projectGenerator/modules/png.inc b/Tools/projectGenerator/modules/png.inc index 4165225e3..97ab5dccf 100644 --- a/Tools/projectGenerator/modules/png.inc +++ b/Tools/projectGenerator/modules/png.inc @@ -30,7 +30,7 @@ beginModule( 'lpng' ); addLibIncludePath( 'lpng' ); // Defines - if ( Generator::$platform == "360" ) + if ( T3D_Generator::$platform == "360" ) addProjectDefines( 'PNG_NO_ASSEMBLER_CODE' ); endModule(); diff --git a/Tools/projectGenerator/modules/razerHydra.inc b/Tools/projectGenerator/modules/razerHydra.inc index c381c976b..8a3bea037 100644 --- a/Tools/projectGenerator/modules/razerHydra.inc +++ b/Tools/projectGenerator/modules/razerHydra.inc @@ -61,7 +61,7 @@ beginModule( 'razerHydra' ); } // Only Windows is supported at this time - if ( Generator::$platform == "win32" ) + if ( T3D_Generator::$platform == "win32" ) { // Source addEngineSrcDir( "platform/input/razerHydra" ); diff --git a/Engine/source/unit/memoryTester.h b/Tools/projectGenerator/modules/testing.inc similarity index 81% rename from Engine/source/unit/memoryTester.h rename to Tools/projectGenerator/modules/testing.inc index bd9dfd71c..384ab14e8 100644 --- a/Engine/source/unit/memoryTester.h +++ b/Tools/projectGenerator/modules/testing.inc @@ -1,5 +1,6 @@ + diff --git a/Tools/projectGenerator/projectGenUtils.inc b/Tools/projectGenerator/projectGenUtils.inc index f3e599ac9..416dfa8f1 100644 --- a/Tools/projectGenerator/projectGenUtils.inc +++ b/Tools/projectGenerator/projectGenUtils.inc @@ -32,7 +32,7 @@ function beginProject($name, $sharedConfig) // Set the game project name, this is what your game's exe/dll will be called setGameProjectName($name); - if (Generator::$platform == "win32" && $sharedConfig) + if (T3D_Generator::$platform == "win32" && $sharedConfig) beginSolutionConfig( $name, '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}' ); @@ -40,18 +40,18 @@ function beginProject($name, $sharedConfig) function endProject($sharedConfig) { - if (Generator::$platform == "win32" && $sharedConfig) + if (T3D_Generator::$platform == "win32" && $sharedConfig) endSolutionConfig(); } function beginSolutionConfig( $name, $guid = '' ) { - Generator::beginSolution( $name, $guid ); + T3D_Generator::beginSolution( $name, $guid ); } function addSolutionProjectRef( $pname ) { - Generator::addSolutionProjectRef( $pname ); + T3D_Generator::addSolutionProjectRef( $pname ); } // Add a reference to an external project, this is used for WPF projects currently @@ -59,114 +59,114 @@ function addSolutionProjectRef( $pname ) // However, it is nice to not have to add the project to the solution whenever you run the project generator function addSolutionProjectRefExt( $pname, $ppath, $pguid ) { - Generator::addSolutionProjectRefExt( $pname, $ppath, $pguid ); + T3D_Generator::addSolutionProjectRefExt( $pname, $ppath, $pguid ); } function endSolutionConfig() { - Generator::endSolution(); + T3D_Generator::endSolution(); } function setPlatform( $platform ) { echo(' - Setting platform to: ' . $platform . "\n"); - Generator::$platform = $platform; + T3D_Generator::$platform = $platform; } function includeLib( $libName ) { - //echo( "GLP: " . Generator::getGeneratorLibsPath() . $libName . "\n" ); + //echo( "GLP: " . T3D_Generator::getGeneratorLibsPath() . $libName . "\n" ); - Generator::includeLib( $libName ); + T3D_Generator::includeLib( $libName ); } function includeModule( $modName ) { - require( Generator::getGeneratorModulesPath() . $modName . '.inc' ); + require( T3D_Generator::getGeneratorModulesPath() . $modName . '.inc' ); } function beginActiveXConfig( $lib_name, $guid = '', $gameDir = 'game', $output_name = '' ) { - Generator::beginActiveXConfig( $lib_name, $guid, $gameDir, $output_name ); + T3D_Generator::beginActiveXConfig( $lib_name, $guid, $gameDir, $output_name ); } function endActiveXConfig() { - Generator::endActiveXConfig(); + T3D_Generator::endActiveXConfig(); } function beginSafariConfig( $lib_name, $guid = '', $gameDir = 'game', $output_name = '' ) { - Generator::beginSafariConfig( $lib_name, $guid, $gameDir, $output_name ); + T3D_Generator::beginSafariConfig( $lib_name, $guid, $gameDir, $output_name ); } function endSafariConfig() { - Generator::endSafariConfig(); + T3D_Generator::endSafariConfig(); } function beginSharedLibConfig( $lib_name, $guid = '', $gameDir = 'game', $output_name = '' ) { - Generator::beginSharedLibConfig( $lib_name, $guid, $gameDir, $output_name ); + T3D_Generator::beginSharedLibConfig( $lib_name, $guid, $gameDir, $output_name ); } function endSharedLibConfig() { - Generator::endSharedLibConfig(); + T3D_Generator::endSharedLibConfig(); } function beginNPPluginConfig( $lib_name, $guid = '', $gameDir = 'game', $output_name = '' ) { - Generator::beginNPPluginConfig( $lib_name, $guid, $gameDir, $output_name ); + T3D_Generator::beginNPPluginConfig( $lib_name, $guid, $gameDir, $output_name ); } function endNPPluginConfig() { - Generator::endNPPluginConfig(); + T3D_Generator::endNPPluginConfig(); } function beginLibConfig( $lib_name, $guid = '', $gameDir = 'game', $output_name = '' ) { - Generator::beginLibConfig( $lib_name, $guid, $gameDir, $output_name ); + T3D_Generator::beginLibConfig( $lib_name, $guid, $gameDir, $output_name ); } function endLibConfig() { - Generator::endLibConfig(); + T3D_Generator::endLibConfig(); } function beginAppConfig( $app_name, $guid = '', $game_dir = 'game', $output_name = '' ) { - Generator::beginAppConfig( $app_name, $guid, $game_dir, $output_name ); + T3D_Generator::beginAppConfig( $app_name, $guid, $game_dir, $output_name ); } function endAppConfig() { - Generator::endAppConfig(); + T3D_Generator::endAppConfig(); } function beginSharedAppConfig( $app_name, $guid = '', $game_dir = 'game', $output_name = '' ) { - Generator::beginSharedAppConfig( $app_name, $guid, $game_dir, $output_name ); + T3D_Generator::beginSharedAppConfig( $app_name, $guid, $game_dir, $output_name ); } function endSharedAppConfig() { - Generator::endSharedAppConfig(); + T3D_Generator::endSharedAppConfig(); } function beginCSProjectConfig( $app_name, $guid = '', $game_dir = 'game', $output_name = '' ) { - Generator::beginCSProjectConfig( $app_name, $guid, $game_dir, $output_name ); + T3D_Generator::beginCSProjectConfig( $app_name, $guid, $game_dir, $output_name ); } function endCSProjectConfig() { - Generator::endCSProjectConfig(); + T3D_Generator::endCSProjectConfig(); } @@ -175,26 +175,26 @@ function endCSProjectConfig() function beginModule( $name ) { - Generator::beginModule( $name ); + T3D_Generator::beginModule( $name ); } function endModule() { - Generator::endModule(); + T3D_Generator::endModule(); } function addSrcDir( $dir, $recurse = false ) { //echo( "ADD SRC DIR: " . $dir . "\n" ); - Generator::addSrcDir( $dir, $recurse ); + T3D_Generator::addSrcDir( $dir, $recurse ); } function addSrcFile( $file ) { //echo( "ADD SRC FILE: " . $file . "\n" ); - Generator::addSrcFile( $file ); + T3D_Generator::addSrcFile( $file ); } function addEngineSrcDir( $dir ) @@ -213,12 +213,12 @@ function addEngineSrcFile( $file ) function addLibSrcDir( $dir ) { - addSrcDir( Generator::getLibSrcDir() . $dir ); + addSrcDir( T3D_Generator::getLibSrcDir() . $dir ); } function addLibSrcFile( $file ) { - addSrcDir( Generator::getLibSrcDir() . $file ); + addSrcDir( T3D_Generator::getLibSrcDir() . $file ); } function addLibIncludePath( $path ) @@ -253,29 +253,29 @@ function getAppEngineBinDir() function getEngineSrcDir() { - return Generator::getEngineSrcDir(); + return T3D_Generator::getEngineSrcDir(); } function getLibSrcDir() { - return Generator::getLibSrcDir(); + return T3D_Generator::getLibSrcDir(); } function getEngineBinDir() { - return Generator::getEngineBinDir(); + return T3D_Generator::getEngineBinDir(); } function addIncludePath( $path ) { //echo( "ADD INCLUDE: " . $path . "\n" ); - Generator::addIncludePath( $path ); + T3D_Generator::addIncludePath( $path ); } /// Add a preprocessor directive/define function addProjectDefine( $d, $v = null ) { - Generator::addProjectDefine( $d, $v ); + T3D_Generator::addProjectDefine( $d, $v ); } /// Add a list of defines in one call function addProjectDefines() @@ -284,143 +284,143 @@ function addProjectDefines() $count = func_num_args(); if( $count > 0 ) - Generator::addProjectDefines( $args ); + T3D_Generator::addProjectDefines( $args ); else echo( "addProjectDefines() - no arguments passed!" ); } function setProjectGUID( $guid ) { - Generator::setProjectGUID( $guid ); + T3D_Generator::setProjectGUID( $guid ); } function setProjectModuleDefinitionFile( $mdef ) { - Generator::setProjectModuleDefinitionFile( $mdef ); + T3D_Generator::setProjectModuleDefinitionFile( $mdef ); } function addProjectLibDir( $dir ) { - Generator::addProjectLibDir( $dir ); + T3D_Generator::addProjectLibDir( $dir ); } function addProjectLibInput( $lib_name, $libDebug = null ) { - Generator::addProjectLibInput( $lib_name, $libDebug ); + T3D_Generator::addProjectLibInput( $lib_name, $libDebug ); } function addProjectIgnoreDefaultLib( $lib ) { - Generator::addProjectIgnoreDefaultLib( $lib ); + T3D_Generator::addProjectIgnoreDefaultLib( $lib ); } function copyFileToProject( $sourcePath, $projPath ) { - Generator::copyFileToProject( $sourcePath, $projPath ); + T3D_Generator::copyFileToProject( $sourcePath, $projPath ); } function addProjectDependency( $pd ) { - Generator::addProjectDependency( $pd ); + T3D_Generator::addProjectDependency( $pd ); } function removeProjectDependency( $pd ) { - Generator::removeProjectDependency( $pd ); + T3D_Generator::removeProjectDependency( $pd ); } function addProjectReference( $refName, $version = "" ) { - Generator::addProjectReference( $refName, $version ); + T3D_Generator::addProjectReference( $refName, $version ); } // disable a specific project compiler warning function disableProjectWarning( $warning ) { - Generator::disableProjectWarning( $warning ); + T3D_Generator::disableProjectWarning( $warning ); } function setGameProjectName($name) { - Generator::setGameProjectName($name); + T3D_Generator::setGameProjectName($name); } function getGameProjectName() { - return Generator::getGameProjectName(); + return T3D_Generator::getGameProjectName(); } function setToolBuild($tb) { - Generator::setToolBuild($tb); + T3D_Generator::setToolBuild($tb); } function getToolBuild() { - return Generator::getToolBuild(); + return T3D_Generator::getToolBuild(); } function setWatermarkBuild($wb) { - Generator::setWatermarkBuild($wb); + T3D_Generator::setWatermarkBuild($wb); } function getWatermarkBuild() { - return Generator::getWatermarkBuild(); + return T3D_Generator::getWatermarkBuild(); } function setPurchaseScreenBuild($psb) { - Generator::setPurchaseScreenBuild($psb); + T3D_Generator::setPurchaseScreenBuild($psb); } function getPurchaseScreenBuild() { - return Generator::getPurchaseScreenBuild(); + return T3D_Generator::getPurchaseScreenBuild(); } function setDemoBuild($db) { - Generator::setDemoBuild($db); + T3D_Generator::setDemoBuild($db); } function getDemoBuild() { - return Generator::getDemoBuild(); + return T3D_Generator::getDemoBuild(); } function setObjectLimitBuild($olb) { - Generator::setObjectLimitBuild($olb); + T3D_Generator::setObjectLimitBuild($olb); } function getObjectLimitBuild() { - return Generator::getObjectLimitBuild(); + return T3D_Generator::getObjectLimitBuild(); } function setTimeOutBuild($tob) { - Generator::setTimeOutBuild($tob); + T3D_Generator::setTimeOutBuild($tob); } function getTimeOutBuild() { - return Generator::getTimeOutBuild(); + return T3D_Generator::getTimeOutBuild(); } function inProjectConfig() { - return Generator::inProjectConfig(); + return T3D_Generator::inProjectConfig(); } // On Windows, 1 - Console, 2 - Windows function setProjectSubSystem( $subSystem ) { - Generator::setProjectSubSystem( $subSystem ); + T3D_Generator::setProjectSubSystem( $subSystem ); } // Sets whether to use /MT or /MD code generation/runtime on Windows @@ -429,7 +429,7 @@ function setProjectSubSystem( $subSystem ) // You must include or install via the redistributable package the appropriate VS runtime for end users. function setDLLRuntime ($val) { - Generator::setDLLRuntime( $val ); + T3D_Generator::setDLLRuntime( $val ); } //-------------------------------------------------------------------------------- UTIL diff --git a/Tools/projectGenerator/projectGenerator.php b/Tools/projectGenerator/projectGenerator.php index 103fa536e..692f5c046 100644 --- a/Tools/projectGenerator/projectGenerator.php +++ b/Tools/projectGenerator/projectGenerator.php @@ -70,7 +70,7 @@ if ( $argc >= 3 ) $torqueRoot = str_replace( "\\", "/", $argv[2] ); // Kick off the generator -Generator::init( $torqueRoot ); +T3D_Generator::init( $torqueRoot ); // Ready to read our config file. echo( " - Loading config file " . realpath($argv[1])."\n" ); @@ -78,12 +78,12 @@ echo( " - Loading config file " . realpath($argv[1])."\n" ); require( $argv[ 1 ] ); // Generate all projects -Generator::generateProjects( $tpl ); +T3D_Generator::generateProjects( $tpl ); // Now the solutions (if any) $tpl->clear_all_cache(); -Generator::generateSolutions( $tpl ); +T3D_Generator::generateSolutions( $tpl ); // finally write out the sample.html for web deployment (if any) WebPlugin::writeSampleHtml(); diff --git a/Tools/projectGenerator/templates/vc2010_dll_proj.tpl b/Tools/projectGenerator/templates/vc2010_dll_proj.tpl index cd520d051..a134420f1 100644 --- a/Tools/projectGenerator/templates/vc2010_dll_proj.tpl +++ b/Tools/projectGenerator/templates/vc2010_dll_proj.tpl @@ -50,15 +50,15 @@ {$projectOffset}../../{$gameFolder}/ {$projectOffset}../Link/VC2010.$(Configuration).$(PlatformName)/$(ProjectName)/ true - {$projOutName}_DEBUG + {$projOutName}_DEBUG DLL {$projectOffset}../../{$gameFolder}/ {$projectOffset}../Link/VC2010.$(Configuration).$(PlatformName)/$(ProjectName)/ false - {$projOutName}_OPTIMIZEDDEBUG + {$projOutName}_OPTIMIZEDDEBUG DLL {$projectOffset}../../{$gameFolder}/ {$projectOffset}../Link/VC2010.$(Configuration).$(PlatformName)/$(ProjectName)/ false - {$projOutName} + {$projOutName} DLL @@ -96,7 +96,7 @@ {foreach item=def from=$projLibsDebug}{$def};{/foreach}%(AdditionalDependencies) - $(OutDir){$projOutName}_DEBUG.dll + $(OutDir)$(TargetName).dll true {foreach item=def from=$projLibDirs}{$def};{/foreach}{$projectOffset}../Link/VC2010.$(Configuration).$(PlatformName);$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) LIBC;LIBCD;{foreach item=def from=$projLibsIgnore}{$def};{/foreach}%(IgnoreSpecificDefaultLibraries) @@ -148,7 +148,7 @@ {foreach item=def from=$projLibsDebug}{$def};{/foreach}%(AdditionalDependencies) - $(OutDir){$projOutName}_OPTIMIZEDDEBUG.dll + $(OutDir)$(TargetName).dll true {foreach item=def from=$projLibDirs}{$def};{/foreach}{$projectOffset}../Link/VC2010.$(Configuration).$(PlatformName);%(AdditionalLibraryDirectories) LIBC;LIBCD;{foreach item=def from=$projLibsIgnore}{$def};{/foreach}%(IgnoreSpecificDefaultLibraries) @@ -200,7 +200,7 @@ {foreach item=def from=$projLibs}{$def};{/foreach}%(AdditionalDependencies) - $(OutDir){$projOutName}.dll + $(OutDir)$(TargetName).dll true {foreach item=def from=$projLibDirs}{$def};{/foreach}{$projectOffset}../Link/VC2010.$(Configuration).$(PlatformName);$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) LIBC;LIBCD;{foreach item=def from=$projLibsIgnore}{$def};{/foreach}%(IgnoreSpecificDefaultLibraries) diff --git a/Tools/projectGenerator/templates/vc2k8_dll_proj.tpl b/Tools/projectGenerator/templates/vc2k8_dll_proj.tpl index f9d02a7eb..e255fc0f4 100644 --- a/Tools/projectGenerator/templates/vc2k8_dll_proj.tpl +++ b/Tools/projectGenerator/templates/vc2k8_dll_proj.tpl @@ -81,9 +81,9 @@ AdditionalDependencies="{foreach item=def from=$projLibsDebug}{$def} {/foreach}" {if $uniformOutputFile eq 1} - OutputFile="{$projectOffset}../../{$gameFolder}/{$projOutName}.dll" + OutputFile="{$projectOffset}../../{$gameFolder}/{$projOutName} DLL.dll" {else} - OutputFile="{$projectOffset}../../{$gameFolder}/{$projOutName}_DEBUG.dll" + OutputFile="{$projectOffset}../../{$gameFolder}/{$projOutName}_DEBUG DLL.dll" {/if} LinkIncremental="2" @@ -191,9 +191,9 @@ AdditionalDependencies="{foreach item=def from=$projLibsDebug}{$def} {/foreach}" {if $uniformOutputFile eq 1} - OutputFile="{$projectOffset}../../{$gameFolder}/{$projOutName}.dll" + OutputFile="{$projectOffset}../../{$gameFolder}/{$projOutName} DLL.dll" {else} - OutputFile="{$projectOffset}../../{$gameFolder}/{$projOutName}_OPTIMIZEDDEBUG.dll" + OutputFile="{$projectOffset}../../{$gameFolder}/{$projOutName}_OPTIMIZEDDEBUG DLL.dll" {/if} LinkIncremental="1" @@ -299,7 +299,7 @@